1a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav/*
2a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Copyright (C) 2014 The Android Open Source Project
3a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
4a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Licensed under the Apache License, Version 2.0 (the "License");
5a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * you may not use this file except in compliance with the License.
6a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * You may obtain a copy of the License at
7a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
8a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *      http://www.apache.org/licenses/LICENSE-2.0
9a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
10a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Unless required by applicable law or agreed to in writing, software
11a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * distributed under the License is distributed on an "AS IS" BASIS,
12a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * See the License for the specific language governing permissions and
14a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * limitations under the License.
15a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */
16a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
17a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpackage com.android.printspooler.util;
18a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
19a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PageRange;
20525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.print.PrintDocumentInfo;
21c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmannimport android.util.Pair;
22a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
23c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmannimport java.util.ArrayList;
24a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Arrays;
25a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Comparator;
26a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
27a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav/**
28a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * This class contains utility functions for working with page ranges.
29a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */
30a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpublic final class PageRangeUtils {
31a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
32a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final PageRange[] ALL_PAGES_RANGE = new PageRange[] {PageRange.ALL_PAGES};
33a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
34a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final Comparator<PageRange> sComparator = new Comparator<PageRange>() {
35a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
36a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public int compare(PageRange lhs, PageRange rhs) {
37a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return lhs.getStart() - rhs.getStart();
38a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
39a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    };
40a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
41a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private PageRangeUtils() {
42a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        /* do nothing - hide constructor */
43a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
44a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
45a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    /**
46525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     * Gets whether page ranges contains a given page.
47525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     *
48525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     * @param pageRanges The page ranges.
49525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     * @param pageIndex The page for which to check.
50525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     * @return Whether the page is within the ranges.
51525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     */
52525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean contains(PageRange[] pageRanges, int pageIndex) {
53525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        final int rangeCount = pageRanges.length;
54525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        for (int i = 0; i < rangeCount; i++) {
55525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            PageRange pageRange = pageRanges[i];
56525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (pageRange.contains(pageIndex)) {
57525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                return true;
58525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
59525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
60525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return false;
61525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
62525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
63525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    /**
64a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * Checks whether one page range array contains another one.
65a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     *
66a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param ourRanges The container page ranges.
67a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param otherRanges The contained page ranges.
68525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov     * @param pageCount The total number of pages.
69a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @return Whether the container page ranges contains the contained ones.
70a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     */
71525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean contains(PageRange[] ourRanges, PageRange[] otherRanges, int pageCount) {
72a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (ourRanges == null || otherRanges == null) {
73a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return false;
74a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
75a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
76a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (Arrays.equals(ourRanges, ALL_PAGES_RANGE)) {
77a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return true;
78a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
79a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
80525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        if (Arrays.equals(otherRanges, ALL_PAGES_RANGE)) {
81525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            otherRanges[0] = new PageRange(0, pageCount - 1);
82525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
83525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
84a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        ourRanges = normalize(ourRanges);
85a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        otherRanges = normalize(otherRanges);
86a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
87a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // Note that the code below relies on the ranges being normalized
88a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // which is they contain monotonically increasing non-intersecting
89a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // sub-ranges whose start is less that or equal to the end.
90a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        int otherRangeIdx = 0;
91a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final int ourRangeCount = ourRanges.length;
92a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final int otherRangeCount = otherRanges.length;
93a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        for (int ourRangeIdx = 0; ourRangeIdx < ourRangeCount; ourRangeIdx++) {
94a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange ourRange = ourRanges[ourRangeIdx];
95a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            for (; otherRangeIdx < otherRangeCount; otherRangeIdx++) {
96a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                PageRange otherRange = otherRanges[otherRangeIdx];
97a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (otherRange.getStart() > ourRange.getEnd()) {
98a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    break;
99a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
100a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (otherRange.getStart() < ourRange.getStart()
101a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        || otherRange.getEnd() > ourRange.getEnd()) {
102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return false;
103a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
104a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
105a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
106525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return (otherRangeIdx >= otherRangeCount);
107a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
108a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
109a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    /**
110a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * Normalizes a page range, which is the resulting page ranges are
111a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * non-overlapping with the start lesser than or equal to the end
112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * and ordered in an ascending order.
113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     *
114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param pageRanges The page ranges to normalize.
115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @return The normalized page ranges.
116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     */
117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public static PageRange[] normalize(PageRange[] pageRanges) {
118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (pageRanges == null) {
119a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return null;
120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
121525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final int oldRangeCount = pageRanges.length;
123a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (oldRangeCount <= 1) {
124a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return pageRanges;
125a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
126525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
127a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        Arrays.sort(pageRanges, sComparator);
128525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
129a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        int newRangeCount = 1;
130a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        for (int i = 0; i < oldRangeCount - 1; i++) {
131a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange currentRange = pageRanges[i];
132a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange nextRange = pageRanges[i + 1];
133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (currentRange.getEnd() + 1 >= nextRange.getStart()) {
134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                pageRanges[i] = null;
135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                pageRanges[i + 1] = new PageRange(currentRange.getStart(),
136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        Math.max(currentRange.getEnd(), nextRange.getEnd()));
137525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            } else {
138525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                newRangeCount++;
139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
141525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (newRangeCount == oldRangeCount) {
143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return pageRanges;
144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
145525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
146525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        int normalRangeIndex = 0;
147525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        PageRange[] normalRanges = new PageRange[newRangeCount];
148525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        for (int i = 0; i < oldRangeCount; i++) {
149525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            PageRange normalRange = pageRanges[i];
150525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (normalRange != null) {
151525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                normalRanges[normalRangeIndex] = normalRange;
152525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                normalRangeIndex++;
153525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
154525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
155525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
156525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return normalRanges;
157a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
158a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
159a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    /**
160c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * Return the next position after {@code pos} that is not a space character.
161c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
162c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param s   The string to parse
163c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param pos The starting position
164c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
165c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @return The position of the first space character
166c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     */
167c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    private static int readWhiteSpace(CharSequence s, int pos) {
168c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        while (pos < s.length() && s.charAt(pos) == ' ') {
169c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            pos++;
170c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
171c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
172c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        return pos;
173c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    }
174c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
175c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    /**
176c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * Read a number from a string at a certain position.
177c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
178c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param s   The string to parse
179c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param pos The starting position
180c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
181c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @return The position after the number + the number read or null if the number was not found
182c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     */
183c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    private static Pair<Integer, Integer> readNumber(CharSequence s, int pos) {
184c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Integer result = 0;
185c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        while (pos < s.length() && s.charAt(pos) >= '0' && s.charAt(pos) <= '9') {
186c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            // Number cannot start with 0
187c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (result == 0 && s.charAt(pos) == '0') {
188c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                break;
189c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
190c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            result = result * 10 + (s.charAt(pos) - '0');
191c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            // Abort on overflow
192c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (result < 0) {
193c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                break;
194c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
195c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            pos++;
196c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
197c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
198c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        // 0 is not a valid page number
199c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        if (result == 0) {
200c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            return new Pair<>(pos, null);
201c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        } else {
202c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            return new Pair<>(pos, result);
203c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
204c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    }
205c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
206c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    /**
207c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * Read a single character from a string at a certain position.
208c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
209c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param s            The string to parse
210c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param pos          The starting position
211c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param expectedChar The character to read
212c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
213c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @return The position after the character + the character read or null if the character was
214c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *         not found
215c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     */
216c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    private static Pair<Integer, Character> readChar(CharSequence s, int pos, char expectedChar) {
217c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        if (pos < s.length() && s.charAt(pos) == expectedChar) {
218c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            return new Pair<>(pos + 1, expectedChar);
219c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        } else {
220c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            return new Pair<>(pos, null);
221c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
222c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    }
223c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
224c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    /**
225c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * Read a page range character from a string at a certain position.
226c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
227c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param s             The string to parse
228c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param pos           The starting position
229c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param maxPageNumber The highest page number to accept.
230c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
231c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @return The position after the page range + the page range read or null if the page range was
232c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *         not found
233c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     */
234c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    private static Pair<Integer, PageRange> readRange(CharSequence s, int pos, int maxPageNumber) {
235c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Pair<Integer, Integer> retInt;
236c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Pair<Integer, Character> retChar;
237c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
238c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Character comma;
239c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        if (pos == 0) {
240c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            // When we reading the first range, we do not want to have a comma
241c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            comma = ',';
242c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        } else {
243c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            retChar = readChar(s, pos, ',');
244c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            pos = retChar.first;
245c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            comma = retChar.second;
246c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
247c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
248c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = readWhiteSpace(s, pos);
249c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
250c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        retInt = readNumber(s, pos);
251c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = retInt.first;
252c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Integer start = retInt.second;
253c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
254c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = readWhiteSpace(s, pos);
255c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
256c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        retChar = readChar(s, pos, '-');
257c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = retChar.first;
258c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Character separator = retChar.second;
259c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
260c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = readWhiteSpace(s, pos);
261c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
262c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        retInt = readNumber(s, pos);
263c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = retInt.first;
264c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        Integer end = retInt.second;
265c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
266c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        pos = readWhiteSpace(s, pos);
267c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
268c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        if (comma != null &&
269c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                // range, maybe unbounded
270c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                ((separator != null && (start != null || end != null)) ||
271c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                        // single page
272c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                        (separator == null && start != null && end == null))) {
273c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (start == null) {
274c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                start = 1;
275c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
276c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
277c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (end == null) {
278c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                if (separator == null) {
279c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                    end = start;
280c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                } else {
281c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                    end = maxPageNumber;
282c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                }
283c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
284c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
285c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (start <= end && start >= 1 && end <= maxPageNumber) {
286c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                return new Pair<>(pos, new PageRange(start - 1, end - 1));
287c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
288c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
289c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
290c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        return new Pair<>(pos, null);
291c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    }
292c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
293c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    /**
294c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * Parse a string into an array of page ranges.
295c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
296c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param s             The string to parse
297c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @param maxPageNumber The highest page number to accept.
298c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     *
299c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     * @return The parsed ranges or null if the string could not be parsed.
300c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann     */
301c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    public static PageRange[] parsePageRanges(CharSequence s, int maxPageNumber) {
302c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        ArrayList<PageRange> ranges = new ArrayList<>();
303c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
304c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        int pos = 0;
305c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        while (pos < s.length()) {
306c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            Pair<Integer, PageRange> retRange = readRange(s, pos, maxPageNumber);
307c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
308c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            if (retRange.second == null) {
309c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                ranges.clear();
310c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann                break;
311c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            }
312c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
313c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            ranges.add(retRange.second);
314c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann            pos = retRange.first;
315c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        }
316c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
317c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann        return PageRangeUtils.normalize(ranges.toArray(new PageRange[ranges.size()]));
318c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    }
319c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann
320c6c319e9889874a1babafa4301dabe193737ebd9Philip P. Moltmann    /**
321a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * Offsets a the start and end of page ranges with the given value.
322a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     *
323a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param pageRanges The page ranges to offset.
324a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param offset The offset value.
325a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     */
326a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public static void offset(PageRange[] pageRanges, int offset) {
327a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (offset == 0) {
328a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return;
329a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
330a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final int pageRangeCount = pageRanges.length;
331a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        for (int i = 0; i < pageRangeCount; i++) {
332a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final int start = pageRanges[i].getStart() + offset;
333a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final int end = pageRanges[i].getEnd() + offset;
334a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            pageRanges[i] = new PageRange(start, end);
335a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
336a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
337a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
338a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    /**
339a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * Gets the number of pages in a normalized range array.
340a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     *
341a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param pageRanges Normalized page ranges.
342a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @param layoutPageCount Page count after reported after layout pass.
343a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     * @return The page count in the ranges.
344a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav     */
345a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public static int getNormalizedPageCount(PageRange[] pageRanges, int layoutPageCount) {
346a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        int pageCount = 0;
347525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        if (pageRanges != null) {
348525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            final int pageRangeCount = pageRanges.length;
349525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            for (int i = 0; i < pageRangeCount; i++) {
350525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                PageRange pageRange = pageRanges[i];
351525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                if (PageRange.ALL_PAGES.equals(pageRange)) {
352525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    return layoutPageCount;
353525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                }
354525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                pageCount += pageRange.getSize();
355525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
356525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
357525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return pageCount;
358525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
359525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
360525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static PageRange asAbsoluteRange(PageRange pageRange, int pageCount) {
361525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        if (PageRange.ALL_PAGES.equals(pageRange)) {
362525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            return new PageRange(0, pageCount - 1);
363525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
364525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return pageRange;
365525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
366525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
367525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean isAllPages(PageRange[] pageRanges) {
368a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final int pageRangeCount = pageRanges.length;
369a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        for (int i = 0; i < pageRangeCount; i++) {
370a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange pageRange = pageRanges[i];
371525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (isAllPages(pageRange)) {
372525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                return true;
373a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
374a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
375525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return false;
376525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
377525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
378525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean isAllPages(PageRange pageRange) {
379525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return PageRange.ALL_PAGES.equals(pageRange);
380525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
381525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
382525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean isAllPages(PageRange[] pageRanges, int pageCount) {
383525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        final int pageRangeCount = pageRanges.length;
384525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        for (int i = 0; i < pageRangeCount; i++) {
385525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            PageRange pageRange = pageRanges[i];
386525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (isAllPages(pageRange, pageCount)) {
387525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                return true;
388525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
389525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
390525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return false;
391525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
392525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
393525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    public static boolean isAllPages(PageRange pageRanges, int pageCount) {
394525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return pageRanges.getStart() == 0 && pageRanges.getEnd() == pageCount - 1;
395525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov    }
396525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
397f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann    /**
398f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     * Compute the pages of the file that correspond to the requested pages in the doc.
399f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     *
400f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     * @param pagesInDocRequested The requested pages, doc-indexed
401f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     * @param pagesWrittenToFile The pages in the file
402f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     * @param pageCount The number of pages in the doc
403f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     *
404f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     * @return The pages, file-indexed
405f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann     */
406f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann    public static PageRange[] computeWhichPagesInFileToPrint(PageRange[] pagesInDocRequested,
407f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann            PageRange[] pagesWrittenToFile, int pageCount) {
408525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        // Adjust the print job pages based on what was requested and written.
409525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        // The cases are ordered in the most expected to the least expected
410525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        // with a special case first where the app does not know the page count
411525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        // so we ask for all to be written.
412f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann        if (Arrays.equals(pagesInDocRequested, ALL_PAGES_RANGE)
413525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                && pageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
414525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            return ALL_PAGES_RANGE;
415f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann        } else if (Arrays.equals(pagesWrittenToFile, pagesInDocRequested)) {
416525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // We got a document with exactly the pages we wanted. Hence,
417525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // the printer has to print all pages in the data.
418525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            return ALL_PAGES_RANGE;
419f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann        } else if (Arrays.equals(pagesWrittenToFile, ALL_PAGES_RANGE)) {
420525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // We requested specific pages but got all of them. Hence,
421525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // the printer has to print only the requested pages.
422f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann            return pagesInDocRequested;
423f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann        } else if (PageRangeUtils.contains(pagesWrittenToFile, pagesInDocRequested, pageCount)) {
424525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // We requested specific pages and got more but not all pages.
425525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // Hence, we have to offset appropriately the printed pages to
426525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // be based off the start of the written ones instead of zero.
427525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // The written pages are always non-null and not empty.
428f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann            final int offset = -pagesWrittenToFile[0].getStart();
429bdace63d5bda8a3f19300b52064a0f77bc5d3754Philip P. Moltmann            PageRangeUtils.offset(pagesInDocRequested.clone(), offset);
430f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann            return pagesInDocRequested;
431f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann        } else if (Arrays.equals(pagesInDocRequested, ALL_PAGES_RANGE)
432f7a5b4fb30792789d9e436bb5107f1a6d743d49cPhilip P. Moltmann                && isAllPages(pagesWrittenToFile, pageCount)) {
433525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // We requested all pages via the special constant and got all
434525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // of them as an explicit enumeration. Hence, the printer has
435525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            // to print only the requested pages.
436525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            return ALL_PAGES_RANGE;
437525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        }
438525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
439525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        return null;
440a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
441a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav}
442