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