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