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