PrintAttributes.java revision d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5
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
34    /** Color mode: Monochrome color scheme, e.g. one color is used. */
35    public static final int COLOR_MODE_MONOCHROME = 1 << 0;
36    /** Color mode: Color color scheme, e.g. many colors are used. */
37    public static final int COLOR_MODE_COLOR = 1 << 1;
38
39    private static final int VALID_COLOR_MODES =
40            COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
41
42    private MediaSize mMediaSize;
43    private Resolution mResolution;
44    private Margins mMinMargins;
45
46    private int mColorMode;
47
48    PrintAttributes() {
49        /* hide constructor */
50    }
51
52    private PrintAttributes(Parcel parcel) {
53        mMediaSize = (parcel.readInt() ==  1) ? MediaSize.createFromParcel(parcel) : null;
54        mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
55        mMinMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
56        mColorMode = parcel.readInt();
57    }
58
59    /**
60     * Gets the media size.
61     *
62     * @return The media size or <code>null</code> if not set.
63     */
64    public MediaSize getMediaSize() {
65        return mMediaSize;
66    }
67
68    /**
69     * Sets the media size.
70     *
71     * @param The media size.
72     *
73     * @hide
74     */
75    public void setMediaSize(MediaSize mediaSize) {
76        mMediaSize = mediaSize;
77    }
78
79    /**
80     * Gets the resolution.
81     *
82     * @return The resolution or <code>null</code> if not set.
83     */
84    public Resolution getResolution() {
85        return mResolution;
86    }
87
88    /**
89     * Sets the resolution.
90     *
91     * @param The resolution.
92     *
93     * @hide
94     */
95    public void setResolution(Resolution resolution) {
96        mResolution = resolution;
97    }
98
99    /**
100     * Gets the minimal margins. If the content does not fit
101     * these margins it will be clipped.
102     *
103     * @return The margins or <code>null</code> if not set.
104     */
105    public Margins getMinMargins() {
106        return mMinMargins;
107    }
108
109    /**
110     * Sets the minimal margins. If the content does not fit
111     * these margins it will be clipped.
112     *
113     * @param The margins.
114     *
115     * @hide
116     */
117    public void setMinMargins(Margins margins) {
118        mMinMargins = margins;
119    }
120
121    /**
122     * Gets the color mode.
123     *
124     * @return The color mode or zero if not set.
125     *
126     * @see #COLOR_MODE_COLOR
127     * @see #COLOR_MODE_MONOCHROME
128     */
129    public int getColorMode() {
130        return mColorMode;
131    }
132
133    /**
134     * Sets the color mode.
135     *
136     * @param The color mode.
137     *
138     * @see #COLOR_MODE_MONOCHROME
139     * @see #COLOR_MODE_COLOR
140     *
141     * @hide
142     */
143    public void setColorMode(int colorMode) {
144        enforceValidColorMode(colorMode);
145        mColorMode = colorMode;
146    }
147
148    @Override
149    public void writeToParcel(Parcel parcel, int flags) {
150        if (mMediaSize != null) {
151            parcel.writeInt(1);
152            mMediaSize.writeToParcel(parcel);
153        } else {
154            parcel.writeInt(0);
155        }
156        if (mResolution != null) {
157            parcel.writeInt(1);
158            mResolution.writeToParcel(parcel);
159        } else {
160            parcel.writeInt(0);
161        }
162        if (mMinMargins != null) {
163            parcel.writeInt(1);
164            mMinMargins.writeToParcel(parcel);
165        } else {
166            parcel.writeInt(0);
167        }
168        parcel.writeInt(mColorMode);
169    }
170
171    @Override
172    public int describeContents() {
173        return 0;
174    }
175
176    @Override
177    public int hashCode() {
178        final int prime = 31;
179        int result = 1;
180        result = prime * result + mColorMode;
181        result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
182        result = prime * result + ((mMediaSize == null) ? 0 : mMediaSize.hashCode());
183        result = prime * result + ((mResolution == null) ? 0 : mResolution.hashCode());
184        return result;
185    }
186
187    @Override
188    public boolean equals(Object obj) {
189        if (this == obj) {
190            return true;
191        }
192        if (obj == null) {
193            return false;
194        }
195        if (getClass() != obj.getClass()) {
196            return false;
197        }
198        PrintAttributes other = (PrintAttributes) obj;
199        if (mColorMode != other.mColorMode) {
200            return false;
201        }
202        if (mMinMargins == null) {
203            if (other.mMinMargins != null) {
204                return false;
205            }
206        } else if (!mMinMargins.equals(other.mMinMargins)) {
207            return false;
208        }
209        if (mMediaSize == null) {
210            if (other.mMediaSize != null) {
211                return false;
212            }
213        } else if (!mMediaSize.equals(other.mMediaSize)) {
214            return false;
215        }
216        if (mResolution == null) {
217            if (other.mResolution != null) {
218                return false;
219            }
220        } else if (!mResolution.equals(other.mResolution)) {
221            return false;
222        }
223        return true;
224    }
225
226    @Override
227    public String toString() {
228        StringBuilder builder = new StringBuilder();
229        builder.append("PrintAttributes{");
230        builder.append("mediaSize: ").append(mMediaSize);
231        if (mMediaSize != null) {
232            builder.append(", orientation: ").append(mMediaSize.isPortrait()
233                    ? "portrait" : "landscape");
234        } else {
235            builder.append(", orientation: ").append("null");
236        }
237        builder.append(", resolution: ").append(mResolution);
238        builder.append(", minMargins: ").append(mMinMargins);
239        builder.append(", colorMode: ").append(colorModeToString(mColorMode));
240        builder.append("}");
241        return builder.toString();
242    }
243
244    /** @hide */
245    public void clear() {
246        mMediaSize = null;
247        mResolution = null;
248        mMinMargins = null;
249        mColorMode = 0;
250    }
251
252    /**
253     * @hide
254     */
255    public void copyFrom(PrintAttributes other) {
256        mMediaSize = other.mMediaSize;
257        mResolution = other.mResolution;
258        mMinMargins = other.mMinMargins;
259        mColorMode = other.mColorMode;
260    }
261
262    /**
263     * This class specifies a supported media size.
264     */
265    public static final class MediaSize {
266        private static final String LOG_TAG = "MediaSize";
267
268        /**
269         * Unknown media size in portrait mode.
270         * <p>
271         * <strong>Note: </strong>This is for specifying orientation without media
272         * size. You should not use the dimensions reported by this class.
273         * </p>
274         */
275        public static final MediaSize UNKNOWN_PORTRAIT =
276                new MediaSize("UNKNOWN_PORTRAIT", "android",
277                        R.string.mediasize_unknown_portrait, Integer.MAX_VALUE, 1);
278
279        /**
280         * Unknown media size in landscape mode.
281         * <p>
282         * <strong>Note: </strong>This is for specifying orientation without media
283         * size. You should not use the dimensions reported by this class.
284         * </p>
285         */
286        public static final MediaSize UNKNOWN_LANDSCAPE =
287                new MediaSize("UNKNOWN_LANDSCAPE", "android",
288                        R.string.mediasize_unknown_landscape, 1, Integer.MAX_VALUE);
289
290        // ISO sizes
291
292        /** ISO A0 media size: 841mm x 1189mm (33.11" x 46.81") */
293        public static final MediaSize ISO_A0 =
294                new MediaSize("ISO_A0", "android", R.string.mediasize_iso_a0, 33110, 46810);
295        /** ISO A1 media size: 594mm x 841mm (23.39" x 33.11") */
296        public static final MediaSize ISO_A1 =
297                new MediaSize("ISO_A1", "android", R.string.mediasize_iso_a1, 23390, 33110);
298        /** ISO A2 media size: 420mm x 594mm (16.54" x 23.39") */
299        public static final MediaSize ISO_A2 =
300                new MediaSize("ISO_A2", "android", R.string.mediasize_iso_a2, 16540, 23390);
301        /** ISO A3 media size: 297mm x 420mm (11.69" x 16.54") */
302        public static final MediaSize ISO_A3 =
303                new MediaSize("ISO_A3", "android", R.string.mediasize_iso_a3, 11690, 16540);
304        /** ISO A4 media size: 210mm x 297mm (8.27" x 11.69") */
305        public static final MediaSize ISO_A4 =
306                new MediaSize("ISO_A4", "android", R.string.mediasize_iso_a4, 8270, 11690);
307        /** ISO A5 media size: 148mm x 210mm (5.83" x 8.27") */
308        public static final MediaSize ISO_A5 =
309                new MediaSize("ISO_A5", "android", R.string.mediasize_iso_a5, 5830, 8270);
310        /** ISO A6 media size: 105mm x 148mm (4.13" x 5.83") */
311        public static final MediaSize ISO_A6 =
312                new MediaSize("ISO_A6", "android", R.string.mediasize_iso_a6, 4130, 5830);
313        /** ISO A7 media size: 74mm x 105mm (2.91" x 4.13") */
314        public static final MediaSize ISO_A7 =
315                new MediaSize("ISO_A7", "android", R.string.mediasize_iso_a7, 2910, 4130);
316        /** ISO A8 media size: 52mm x 74mm (2.05" x 2.91") */
317        public static final MediaSize ISO_A8 =
318                new MediaSize("ISO_A8", "android", R.string.mediasize_iso_a8, 2050, 2910);
319        /** ISO A9 media size: 37mm x 52mm (1.46" x 2.05") */
320        public static final MediaSize ISO_A9 =
321                new MediaSize("ISO_A9", "android", R.string.mediasize_iso_a9, 1460, 2050);
322        /** ISO A10 media size: 26mm x 37mm (1.02" x 1.46") */
323        public static final MediaSize ISO_A10 =
324                new MediaSize("ISO_A10", "android", R.string.mediasize_iso_a10, 1020, 1460);
325
326        /** ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67") */
327        public static final MediaSize ISO_B0 =
328                new MediaSize("ISO_B0", "android", R.string.mediasize_iso_b0, 39370, 55670);
329        /** ISO B1 media size: 707mm x 1000mm (27.83" x 39.37") */
330        public static final MediaSize ISO_B1 =
331                new MediaSize("ISO_B1", "android", R.string.mediasize_iso_b1, 27830, 39370);
332        /** ISO B2 media size: 500mm x 707mm (19.69" x 27.83") */
333        public static final MediaSize ISO_B2 =
334                new MediaSize("ISO_B2", "android", R.string.mediasize_iso_b2, 19690, 27830);
335        /** ISO B3 media size: 353mm x 500mm (13.90" x 19.69") */
336        public static final MediaSize ISO_B3 =
337                new MediaSize("ISO_B3", "android", R.string.mediasize_iso_b3, 13900, 19690);
338        /** ISO B4 media size: 250mm x 353mm (9.84" x 13.90") */
339        public static final MediaSize ISO_B4 =
340                new MediaSize("ISO_B4", "android", R.string.mediasize_iso_b4, 9840, 13900);
341        /** ISO B5 media size: 176mm x 250mm (6.93" x 9.84") */
342        public static final MediaSize ISO_B5 =
343                new MediaSize("ISO_B5", "android", R.string.mediasize_iso_b5, 6930, 9840);
344        /** ISO B6 media size: 125mm x 176mm (4.92" x 6.93") */
345        public static final MediaSize ISO_B6 =
346                new MediaSize("ISO_B6", "android", R.string.mediasize_iso_b6, 4920, 6930);
347        /** ISO B7 media size: 88mm x 125mm (3.46" x 4.92") */
348        public static final MediaSize ISO_B7 =
349                new MediaSize("ISO_B7", "android", R.string.mediasize_iso_b7, 3460, 4920);
350        /** ISO B8 media size: 62mm x 88mm (2.44" x 3.46") */
351        public static final MediaSize ISO_B8 =
352                new MediaSize("ISO_B8", "android", R.string.mediasize_iso_b8, 2440, 3460);
353        /** ISO B9 media size: 44mm x 62mm (1.73" x 2.44") */
354        public static final MediaSize ISO_B9 =
355                new MediaSize("ISO_B9", "android", R.string.mediasize_iso_b9, 1730, 2440);
356        /** ISO B10 media size: 31mm x 44mm (1.22" x 1.73") */
357        public static final MediaSize ISO_B10 =
358                new MediaSize("ISO_B10", "android", R.string.mediasize_iso_b10, 1220, 1730);
359
360        /** ISO C0 media size: 917mm x 1297mm (36.10" x 51.06") */
361        public static final MediaSize ISO_C0 =
362                new MediaSize("ISO_C0", "android", R.string.mediasize_iso_c0, 36100, 51060);
363        /** ISO C1 media size: 648mm x 917mm (25.51" x 36.10") */
364        public static final MediaSize ISO_C1 =
365                new MediaSize("ISO_C1", "android", R.string.mediasize_iso_c1, 25510, 36100);
366        /** ISO C2 media size: 458mm x 648mm (18.03" x 25.51") */
367        public static final MediaSize ISO_C2 =
368                new MediaSize("ISO_C2", "android", R.string.mediasize_iso_c2, 18030, 25510);
369        /** ISO C3 media size: 324mm x 458mm (12.76" x 18.03") */
370        public static final MediaSize ISO_C3 =
371                new MediaSize("ISO_C3", "android", R.string.mediasize_iso_c3, 12760, 18030);
372        /** ISO C4 media size: 229mm x 324mm (9.02" x 12.76") */
373        public static final MediaSize ISO_C4 =
374                new MediaSize("ISO_C4", "android", R.string.mediasize_iso_c4, 9020, 12760);
375        /** ISO C5 media size: 162mm x 229mm (6.38" x 9.02") */
376        public static final MediaSize ISO_C5 =
377                new MediaSize("ISO_C5", "android", R.string.mediasize_iso_c5, 6380, 9020);
378        /** ISO C6 media size: 114mm x 162mm (4.49" x 6.38") */
379        public static final MediaSize ISO_C6 =
380                new MediaSize("ISO_C6", "android", R.string.mediasize_iso_c6, 4490, 6380);
381        /** ISO C7 media size: 81mm x 114mm (3.19" x 4.49") */
382        public static final MediaSize ISO_C7 =
383                new MediaSize("ISO_C7", "android", R.string.mediasize_iso_c7, 3190, 4490);
384        /** ISO C8 media size: 57mm x 81mm (2.24" x 3.19") */
385        public static final MediaSize ISO_C8 =
386                new MediaSize("ISO_C8", "android", R.string.mediasize_iso_c8, 2240, 3190);
387        /** ISO C9 media size: 40mm x 57mm (1.57" x 2.24") */
388        public static final MediaSize ISO_C9 =
389                new MediaSize("ISO_C9", "android", R.string.mediasize_iso_c9, 1570, 2240);
390        /** ISO C10 media size: 28mm x 40mm (1.10" x 1.57") */
391        public static final MediaSize ISO_C10 =
392                new MediaSize("ISO_C10", "android", R.string.mediasize_iso_c10, 1100, 1570);
393
394        // North America
395
396        /** North America Letter media size: 8.5" x 11" (279mm x 216mm) */
397        public static final MediaSize NA_LETTER =
398                new MediaSize("NA_LETTER", "android", R.string.mediasize_na_letter, 8500, 11000);
399        /** North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm) */
400        public static final MediaSize NA_GOVT_LETTER =
401                new MediaSize("NA_GOVT_LETTER", "android",
402                        R.string.mediasize_na_gvrnmt_letter, 8000, 10500);
403        /** North America Legal media size: 8.5" x 14" (216mm x 356mm) */
404        public static final MediaSize NA_LEGAL =
405                new MediaSize("NA_LEGAL", "android", R.string.mediasize_na_legal, 8500, 14000);
406        /** North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm) */
407        public static final MediaSize NA_JUNIOR_LEGAL =
408                new MediaSize("NA_JUNIOR_LEGAL", "android",
409                        R.string.mediasize_na_junior_legal, 8000, 5000);
410        /** North America Ledger media size: 17" x 11" (432mm × 279mm) */
411        public static final MediaSize NA_LEDGER =
412                new MediaSize("NA_LEDGER", "android", R.string.mediasize_na_ledger, 17000, 11000);
413        /** North America Tabloid media size: 11" x 17" (279mm × 432mm) */
414        public static final MediaSize NA_TABLOID =
415                new MediaSize("NA_TABLOID", "android",
416                        R.string.mediasize_na_tabloid, 11000, 17000);
417        /** North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm) */
418        public static final MediaSize NA_INDEX_3X5 =
419                new MediaSize("NA_INDEX_3X5", "android",
420                        R.string.mediasize_na_index_3x5, 3000, 5000);
421        /** North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm) */
422        public static final MediaSize NA_INDEX_4X6 =
423                new MediaSize("NA_INDEX_4X6", "android",
424                        R.string.mediasize_na_index_4x6, 4000, 6000);
425        /** North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm) */
426        public static final MediaSize NA_INDEX_5X8 =
427                new MediaSize("NA_INDEX_5X8", "android",
428                        R.string.mediasize_na_index_5x8, 5000, 8000);
429        /** North America Monarch media size: 7.25" x 10.5" (184mm x 267mm) */
430        public static final MediaSize NA_MONARCH =
431                new MediaSize("NA_MONARCH", "android",
432                        R.string.mediasize_na_monarch, 7250, 10500);
433        /** North America Quarto media size: 8" x 10" (203mm x 254mm) */
434        public static final MediaSize NA_QUARTO =
435                new MediaSize("NA_QUARTO", "android",
436                        R.string.mediasize_na_quarto, 8000, 10000);
437        /** North America Foolscap media size: 8" x 13" (203mm x 330mm) */
438        public static final MediaSize NA_FOOLSCAP =
439                new MediaSize("NA_FOOLSCAP", "android",
440                        R.string.mediasize_na_foolscap, 8000, 13000);
441
442        // Chinese
443
444        /** Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543") */
445        public static final MediaSize ROC_8K =
446                new MediaSize("ROC_8K", "android",
447                        R.string.mediasize_chinese_roc_8k, 10629, 15354);
448        /** Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629") */
449        public static final MediaSize ROC_16K =
450                new MediaSize("ROC_16K", "android",
451                        R.string.mediasize_chinese_roc_16k, 7677, 10629);
452
453        /** Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496") */
454        public static final MediaSize PRC_1 =
455                new MediaSize("PRC_1", "android",
456                        R.string.mediasize_chinese_prc_1, 4015, 6496);
457        /** Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929") */
458        public static final MediaSize PRC_2 =
459                new MediaSize("PRC_2", "android",
460                        R.string.mediasize_chinese_prc_2, 4015, 6929);
461        /** Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929") */
462        public static final MediaSize PRC_3 =
463                new MediaSize("PRC_3", "android",
464                        R.string.mediasize_chinese_prc_3, 4921, 6929);
465        /** Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189") */
466        public static final MediaSize PRC_4 =
467                new MediaSize("PRC_4", "android",
468                        R.string.mediasize_chinese_prc_4, 4330, 8189);
469        /** Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661") */
470        public static final MediaSize PRC_5 =
471                new MediaSize("PRC_5", "android",
472                        R.string.mediasize_chinese_prc_5, 4330, 8661);
473        /** Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599") */
474        public static final MediaSize PRC_6 =
475                new MediaSize("PRC_6", "android",
476                        R.string.mediasize_chinese_prc_6, 4724, 12599);
477        /** Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055") */
478        public static final MediaSize PRC_7 =
479                new MediaSize("PRC_7", "android",
480                        R.string.mediasize_chinese_prc_7, 6299, 9055);
481        /** Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165") */
482        public static final MediaSize PRC_8 =
483                new MediaSize("PRC_8", "android",
484                        R.string.mediasize_chinese_prc_8, 4724, 12165);
485        /** Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756") */
486        public static final MediaSize PRC_9 =
487                new MediaSize("PRC_9", "android",
488                        R.string.mediasize_chinese_prc_9, 9016, 12756);
489        /** Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032") */
490        public static final MediaSize PRC_10 =
491                new MediaSize("PRC_10", "android",
492                        R.string.mediasize_chinese_prc_10, 12756, 18032);
493
494        /** Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465") */
495        public static final MediaSize PRC_16k =
496                new MediaSize("PRC_16k", "android",
497                        R.string.mediasize_chinese_prc_16k, 5749, 8465);
498        /** Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315") */
499        public static final MediaSize OM_PA_KAI =
500                new MediaSize("OM_PA_KAI", "android",
501                        R.string.mediasize_chinese_om_pa_kai, 10512, 15315);
502        /** Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551") */
503        public static final MediaSize OM_DAI_PA_KAI =
504                new MediaSize("OM_DAI_PA_KAI", "android",
505                        R.string.mediasize_chinese_om_dai_pa_kai, 10827, 15551);
506        /** Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827") */
507        public static final MediaSize OM_JUURO_KU_KAI =
508                new MediaSize("OM_JUURO_KU_KAI", "android",
509                        R.string.mediasize_chinese_om_jurro_ku_kai, 7796, 10827);
510
511        // Japanese
512
513        /** Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772") */
514        public static final MediaSize JIS_B10 =
515                new MediaSize("JIS_B10", "android",
516                        R.string.mediasize_japanese_jis_b10, 1259, 1772);
517        /** Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52") */
518        public static final MediaSize JIS_B9 =
519                new MediaSize("JIS_B9", "android",
520                        R.string.mediasize_japanese_jis_b9, 1772, 2520);
521        /** Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583") */
522        public static final MediaSize JIS_B8 =
523                new MediaSize("JIS_B8", "android",
524                        R.string.mediasize_japanese_jis_b8, 2520, 3583);
525        /** Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049") */
526        public static final MediaSize JIS_B7 =
527                new MediaSize("JIS_B7", "android",
528                        R.string.mediasize_japanese_jis_b7, 3583, 5049);
529        /** Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165") */
530        public static final MediaSize JIS_B6 =
531                new MediaSize("JIS_B6", "android",
532                        R.string.mediasize_japanese_jis_b6, 5049, 7165);
533        /** Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118") */
534        public static final MediaSize JIS_B5 =
535                new MediaSize("JIS_B5", "android",
536                        R.string.mediasize_japanese_jis_b5, 7165, 10118);
537        /** Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331") */
538        public static final MediaSize JIS_B4 =
539                new MediaSize("JIS_B4", "android",
540                        R.string.mediasize_japanese_jis_b4, 10118, 14331);
541        /** Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276") */
542        public static final MediaSize JIS_B3 =
543                new MediaSize("JIS_B3", "android",
544                        R.string.mediasize_japanese_jis_b3, 14331, 20276);
545        /** Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661") */
546        public static final MediaSize JIS_B2 =
547                new MediaSize("JIS_B2", "android",
548                        R.string.mediasize_japanese_jis_b2, 20276, 28661);
549        /** Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551") */
550        public static final MediaSize JIS_B1 =
551                new MediaSize("JIS_B1", "android",
552                        R.string.mediasize_japanese_jis_b1, 28661, 40551);
553        /** Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323") */
554        public static final MediaSize JIS_B0 =
555                new MediaSize("JIS_B0", "android",
556                        R.string.mediasize_japanese_jis_b0, 40551, 57323);
557
558        /** Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992") */
559        public static final MediaSize JIS_EXEC =
560                new MediaSize("JIS_EXEC", "android",
561                        R.string.mediasize_japanese_jis_exec, 8504, 12992);
562
563        /** Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071") */
564        public static final MediaSize JPN_CHOU4 =
565                new MediaSize("JPN_CHOU4", "android",
566                        R.string.mediasize_japanese_chou4, 3543, 8071);
567        /** Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252") */
568        public static final MediaSize JPN_CHOU3 =
569                new MediaSize("JPN_CHOU3", "android",
570                        R.string.mediasize_japanese_chou3, 4724, 9252);
571        /** Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748") */
572        public static final MediaSize JPN_CHOU2 =
573                new MediaSize("JPN_CHOU2", "android",
574                        R.string.mediasize_japanese_chou2, 4374, 5748);
575
576        /** Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827") */
577        public static final MediaSize JPN_HAGAKI =
578                new MediaSize("JPN_HAGAKI", "android",
579                        R.string.mediasize_japanese_hagaki, 3937, 5827);
580        /** Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874") */
581        public static final MediaSize JPN_OUFUKU =
582                new MediaSize("JPN_OUFUKU", "android",
583                        R.string.mediasize_japanese_oufuku, 5827, 7874);
584
585        /** Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681") */
586        public static final MediaSize JPN_KAHU =
587                new MediaSize("JPN_KAHU", "android",
588                        R.string.mediasize_japanese_kahu, 9449, 12681);
589        /** Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071") */
590        public static final MediaSize JPN_KAKU2 =
591                new MediaSize("JPN_KAKU2", "android",
592                        R.string.mediasize_japanese_kaku2, 9449, 13071);
593
594        /** Japanese You4 media size: 105mm x 235mm (4.134" x 9.252") */
595        public static final MediaSize JPN_YOU4 =
596                new MediaSize("JPN_YOU4", "android",
597                        R.string.mediasize_japanese_you4, 4134, 9252);
598
599        private final String mId;
600        /**@hide */
601        public final String mLabel;
602        /**@hide */
603        public final String mPackageName;
604        /**@hide */
605        public final int mLabelResId;
606        private final int mWidthMils;
607        private final int mHeightMils;
608
609        /**
610         * Creates a new instance. This is the preferred constructor since
611         * it enables the media size label to be shown in a localized fashion
612         * on a locale change.
613         *
614         * @param id The unique media size id.
615         * @param packageName The name of the creating package.
616         * @param labelResId The resource if of a human readable label.
617         * @param widthMils The width in mils (thousands of an inch).
618         * @param heightMils The height in mils (thousands of an inch).
619         *
620         * @throws IllegalArgumentException If the id is empty.
621         * @throws IllegalArgumentException If the label is empty.
622         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
623         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
624         *
625         * @hide
626         */
627        public MediaSize(String id, String packageName, int labelResId,
628                int widthMils, int heightMils) {
629            if (TextUtils.isEmpty(id)) {
630                throw new IllegalArgumentException("id cannot be empty.");
631            }
632            if (TextUtils.isEmpty(packageName)) {
633                throw new IllegalArgumentException("packageName cannot be empty.");
634            }
635            if (labelResId <= 0) {
636                throw new IllegalArgumentException("labelResId must be greater than zero.");
637            }
638            if (widthMils <= 0) {
639                throw new IllegalArgumentException("widthMils "
640                        + "cannot be less than or equal to zero.");
641            }
642            if (heightMils <= 0) {
643                throw new IllegalArgumentException("heightMils "
644                       + "cannot be less than or euqual to zero.");
645            }
646            mPackageName = packageName;
647            mId = id;
648            mLabelResId = labelResId;
649            mWidthMils = widthMils;
650            mHeightMils = heightMils;
651            mLabel = null;
652        }
653
654        /**
655         * Creates a new instance.
656         *
657         * @param id The unique media size id.
658         * @param label The <strong>internationalized</strong> human readable label.
659         * @param widthMils The width in mils (thousands of an inch).
660         * @param heightMils The height in mils (thousands of an inch).
661         *
662         * @throws IllegalArgumentException If the id is empty.
663         * @throws IllegalArgumentException If the label is empty.
664         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
665         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
666         */
667        public MediaSize(String id, String label, int widthMils, int heightMils) {
668            if (TextUtils.isEmpty(id)) {
669                throw new IllegalArgumentException("id cannot be empty.");
670            }
671            if (TextUtils.isEmpty(label)) {
672                throw new IllegalArgumentException("label cannot be empty.");
673            }
674            if (widthMils <= 0) {
675                throw new IllegalArgumentException("widthMils "
676                        + "cannot be less than or equal to zero.");
677            }
678            if (heightMils <= 0) {
679                throw new IllegalArgumentException("heightMils "
680                       + "cannot be less than or euqual to zero.");
681            }
682            mId = id;
683            mLabel = label;
684            mWidthMils = widthMils;
685            mHeightMils = heightMils;
686            mLabelResId = 0;
687            mPackageName = null;
688        }
689
690        /** @hide */
691        public MediaSize(String id, String label, String packageName,
692                int widthMils, int heightMils, int labelResId) {
693            mPackageName = packageName;
694            mId = id;
695            mLabelResId = labelResId;
696            mWidthMils = widthMils;
697            mHeightMils = heightMils;
698            mLabel = label;
699        }
700
701        /**
702         * Gets the unique media size id.
703         *
704         * @return The unique media size id.
705         */
706        public String getId() {
707            return mId;
708        }
709
710        /**
711         * Gets the human readable media size label.
712         *
713         * @param packageManager The package manager for loading the label.
714         * @return The human readable label.
715         */
716        public String getLabel(PackageManager packageManager) {
717            if (!TextUtils.isEmpty(mPackageName) && mLabelResId > 0) {
718                try {
719                    return packageManager.getResourcesForApplication(
720                            mPackageName).getString(mLabelResId);
721                } catch (NotFoundException nfe) {
722                    Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
723                            + " from package " + mPackageName);
724                } catch (NameNotFoundException nnfee) {
725                    Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
726                            + " from package " + mPackageName);
727                }
728            }
729            return mLabel;
730        }
731
732        /**
733         * Gets the media width in mils (thousands of an inch).
734         *
735         * @return The media width.
736         */
737        public int getWidthMils() {
738            return mWidthMils;
739        }
740
741        /**
742         * Gets the media height in mils (thousands of an inch).
743         *
744         * @return The media height.
745         */
746        public int getHeightMils() {
747            return mHeightMils;
748        }
749
750        /**
751         * Gets whether this media size is in portrait which is the
752         * height is greater or equal to the width.
753         *
754         * @return True if the media size is in portrait, false if
755         * it is in landscape.
756         */
757        public boolean isPortrait() {
758            return mHeightMils >= mWidthMils;
759        }
760
761        /**
762         * Returns a new media size in a portrait orientation
763         * which is the height is the greater dimension.
764         *
765         * @return New instance in landscape orientation.
766         */
767        public MediaSize asPortrait() {
768            return new MediaSize(mId, mLabel, mPackageName,
769                    Math.min(mWidthMils, mHeightMils),
770                    Math.max(mWidthMils, mHeightMils),
771                    mLabelResId);
772        }
773
774        /**
775         * Returns a new media size in a landscape orientation
776         * which is the height is the lesser dimension.
777         *
778         * @return New instance in landscape orientation.
779         */
780        public MediaSize asLandscape() {
781            return new MediaSize(mId, mLabel, mPackageName,
782                    Math.max(mWidthMils, mHeightMils),
783                    Math.min(mWidthMils, mHeightMils),
784                    mLabelResId);
785        }
786
787        void writeToParcel(Parcel parcel) {
788            parcel.writeString(mId);
789            parcel.writeString(mLabel);
790            parcel.writeString(mPackageName);
791            parcel.writeInt(mWidthMils);
792            parcel.writeInt(mHeightMils);
793            parcel.writeInt(mLabelResId);
794        }
795
796        static MediaSize createFromParcel(Parcel parcel) {
797            return new MediaSize(
798                    parcel.readString(),
799                    parcel.readString(),
800                    parcel.readString(),
801                    parcel.readInt(),
802                    parcel.readInt(),
803                    parcel.readInt());
804        }
805
806        @Override
807        public int hashCode() {
808            final int prime = 31;
809            int result = 1;
810            result = prime * result + mWidthMils;
811            result = prime * result + mHeightMils;
812            return result;
813        }
814
815        @Override
816        public boolean equals(Object obj) {
817            if (this == obj) {
818                return true;
819            }
820            if (obj == null) {
821                return false;
822            }
823            if (getClass() != obj.getClass()) {
824                return false;
825            }
826            MediaSize other = (MediaSize) obj;
827            if (mWidthMils != other.mWidthMils) {
828                return false;
829            }
830            if (mHeightMils != other.mHeightMils) {
831                return false;
832            }
833            return true;
834        }
835
836        @Override
837        public String toString() {
838            StringBuilder builder = new StringBuilder();
839            builder.append("MediaSize{");
840            builder.append("id: ").append(mId);
841            builder.append(", label: ").append(mLabel);
842            builder.append(", packageName: ").append(mPackageName);
843            builder.append(", heightMils: ").append(mHeightMils);
844            builder.append(", widthMils: ").append(mWidthMils);
845            builder.append(", labelResId: ").append(mLabelResId);
846            builder.append("}");
847            return builder.toString();
848        }
849    }
850
851    /**
852     * This class specifies a supported resolution in dpi (dots per inch).
853     */
854    public static final class Resolution {
855        private final String mId;
856        private final String mLabel;
857        private final int mHorizontalDpi;
858        private final int mVerticalDpi;
859
860        /**
861         * Creates a new instance.
862         *
863         * @param id The unique resolution id.
864         * @param label The <strong>internationalized</strong> human readable label.
865         * @param horizontalDpi The horizontal resolution in dpi.
866         * @param verticalDpi The vertical resolution in dpi.
867         *
868         * @throws IllegalArgumentException If the id is empty.
869         * @throws IllegalArgumentException If the label is empty.
870         * @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
871         * @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
872         */
873        public Resolution(String id, String label, int horizontalDpi, int verticalDpi) {
874            if (TextUtils.isEmpty(id)) {
875                throw new IllegalArgumentException("id cannot be empty.");
876            }
877            if (TextUtils.isEmpty(label)) {
878                throw new IllegalArgumentException("label cannot be empty.");
879            }
880            if (horizontalDpi <= 0) {
881                throw new IllegalArgumentException("horizontalDpi "
882                        + "cannot be less than or equal to zero.");
883            }
884            if (verticalDpi <= 0) {
885                throw new IllegalArgumentException("verticalDpi"
886                       + " cannot be less than or equal to zero.");
887            }
888            mId = id;
889            mLabel = label;
890            mHorizontalDpi = horizontalDpi;
891            mVerticalDpi = verticalDpi;
892        }
893
894        /**
895         * Gets the unique resolution id.
896         *
897         * @return The unique resolution id.
898         */
899        public String getId() {
900            return mId;
901        }
902
903        /**
904         * Gets the resolution human readable label.
905         *
906         * @return The human readable label.
907         */
908        public String getLabel() {
909            return mLabel;
910        }
911
912        /**
913         * Gets the vertical resolution in dpi.
914         *
915         * @return The horizontal resolution.
916         */
917        public int getHorizontalDpi() {
918            return mHorizontalDpi;
919        }
920
921        /**
922         * Gets the vertical resolution in dpi.
923         *
924         * @return The vertical resolution.
925         */
926        public int getVerticalDpi() {
927            return mVerticalDpi;
928        }
929
930        void writeToParcel(Parcel parcel) {
931            parcel.writeString(mId);
932            parcel.writeString(mLabel);
933            parcel.writeInt(mHorizontalDpi);
934            parcel.writeInt(mVerticalDpi);
935        }
936
937        static Resolution createFromParcel(Parcel parcel) {
938            return new Resolution(
939                    parcel.readString(),
940                    parcel.readString(),
941                    parcel.readInt(),
942                    parcel.readInt());
943        }
944
945        @Override
946        public int hashCode() {
947            final int prime = 31;
948            int result = 1;
949            result = prime * result + mHorizontalDpi;
950            result = prime * result + mVerticalDpi;
951            return result;
952        }
953
954        @Override
955        public boolean equals(Object obj) {
956            if (this == obj) {
957                return true;
958            }
959            if (obj == null) {
960                return false;
961            }
962            if (getClass() != obj.getClass()) {
963                return false;
964            }
965            Resolution other = (Resolution) obj;
966            if (mHorizontalDpi != other.mHorizontalDpi) {
967                return false;
968            }
969            if (mVerticalDpi != other.mVerticalDpi) {
970                return false;
971            }
972            return true;
973        }
974
975        @Override
976        public String toString() {
977            StringBuilder builder = new StringBuilder();
978            builder.append("Resolution{");
979            builder.append("id: ").append(mId);
980            builder.append(", label: ").append(mLabel);
981            builder.append(", horizontalDpi: ").append(mHorizontalDpi);
982            builder.append(", verticalDpi: ").append(mVerticalDpi);
983            builder.append("}");
984            return builder.toString();
985        }
986    }
987
988    /**
989     * This class specifies content margins.
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