PrintAttributes.java revision 0d1daa50f6d180c57f92596501e2e5c0b5ef9997
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.print;
18
19import android.content.pm.PackageManager;
20import android.content.pm.PackageManager.NameNotFoundException;
21import android.content.res.Resources;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.text.TextUtils;
25
26import com.android.internal.R;
27
28/**
29 * This class represents the attributes of a print job.
30 */
31public final class PrintAttributes implements Parcelable {
32    /** Duplex mode: No duplexing */
33    public static final int DUPLEX_MODE_NONE = 1 << 0;
34    /** Duplex mode: Turn a page along its long edge, e.g. like a book */
35    public static final int DUPLEX_MODE_LONG_EDGE = 1 << 1;
36    /** Duplex mode: Turn a page along its short edge, e.g. like a notepad */
37    public static final int DUPLEX_MODE_SHORT_EDGE = 1 << 2;
38
39
40    /** Orientation: Portrait page orientation. */
41    public static final int ORIENTATION_PORTRAIT = 1 << 0;
42    /** Orientation: Landscape page orientation. */
43    public static final int ORIENTATION_LANDSCAPE = 1 << 1;
44
45
46    /** Color mode: Monochrome color scheme, e.g. one color is used. */
47    public static final int COLOR_MODE_MONOCHROME = 1 << 0;
48    /** Color mode: Color color scheme, e.g. many colors are used. */
49    public static final int COLOR_MODE_COLOR = 1 << 1;
50
51
52    /** Fitting mode: No fitting. */
53    public static final int FITTING_MODE_NONE = 0x00000001;
54    /** Fitting mode: Fit the content to the page. */
55    public static final int FITTING_MODE_FIT_TO_PAGE = 0x00000002;
56
57
58    private static final int VALID_DUPLEX_MODES =
59            DUPLEX_MODE_NONE | DUPLEX_MODE_LONG_EDGE | DUPLEX_MODE_SHORT_EDGE;
60
61    private static final int VALID_COLOR_MODES =
62            COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
63
64    private static final int VALID_FITTING_MODES =
65            FITTING_MODE_NONE | FITTING_MODE_FIT_TO_PAGE;
66
67    private static final int VALID_ORIENTATIONS =
68            ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE;
69
70    private MediaSize mMediaSize;
71    private Resolution mResolution;
72    private Margins mMargins;
73    private Tray mInputTray;
74    private Tray mOutputTray;
75
76    private int mDuplexMode;
77    private int mColorMode;
78    private int mFittingMode;
79    private int mOrientation;
80    private int mCopies;
81
82    PrintAttributes() {
83        /* hide constructor */
84    }
85
86    private PrintAttributes(Parcel parcel) {
87        mMediaSize = (parcel.readInt() ==  1) ? MediaSize.createFromParcel(parcel) : null;
88        mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
89        mMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
90        mInputTray = (parcel.readInt() ==  1) ? Tray.createFromParcel(parcel) : null;
91        mOutputTray = (parcel.readInt() ==  1) ? Tray.createFromParcel(parcel) : null;
92        mDuplexMode = parcel.readInt();
93        mColorMode = parcel.readInt();
94        mFittingMode = parcel.readInt();
95        mOrientation = parcel.readInt();
96        mCopies = parcel.readInt();
97    }
98
99    /**
100     * Gets the media size.
101     *
102     * @return The media size or <code>null</code> if not set.
103     */
104    public MediaSize getMediaSize() {
105        return mMediaSize;
106    }
107
108    /**
109     * Sets the media size.
110     *
111     * @param The media size.
112     *
113     * @hide
114     */
115    public void setMediaSize(MediaSize mediaSize) {
116        mMediaSize = mediaSize;
117    }
118
119    /**
120     * Gets the resolution.
121     *
122     * @return The resolution or <code>null</code> if not set.
123     */
124    public Resolution getResolution() {
125        return mResolution;
126    }
127
128    /**
129     * Sets the resolution.
130     *
131     * @param The resolution.
132     *
133     * @hide
134     */
135    public void setResolution(Resolution resolution) {
136        mResolution = resolution;
137    }
138
139    /**
140     * Gets the margins.
141     *
142     * @return The margins or <code>null</code> if not set.
143     */
144    public Margins getMargins() {
145        return mMargins;
146    }
147
148    /**
149     * Sets the margins.
150     *
151     * @param The margins.
152     *
153     * @hide
154     */
155    public void setMargins(Margins margins) {
156        mMargins = margins;
157    }
158
159    /**
160     * Sets the input tray.
161     *
162     * @return The input tray or <code>null</code> if not set.
163     */
164    public Tray getInputTray() {
165        return mInputTray;
166    }
167
168    /**
169     * Gets the input tray.
170     *
171     * @param The input tray.
172     *
173     * @hide
174     */
175    public void setInputTray(Tray inputTray) {
176        mInputTray = inputTray;
177    }
178
179    /**
180     * Gets the output tray.
181     *
182     * @return The output tray or <code>null</code> if not set.
183     */
184    public Tray getOutputTray() {
185        return mOutputTray;
186    }
187
188    /**
189     * Sets the output tray.
190     *
191     * @param The output tray.
192     *
193     * @hide
194     */
195    public void setOutputTray(Tray outputTray) {
196        mOutputTray = outputTray;
197    }
198
199    /**
200     * Gets the duplex mode.
201     *
202     * @return The duplex mode or zero if not set.
203     *
204     * @see #DUPLEX_MODE_NONE
205     * @see #DUPLEX_MODE_SHORT_EDGE
206     * @see #DUPLEX_MODE_LONG_EDGE
207     */
208    public int getDuplexMode() {
209        return mDuplexMode;
210    }
211
212    /**
213     * Sets the duplex mode.
214     *
215     * @param The duplex mode.
216     *
217     * @hide
218     */
219    public void setDuplexMode(int duplexMode) {
220        enforceValidDuplexMode(duplexMode);
221        mDuplexMode = duplexMode;
222    }
223
224    /**
225     * Gets the color mode.
226     *
227     * @return The color mode or zero if not set.
228     *
229     * @see #COLOR_MODE_COLOR
230     * @see #COLOR_MODE_MONOCHROME
231     */
232    public int getColorMode() {
233        return mColorMode;
234    }
235
236    /**
237     * Sets the color mode.
238     *
239     * @param The color mode.
240     *
241     * @see #COLOR_MODE_MONOCHROME
242     * @see #COLOR_MODE_COLOR
243     *
244     * @hide
245     */
246    public void setColorMode(int colorMode) {
247        enforceValidColorMode(colorMode);
248        mColorMode = colorMode;
249    }
250
251    /**
252     * Gets the fitting mode.
253     *
254     * @return The fitting mode or zero if not set.
255     *
256     * @see #FITTING_MODE_NONE
257     * @see #FITTING_MODE_FIT_TO_PAGE
258     */
259    public int getFittingMode() {
260        return mFittingMode;
261    }
262
263    /**
264     * Sets the fitting mode.
265     *
266     * @param The fitting mode.
267     *
268     * @see #FITTING_MODE_NONE
269     * @see #FITTING_MODE_FIT_TO_PAGE
270     *
271     * @hide
272     */
273    public void setFittingMode(int fittingMode) {
274        enfoceValidFittingMode(fittingMode);
275        mFittingMode = fittingMode;
276    }
277
278    /**
279     * Gets the orientation.
280     *
281     * @return The orientation or zero if not set.
282     *
283     * @see #ORIENTATION_PORTRAIT
284     * @see #ORIENTATION_LANDSCAPE
285     */
286    public int getOrientation() {
287        return mOrientation;
288    }
289
290    /**
291     * Sets the orientation.
292     *
293     * @param The orientation.
294     *
295     * @see #ORIENTATION_PORTRAIT
296     * @see #ORIENTATION_LANDSCAPE
297     *
298     * @hide
299     */
300    public void setOrientation(int orientation) {
301        enforceValidOrientation(orientation);
302        mOrientation = orientation;
303    }
304
305    /**
306     * Gets the number of copies.
307     *
308     * @return The number of copies or zero if not set.
309     */
310    public int getCopies() {
311        return mCopies;
312    }
313
314    /**
315     * Sets the number of copies.
316     *
317     * @param copyCount The number of copies.
318     *
319     * @hide
320     */
321    public void setCopies(int copyCount) {
322        if (copyCount < 1) {
323            throw new IllegalArgumentException("Copies must be more than one.");
324        }
325        mCopies = copyCount;
326    }
327
328    @Override
329    public void writeToParcel(Parcel parcel, int flags) {
330        if (mMediaSize != null) {
331            parcel.writeInt(1);
332            mMediaSize.writeToParcel(parcel);
333        } else {
334            parcel.writeInt(0);
335        }
336        if (mResolution != null) {
337            parcel.writeInt(1);
338            mResolution.writeToParcel(parcel);
339        } else {
340            parcel.writeInt(0);
341        }
342        if (mMargins != null) {
343            parcel.writeInt(1);
344            mMargins.writeToParcel(parcel);
345        } else {
346            parcel.writeInt(0);
347        }
348        if (mInputTray != null) {
349            parcel.writeInt(1);
350            mInputTray.writeToParcel(parcel);
351        } else {
352            parcel.writeInt(0);
353        }
354        if (mOutputTray != null) {
355            parcel.writeInt(1);
356            mOutputTray.writeToParcel(parcel);
357        } else {
358            parcel.writeInt(0);
359        }
360        parcel.writeInt(mDuplexMode);
361        parcel.writeInt(mColorMode);
362        parcel.writeInt(mFittingMode);
363        parcel.writeInt(mOrientation);
364        parcel.writeInt(mCopies);
365    }
366
367    @Override
368    public int describeContents() {
369        return 0;
370    }
371
372    /** hide */
373    public void clear() {
374        mMediaSize = null;
375        mResolution = null;
376        mMargins = null;
377        mInputTray = null;
378        mOutputTray = null;
379        mDuplexMode = 0;
380        mColorMode = 0;
381        mFittingMode = 0;
382        mOrientation = 0;
383        mCopies = 0;
384    }
385
386    /**
387     * @hide
388     */
389    public void copyFrom(PrintAttributes other) {
390        mMediaSize = other.mMediaSize;
391        mResolution = other.mResolution;
392        mMargins = other.mMargins;
393        mInputTray = other.mInputTray;
394        mOutputTray = other.mOutputTray;
395        mDuplexMode = other.mDuplexMode;
396        mColorMode = other.mColorMode;
397        mFittingMode = other.mFittingMode;
398        mOrientation = other.mOrientation;
399        mCopies = other.mCopies;
400    }
401
402    /**
403     * This class specifies a supported media size.
404     */
405    public static final class MediaSize {
406
407        // TODO: Verify media sizes and add more standard ones.
408
409        // ISO sizes
410
411        /**
412         * ISO A0 media size: 841mm x 1189mm (33.11" x 46.81")
413         *
414         * @see #createMediaSize(PackageManager, int)
415         */
416        public static final int ISO_A0 = 1;
417
418        /**
419         * ISO A1 media size: 594mm x 841mm (23.39" x 33.11")
420         *
421         * @see #createMediaSize(PackageManager, int)
422         */
423        public static final int ISO_A1 = 2;
424
425        /**
426         *
427         *ISO A2 media size: 420mm x 594mm (16.54" x 23.39")
428         *
429         * @see #createMediaSize(PackageManager, int)
430         */
431        public static final int ISO_A2 = 3;
432
433        /**
434         * ISO A3 media size: 297mm x 420mm (11.69" x 16.54")
435         *
436         * @see #createMediaSize(PackageManager, int)
437         */
438        public static final int ISO_A3 = 4;
439
440        /**
441         * ISO A4 media size: 210mm x 297mm (8.27" x 11.69")
442         *
443         * @see #createMediaSize(PackageManager, int)
444         */
445        public static final int ISO_A4 = 5;
446
447        /**
448         * ISO A5 media size: 148mm x 210mm (5.83" x 8.27")
449         *
450         * @see #createMediaSize(PackageManager, int)
451         */
452        public static final int ISO_A5 = 6;
453
454        /**
455         * ISO A6 media size: 105mm x 148mm (4.13" x 5.83")
456         *
457         * @see #createMediaSize(PackageManager, int)
458         */
459        public static final int ISO_A6 = 7;
460
461        /**
462         * ISO A7 media size: 74mm x 105mm (2.91" x 4.13")
463         *
464         * @see #createMediaSize(PackageManager, int)
465         */
466        public static final int ISO_A7 = 8;
467
468        /**
469         * ISO A8 media size: 52mm x 74mm (2.05" x 2.91")
470         *
471         * @see #createMediaSize(PackageManager, int)
472         */
473        public static final int ISO_A8 = 9;
474
475        /**
476         * ISO A9 media size: 37mm x 52mm (1.46" x 2.05")
477         *
478         * @see #createMediaSize(PackageManager, int)
479         */
480        public static final int ISO_A9 = 10;
481
482        /**
483         * ISO A10 media size: 26mm x 37mm (1.02" x 1.46")
484         *
485         * @see #createMediaSize(PackageManager, int)
486         */
487        public static final int ISO_A10 = 11;
488
489
490        /**
491         * ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67")
492         *
493         * @see #createMediaSize(PackageManager, int)
494         */
495        public static final int ISO_B0 = 100;
496
497        /**
498         * ISO B1 media size: 707mm x 1000mm (27.83" x 39.37")
499         *
500         * @see #createMediaSize(PackageManager, int)
501         */
502        public static final int ISO_B1 = 101;
503
504        /**
505         * ISO B2 media size: 500mm x 707mm (19.69" x 27.83")
506         *
507         * @see #createMediaSize(PackageManager, int)
508         */
509        public static final int ISO_B2 = 102;
510
511        /**
512         * ISO B3 media size: 353mm x 500mm (13.90" x 19.69")
513         *
514         * @see #createMediaSize(PackageManager, int)
515         */
516        public static final int ISO_B3 = 103;
517
518        /**
519         * ISO B4 media size: 250mm x 353mm (9.84" x 13.90")
520         *
521         * @see #createMediaSize(PackageManager, int)
522         */
523        public static final int ISO_B4 = 104;
524
525        /**
526         * ISO B5 media size: 176mm x 250mm (6.93" x 9.84")
527         *
528         * @see #createMediaSize(PackageManager, int)
529         */
530        public static final int ISO_B5 = 105;
531
532        /**
533         * ISO B6 media size: 125mm x 176mm (4.92" x 6.93")
534         *
535         * @see #createMediaSize(PackageManager, int)
536         */
537        public static final int ISO_B6 = 106;
538
539        /**
540         * ISO B7 media size: 88mm x 125mm (3.46" x 4.92")
541         *
542         * @see #createMediaSize(PackageManager, int)
543         */
544        public static final int ISO_B7 = 107;
545
546        /** ISO B8 media size: 62mm x 88mm (2.44" x 3.46")
547         *
548         * @see #createMediaSize(PackageManager, int)
549         */
550        public static final int ISO_B8 = 108;
551
552        /**
553         * ISO B9 media size: 44mm x 62mm (1.73" x 2.44")
554         *
555         * @see #createMediaSize(PackageManager, int)
556         */
557        public static final int ISO_B9 = 109;
558
559        /**
560         * ISO B10 media size: 31mm x 44mm (1.22" x 1.73")
561         *
562         * @see #createMediaSize(PackageManager, int)
563         */
564        public static final int ISO_B10 = 110;
565
566
567        /**
568         * ISO C0 media size: 917mm x 1297mm (36.10" x 51.06")
569         *
570         * @see #createMediaSize(PackageManager, int)
571         */
572        public static final int ISO_C0 = 200;
573
574        /**
575         * ISO C1 media size: 648mm x 917mm (25.51" x 36.10")
576         *
577         * @see #createMediaSize(PackageManager, int)
578         */
579
580        public static final int ISO_C1 = 201;
581        /**
582         * ISO C2 media size: 458mm x 648mm (18.03" x 25.51")
583         *
584         * @see #createMediaSize(PackageManager, int)
585         */
586        public static final int ISO_C2 = 202;
587
588        /**
589         * ISO C3 media size: 324mm x 458mm (12.76" x 18.03")
590         *
591         * @see #createMediaSize(PackageManager, int)
592         */
593        public static final int ISO_C3 = 203;
594
595        /**
596         * ISO C4 media size: 229mm x 324mm (9.02" x 12.76")
597         *
598         * @see #createMediaSize(PackageManager, int)
599         */
600        public static final int ISO_C4 = 204;
601
602        /**
603         * ISO C5 media size: 162mm x 229mm (6.38" x 9.02")
604         *
605         * @see #createMediaSize(PackageManager, int)
606         */
607        public static final int ISO_C5 = 205;
608
609        /**
610         * ISO C6 media size: 114mm x 162mm (4.49" x 6.38")
611         *
612         * @see #createMediaSize(PackageManager, int)
613         */
614        public static final int ISO_C6 = 206;
615
616        /**
617         * ISO C7 media size: 81mm x 114mm (3.19" x 4.49")
618         *
619         * @see #createMediaSize(PackageManager, int)
620         */
621        public static final int ISO_C7 = 207;
622
623        /**
624         * ISO C8 media size: 57mm x 81mm (2.24" x 3.19")
625         *
626         * @see #createMediaSize(PackageManager, int)
627         */
628        public static final int ISO_C8 = 208;
629
630        /**
631         * ISO C9 media size: 40mm x 57mm (1.57" x 2.24")
632         *
633         * @see #createMediaSize(PackageManager, int)
634         */
635        public static final int ISO_C9 = 209;
636
637        /**
638         * ISO C10 media size: 28mm x 40mm (1.10" x 1.57")
639         *
640         * @see #createMediaSize(PackageManager, int)
641         */
642        public static final int ISO_C10 = 210;
643
644
645        // North America
646
647        /**
648         * North America Letter media size: 8.5" x 11"
649         *
650         * @see #createMediaSize(PackageManager, int)
651         */
652        public static final int NA_LETTER = 300;
653
654        /**
655         * North America Government-Letter media size: 8.0" x 10.5"
656         *
657         * @see #createMediaSize(PackageManager, int)
658         */
659        public static final int NA_GOVT_LETTER = 301;
660
661        /**
662         * North America Legal media size: 8.5" x 14"
663         *
664         * @see #createMediaSize(PackageManager, int)
665         */
666        public static final int NA_LEGAL = 302;
667
668        /**
669         * North America Junior Legal media size: 8.0" x 5.0"
670         *
671         * @see #createMediaSize(PackageManager, int)
672         */
673        public static final int NA_JUNIOR_LEGAL = 303;
674
675        /**
676         * North America Ledger media size: 17" x 11"
677         *
678         * @see #createMediaSize(PackageManager, int)
679         */
680        public static final int NA_LEDGER = 304;
681
682        /**
683         * North America Tabloid media size: 11" x 17"
684         *
685         * @see #createMediaSize(PackageManager, int)
686         */
687        public static final int NA_TBLOID = 305;
688
689        /**
690         * Creates a standard media size with a localized label.
691         *
692         * @param pm Package manager used to load the label.
693         * @param mediaSize Media size constant.
694         * @return A {@link MediaSize} instance with a localized label.
695         */
696        public static MediaSize createMediaSize(PackageManager pm, int mediaSize) {
697            final Resources resources;
698            try {
699                resources = pm.getResourcesForApplication("android");
700            } catch (NameNotFoundException nnfe) {
701                return null;
702            }
703            switch (mediaSize) {
704                case ISO_A0: {
705                    return new MediaSize("ISO_A0", resources
706                            .getString(R.string.mediaSize_iso_a0), 33110, 46810);
707                }
708                case ISO_A1: {
709                    return new MediaSize("ISO_A1", resources
710                            .getString(R.string.mediaSize_iso_a1), 23390, 33110);
711                }
712                case ISO_A2: {
713                    return new MediaSize("ISO_A2", resources
714                            .getString(R.string.mediaSize_iso_a2), 16540, 23390);
715                }
716                case ISO_A3: {
717                    return new MediaSize("ISO_A3", resources
718                            .getString(R.string.mediaSize_iso_a3), 11690, 16540);
719                }
720                case ISO_A4: {
721                    return new MediaSize("ISO_A4", resources
722                            .getString(R.string.mediaSize_iso_a4), 8270, 11690);
723                }
724                case ISO_A5: {
725                    return new MediaSize("ISO_A5", resources
726                            .getString(R.string.mediaSize_iso_a5), 5830, 8270);
727                }
728                case ISO_A6: {
729                    return new MediaSize("ISO_A6", resources
730                            .getString(R.string.mediaSize_iso_a6), 4130, 5830);
731                }
732                case ISO_A7: {
733                    return new MediaSize("ISO_A7", resources
734                            .getString(R.string.mediaSize_iso_a7), 2910, 4130);
735                }
736                case ISO_A8: {
737                    return new MediaSize("ISO_A8", resources
738                            .getString(R.string.mediaSize_iso_a8), 2050, 2910);
739                }
740                case ISO_A9: {
741                    return new MediaSize("ISO_A9", resources
742                            .getString(R.string.mediaSize_iso_a9), 1460, 2050);
743                }
744                case ISO_A10: {
745                    return new MediaSize("ISO_A10", resources
746                            .getString(R.string.mediaSize_iso_a10), 1020, 1460);
747                }
748                case ISO_B0: {
749                    return new MediaSize("ISO_B0", resources
750                            .getString(R.string.mediaSize_iso_b0), 39370, 55670);
751                }
752                case ISO_B1: {
753                    return new MediaSize("ISO_B1", resources
754                            .getString(R.string.mediaSize_iso_b1), 27830, 39370);
755                }
756                case ISO_B2: {
757                    return new MediaSize("ISO_B2", resources
758                            .getString(R.string.mediaSize_iso_b2), 19690, 27830);
759                }
760                case ISO_B3: {
761                    return new MediaSize("ISO_B3", resources
762                            .getString(R.string.mediaSize_iso_b3), 13900, 19690);
763                }
764                case ISO_B4: {
765                    return new MediaSize("ISO_B4", resources
766                            .getString(R.string.mediaSize_iso_b4), 9840, 13900);
767                }
768                case ISO_B5: {
769                    return new MediaSize("ISO_B5", resources
770                            .getString(R.string.mediaSize_iso_b5), 6930, 9840);
771                }
772                case ISO_B6: {
773                    return new MediaSize("ISO_B6", resources
774                            .getString(R.string.mediaSize_iso_b6), 4920, 6930);
775                }
776                case ISO_B7: {
777                    return new MediaSize("ISO_B7", resources
778                            .getString(R.string.mediaSize_iso_b7), 3460, 4920);
779                }
780                case ISO_B8: {
781                    return new MediaSize("ISO_B8", resources
782                            .getString(R.string.mediaSize_iso_b8), 2440, 3460);
783                }
784                case ISO_B9: {
785                    return new MediaSize("ISO_B9", resources
786                            .getString(R.string.mediaSize_iso_b9), 1730, 2440);
787                }
788                case ISO_B10: {
789                    return new MediaSize("ISO_B10", resources
790                            .getString(R.string.mediaSize_iso_b10), 1220, 1730);
791                }
792                case ISO_C0: {
793                    return new MediaSize("ISO_C0", resources
794                            .getString(R.string.mediaSize_iso_c0), 36100, 51060);
795                }
796                case ISO_C1: {
797                    return new MediaSize("ISO_C1", resources
798                            .getString(R.string.mediaSize_iso_c1), 25510, 36100);
799                }
800                case ISO_C2: {
801                    return new MediaSize("ISO_C2", resources
802                            .getString(R.string.mediaSize_iso_c2), 18030, 25510);
803                }
804                case ISO_C3: {
805                    return new MediaSize("ISO_C3", resources
806                            .getString(R.string.mediaSize_iso_c3), 12760, 18030);
807                }
808                case ISO_C4: {
809                    return new MediaSize("ISO_C4", resources
810                            .getString(R.string.mediaSize_iso_c4), 9020, 12760);
811                }
812                case ISO_C5: {
813                    return new MediaSize("ISO_C5", resources
814                            .getString(R.string.mediaSize_iso_c5), 6380, 9020);
815                }
816                case ISO_C6: {
817                    return new MediaSize("ISO_C6", resources
818                            .getString(R.string.mediaSize_iso_c6), 4490, 6380);
819                }
820                case ISO_C7: {
821                    return new MediaSize("ISO_C7", resources
822                            .getString(R.string.mediaSize_iso_c7), 3190, 4490);
823                }
824                case ISO_C8: {
825                    return new MediaSize("ISO_C8", resources
826                            .getString(R.string.mediaSize_iso_c8), 2240, 3190);
827                }
828                case ISO_C9: {
829                    return new MediaSize("ISO_C9", resources
830                            .getString(R.string.mediaSize_iso_c9), 1570, 2240);
831                }
832                case ISO_C10: {
833                    return new MediaSize("ISO_C10", resources
834                            .getString(R.string.mediaSize_iso_c10), 1100, 1570);
835                }
836                case NA_LETTER: {
837                    return new MediaSize("NA_LETTER", resources
838                            .getString(R.string.mediaSize_na_letter), 8500, 11000);
839                }
840                case NA_GOVT_LETTER: {
841                    return new MediaSize("NA_GOVT_LETTER", resources
842                            .getString(R.string.mediaSize_na_gvrnmt_letter), 8000, 10500);
843                }
844                case NA_LEGAL: {
845                    return new MediaSize("NA_LEGAL", resources
846                            .getString(R.string.mediaSize_na_legal), 8500, 14000);
847                }
848                case NA_JUNIOR_LEGAL: {
849                    return new MediaSize("NA_JUNIOR_LEGAL", resources
850                            .getString(R.string.mediaSize_na_junior_legal), 8000, 5000);
851                }
852                case NA_LEDGER: {
853                    return new MediaSize("NA_LEDGER", resources
854                            .getString(R.string.mediaSize_na_ledger), 17000, 11000);
855                }
856                case NA_TBLOID: {
857                    return new MediaSize("NA_TABLOID", resources
858                            .getString(R.string.mediaSize_na_tabloid), 11000, 17000);
859                }
860                default: {
861                    throw new IllegalArgumentException("Unknown media size.");
862                }
863            }
864        }
865
866        private final String mId;
867        private final CharSequence mLabel;
868        private final int mWidthMils;
869        private final int mHeightMils;
870
871        /**
872         * Creates a new instance.
873         *
874         * @param id The unique media size id.
875         * @param label The <strong>internationalized</strong> human readable label.
876         * @param widthMils The width in mils (thousands of an inch).
877         * @param heightMils The height in mils (thousands of an inch).
878         *
879         * @throws IllegalArgumentException If the id is empty.
880         * @throws IllegalArgumentException If the label is empty.
881         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
882         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
883         */
884        public MediaSize(String id, CharSequence label, int widthMils, int heightMils) {
885            if (TextUtils.isEmpty(id)) {
886                throw new IllegalArgumentException("id cannot be empty.");
887            }
888            if (TextUtils.isEmpty(label)) {
889                throw new IllegalArgumentException("label cannot be empty.");
890            }
891            if (widthMils <= 0) {
892                throw new IllegalArgumentException("widthMils "
893                        + "cannot be less than or equal to zero.");
894            }
895            if (heightMils <= 0) {
896                throw new IllegalArgumentException("heightMils "
897                       + "cannot be less than or euqual to zero.");
898            }
899            mId = id;
900            mLabel = label;
901            mWidthMils = widthMils;
902            mHeightMils = heightMils;
903        }
904
905        /**
906         * Gets the unique media size id.
907         *
908         * @return The unique media size id.
909         */
910        public String getId() {
911            return mId;
912        }
913
914        /**
915         * Gets the human readable media size label.
916         *
917         * @return The human readable label.
918         */
919        public CharSequence getLabel() {
920            return mLabel;
921        }
922
923        /**
924         * Gets the media width in mils (thousands of an inch).
925         *
926         * @return The media width.
927         */
928        public int getWidthMils() {
929            return mWidthMils;
930        }
931
932        /**
933         * Gets the media height in mils (thousands of an inch).
934         *
935         * @return The media height.
936         */
937        public int getHeightMils() {
938            return mHeightMils;
939        }
940
941        void writeToParcel(Parcel parcel) {
942            parcel.writeString(mId);
943            parcel.writeCharSequence(mLabel);
944            parcel.writeInt(mWidthMils);
945            parcel.writeInt(mHeightMils);
946        }
947
948        static MediaSize createFromParcel(Parcel parcel) {
949            return new MediaSize(
950                    parcel.readString(),
951                    parcel.readCharSequence(),
952                    parcel.readInt(),
953                    parcel.readInt());
954        }
955
956        @Override
957        public String toString() {
958            StringBuilder builder = new StringBuilder();
959            builder.append("MediaSize{");
960            builder.append("id: ").append(mId);
961            builder.append(", label: ").append(mLabel);
962            builder.append(", heightMils: ").append(mHeightMils);
963            builder.append(", widthMils: ").append(mWidthMils);
964            builder.append("}");
965            return builder.toString();
966        }
967    }
968
969    /**
970     * This class specifies a supported resolution in dpi (dots per inch).
971     */
972    public static final class Resolution {
973        private final String mId;
974        private final CharSequence mLabel;
975        private final int mHorizontalDpi;
976        private final int mVerticalDpi;
977
978        /**
979         * Creates a new instance.
980         *
981         * @param id The unique resolution id.
982         * @param label The <strong>internationalized</strong> human readable label.
983         * @param horizontalDpi The horizontal resolution in dpi.
984         * @param verticalDpi The vertical resolution in dpi.
985         *
986         * @throws IllegalArgumentException If the id is empty.
987         * @throws IllegalArgumentException If the label is empty.
988         * @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
989         * @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
990         */
991        public Resolution(String id, CharSequence label, int horizontalDpi, int verticalDpi) {
992            if (TextUtils.isEmpty(id)) {
993                throw new IllegalArgumentException("id cannot be empty.");
994            }
995            if (TextUtils.isEmpty(label)) {
996                throw new IllegalArgumentException("label cannot be empty.");
997            }
998            if (horizontalDpi <= 0) {
999                throw new IllegalArgumentException("horizontalDpi "
1000                        + "cannot be less than or equal to zero.");
1001            }
1002            if (verticalDpi <= 0) {
1003                throw new IllegalArgumentException("verticalDpi"
1004                       + " cannot be less than or equal to zero.");
1005            }
1006            mId = id;
1007            mLabel = label;
1008            mHorizontalDpi = horizontalDpi;
1009            mVerticalDpi = verticalDpi;
1010        }
1011
1012        /**
1013         * Gets the unique resolution id.
1014         *
1015         * @return The unique resolution id.
1016         */
1017        public String getId() {
1018            return mId;
1019        }
1020
1021        /**
1022         * Gets the resolution human readable label.
1023         *
1024         * @return The human readable label.
1025         */
1026        public CharSequence getLabel() {
1027            return mLabel;
1028        }
1029
1030        /**
1031         * Gets the horizontal resolution in dpi.
1032         *
1033         * @return The horizontal resolution.
1034         */
1035        public int getHorizontalDpi() {
1036            return mHorizontalDpi;
1037        }
1038
1039        /**
1040         * Gets the vertical resolution in dpi.
1041         *
1042         * @return The vertical resolution.
1043         */
1044        public int getVerticalDpi() {
1045            return mVerticalDpi;
1046        }
1047
1048        void writeToParcel(Parcel parcel) {
1049            parcel.writeString(mId);
1050            parcel.writeCharSequence(mLabel);
1051            parcel.writeInt(mHorizontalDpi);
1052            parcel.writeInt(mVerticalDpi);
1053        }
1054
1055        static Resolution createFromParcel(Parcel parcel) {
1056            return new Resolution(
1057                    parcel.readString(),
1058                    parcel.readCharSequence(),
1059                    parcel.readInt(),
1060                    parcel.readInt());
1061        }
1062
1063        @Override
1064        public String toString() {
1065            StringBuilder builder = new StringBuilder();
1066            builder.append("Resolution{");
1067            builder.append("id: ").append(mId);
1068            builder.append(", label: ").append(mLabel);
1069            builder.append(", horizontalDpi: ").append(mHorizontalDpi);
1070            builder.append(", verticalDpi: ").append(mVerticalDpi);
1071            builder.append("}");
1072            return builder.toString();
1073        }
1074    }
1075
1076    /**
1077     * This class specifies content margins.
1078     */
1079    public static final class Margins {
1080        private final int mLeftMils;
1081        private final int mTopMils;
1082        private final int mRightMils;
1083        private final int mBottomMils;
1084
1085        /**
1086         * Creates a new instance.
1087         *
1088         * @param leftMils The left margin in mils (thousands of an inch).
1089         * @param topMils The top margin in mils (thousands of an inch).
1090         * @param rightMils The right margin in mils (thousands of an inch).
1091         * @param bottomMils The bottom margin in mils (thousands of an inch).
1092         *
1093         * @throws IllegalArgumentException If the leftMils is less than zero.
1094         * @throws IllegalArgumentException If the topMils is less than zero.
1095         * @throws IllegalArgumentException If the rightMils is less than zero.
1096         * @throws IllegalArgumentException If the bottomMils is less than zero.
1097         */
1098        public Margins(int leftMils, int topMils, int rightMils, int bottomMils) {
1099            if (leftMils < 0) {
1100                throw new IllegalArgumentException("leftMils cannot be less than zero.");
1101            }
1102            if (topMils < 0) {
1103                throw new IllegalArgumentException("topMils cannot be less than zero.");
1104            }
1105            if (rightMils < 0) {
1106                throw new IllegalArgumentException("rightMils cannot be less than zero.");
1107            }
1108            if (bottomMils < 0) {
1109                throw new IllegalArgumentException("bottomMils cannot be less than zero.");
1110            }
1111            mTopMils = topMils;
1112            mLeftMils = leftMils;
1113            mRightMils = rightMils;
1114            mBottomMils = bottomMils;
1115        }
1116
1117        /**
1118         * Gets the left margin in mils (thousands of an inch).
1119         *
1120         * @return The left margin.
1121         */
1122        public int getLeftMils() {
1123            return mLeftMils;
1124        }
1125
1126        /**
1127         * Gets the top margin in mils (thousands of an inch).
1128         *
1129         * @return The top margin.
1130         */
1131        public int getTopMils() {
1132            return mTopMils;
1133        }
1134
1135        /**
1136         * Gets the right margin in mils (thousands of an inch).
1137         *
1138         * @return The right margin.
1139         */
1140        public int getRightMils() {
1141            return mRightMils;
1142        }
1143
1144        /**
1145         * Gets the bottom margin in mils (thousands of an inch).
1146         *
1147         * @return The bottom margin.
1148         */
1149        public int getBottomMils() {
1150            return mBottomMils;
1151        }
1152
1153        void writeToParcel(Parcel parcel) {
1154            parcel.writeInt(mLeftMils);
1155            parcel.writeInt(mTopMils);
1156            parcel.writeInt(mRightMils);
1157            parcel.writeInt(mBottomMils);
1158        }
1159
1160        static Margins createFromParcel(Parcel parcel) {
1161            return new Margins(
1162                    parcel.readInt(),
1163                    parcel.readInt(),
1164                    parcel.readInt(),
1165                    parcel.readInt());
1166        }
1167
1168        @Override
1169        public String toString() {
1170            StringBuilder builder = new StringBuilder();
1171            builder.append("Margins{");
1172            builder.append("leftMils: ").append(mLeftMils);
1173            builder.append(", topMils: ").append(mTopMils);
1174            builder.append(", rightMils: ").append(mRightMils);
1175            builder.append(", bottomMils: ").append(mBottomMils);
1176            builder.append("}");
1177            return builder.toString();
1178        }
1179    }
1180
1181    /**
1182     * Represents a printer tray.
1183     */
1184    public static final class Tray {
1185        private final String mId;
1186        private final CharSequence mLabel;
1187
1188        /**
1189         * Creates a new instance.
1190         *
1191         * @param id The unique tray id.
1192         * @param label The <strong>internationalized</strong> human readable label.
1193         *
1194         * @throws IllegalArgumentException If the id is empty.
1195         * @throws IllegalArgumentException If the label is empty.
1196         */
1197        public Tray(String id, CharSequence label) {
1198            if (TextUtils.isEmpty(id)) {
1199                throw new IllegalArgumentException("id cannot be empty.");
1200            }
1201            if (TextUtils.isEmpty(label)) {
1202                throw new IllegalArgumentException("label cannot be empty.");
1203            }
1204            mId = id;
1205            mLabel = label;
1206        }
1207
1208        /**
1209         * Gets the unique tray id.
1210         *
1211         * @return The unique tray id.
1212         */
1213        public String getId() {
1214            return mId;
1215        }
1216
1217        /**
1218         * Gets the tray human readable label.
1219         *
1220         * @return The human readable label.
1221         */
1222        public CharSequence getLabel() {
1223            return mLabel;
1224        }
1225
1226        void writeToParcel(Parcel parcel) {
1227            parcel.writeString(mId);
1228            parcel.writeCharSequence(mLabel);
1229        }
1230
1231        static Tray createFromParcel(Parcel parcel) {
1232            return new Tray(
1233                    parcel.readString(),
1234                    parcel.readCharSequence());
1235        }
1236
1237        @Override
1238        public String toString() {
1239            StringBuilder builder = new StringBuilder();
1240            builder.append("Tray{");
1241            builder.append("id: ").append(mId);
1242            builder.append("id: ").append(mId);
1243            builder.append(", label: ").append(mLabel);
1244            builder.append("}");
1245            return builder.toString();
1246        }
1247    }
1248
1249    @Override
1250    public String toString() {
1251        StringBuilder builder = new StringBuilder();
1252        builder.append("PrintAttributes{");
1253        builder.append("mediaSize: ").append(mMediaSize);
1254        builder.append(", resolution: ").append(mResolution);
1255        builder.append(", margins: ").append(mMargins);
1256        builder.append(", duplexMode: ").append(duplexModeToString(mDuplexMode));
1257        builder.append(", colorMode: ").append(colorModeToString(mColorMode));
1258        builder.append(", fittingMode: ").append(fittingModeToString(mFittingMode));
1259        builder.append(", orientation: ").append(orientationToString(mOrientation));
1260        builder.append(", copies: ").append(mCopies);
1261        return builder.toString();
1262    }
1263
1264    private static String duplexModeToString(int duplexMode) {
1265        switch (duplexMode) {
1266            case DUPLEX_MODE_NONE: {
1267                return "DUPLEX_MODE_NONE";
1268            }
1269            case DUPLEX_MODE_LONG_EDGE: {
1270                return "DUPLEX_MODE_LONG_EDGE";
1271            }
1272            case DUPLEX_MODE_SHORT_EDGE: {
1273                return "DUPLEX_MODE_SHORT_EDGE";
1274            }
1275            default:
1276                return "DUPLEX_MODE_UNKNOWN";
1277        }
1278    }
1279
1280    private static String colorModeToString(int colorMode) {
1281        switch (colorMode) {
1282            case COLOR_MODE_MONOCHROME: {
1283                return "COLOR_MODE_MONOCHROME";
1284            }
1285            case COLOR_MODE_COLOR: {
1286                return "COLOR_MODE_COLOR";
1287            }
1288            default:
1289                return "COLOR_MODE_UNKNOWN";
1290        }
1291    }
1292
1293    private static String orientationToString(int orientation) {
1294        switch (orientation) {
1295            case ORIENTATION_PORTRAIT: {
1296                return "ORIENTATION_PORTRAIT";
1297            }
1298            case ORIENTATION_LANDSCAPE: {
1299                return "ORIENTATION_LANDSCAPE";
1300            }
1301            default:
1302                return "ORIENTATION_UNKNOWN";
1303        }
1304    }
1305
1306    private static String fittingModeToString(int fittingMode) {
1307        switch (fittingMode) {
1308            case FITTING_MODE_NONE: {
1309                return "FITTING_MODE_NONE";
1310            }
1311            case FITTING_MODE_FIT_TO_PAGE: {
1312                return "FITTING_MODE_FIT_TO_PAGE";
1313            }
1314            default:
1315                return "FITTING_MODE_UNKNOWN";
1316        }
1317    }
1318
1319    static void enforceValidDuplexMode(int duplexMode) {
1320        if ((duplexMode & VALID_DUPLEX_MODES) == 0) {
1321            throw new IllegalArgumentException("invalid duplex mode: " + duplexMode);
1322        }
1323    }
1324
1325    static void enforceValidColorMode(int colorMode) {
1326        if ((colorMode & VALID_COLOR_MODES) == 0) {
1327            throw new IllegalArgumentException("invalid color mode: " + colorMode);
1328        }
1329    }
1330
1331    static void enfoceValidFittingMode(int fittingMode) {
1332        if ((fittingMode & VALID_FITTING_MODES) == 0) {
1333            throw new IllegalArgumentException("invalid fitting mode: " + fittingMode);
1334        }
1335    }
1336
1337    static void enforceValidOrientation(int orientation) {
1338        if ((orientation & VALID_ORIENTATIONS) == 0) {
1339            throw new IllegalArgumentException("invalid orientation: " + orientation);
1340        }
1341    }
1342
1343    /**
1344     * Builder for creating {@link PrintAttributes}.
1345     */
1346    public static final class Builder {
1347        private final PrintAttributes mAttributes = new PrintAttributes();
1348
1349        /**
1350         * Sets the media size.
1351         *
1352         * @param mediaSize The media size.
1353         * @return This builder.
1354         */
1355        public Builder setMediaSize(MediaSize mediaSize) {
1356            mAttributes.setMediaSize(mediaSize);
1357            return this;
1358        }
1359
1360        /**
1361         * Sets the resolution.
1362         *
1363         * @param resolution The resolution.
1364         * @return This builder.
1365         */
1366        public Builder setResolution(Resolution resolution) {
1367            mAttributes.setResolution(resolution);
1368            return this;
1369        }
1370
1371        /**
1372         * Sets the margins.
1373         *
1374         * @param margins The margins.
1375         * @return This builder.
1376         */
1377        public Builder setMargins(Margins margins) {
1378            mAttributes.setMargins(margins);
1379            return this;
1380        }
1381
1382        /**
1383         * Sets the input tray.
1384         *
1385         * @param inputTray The tray.
1386         * @return This builder.
1387         */
1388        public Builder setInputTray(Tray inputTray) {
1389            mAttributes.setInputTray(inputTray);
1390            return this;
1391        }
1392
1393        /**
1394         * Sets the output tray.
1395         *
1396         * @param outputTray The tray.
1397         * @return This builder.
1398         */
1399        public Builder setOutputTray(Tray outputTray) {
1400            mAttributes.setOutputTray(outputTray);
1401            return this;
1402        }
1403
1404        /**
1405         * Sets the duplex mode.
1406         *
1407         * @param duplexMode A valid duplex mode or zero.
1408         * @return This builder.
1409         *
1410         * @see PrintAttributes#DUPLEX_MODE_NONE
1411         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
1412         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
1413         */
1414        public Builder setDuplexMode(int duplexMode) {
1415            if (Integer.bitCount(duplexMode) != 1) {
1416                throw new IllegalArgumentException("can specify at most one duplexMode bit.");
1417            }
1418            mAttributes.setDuplexMode(duplexMode);
1419            return this;
1420        }
1421
1422        /**
1423         * Sets the color mode.
1424         *
1425         * @param colorMode A valid color mode or zero.
1426         * @return This builder.
1427         *
1428         * @see PrintAttributes#COLOR_MODE_MONOCHROME
1429         * @see PrintAttributes#COLOR_MODE_COLOR
1430         */
1431        public Builder setColorMode(int colorMode) {
1432            if (Integer.bitCount(colorMode) > 1) {
1433                throw new IllegalArgumentException("can specify at most one colorMode bit.");
1434            }
1435            mAttributes.setColorMode(colorMode);
1436            return this;
1437        }
1438
1439        /**
1440         * Sets the fitting mode.
1441         *
1442         * @param fittingMode A valid fitting mode or zero.
1443         * @return This builder.
1444         *
1445         * @see PrintAttributes#FITTING_MODE_NONE
1446         * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
1447         */
1448        public Builder setFittingMode(int fittingMode) {
1449            if (Integer.bitCount(fittingMode) > 1) {
1450                throw new IllegalArgumentException("can specify at most one fittingMode bit.");
1451            }
1452            mAttributes.setFittingMode(fittingMode);
1453            return this;
1454        }
1455
1456        /**
1457         * Sets the orientation.
1458         *
1459         * @param orientation A valid orientation or zero.
1460         * @return This builder.
1461         *
1462         * @see PrintAttributes#ORIENTATION_PORTRAIT
1463         * @see PrintAttributes#ORIENTATION_LANDSCAPE
1464         */
1465        public Builder setOrientation(int orientation) {
1466            if (Integer.bitCount(orientation) > 1) {
1467                throw new IllegalArgumentException("can specify at most one orientation bit.");
1468            }
1469            mAttributes.setOrientation(orientation);
1470            return this;
1471        }
1472
1473        /**
1474         * Sets the number of copies.
1475         *
1476         * @param copyCount A greater or equal to zero copy count.
1477         * @return This builder.
1478         */
1479        public Builder setCopyCount(int copyCount) {
1480            mAttributes.setCopies(copyCount);
1481            return this;
1482        }
1483
1484        /**
1485         * Creates a new {@link PrintAttributes} instance.
1486         *
1487         * @return The new instance.
1488         */
1489        public PrintAttributes create() {
1490            return mAttributes;
1491        }
1492    }
1493
1494    public static final Parcelable.Creator<PrintAttributes> CREATOR =
1495            new Creator<PrintAttributes>() {
1496        @Override
1497        public PrintAttributes createFromParcel(Parcel parcel) {
1498            return new PrintAttributes(parcel);
1499        }
1500
1501        @Override
1502        public PrintAttributes[] newArray(int size) {
1503            return new PrintAttributes[size];
1504        }
1505    };
1506}
1507