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