• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.print;
18 
19 import android.content.pm.PackageManager;
20 import android.content.pm.PackageManager.NameNotFoundException;
21 import android.content.res.Resources.NotFoundException;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.text.TextUtils;
25 import android.util.ArrayMap;
26 import android.util.Log;
27 
28 import com.android.internal.R;
29 
30 import java.util.Map;
31 
32 /**
33  * This class represents the attributes of a print job. These attributes
34  * describe how the printed content should be laid out. For example, the
35  * print attributes may state that the content should be laid out on a
36  * letter size with 300 DPI (dots per inch) resolution, have a margin of
37  * 10 mills (thousand of an inch) on all sides, and be black and white.
38  */
39 public final class PrintAttributes implements Parcelable {
40     /** Color mode: Monochrome color scheme, for example one color is used. */
41     public static final int COLOR_MODE_MONOCHROME = 1 << 0;
42     /** Color mode: Color color scheme, for example many colors are used. */
43     public static final int COLOR_MODE_COLOR = 1 << 1;
44 
45     private static final int VALID_COLOR_MODES =
46             COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
47 
48     private MediaSize mMediaSize;
49     private Resolution mResolution;
50     private Margins mMinMargins;
51 
52     private int mColorMode;
53 
PrintAttributes()54     PrintAttributes() {
55         /* hide constructor */
56     }
57 
PrintAttributes(Parcel parcel)58     private PrintAttributes(Parcel parcel) {
59         mMediaSize = (parcel.readInt() ==  1) ? MediaSize.createFromParcel(parcel) : null;
60         mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
61         mMinMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
62         mColorMode = parcel.readInt();
63     }
64 
65     /**
66      * Gets the media size.
67      *
68      * @return The media size or <code>null</code> if not set.
69      */
getMediaSize()70     public MediaSize getMediaSize() {
71         return mMediaSize;
72     }
73 
74     /**
75      * Sets the media size.
76      *
77      * @param The media size.
78      *
79      * @hide
80      */
setMediaSize(MediaSize mediaSize)81     public void setMediaSize(MediaSize mediaSize) {
82         mMediaSize = mediaSize;
83     }
84 
85     /**
86      * Gets the resolution.
87      *
88      * @return The resolution or <code>null</code> if not set.
89      */
getResolution()90     public Resolution getResolution() {
91         return mResolution;
92     }
93 
94     /**
95      * Sets the resolution.
96      *
97      * @param The resolution.
98      *
99      * @hide
100      */
setResolution(Resolution resolution)101     public void setResolution(Resolution resolution) {
102         mResolution = resolution;
103     }
104 
105     /**
106      * Gets the minimal margins. If the content does not fit
107      * these margins it will be clipped.
108      * <p>
109      * <strong>These margins are physically imposed by the printer and they
110      * are <em>not</em> rotated, i.e. they are the same for both portrait and
111      * landscape. For example, a printer may not be able to print in a stripe
112      * on both left and right sides of the page.
113      * </strong>
114      * </p>
115      *
116      * @return The margins or <code>null</code> if not set.
117      */
getMinMargins()118     public Margins getMinMargins() {
119         return mMinMargins;
120     }
121 
122     /**
123      * Sets the minimal margins. If the content does not fit
124      * these margins it will be clipped.
125      * <p>
126      * <strong>These margins are physically imposed by the printer and they
127      * are <em>not</em> rotated, i.e. they are the same for both portrait and
128      * landscape. For example, a printer may not be able to print in a stripe
129      * on both left and right sides of the page.
130      * </strong>
131      * </p>
132      *
133      * @param The margins.
134      *
135      * @hide
136      */
setMinMargins(Margins margins)137     public void setMinMargins(Margins margins) {
138         mMinMargins = margins;
139     }
140 
141     /**
142      * Gets the color mode.
143      *
144      * @return The color mode or zero if not set.
145      *
146      * @see #COLOR_MODE_COLOR
147      * @see #COLOR_MODE_MONOCHROME
148      */
getColorMode()149     public int getColorMode() {
150         return mColorMode;
151     }
152 
153     /**
154      * Sets the color mode.
155      *
156      * @param The color mode.
157      *
158      * @see #COLOR_MODE_MONOCHROME
159      * @see #COLOR_MODE_COLOR
160      *
161      * @hide
162      */
setColorMode(int colorMode)163     public void setColorMode(int colorMode) {
164         enforceValidColorMode(colorMode);
165         mColorMode = colorMode;
166     }
167 
168     /**
169      * Gets whether this print attributes are in portrait orientation,
170      * which is the media size is in portrait and all orientation dependent
171      * attributes such as resolution and margins are properly adjusted.
172      *
173      * @return Whether this print attributes are in portrait.
174      *
175      * @hide
176      */
isPortrait()177     public boolean isPortrait() {
178         return mMediaSize.isPortrait();
179     }
180 
181     /**
182      * Gets a new print attributes instance which is in portrait orientation,
183      * which is the media size is in portrait and all orientation dependent
184      * attributes such as resolution and margins are properly adjusted.
185      *
186      * @return New instance in portrait orientation if this one is in
187      * landscape, otherwise this instance.
188      *
189      * @hide
190      */
asPortrait()191     public PrintAttributes asPortrait() {
192         if (isPortrait()) {
193             return this;
194         }
195 
196         PrintAttributes attributes = new PrintAttributes();
197 
198         // Rotate the media size.
199         attributes.setMediaSize(getMediaSize().asPortrait());
200 
201         // Rotate the resolution.
202         Resolution oldResolution = getResolution();
203         Resolution newResolution = new Resolution(
204                 oldResolution.getId(),
205                 oldResolution.getLabel(),
206                 oldResolution.getVerticalDpi(),
207                 oldResolution.getHorizontalDpi());
208         attributes.setResolution(newResolution);
209 
210         // Do not rotate the physical margins.
211         attributes.setMinMargins(getMinMargins());
212 
213         attributes.setColorMode(getColorMode());
214 
215         return attributes;
216     }
217 
218     /**
219      * Gets a new print attributes instance which is in landscape orientation,
220      * which is the media size is in landscape and all orientation dependent
221      * attributes such as resolution and margins are properly adjusted.
222      *
223      * @return New instance in landscape orientation if this one is in
224      * portrait, otherwise this instance.
225      *
226      * @hide
227      */
asLandscape()228     public PrintAttributes asLandscape() {
229         if (!isPortrait()) {
230             return this;
231         }
232 
233         PrintAttributes attributes = new PrintAttributes();
234 
235         // Rotate the media size.
236         attributes.setMediaSize(getMediaSize().asLandscape());
237 
238         // Rotate the resolution.
239         Resolution oldResolution = getResolution();
240         Resolution newResolution = new Resolution(
241                 oldResolution.getId(),
242                 oldResolution.getLabel(),
243                 oldResolution.getVerticalDpi(),
244                 oldResolution.getHorizontalDpi());
245         attributes.setResolution(newResolution);
246 
247         // Do not rotate the physical margins.
248         attributes.setMinMargins(getMinMargins());
249 
250         attributes.setColorMode(getColorMode());
251 
252         return attributes;
253     }
254 
255     @Override
writeToParcel(Parcel parcel, int flags)256     public void writeToParcel(Parcel parcel, int flags) {
257         if (mMediaSize != null) {
258             parcel.writeInt(1);
259             mMediaSize.writeToParcel(parcel);
260         } else {
261             parcel.writeInt(0);
262         }
263         if (mResolution != null) {
264             parcel.writeInt(1);
265             mResolution.writeToParcel(parcel);
266         } else {
267             parcel.writeInt(0);
268         }
269         if (mMinMargins != null) {
270             parcel.writeInt(1);
271             mMinMargins.writeToParcel(parcel);
272         } else {
273             parcel.writeInt(0);
274         }
275         parcel.writeInt(mColorMode);
276     }
277 
278     @Override
describeContents()279     public int describeContents() {
280         return 0;
281     }
282 
283     @Override
hashCode()284     public int hashCode() {
285         final int prime = 31;
286         int result = 1;
287         result = prime * result + mColorMode;
288         result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
289         result = prime * result + ((mMediaSize == null) ? 0 : mMediaSize.hashCode());
290         result = prime * result + ((mResolution == null) ? 0 : mResolution.hashCode());
291         return result;
292     }
293 
294     @Override
equals(Object obj)295     public boolean equals(Object obj) {
296         if (this == obj) {
297             return true;
298         }
299         if (obj == null) {
300             return false;
301         }
302         if (getClass() != obj.getClass()) {
303             return false;
304         }
305         PrintAttributes other = (PrintAttributes) obj;
306         if (mColorMode != other.mColorMode) {
307             return false;
308         }
309         if (mMinMargins == null) {
310             if (other.mMinMargins != null) {
311                 return false;
312             }
313         } else if (!mMinMargins.equals(other.mMinMargins)) {
314             return false;
315         }
316         if (mMediaSize == null) {
317             if (other.mMediaSize != null) {
318                 return false;
319             }
320         } else if (!mMediaSize.equals(other.mMediaSize)) {
321             return false;
322         }
323         if (mResolution == null) {
324             if (other.mResolution != null) {
325                 return false;
326             }
327         } else if (!mResolution.equals(other.mResolution)) {
328             return false;
329         }
330         return true;
331     }
332 
333     @Override
toString()334     public String toString() {
335         StringBuilder builder = new StringBuilder();
336         builder.append("PrintAttributes{");
337         builder.append("mediaSize: ").append(mMediaSize);
338         if (mMediaSize != null) {
339             builder.append(", orientation: ").append(mMediaSize.isPortrait()
340                     ? "portrait" : "landscape");
341         } else {
342             builder.append(", orientation: ").append("null");
343         }
344         builder.append(", resolution: ").append(mResolution);
345         builder.append(", minMargins: ").append(mMinMargins);
346         builder.append(", colorMode: ").append(colorModeToString(mColorMode));
347         builder.append("}");
348         return builder.toString();
349     }
350 
351     /** @hide */
clear()352     public void clear() {
353         mMediaSize = null;
354         mResolution = null;
355         mMinMargins = null;
356         mColorMode = 0;
357     }
358 
359     /**
360      * @hide
361      */
copyFrom(PrintAttributes other)362     public void copyFrom(PrintAttributes other) {
363         mMediaSize = other.mMediaSize;
364         mResolution = other.mResolution;
365         mMinMargins = other.mMinMargins;
366         mColorMode = other.mColorMode;
367     }
368 
369     /**
370      * This class specifies a supported media size. Media size is the
371      * dimension of the media on which the content is printed. For
372      * example, the {@link #NA_LETTER} media size designates a page
373      * with size 8.5" x 11".
374      */
375     public static final class MediaSize {
376         private static final String LOG_TAG = "MediaSize";
377 
378         private static final Map<String, MediaSize> sIdToMediaSizeMap =
379                 new ArrayMap<String, MediaSize>();
380 
381         /**
382          * Unknown media size in portrait mode.
383          * <p>
384          * <strong>Note: </strong>This is for specifying orientation without media
385          * size. You should not use the dimensions reported by this instance.
386          * </p>
387          */
388         public static final MediaSize UNKNOWN_PORTRAIT =
389                 new MediaSize("UNKNOWN_PORTRAIT", "android",
390                         R.string.mediasize_unknown_portrait, 1, Integer.MAX_VALUE);
391 
392         /**
393          * Unknown media size in landscape mode.
394          * <p>
395          * <strong>Note: </strong>This is for specifying orientation without media
396          * size. You should not use the dimensions reported by this instance.
397          * </p>
398          */
399         public static final MediaSize UNKNOWN_LANDSCAPE =
400                 new MediaSize("UNKNOWN_LANDSCAPE", "android",
401                         R.string.mediasize_unknown_landscape, Integer.MAX_VALUE, 1);
402 
403         // ISO sizes
404 
405         /** ISO A0 media size: 841mm x 1189mm (33.11" x 46.81") */
406         public static final MediaSize ISO_A0 =
407                 new MediaSize("ISO_A0", "android", R.string.mediasize_iso_a0, 33110, 46810);
408         /** ISO A1 media size: 594mm x 841mm (23.39" x 33.11") */
409         public static final MediaSize ISO_A1 =
410                 new MediaSize("ISO_A1", "android", R.string.mediasize_iso_a1, 23390, 33110);
411         /** ISO A2 media size: 420mm x 594mm (16.54" x 23.39") */
412         public static final MediaSize ISO_A2 =
413                 new MediaSize("ISO_A2", "android", R.string.mediasize_iso_a2, 16540, 23390);
414         /** ISO A3 media size: 297mm x 420mm (11.69" x 16.54") */
415         public static final MediaSize ISO_A3 =
416                 new MediaSize("ISO_A3", "android", R.string.mediasize_iso_a3, 11690, 16540);
417         /** ISO A4 media size: 210mm x 297mm (8.27" x 11.69") */
418         public static final MediaSize ISO_A4 =
419                 new MediaSize("ISO_A4", "android", R.string.mediasize_iso_a4, 8270, 11690);
420         /** ISO A5 media size: 148mm x 210mm (5.83" x 8.27") */
421         public static final MediaSize ISO_A5 =
422                 new MediaSize("ISO_A5", "android", R.string.mediasize_iso_a5, 5830, 8270);
423         /** ISO A6 media size: 105mm x 148mm (4.13" x 5.83") */
424         public static final MediaSize ISO_A6 =
425                 new MediaSize("ISO_A6", "android", R.string.mediasize_iso_a6, 4130, 5830);
426         /** ISO A7 media size: 74mm x 105mm (2.91" x 4.13") */
427         public static final MediaSize ISO_A7 =
428                 new MediaSize("ISO_A7", "android", R.string.mediasize_iso_a7, 2910, 4130);
429         /** ISO A8 media size: 52mm x 74mm (2.05" x 2.91") */
430         public static final MediaSize ISO_A8 =
431                 new MediaSize("ISO_A8", "android", R.string.mediasize_iso_a8, 2050, 2910);
432         /** ISO A9 media size: 37mm x 52mm (1.46" x 2.05") */
433         public static final MediaSize ISO_A9 =
434                 new MediaSize("ISO_A9", "android", R.string.mediasize_iso_a9, 1460, 2050);
435         /** ISO A10 media size: 26mm x 37mm (1.02" x 1.46") */
436         public static final MediaSize ISO_A10 =
437                 new MediaSize("ISO_A10", "android", R.string.mediasize_iso_a10, 1020, 1460);
438 
439         /** ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67") */
440         public static final MediaSize ISO_B0 =
441                 new MediaSize("ISO_B0", "android", R.string.mediasize_iso_b0, 39370, 55670);
442         /** ISO B1 media size: 707mm x 1000mm (27.83" x 39.37") */
443         public static final MediaSize ISO_B1 =
444                 new MediaSize("ISO_B1", "android", R.string.mediasize_iso_b1, 27830, 39370);
445         /** ISO B2 media size: 500mm x 707mm (19.69" x 27.83") */
446         public static final MediaSize ISO_B2 =
447                 new MediaSize("ISO_B2", "android", R.string.mediasize_iso_b2, 19690, 27830);
448         /** ISO B3 media size: 353mm x 500mm (13.90" x 19.69") */
449         public static final MediaSize ISO_B3 =
450                 new MediaSize("ISO_B3", "android", R.string.mediasize_iso_b3, 13900, 19690);
451         /** ISO B4 media size: 250mm x 353mm (9.84" x 13.90") */
452         public static final MediaSize ISO_B4 =
453                 new MediaSize("ISO_B4", "android", R.string.mediasize_iso_b4, 9840, 13900);
454         /** ISO B5 media size: 176mm x 250mm (6.93" x 9.84") */
455         public static final MediaSize ISO_B5 =
456                 new MediaSize("ISO_B5", "android", R.string.mediasize_iso_b5, 6930, 9840);
457         /** ISO B6 media size: 125mm x 176mm (4.92" x 6.93") */
458         public static final MediaSize ISO_B6 =
459                 new MediaSize("ISO_B6", "android", R.string.mediasize_iso_b6, 4920, 6930);
460         /** ISO B7 media size: 88mm x 125mm (3.46" x 4.92") */
461         public static final MediaSize ISO_B7 =
462                 new MediaSize("ISO_B7", "android", R.string.mediasize_iso_b7, 3460, 4920);
463         /** ISO B8 media size: 62mm x 88mm (2.44" x 3.46") */
464         public static final MediaSize ISO_B8 =
465                 new MediaSize("ISO_B8", "android", R.string.mediasize_iso_b8, 2440, 3460);
466         /** ISO B9 media size: 44mm x 62mm (1.73" x 2.44") */
467         public static final MediaSize ISO_B9 =
468                 new MediaSize("ISO_B9", "android", R.string.mediasize_iso_b9, 1730, 2440);
469         /** ISO B10 media size: 31mm x 44mm (1.22" x 1.73") */
470         public static final MediaSize ISO_B10 =
471                 new MediaSize("ISO_B10", "android", R.string.mediasize_iso_b10, 1220, 1730);
472 
473         /** ISO C0 media size: 917mm x 1297mm (36.10" x 51.06") */
474         public static final MediaSize ISO_C0 =
475                 new MediaSize("ISO_C0", "android", R.string.mediasize_iso_c0, 36100, 51060);
476         /** ISO C1 media size: 648mm x 917mm (25.51" x 36.10") */
477         public static final MediaSize ISO_C1 =
478                 new MediaSize("ISO_C1", "android", R.string.mediasize_iso_c1, 25510, 36100);
479         /** ISO C2 media size: 458mm x 648mm (18.03" x 25.51") */
480         public static final MediaSize ISO_C2 =
481                 new MediaSize("ISO_C2", "android", R.string.mediasize_iso_c2, 18030, 25510);
482         /** ISO C3 media size: 324mm x 458mm (12.76" x 18.03") */
483         public static final MediaSize ISO_C3 =
484                 new MediaSize("ISO_C3", "android", R.string.mediasize_iso_c3, 12760, 18030);
485         /** ISO C4 media size: 229mm x 324mm (9.02" x 12.76") */
486         public static final MediaSize ISO_C4 =
487                 new MediaSize("ISO_C4", "android", R.string.mediasize_iso_c4, 9020, 12760);
488         /** ISO C5 media size: 162mm x 229mm (6.38" x 9.02") */
489         public static final MediaSize ISO_C5 =
490                 new MediaSize("ISO_C5", "android", R.string.mediasize_iso_c5, 6380, 9020);
491         /** ISO C6 media size: 114mm x 162mm (4.49" x 6.38") */
492         public static final MediaSize ISO_C6 =
493                 new MediaSize("ISO_C6", "android", R.string.mediasize_iso_c6, 4490, 6380);
494         /** ISO C7 media size: 81mm x 114mm (3.19" x 4.49") */
495         public static final MediaSize ISO_C7 =
496                 new MediaSize("ISO_C7", "android", R.string.mediasize_iso_c7, 3190, 4490);
497         /** ISO C8 media size: 57mm x 81mm (2.24" x 3.19") */
498         public static final MediaSize ISO_C8 =
499                 new MediaSize("ISO_C8", "android", R.string.mediasize_iso_c8, 2240, 3190);
500         /** ISO C9 media size: 40mm x 57mm (1.57" x 2.24") */
501         public static final MediaSize ISO_C9 =
502                 new MediaSize("ISO_C9", "android", R.string.mediasize_iso_c9, 1570, 2240);
503         /** ISO C10 media size: 28mm x 40mm (1.10" x 1.57") */
504         public static final MediaSize ISO_C10 =
505                 new MediaSize("ISO_C10", "android", R.string.mediasize_iso_c10, 1100, 1570);
506 
507         // North America
508 
509         /** North America Letter media size: 8.5" x 11" (279mm x 216mm) */
510         public static final MediaSize NA_LETTER =
511                 new MediaSize("NA_LETTER", "android", R.string.mediasize_na_letter, 8500, 11000);
512         /** North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm) */
513         public static final MediaSize NA_GOVT_LETTER =
514                 new MediaSize("NA_GOVT_LETTER", "android",
515                         R.string.mediasize_na_gvrnmt_letter, 8000, 10500);
516         /** North America Legal media size: 8.5" x 14" (216mm x 356mm) */
517         public static final MediaSize NA_LEGAL =
518                 new MediaSize("NA_LEGAL", "android", R.string.mediasize_na_legal, 8500, 14000);
519         /** North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm) */
520         public static final MediaSize NA_JUNIOR_LEGAL =
521                 new MediaSize("NA_JUNIOR_LEGAL", "android",
522                         R.string.mediasize_na_junior_legal, 8000, 5000);
523         /** North America Ledger media size: 17" x 11" (432mm × 279mm) */
524         public static final MediaSize NA_LEDGER =
525                 new MediaSize("NA_LEDGER", "android", R.string.mediasize_na_ledger, 17000, 11000);
526         /** North America Tabloid media size: 11" x 17" (279mm × 432mm) */
527         public static final MediaSize NA_TABLOID =
528                 new MediaSize("NA_TABLOID", "android",
529                         R.string.mediasize_na_tabloid, 11000, 17000);
530         /** North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm) */
531         public static final MediaSize NA_INDEX_3X5 =
532                 new MediaSize("NA_INDEX_3X5", "android",
533                         R.string.mediasize_na_index_3x5, 3000, 5000);
534         /** North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm) */
535         public static final MediaSize NA_INDEX_4X6 =
536                 new MediaSize("NA_INDEX_4X6", "android",
537                         R.string.mediasize_na_index_4x6, 4000, 6000);
538         /** North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm) */
539         public static final MediaSize NA_INDEX_5X8 =
540                 new MediaSize("NA_INDEX_5X8", "android",
541                         R.string.mediasize_na_index_5x8, 5000, 8000);
542         /** North America Monarch media size: 7.25" x 10.5" (184mm x 267mm) */
543         public static final MediaSize NA_MONARCH =
544                 new MediaSize("NA_MONARCH", "android",
545                         R.string.mediasize_na_monarch, 7250, 10500);
546         /** North America Quarto media size: 8" x 10" (203mm x 254mm) */
547         public static final MediaSize NA_QUARTO =
548                 new MediaSize("NA_QUARTO", "android",
549                         R.string.mediasize_na_quarto, 8000, 10000);
550         /** North America Foolscap media size: 8" x 13" (203mm x 330mm) */
551         public static final MediaSize NA_FOOLSCAP =
552                 new MediaSize("NA_FOOLSCAP", "android",
553                         R.string.mediasize_na_foolscap, 8000, 13000);
554 
555         // Chinese
556 
557         /** Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543") */
558         public static final MediaSize ROC_8K =
559                 new MediaSize("ROC_8K", "android",
560                         R.string.mediasize_chinese_roc_8k, 10629, 15354);
561         /** Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629") */
562         public static final MediaSize ROC_16K =
563                 new MediaSize("ROC_16K", "android",
564                         R.string.mediasize_chinese_roc_16k, 7677, 10629);
565 
566         /** Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496") */
567         public static final MediaSize PRC_1 =
568                 new MediaSize("PRC_1", "android",
569                         R.string.mediasize_chinese_prc_1, 4015, 6496);
570         /** Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929") */
571         public static final MediaSize PRC_2 =
572                 new MediaSize("PRC_2", "android",
573                         R.string.mediasize_chinese_prc_2, 4015, 6929);
574         /** Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929") */
575         public static final MediaSize PRC_3 =
576                 new MediaSize("PRC_3", "android",
577                         R.string.mediasize_chinese_prc_3, 4921, 6929);
578         /** Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189") */
579         public static final MediaSize PRC_4 =
580                 new MediaSize("PRC_4", "android",
581                         R.string.mediasize_chinese_prc_4, 4330, 8189);
582         /** Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661") */
583         public static final MediaSize PRC_5 =
584                 new MediaSize("PRC_5", "android",
585                         R.string.mediasize_chinese_prc_5, 4330, 8661);
586         /** Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599") */
587         public static final MediaSize PRC_6 =
588                 new MediaSize("PRC_6", "android",
589                         R.string.mediasize_chinese_prc_6, 4724, 12599);
590         /** Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055") */
591         public static final MediaSize PRC_7 =
592                 new MediaSize("PRC_7", "android",
593                         R.string.mediasize_chinese_prc_7, 6299, 9055);
594         /** Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165") */
595         public static final MediaSize PRC_8 =
596                 new MediaSize("PRC_8", "android",
597                         R.string.mediasize_chinese_prc_8, 4724, 12165);
598         /** Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756") */
599         public static final MediaSize PRC_9 =
600                 new MediaSize("PRC_9", "android",
601                         R.string.mediasize_chinese_prc_9, 9016, 12756);
602         /** Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032") */
603         public static final MediaSize PRC_10 =
604                 new MediaSize("PRC_10", "android",
605                         R.string.mediasize_chinese_prc_10, 12756, 18032);
606 
607         /** Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465") */
608         public static final MediaSize PRC_16K =
609                 new MediaSize("PRC_16K", "android",
610                         R.string.mediasize_chinese_prc_16k, 5749, 8465);
611         /** Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315") */
612         public static final MediaSize OM_PA_KAI =
613                 new MediaSize("OM_PA_KAI", "android",
614                         R.string.mediasize_chinese_om_pa_kai, 10512, 15315);
615         /** Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551") */
616         public static final MediaSize OM_DAI_PA_KAI =
617                 new MediaSize("OM_DAI_PA_KAI", "android",
618                         R.string.mediasize_chinese_om_dai_pa_kai, 10827, 15551);
619         /** Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827") */
620         public static final MediaSize OM_JUURO_KU_KAI =
621                 new MediaSize("OM_JUURO_KU_KAI", "android",
622                         R.string.mediasize_chinese_om_jurro_ku_kai, 7796, 10827);
623 
624         // Japanese
625 
626         /** Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772") */
627         public static final MediaSize JIS_B10 =
628                 new MediaSize("JIS_B10", "android",
629                         R.string.mediasize_japanese_jis_b10, 1259, 1772);
630         /** Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52") */
631         public static final MediaSize JIS_B9 =
632                 new MediaSize("JIS_B9", "android",
633                         R.string.mediasize_japanese_jis_b9, 1772, 2520);
634         /** Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583") */
635         public static final MediaSize JIS_B8 =
636                 new MediaSize("JIS_B8", "android",
637                         R.string.mediasize_japanese_jis_b8, 2520, 3583);
638         /** Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049") */
639         public static final MediaSize JIS_B7 =
640                 new MediaSize("JIS_B7", "android",
641                         R.string.mediasize_japanese_jis_b7, 3583, 5049);
642         /** Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165") */
643         public static final MediaSize JIS_B6 =
644                 new MediaSize("JIS_B6", "android",
645                         R.string.mediasize_japanese_jis_b6, 5049, 7165);
646         /** Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118") */
647         public static final MediaSize JIS_B5 =
648                 new MediaSize("JIS_B5", "android",
649                         R.string.mediasize_japanese_jis_b5, 7165, 10118);
650         /** Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331") */
651         public static final MediaSize JIS_B4 =
652                 new MediaSize("JIS_B4", "android",
653                         R.string.mediasize_japanese_jis_b4, 10118, 14331);
654         /** Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276") */
655         public static final MediaSize JIS_B3 =
656                 new MediaSize("JIS_B3", "android",
657                         R.string.mediasize_japanese_jis_b3, 14331, 20276);
658         /** Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661") */
659         public static final MediaSize JIS_B2 =
660                 new MediaSize("JIS_B2", "android",
661                         R.string.mediasize_japanese_jis_b2, 20276, 28661);
662         /** Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551") */
663         public static final MediaSize JIS_B1 =
664                 new MediaSize("JIS_B1", "android",
665                         R.string.mediasize_japanese_jis_b1, 28661, 40551);
666         /** Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323") */
667         public static final MediaSize JIS_B0 =
668                 new MediaSize("JIS_B0", "android",
669                         R.string.mediasize_japanese_jis_b0, 40551, 57323);
670 
671         /** Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992") */
672         public static final MediaSize JIS_EXEC =
673                 new MediaSize("JIS_EXEC", "android",
674                         R.string.mediasize_japanese_jis_exec, 8504, 12992);
675 
676         /** Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071") */
677         public static final MediaSize JPN_CHOU4 =
678                 new MediaSize("JPN_CHOU4", "android",
679                         R.string.mediasize_japanese_chou4, 3543, 8071);
680         /** Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252") */
681         public static final MediaSize JPN_CHOU3 =
682                 new MediaSize("JPN_CHOU3", "android",
683                         R.string.mediasize_japanese_chou3, 4724, 9252);
684         /** Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748") */
685         public static final MediaSize JPN_CHOU2 =
686                 new MediaSize("JPN_CHOU2", "android",
687                         R.string.mediasize_japanese_chou2, 4374, 5748);
688 
689         /** Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827") */
690         public static final MediaSize JPN_HAGAKI =
691                 new MediaSize("JPN_HAGAKI", "android",
692                         R.string.mediasize_japanese_hagaki, 3937, 5827);
693         /** Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874") */
694         public static final MediaSize JPN_OUFUKU =
695                 new MediaSize("JPN_OUFUKU", "android",
696                         R.string.mediasize_japanese_oufuku, 5827, 7874);
697 
698         /** Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681") */
699         public static final MediaSize JPN_KAHU =
700                 new MediaSize("JPN_KAHU", "android",
701                         R.string.mediasize_japanese_kahu, 9449, 12681);
702         /** Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071") */
703         public static final MediaSize JPN_KAKU2 =
704                 new MediaSize("JPN_KAKU2", "android",
705                         R.string.mediasize_japanese_kaku2, 9449, 13071);
706 
707         /** Japanese You4 media size: 105mm x 235mm (4.134" x 9.252") */
708         public static final MediaSize JPN_YOU4 =
709                 new MediaSize("JPN_YOU4", "android",
710                         R.string.mediasize_japanese_you4, 4134, 9252);
711 
712         private final String mId;
713         /**@hide */
714         public final String mLabel;
715         /**@hide */
716         public final String mPackageName;
717         /**@hide */
718         public final int mLabelResId;
719         private final int mWidthMils;
720         private final int mHeightMils;
721 
722         /**
723          * Creates a new instance.
724          *
725          * @param id The unique media size id.
726          * @param packageName The name of the creating package.
727          * @param labelResId The resource if of a human readable label.
728          * @param widthMils The width in mils (thousands of an inch).
729          * @param heightMils The height in mils (thousands of an inch).
730          *
731          * @throws IllegalArgumentException If the id is empty or the label
732          * is empty or the widthMils is less than or equal to zero or the
733          * heightMils is less than or equal to zero.
734          *
735          * @hide
736          */
MediaSize(String id, String packageName, int labelResId, int widthMils, int heightMils)737         public MediaSize(String id, String packageName, int labelResId,
738                 int widthMils, int heightMils) {
739             if (TextUtils.isEmpty(id)) {
740                 throw new IllegalArgumentException("id cannot be empty.");
741             }
742             if (TextUtils.isEmpty(packageName)) {
743                 throw new IllegalArgumentException("packageName cannot be empty.");
744             }
745             if (labelResId <= 0) {
746                 throw new IllegalArgumentException("labelResId must be greater than zero.");
747             }
748             if (widthMils <= 0) {
749                 throw new IllegalArgumentException("widthMils "
750                         + "cannot be less than or equal to zero.");
751             }
752             if (heightMils <= 0) {
753                 throw new IllegalArgumentException("heightMils "
754                        + "cannot be less than or euqual to zero.");
755             }
756             mPackageName = packageName;
757             mId = id;
758             mLabelResId = labelResId;
759             mWidthMils = widthMils;
760             mHeightMils = heightMils;
761             mLabel = null;
762 
763             // Build this mapping only for predefined media sizes.
764             sIdToMediaSizeMap.put(mId, this);
765         }
766 
767         /**
768          * Creates a new instance.
769          *
770          * @param id The unique media size id. It is unique amongst other media sizes
771          *        supported by the printer.
772          * @param label The <strong>localized</strong> human readable label.
773          * @param widthMils The width in mils (thousands of an inch).
774          * @param heightMils The height in mils (thousands of an inch).
775          *
776          * @throws IllegalArgumentException If the id is empty or the label is empty
777          * or the widthMils is less than or equal to zero or the heightMils is less
778          * than or equal to zero.
779          */
MediaSize(String id, String label, int widthMils, int heightMils)780         public MediaSize(String id, String label, int widthMils, int heightMils) {
781             if (TextUtils.isEmpty(id)) {
782                 throw new IllegalArgumentException("id cannot be empty.");
783             }
784             if (TextUtils.isEmpty(label)) {
785                 throw new IllegalArgumentException("label cannot be empty.");
786             }
787             if (widthMils <= 0) {
788                 throw new IllegalArgumentException("widthMils "
789                         + "cannot be less than or equal to zero.");
790             }
791             if (heightMils <= 0) {
792                 throw new IllegalArgumentException("heightMils "
793                        + "cannot be less than or euqual to zero.");
794             }
795             mId = id;
796             mLabel = label;
797             mWidthMils = widthMils;
798             mHeightMils = heightMils;
799             mLabelResId = 0;
800             mPackageName = null;
801         }
802 
803         /** @hide */
MediaSize(String id, String label, String packageName, int widthMils, int heightMils, int labelResId)804         public MediaSize(String id, String label, String packageName,
805                 int widthMils, int heightMils, int labelResId) {
806             mPackageName = packageName;
807             mId = id;
808             mLabelResId = labelResId;
809             mWidthMils = widthMils;
810             mHeightMils = heightMils;
811             mLabel = label;
812         }
813 
814         /**
815          * Gets the unique media size id. It is unique amongst other media sizes
816          * supported by the printer.
817          * <p>
818          * This id is defined by the client that generated the media size
819          * instance and should not be interpreted by other parties.
820          * </p>
821          *
822          * @return The unique media size id.
823          */
getId()824         public String getId() {
825             return mId;
826         }
827 
828         /**
829          * Gets the human readable media size label.
830          *
831          * @param packageManager The package manager for loading the label.
832          * @return The human readable label.
833          */
getLabel(PackageManager packageManager)834         public String getLabel(PackageManager packageManager) {
835             if (!TextUtils.isEmpty(mPackageName) && mLabelResId > 0) {
836                 try {
837                     return packageManager.getResourcesForApplication(
838                             mPackageName).getString(mLabelResId);
839                 } catch (NotFoundException nfe) {
840                     Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
841                             + " from package " + mPackageName);
842                 } catch (NameNotFoundException nnfee) {
843                     Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
844                             + " from package " + mPackageName);
845                 }
846             }
847             return mLabel;
848         }
849 
850         /**
851          * Gets the media width in mils (thousands of an inch).
852          *
853          * @return The media width.
854          */
getWidthMils()855         public int getWidthMils() {
856             return mWidthMils;
857         }
858 
859         /**
860          * Gets the media height in mils (thousands of an inch).
861          *
862          * @return The media height.
863          */
getHeightMils()864         public int getHeightMils() {
865             return mHeightMils;
866         }
867 
868         /**
869          * Gets whether this media size is in portrait which is the
870          * height is greater or equal to the width.
871          *
872          * @return True if the media size is in portrait, false if
873          * it is in landscape.
874          */
isPortrait()875         public boolean isPortrait() {
876             return mHeightMils >= mWidthMils;
877         }
878 
879         /**
880          * Returns a new media size instance in a portrait orientation,
881          * which is the height is the greater dimension.
882          *
883          * @return New instance in landscape orientation if this one
884          * is in landscape, otherwise this instance.
885          */
asPortrait()886         public MediaSize asPortrait() {
887             if (isPortrait()) {
888                 return this;
889             }
890             return new MediaSize(mId, mLabel, mPackageName,
891                     Math.min(mWidthMils, mHeightMils),
892                     Math.max(mWidthMils, mHeightMils),
893                     mLabelResId);
894         }
895 
896         /**
897          * Returns a new media size instance in a landscape orientation,
898          * which is the height is the lesser dimension.
899          *
900          * @return New instance in landscape orientation if this one
901          * is in portrait, otherwise this instance.
902          */
asLandscape()903         public MediaSize asLandscape() {
904             if (!isPortrait()) {
905                 return this;
906             }
907             return new MediaSize(mId, mLabel, mPackageName,
908                     Math.max(mWidthMils, mHeightMils),
909                     Math.min(mWidthMils, mHeightMils),
910                     mLabelResId);
911         }
912 
writeToParcel(Parcel parcel)913         void writeToParcel(Parcel parcel) {
914             parcel.writeString(mId);
915             parcel.writeString(mLabel);
916             parcel.writeString(mPackageName);
917             parcel.writeInt(mWidthMils);
918             parcel.writeInt(mHeightMils);
919             parcel.writeInt(mLabelResId);
920         }
921 
createFromParcel(Parcel parcel)922         static MediaSize createFromParcel(Parcel parcel) {
923             return new MediaSize(
924                     parcel.readString(),
925                     parcel.readString(),
926                     parcel.readString(),
927                     parcel.readInt(),
928                     parcel.readInt(),
929                     parcel.readInt());
930         }
931 
932         @Override
hashCode()933         public int hashCode() {
934             final int prime = 31;
935             int result = 1;
936             result = prime * result + mWidthMils;
937             result = prime * result + mHeightMils;
938             return result;
939         }
940 
941         @Override
equals(Object obj)942         public boolean equals(Object obj) {
943             if (this == obj) {
944                 return true;
945             }
946             if (obj == null) {
947                 return false;
948             }
949             if (getClass() != obj.getClass()) {
950                 return false;
951             }
952             MediaSize other = (MediaSize) obj;
953             if (mWidthMils != other.mWidthMils) {
954                 return false;
955             }
956             if (mHeightMils != other.mHeightMils) {
957                 return false;
958             }
959             return true;
960         }
961 
962         @Override
toString()963         public String toString() {
964             StringBuilder builder = new StringBuilder();
965             builder.append("MediaSize{");
966             builder.append("id: ").append(mId);
967             builder.append(", label: ").append(mLabel);
968             builder.append(", packageName: ").append(mPackageName);
969             builder.append(", heightMils: ").append(mHeightMils);
970             builder.append(", widthMils: ").append(mWidthMils);
971             builder.append(", labelResId: ").append(mLabelResId);
972             builder.append("}");
973             return builder.toString();
974         }
975 
976         /**
977          * Gets a standard media size given its id.
978          *
979          * @param id The media size id.
980          * @return The media size for the given id or null.
981          *
982          * @hide
983          */
getStandardMediaSizeById(String id)984         public static MediaSize getStandardMediaSizeById(String id) {
985             return sIdToMediaSizeMap.get(id);
986         }
987     }
988 
989     /**
990      * This class specifies a supported resolution in DPI (dots per inch).
991      * Resolution defines how many points with different color can be placed
992      * on one inch in horizontal or vertical direction of the target media.
993      * For example, a printer with 600 DPI can produce higher quality images
994      * the one with 300 DPI resolution.
995      */
996     public static final class Resolution {
997         private final String mId;
998         private final String mLabel;
999         private final int mHorizontalDpi;
1000         private final int mVerticalDpi;
1001 
1002         /**
1003          * Creates a new instance.
1004          *
1005          * @param id The unique resolution id. It is unique amongst other resolutions
1006          *        supported by the printer.
1007          * @param label The <strong>localized</strong> human readable label.
1008          * @param horizontalDpi The horizontal resolution in DPI (dots per inch).
1009          * @param verticalDpi The vertical resolution in DPI (dots per inch).
1010          *
1011          * @throws IllegalArgumentException If the id is empty or the label is empty
1012          * or the horizontalDpi is less than or equal to zero or the verticalDpi is
1013          * less than or equal to zero.
1014          */
Resolution(String id, String label, int horizontalDpi, int verticalDpi)1015         public Resolution(String id, String label, int horizontalDpi, int verticalDpi) {
1016             if (TextUtils.isEmpty(id)) {
1017                 throw new IllegalArgumentException("id cannot be empty.");
1018             }
1019             if (TextUtils.isEmpty(label)) {
1020                 throw new IllegalArgumentException("label cannot be empty.");
1021             }
1022             if (horizontalDpi <= 0) {
1023                 throw new IllegalArgumentException("horizontalDpi "
1024                         + "cannot be less than or equal to zero.");
1025             }
1026             if (verticalDpi <= 0) {
1027                 throw new IllegalArgumentException("verticalDpi"
1028                        + " cannot be less than or equal to zero.");
1029             }
1030             mId = id;
1031             mLabel = label;
1032             mHorizontalDpi = horizontalDpi;
1033             mVerticalDpi = verticalDpi;
1034         }
1035 
1036         /**
1037          * Gets the unique resolution id. It is unique amongst other resolutions
1038          * supported by the printer.
1039          * <p>
1040          * This id is defined by the client that generated the resolution
1041          * instance and should not be interpreted by other parties.
1042          * </p>
1043          *
1044          * @return The unique resolution id.
1045          */
getId()1046         public String getId() {
1047             return mId;
1048         }
1049 
1050         /**
1051          * Gets the resolution human readable label.
1052          *
1053          * @return The human readable label.
1054          */
getLabel()1055         public String getLabel() {
1056             return mLabel;
1057         }
1058 
1059         /**
1060          * Gets the horizontal resolution in DPI (dots per inch).
1061          *
1062          * @return The horizontal resolution.
1063          */
getHorizontalDpi()1064         public int getHorizontalDpi() {
1065             return mHorizontalDpi;
1066         }
1067 
1068         /**
1069          * Gets the vertical resolution in DPI (dots per inch).
1070          *
1071          * @return The vertical resolution.
1072          */
getVerticalDpi()1073         public int getVerticalDpi() {
1074             return mVerticalDpi;
1075         }
1076 
writeToParcel(Parcel parcel)1077         void writeToParcel(Parcel parcel) {
1078             parcel.writeString(mId);
1079             parcel.writeString(mLabel);
1080             parcel.writeInt(mHorizontalDpi);
1081             parcel.writeInt(mVerticalDpi);
1082         }
1083 
createFromParcel(Parcel parcel)1084         static Resolution createFromParcel(Parcel parcel) {
1085             return new Resolution(
1086                     parcel.readString(),
1087                     parcel.readString(),
1088                     parcel.readInt(),
1089                     parcel.readInt());
1090         }
1091 
1092         @Override
hashCode()1093         public int hashCode() {
1094             final int prime = 31;
1095             int result = 1;
1096             result = prime * result + mHorizontalDpi;
1097             result = prime * result + mVerticalDpi;
1098             return result;
1099         }
1100 
1101         @Override
equals(Object obj)1102         public boolean equals(Object obj) {
1103             if (this == obj) {
1104                 return true;
1105             }
1106             if (obj == null) {
1107                 return false;
1108             }
1109             if (getClass() != obj.getClass()) {
1110                 return false;
1111             }
1112             Resolution other = (Resolution) obj;
1113             if (mHorizontalDpi != other.mHorizontalDpi) {
1114                 return false;
1115             }
1116             if (mVerticalDpi != other.mVerticalDpi) {
1117                 return false;
1118             }
1119             return true;
1120         }
1121 
1122         @Override
toString()1123         public String toString() {
1124             StringBuilder builder = new StringBuilder();
1125             builder.append("Resolution{");
1126             builder.append("id: ").append(mId);
1127             builder.append(", label: ").append(mLabel);
1128             builder.append(", horizontalDpi: ").append(mHorizontalDpi);
1129             builder.append(", verticalDpi: ").append(mVerticalDpi);
1130             builder.append("}");
1131             return builder.toString();
1132         }
1133     }
1134 
1135     /**
1136      * This class specifies content margins. Margins define the white space
1137      * around the content where the left margin defines the amount of white
1138      * space on the left of the content and so on.
1139      */
1140     public static final class Margins {
1141         public static final Margins NO_MARGINS = new Margins(0,  0,  0,  0);
1142 
1143         private final int mLeftMils;
1144         private final int mTopMils;
1145         private final int mRightMils;
1146         private final int mBottomMils;
1147 
1148         /**
1149          * Creates a new instance.
1150          *
1151          * @param leftMils The left margin in mils (thousands of an inch).
1152          * @param topMils The top margin in mils (thousands of an inch).
1153          * @param rightMils The right margin in mils (thousands of an inch).
1154          * @param bottomMils The bottom margin in mils (thousands of an inch).
1155          */
Margins(int leftMils, int topMils, int rightMils, int bottomMils)1156         public Margins(int leftMils, int topMils, int rightMils, int bottomMils) {
1157             mTopMils = topMils;
1158             mLeftMils = leftMils;
1159             mRightMils = rightMils;
1160             mBottomMils = bottomMils;
1161         }
1162 
1163         /**
1164          * Gets the left margin in mils (thousands of an inch).
1165          *
1166          * @return The left margin.
1167          */
getLeftMils()1168         public int getLeftMils() {
1169             return mLeftMils;
1170         }
1171 
1172         /**
1173          * Gets the top margin in mils (thousands of an inch).
1174          *
1175          * @return The top margin.
1176          */
getTopMils()1177         public int getTopMils() {
1178             return mTopMils;
1179         }
1180 
1181         /**
1182          * Gets the right margin in mils (thousands of an inch).
1183          *
1184          * @return The right margin.
1185          */
getRightMils()1186         public int getRightMils() {
1187             return mRightMils;
1188         }
1189 
1190         /**
1191          * Gets the bottom margin in mils (thousands of an inch).
1192          *
1193          * @return The bottom margin.
1194          */
getBottomMils()1195         public int getBottomMils() {
1196             return mBottomMils;
1197         }
1198 
writeToParcel(Parcel parcel)1199         void writeToParcel(Parcel parcel) {
1200             parcel.writeInt(mLeftMils);
1201             parcel.writeInt(mTopMils);
1202             parcel.writeInt(mRightMils);
1203             parcel.writeInt(mBottomMils);
1204         }
1205 
createFromParcel(Parcel parcel)1206         static Margins createFromParcel(Parcel parcel) {
1207             return new Margins(
1208                     parcel.readInt(),
1209                     parcel.readInt(),
1210                     parcel.readInt(),
1211                     parcel.readInt());
1212         }
1213 
1214         @Override
hashCode()1215         public int hashCode() {
1216             final int prime = 31;
1217             int result = 1;
1218             result = prime * result + mBottomMils;
1219             result = prime * result + mLeftMils;
1220             result = prime * result + mRightMils;
1221             result = prime * result + mTopMils;
1222             return result;
1223         }
1224 
1225         @Override
equals(Object obj)1226         public boolean equals(Object obj) {
1227             if (this == obj) {
1228                 return true;
1229             }
1230             if (obj == null) {
1231                 return false;
1232             }
1233             if (getClass() != obj.getClass()) {
1234                 return false;
1235             }
1236             Margins other = (Margins) obj;
1237             if (mBottomMils != other.mBottomMils) {
1238                 return false;
1239             }
1240             if (mLeftMils != other.mLeftMils) {
1241                 return false;
1242             }
1243             if (mRightMils != other.mRightMils) {
1244                 return false;
1245             }
1246             if (mTopMils != other.mTopMils) {
1247                 return false;
1248             }
1249             return true;
1250         }
1251 
1252         @Override
toString()1253         public String toString() {
1254             StringBuilder builder = new StringBuilder();
1255             builder.append("Margins{");
1256             builder.append("leftMils: ").append(mLeftMils);
1257             builder.append(", topMils: ").append(mTopMils);
1258             builder.append(", rightMils: ").append(mRightMils);
1259             builder.append(", bottomMils: ").append(mBottomMils);
1260             builder.append("}");
1261             return builder.toString();
1262         }
1263     }
1264 
colorModeToString(int colorMode)1265     static String colorModeToString(int colorMode) {
1266         switch (colorMode) {
1267             case COLOR_MODE_MONOCHROME: {
1268                 return "COLOR_MODE_MONOCHROME";
1269             }
1270             case COLOR_MODE_COLOR: {
1271                 return "COLOR_MODE_COLOR";
1272             }
1273             default:
1274                 return "COLOR_MODE_UNKNOWN";
1275         }
1276     }
1277 
enforceValidColorMode(int colorMode)1278     static void enforceValidColorMode(int colorMode) {
1279         if ((colorMode & VALID_COLOR_MODES) == 0 && Integer.bitCount(colorMode) == 1) {
1280             throw new IllegalArgumentException("invalid color mode: " + colorMode);
1281         }
1282     }
1283 
1284     /**
1285      * Builder for creating {@link PrintAttributes}.
1286      */
1287     public static final class Builder {
1288         private final PrintAttributes mAttributes = new PrintAttributes();
1289 
1290         /**
1291          * Sets the media size.
1292          *
1293          * @param mediaSize The media size.
1294          * @return This builder.
1295          */
setMediaSize(MediaSize mediaSize)1296         public Builder setMediaSize(MediaSize mediaSize) {
1297             mAttributes.setMediaSize(mediaSize);
1298             return this;
1299         }
1300 
1301         /**
1302          * Sets the resolution.
1303          *
1304          * @param resolution The resolution.
1305          * @return This builder.
1306          */
setResolution(Resolution resolution)1307         public Builder setResolution(Resolution resolution) {
1308             mAttributes.setResolution(resolution);
1309             return this;
1310         }
1311 
1312         /**
1313          * Sets the minimal margins. If the content does not fit
1314          * these margins it will be clipped.
1315          *
1316          * @param margins The margins.
1317          * @return This builder.
1318          */
setMinMargins(Margins margins)1319         public Builder setMinMargins(Margins margins) {
1320             mAttributes.setMinMargins(margins);
1321             return this;
1322         }
1323 
1324         /**
1325          * Sets the color mode.
1326          *
1327          * @param colorMode A valid color mode or zero.
1328          * @return This builder.
1329          *
1330          * @see PrintAttributes#COLOR_MODE_MONOCHROME
1331          * @see PrintAttributes#COLOR_MODE_COLOR
1332          */
setColorMode(int colorMode)1333         public Builder setColorMode(int colorMode) {
1334             if (Integer.bitCount(colorMode) > 1) {
1335                 throw new IllegalArgumentException("can specify at most one colorMode bit.");
1336             }
1337             mAttributes.setColorMode(colorMode);
1338             return this;
1339         }
1340 
1341         /**
1342          * Creates a new {@link PrintAttributes} instance.
1343          *
1344          * @return The new instance.
1345          */
build()1346         public PrintAttributes build() {
1347             return mAttributes;
1348         }
1349     }
1350 
1351     public static final Parcelable.Creator<PrintAttributes> CREATOR =
1352             new Creator<PrintAttributes>() {
1353         @Override
1354         public PrintAttributes createFromParcel(Parcel parcel) {
1355             return new PrintAttributes(parcel);
1356         }
1357 
1358         @Override
1359         public PrintAttributes[] newArray(int size) {
1360             return new PrintAttributes[size];
1361         }
1362     };
1363 }
1364