1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/cloud_devices/common/printer_description.h" 6 7 #include <algorithm> 8 9 #include "base/json/json_reader.h" 10 #include "base/json/json_writer.h" 11 #include "base/strings/string_util.h" 12 #include "base/values.h" 13 #include "components/cloud_devices/common/cloud_device_description_consts.h" 14 #include "components/cloud_devices/common/description_items_inl.h" 15 16 namespace cloud_devices { 17 18 namespace printer { 19 20 namespace { 21 22 const int32 kMaxPageNumber = 1000000; 23 24 const char kSectionPrint[] = "print"; 25 const char kSectionPrinter[] = "printer"; 26 27 const char kCustomName[] = "custom_display_name"; 28 const char kKeyContentType[] = "content_type"; 29 const char kKeyName[] = "name"; 30 const char kKeyType[] = "type"; 31 const char kKeyVendorId[] = "vendor_id"; 32 33 // extern is required to be used in templates. 34 extern const char kOptionCollate[] = "collate"; 35 extern const char kOptionColor[] = "color"; 36 extern const char kOptionContentType[] = "supported_content_type"; 37 extern const char kOptionCopies[] = "copies"; 38 extern const char kOptionDpi[] = "dpi"; 39 extern const char kOptionDuplex[] = "duplex"; 40 extern const char kOptionFitToPage[] = "fit_to_page"; 41 extern const char kOptionMargins[] = "margins"; 42 extern const char kOptionMediaSize[] = "media_size"; 43 extern const char kOptionPageOrientation[] = "page_orientation"; 44 extern const char kOptionPageRange[] = "page_range"; 45 extern const char kOptionReverse[] = "reverse_order"; 46 extern const char kOptionPwgRasterConfig[] = "pwg_raster_config"; 47 48 const char kMargineBottom[] = "bottom_microns"; 49 const char kMargineLeft[] = "left_microns"; 50 const char kMargineRight[] = "right_microns"; 51 const char kMargineTop[] = "top_microns"; 52 53 const char kDpiHorizontal[] = "horizontal_dpi"; 54 const char kDpiVertical[] = "vertical_dpi"; 55 56 const char kMediaWidth[] = "width_microns"; 57 const char kMediaHeight[] = "height_microns"; 58 const char kMediaIsContinuous[] = "is_continuous_feed"; 59 60 const char kPageRangeInterval[] = "interval"; 61 const char kPageRangeEnd[] = "end"; 62 const char kPageRangeStart[] = "start"; 63 64 const char kPwgRasterDocumentSheetBack[] = "document_sheet_back"; 65 const char kPwgRasterReverseOrderStreaming[] = "reverse_order_streaming"; 66 const char kPwgRasterRotateAllPages[] = "rotate_all_pages"; 67 68 const char kTypeColorColor[] = "STANDARD_COLOR"; 69 const char kTypeColorMonochrome[] = "STANDARD_MONOCHROME"; 70 const char kTypeColorCustomColor[] = "CUSTOM_COLOR"; 71 const char kTypeColorCustomMonochrome[] = "CUSTOM_MONOCHROME"; 72 const char kTypeColorAuto[] = "AUTO"; 73 74 const char kTypeDuplexLongEdge[] = "LONG_EDGE"; 75 const char kTypeDuplexNoDuplex[] = "NO_DUPLEX"; 76 const char kTypeDuplexShortEdge[] = "SHORT_EDGE"; 77 78 const char kTypeFitToPageFillPage[] = "FILL_PAGE"; 79 const char kTypeFitToPageFitToPage[] = "FIT_TO_PAGE"; 80 const char kTypeFitToPageGrowToPage[] = "GROW_TO_PAGE"; 81 const char kTypeFitToPageNoFitting[] = "NO_FITTING"; 82 const char kTypeFitToPageShrinkToPage[] = "SHRINK_TO_PAGE"; 83 84 const char kTypeMarginsBorderless[] = "BORDERLESS"; 85 const char kTypeMarginsCustom[] = "CUSTOM"; 86 const char kTypeMarginsStandard[] = "STANDARD"; 87 const char kTypeOrientationAuto[] = "AUTO"; 88 89 const char kTypeOrientationLandscape[] = "LANDSCAPE"; 90 const char kTypeOrientationPortrait[] = "PORTRAIT"; 91 92 const char kTypeDocumentSheetBackNormal[] = "NORMAL"; 93 const char kTypeDocumentSheetBackRotated[] = "ROTATED"; 94 const char kTypeDocumentSheetBackManualTumble[] = "MANUAL_TUMBLE"; 95 const char kTypeDocumentSheetBackFlipped[] = "FLIPPED"; 96 97 const struct ColorNames { 98 ColorType id; 99 const char* const json_name; 100 } kColorNames[] = { 101 {STANDARD_COLOR, kTypeColorColor}, 102 {STANDARD_MONOCHROME, kTypeColorMonochrome}, 103 {CUSTOM_COLOR, kTypeColorCustomColor}, 104 {CUSTOM_MONOCHROME, kTypeColorCustomMonochrome}, 105 {AUTO_COLOR, kTypeColorAuto}, 106 }; 107 108 const struct DuplexNames { 109 DuplexType id; 110 const char* const json_name; 111 } kDuplexNames[] = { 112 {NO_DUPLEX, kTypeDuplexNoDuplex}, 113 {LONG_EDGE, kTypeDuplexLongEdge}, 114 {SHORT_EDGE, kTypeDuplexShortEdge}, 115 }; 116 117 const struct OrientationNames { 118 OrientationType id; 119 const char* const json_name; 120 } kOrientationNames[] = { 121 {PORTRAIT, kTypeOrientationPortrait}, 122 {LANDSCAPE, kTypeOrientationLandscape}, 123 {AUTO_ORIENTATION, kTypeOrientationAuto}, 124 }; 125 126 const struct MarginsNames { 127 MarginsType id; 128 const char* const json_name; 129 } kMarginsNames[] = { 130 {NO_MARGINS, kTypeMarginsBorderless}, 131 {STANDARD_MARGINS, kTypeMarginsStandard}, 132 {CUSTOM_MARGINS, kTypeMarginsCustom}, 133 }; 134 135 const struct FitToPageNames { 136 FitToPageType id; 137 const char* const json_name; 138 } kFitToPageNames[] = { 139 {NO_FITTING, kTypeFitToPageNoFitting}, 140 {FIT_TO_PAGE, kTypeFitToPageFitToPage}, 141 {GROW_TO_PAGE, kTypeFitToPageGrowToPage}, 142 {SHRINK_TO_PAGE, kTypeFitToPageShrinkToPage}, 143 {FILL_PAGE, kTypeFitToPageFillPage}, 144 }; 145 146 const struct DocumentSheetBackNames { 147 DocumentSheetBack id; 148 const char* const json_name; 149 } kDocumentSheetBackNames[] = { 150 {NORMAL, kTypeDocumentSheetBackNormal}, 151 {ROTATED, kTypeDocumentSheetBackRotated}, 152 {MANUAL_TUMBLE, kTypeDocumentSheetBackManualTumble}, 153 {FLIPPED, kTypeDocumentSheetBackFlipped}}; 154 155 const int32 kInchToUm = 25400; 156 const int32 kMmToUm = 1000; 157 const int32 kSizeTrasholdUm = 1000; 158 159 #define MAP_CLOUD_PRINT_MEDIA_TYPE(type, width, height, unit_um) \ 160 { \ 161 type, #type, static_cast<int>(width* unit_um + 0.5), \ 162 static_cast<int>(height* unit_um + 0.5) \ 163 } 164 165 const struct MediaDefinition { 166 MediaType id; 167 const char* const json_name; 168 int width_um; 169 int height_um; 170 } kMediaDefinitions[] = { 171 {CUSTOM_MEDIA, "CUSTOM", 0, 0}, 172 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_3X5, 3, 5, kInchToUm), 173 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_PERSONAL, 3.625f, 6.5f, kInchToUm), 174 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_MONARCH, 3.875f, 7.5f, kInchToUm), 175 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_9, 3.875f, 8.875f, kInchToUm), 176 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6, 4, 6, kInchToUm), 177 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_10, 4.125f, 9.5f, kInchToUm), 178 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_A2, 4.375f, 5.75f, kInchToUm), 179 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_11, 4.5f, 10.375f, kInchToUm), 180 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_12, 4.75f, 11, kInchToUm), 181 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_5X7, 5, 7, kInchToUm), 182 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_5X8, 5, 8, kInchToUm), 183 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_14, 5, 11.5f, kInchToUm), 184 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INVOICE, 5.5f, 8.5f, kInchToUm), 185 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6_EXT, 6, 8, kInchToUm), 186 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_6X9, 6, 9, kInchToUm), 187 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C5, 6.5f, 9.5f, kInchToUm), 188 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_7X9, 7, 9, kInchToUm), 189 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EXECUTIVE, 7.25f, 10.5f, kInchToUm), 190 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LETTER, 8, 10, kInchToUm), 191 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LEGAL, 8, 13, kInchToUm), 192 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_QUARTO, 8.5f, 10.83f, kInchToUm), 193 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER, 8.5f, 11, kInchToUm), 194 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_EUR, 8.5f, 12, kInchToUm), 195 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_PLUS, 8.5f, 12.69f, kInchToUm), 196 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FOOLSCAP, 8.5f, 13, kInchToUm), 197 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL, 8.5f, 14, kInchToUm), 198 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_A, 8.94f, 14, kInchToUm), 199 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_9X11, 9, 11, kInchToUm), 200 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_A, 9, 12, kInchToUm), 201 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_EXTRA, 9.5f, 12, kInchToUm), 202 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL_EXTRA, 9.5f, 15, kInchToUm), 203 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X11, 10, 11, kInchToUm), 204 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X13, 10, 13, kInchToUm), 205 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X14, 10, 14, kInchToUm), 206 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X15, 10, 15, kInchToUm), 207 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X12, 11, 12, kInchToUm), 208 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EDP, 11, 14, kInchToUm), 209 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_US, 11, 14.875f, kInchToUm), 210 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X15, 11, 15, kInchToUm), 211 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEDGER, 11, 17, kInchToUm), 212 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EUR_EDP, 12, 14, kInchToUm), 213 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_B, 12, 18, kInchToUm), 214 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_12X19, 12, 19, kInchToUm), 215 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_B_PLUS, 12, 19.17f, kInchToUm), 216 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_B, 13, 19, kInchToUm), 217 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C, 17, 22, kInchToUm), 218 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_C, 18, 24, kInchToUm), 219 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_D, 22, 34, kInchToUm), 220 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_D, 24, 36, kInchToUm), 221 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ASME_F, 28, 40, kInchToUm), 222 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_WIDE_FORMAT, 30, 42, kInchToUm), 223 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_E, 34, 44, kInchToUm), 224 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_E, 36, 48, kInchToUm), 225 MAP_CLOUD_PRINT_MEDIA_TYPE(NA_F, 44, 68, kInchToUm), 226 MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_16K, 7.75f, 10.75f, kInchToUm), 227 MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_8K, 10.75f, 15.5f, kInchToUm), 228 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_32K, 97, 151, kMmToUm), 229 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_1, 102, 165, kMmToUm), 230 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_2, 102, 176, kMmToUm), 231 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_4, 110, 208, kMmToUm), 232 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_5, 110, 220, kMmToUm), 233 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_8, 120, 309, kMmToUm), 234 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_6, 120, 230, kMmToUm), 235 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_3, 125, 176, kMmToUm), 236 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_16K, 146, 215, kMmToUm), 237 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_7, 160, 230, kMmToUm), 238 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_JUURO_KU_KAI, 198, 275, kMmToUm), 239 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_PA_KAI, 267, 389, kMmToUm), 240 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_DAI_PA_KAI, 275, 395, kMmToUm), 241 MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_10, 324, 458, kMmToUm), 242 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A10, 26, 37, kMmToUm), 243 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A9, 37, 52, kMmToUm), 244 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A8, 52, 74, kMmToUm), 245 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A7, 74, 105, kMmToUm), 246 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A6, 105, 148, kMmToUm), 247 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5, 148, 210, kMmToUm), 248 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5_EXTRA, 174, 235, kMmToUm), 249 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4, 210, 297, kMmToUm), 250 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_TAB, 225, 297, kMmToUm), 251 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_EXTRA, 235, 322, kMmToUm), 252 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3, 297, 420, kMmToUm), 253 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X3, 297, 630, kMmToUm), 254 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X4, 297, 841, kMmToUm), 255 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X5, 297, 1051, kMmToUm), 256 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X6, 297, 1261, kMmToUm), 257 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X7, 297, 1471, kMmToUm), 258 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X8, 297, 1682, kMmToUm), 259 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X9, 297, 1892, kMmToUm), 260 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3_EXTRA, 322, 445, kMmToUm), 261 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2, 420, 594, kMmToUm), 262 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X3, 420, 891, kMmToUm), 263 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X4, 420, 1189, kMmToUm), 264 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X5, 420, 1486, kMmToUm), 265 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X6, 420, 1783, kMmToUm), 266 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X7, 420, 2080, kMmToUm), 267 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1, 594, 841, kMmToUm), 268 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X3, 594, 1261, kMmToUm), 269 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X4, 594, 1682, kMmToUm), 270 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X5, 594, 2102, kMmToUm), 271 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0, 841, 1189, kMmToUm), 272 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X3, 841, 1783, kMmToUm), 273 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X4, 841, 2378, kMmToUm), 274 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_2A0, 1189, 1682, kMmToUm), 275 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0X3, 1189, 2523, kMmToUm), 276 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B10, 31, 44, kMmToUm), 277 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B9, 44, 62, kMmToUm), 278 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B8, 62, 88, kMmToUm), 279 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B7, 88, 125, kMmToUm), 280 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6, 125, 176, kMmToUm), 281 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6C4, 125, 324, kMmToUm), 282 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5, 176, 250, kMmToUm), 283 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5_EXTRA, 201, 276, kMmToUm), 284 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B4, 250, 353, kMmToUm), 285 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B3, 353, 500, kMmToUm), 286 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B2, 500, 707, kMmToUm), 287 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B1, 707, 1000, kMmToUm), 288 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B0, 1000, 1414, kMmToUm), 289 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C10, 28, 40, kMmToUm), 290 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C9, 40, 57, kMmToUm), 291 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C8, 57, 81, kMmToUm), 292 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7, 81, 114, kMmToUm), 293 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7C6, 81, 162, kMmToUm), 294 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6, 114, 162, kMmToUm), 295 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6C5, 114, 229, kMmToUm), 296 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C5, 162, 229, kMmToUm), 297 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C4, 229, 324, kMmToUm), 298 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C3, 324, 458, kMmToUm), 299 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C2, 458, 648, kMmToUm), 300 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C1, 648, 917, kMmToUm), 301 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C0, 917, 1297, kMmToUm), 302 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_DL, 110, 220, kMmToUm), 303 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA2, 430, 610, kMmToUm), 304 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA2, 450, 640, kMmToUm), 305 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA1, 610, 860, kMmToUm), 306 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA1, 640, 900, kMmToUm), 307 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA0, 860, 1220, kMmToUm), 308 MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA0, 900, 1280, kMmToUm), 309 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B10, 32, 45, kMmToUm), 310 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B9, 45, 64, kMmToUm), 311 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B8, 64, 91, kMmToUm), 312 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B7, 91, 128, kMmToUm), 313 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B6, 128, 182, kMmToUm), 314 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B5, 182, 257, kMmToUm), 315 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B4, 257, 364, kMmToUm), 316 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B3, 364, 515, kMmToUm), 317 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B2, 515, 728, kMmToUm), 318 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B1, 728, 1030, kMmToUm), 319 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B0, 1030, 1456, kMmToUm), 320 MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_EXEC, 216, 330, kMmToUm), 321 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU4, 90, 205, kMmToUm), 322 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_HAGAKI, 100, 148, kMmToUm), 323 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_YOU4, 105, 235, kMmToUm), 324 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU2, 111.1f, 146, kMmToUm), 325 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU3, 120, 235, kMmToUm), 326 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_OUFUKU, 148, 200, kMmToUm), 327 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAHU, 240, 322.1f, kMmToUm), 328 MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAKU2, 240, 332, kMmToUm), 329 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_SMALL_PHOTO, 100, 150, kMmToUm), 330 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_ITALIAN, 110, 230, kMmToUm), 331 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_POSTFIX, 114, 229, kMmToUm), 332 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_LARGE_PHOTO, 200, 300, kMmToUm), 333 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO, 210, 330, kMmToUm), 334 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO_SP, 215, 315, kMmToUm), 335 MAP_CLOUD_PRINT_MEDIA_TYPE(OM_INVITE, 220, 220, kMmToUm)}; 336 #undef MAP_CLOUD_PRINT_MEDIA_TYPE 337 338 const MediaDefinition& FindMediaByType(MediaType type) { 339 for (size_t i = 0; i < arraysize(kMediaDefinitions); ++i) { 340 if (kMediaDefinitions[i].id == type) 341 return kMediaDefinitions[i]; 342 } 343 NOTREACHED(); 344 return kMediaDefinitions[0]; 345 } 346 347 const MediaDefinition* FindMediaBySize(int32 width_um, int32 height_um) { 348 const MediaDefinition* result = NULL; 349 for (size_t i = 0; i < arraysize(kMediaDefinitions); ++i) { 350 int32 diff = std::max(std::abs(width_um - kMediaDefinitions[i].width_um), 351 std::abs(height_um - kMediaDefinitions[i].height_um)); 352 if (diff < kSizeTrasholdUm) 353 result = &kMediaDefinitions[i]; 354 } 355 return result; 356 } 357 358 template <class T, class IdType> 359 std::string TypeToString(const T& names, IdType id) { 360 for (size_t i = 0; i < arraysize(names); ++i) { 361 if (id == names[i].id) 362 return names[i].json_name; 363 } 364 NOTREACHED(); 365 return std::string(); 366 } 367 368 template <class T, class IdType> 369 bool TypeFromString(const T& names, const std::string& type, IdType* id) { 370 for (size_t i = 0; i < arraysize(names); ++i) { 371 if (type == names[i].json_name) { 372 *id = names[i].id; 373 return true; 374 } 375 } 376 return false; 377 } 378 379 } // namespace 380 381 PwgRasterConfig::PwgRasterConfig() 382 : document_sheet_back(ROTATED), 383 reverse_order_streaming(false), 384 rotate_all_pages(false) { 385 } 386 387 Color::Color() : type(AUTO_COLOR) { 388 } 389 390 Color::Color(ColorType type) : type(type) { 391 } 392 393 bool Color::operator==(const Color& other) const { 394 return type == other.type && vendor_id == other.vendor_id && 395 custom_display_name == other.custom_display_name; 396 } 397 398 bool Color::IsValid() const { 399 if (type != CUSTOM_COLOR && type != CUSTOM_MONOCHROME) 400 return true; 401 return !vendor_id.empty() && !custom_display_name.empty(); 402 } 403 404 Margins::Margins() 405 : type(STANDARD_MARGINS), top_um(0), right_um(0), bottom_um(0), left_um(0) { 406 } 407 408 Margins::Margins(MarginsType type, 409 int32 top_um, 410 int32 right_um, 411 int32 bottom_um, 412 int32 left_um) 413 : type(type), 414 top_um(top_um), 415 right_um(right_um), 416 bottom_um(bottom_um), 417 left_um(left_um) { 418 } 419 420 bool Margins::operator==(const Margins& other) const { 421 return type == other.type && top_um == other.top_um && 422 right_um == other.right_um && bottom_um == other.bottom_um; 423 } 424 425 Dpi::Dpi() : horizontal(0), vertical(0) { 426 } 427 428 Dpi::Dpi(int32 horizontal, int32 vertical) 429 : horizontal(horizontal), vertical(vertical) { 430 } 431 432 bool Dpi::IsValid() const { 433 return horizontal > 0 && vertical > 0; 434 } 435 436 bool Dpi::operator==(const Dpi& other) const { 437 return horizontal == other.horizontal && vertical == other.vertical; 438 } 439 440 Media::Media() 441 : type(CUSTOM_MEDIA), width_um(0), height_um(0), is_continuous_feed(false) { 442 } 443 444 Media::Media(MediaType type) 445 : type(type), 446 width_um(0), 447 height_um(0), 448 is_continuous_feed(false) { 449 const MediaDefinition& media = FindMediaByType(type); 450 width_um = media.width_um; 451 height_um = media.height_um; 452 is_continuous_feed = width_um <= 0 || height_um <= 0; 453 } 454 455 Media::Media(MediaType type, int32 width_um, int32 height_um) 456 : type(type), 457 width_um(width_um), 458 height_um(height_um), 459 is_continuous_feed(width_um <= 0 || height_um <= 0) { 460 } 461 462 Media::Media(const std::string& custom_display_name, 463 const std::string& vendor_id, 464 int32 width_um, 465 int32 height_um) 466 : type(CUSTOM_MEDIA), 467 width_um(width_um), 468 height_um(height_um), 469 is_continuous_feed(width_um <= 0 || height_um <= 0), 470 custom_display_name(custom_display_name), 471 vendor_id(vendor_id) { 472 } 473 474 bool Media::MatchBySize() { 475 const MediaDefinition* media = FindMediaBySize(width_um, height_um); 476 if (!media) 477 return false; 478 type = media->id; 479 return true; 480 } 481 482 bool Media::IsValid() const { 483 if (is_continuous_feed) { 484 if (width_um <= 0 && height_um <= 0) 485 return false; 486 } else { 487 if (width_um <= 0 || height_um <= 0) 488 return false; 489 } 490 return true; 491 } 492 493 bool Media::operator==(const Media& other) const { 494 return type == other.type && width_um == other.width_um && 495 height_um == other.height_um && 496 is_continuous_feed == other.is_continuous_feed; 497 } 498 499 Interval::Interval() : start(0), end(0) { 500 } 501 502 Interval::Interval(int32 start, int32 end) : start(start), end(end) { 503 } 504 505 Interval::Interval(int32 start) : start(start), end(kMaxPageNumber) { 506 } 507 508 bool Interval::operator==(const Interval& other) const { 509 return start == other.start && end == other.end; 510 } 511 512 template <const char* kName> 513 class ItemsTraits { 514 public: 515 static std::string GetCapabilityPath() { 516 std::string result = kSectionPrinter; 517 result += '.'; 518 result += kName; 519 return result; 520 } 521 522 static std::string GetTicketItemPath() { 523 std::string result = kSectionPrint; 524 result += '.'; 525 result += kName; 526 return result; 527 } 528 }; 529 530 class NoValueValidation { 531 public: 532 template <class Option> 533 static bool IsValid(const Option&) { 534 return true; 535 } 536 }; 537 538 class ContentTypeTraits : public NoValueValidation, 539 public ItemsTraits<kOptionContentType> { 540 public: 541 static bool Load(const base::DictionaryValue& dict, ContentType* option) { 542 return dict.GetString(kKeyContentType, option); 543 } 544 545 static void Save(ContentType option, base::DictionaryValue* dict) { 546 dict->SetString(kKeyContentType, option); 547 } 548 }; 549 550 class PwgRasterConfigTraits : public NoValueValidation, 551 public ItemsTraits<kOptionPwgRasterConfig> { 552 public: 553 static bool Load(const base::DictionaryValue& dict, PwgRasterConfig* option) { 554 std::string document_sheet_back; 555 PwgRasterConfig option_out; 556 if (dict.GetString(kPwgRasterDocumentSheetBack, &document_sheet_back)) { 557 if (!TypeFromString(kDocumentSheetBackNames, 558 document_sheet_back, 559 &option_out.document_sheet_back)) { 560 return false; 561 } 562 } 563 564 dict.GetBoolean(kPwgRasterReverseOrderStreaming, 565 &option_out.reverse_order_streaming); 566 dict.GetBoolean(kPwgRasterRotateAllPages, &option_out.rotate_all_pages); 567 *option = option_out; 568 return true; 569 } 570 571 static void Save(const PwgRasterConfig& option, base::DictionaryValue* dict) { 572 dict->SetString( 573 kPwgRasterDocumentSheetBack, 574 TypeToString(kDocumentSheetBackNames, option.document_sheet_back)); 575 if (option.reverse_order_streaming) 576 dict->SetBoolean(kPwgRasterReverseOrderStreaming, 577 option.reverse_order_streaming); 578 579 if (option.rotate_all_pages) 580 dict->SetBoolean(kPwgRasterRotateAllPages, option.rotate_all_pages); 581 } 582 }; 583 584 class ColorTraits : public ItemsTraits<kOptionColor> { 585 public: 586 static bool IsValid(const Color& option) { return option.IsValid(); } 587 588 static bool Load(const base::DictionaryValue& dict, Color* option) { 589 std::string type_str; 590 if (!dict.GetString(kKeyType, &type_str)) 591 return false; 592 if (!TypeFromString(kColorNames, type_str, &option->type)) 593 return false; 594 dict.GetString(kKeyVendorId, &option->vendor_id); 595 dict.GetString(kCustomName, &option->custom_display_name); 596 return true; 597 } 598 599 static void Save(const Color& option, base::DictionaryValue* dict) { 600 dict->SetString(kKeyType, TypeToString(kColorNames, option.type)); 601 if (!option.vendor_id.empty()) 602 dict->SetString(kKeyVendorId, option.vendor_id); 603 if (!option.custom_display_name.empty()) 604 dict->SetString(kCustomName, option.custom_display_name); 605 } 606 }; 607 608 class DuplexTraits : public NoValueValidation, 609 public ItemsTraits<kOptionDuplex> { 610 public: 611 static bool Load(const base::DictionaryValue& dict, DuplexType* option) { 612 std::string type_str; 613 return dict.GetString(kKeyType, &type_str) && 614 TypeFromString(kDuplexNames, type_str, option); 615 } 616 617 static void Save(DuplexType option, base::DictionaryValue* dict) { 618 dict->SetString(kKeyType, TypeToString(kDuplexNames, option)); 619 } 620 }; 621 622 class OrientationTraits : public NoValueValidation, 623 public ItemsTraits<kOptionPageOrientation> { 624 public: 625 static bool Load(const base::DictionaryValue& dict, OrientationType* option) { 626 std::string type_str; 627 return dict.GetString(kKeyType, &type_str) && 628 TypeFromString(kOrientationNames, type_str, option); 629 } 630 631 static void Save(OrientationType option, base::DictionaryValue* dict) { 632 dict->SetString(kKeyType, TypeToString(kOrientationNames, option)); 633 } 634 }; 635 636 class CopiesTraits : public ItemsTraits<kOptionCopies> { 637 public: 638 static bool IsValid(int32 option) { return option >= 1; } 639 640 static bool Load(const base::DictionaryValue& dict, int32* option) { 641 return dict.GetInteger(kOptionCopies, option); 642 } 643 644 static void Save(int32 option, base::DictionaryValue* dict) { 645 dict->SetInteger(kOptionCopies, option); 646 } 647 }; 648 649 class MarginsTraits : public NoValueValidation, 650 public ItemsTraits<kOptionMargins> { 651 public: 652 static bool Load(const base::DictionaryValue& dict, Margins* option) { 653 std::string type_str; 654 if (!dict.GetString(kKeyType, &type_str)) 655 return false; 656 if (!TypeFromString(kMarginsNames, type_str, &option->type)) 657 return false; 658 return dict.GetInteger(kMargineTop, &option->top_um) && 659 dict.GetInteger(kMargineRight, &option->right_um) && 660 dict.GetInteger(kMargineBottom, &option->bottom_um) && 661 dict.GetInteger(kMargineLeft, &option->left_um); 662 } 663 664 static void Save(const Margins& option, base::DictionaryValue* dict) { 665 dict->SetString(kKeyType, TypeToString(kMarginsNames, option.type)); 666 dict->SetInteger(kMargineTop, option.top_um); 667 dict->SetInteger(kMargineRight, option.right_um); 668 dict->SetInteger(kMargineBottom, option.bottom_um); 669 dict->SetInteger(kMargineLeft, option.left_um); 670 } 671 }; 672 673 class DpiTraits : public ItemsTraits<kOptionDpi> { 674 public: 675 static bool IsValid(const Dpi& option) { return option.IsValid(); } 676 677 static bool Load(const base::DictionaryValue& dict, Dpi* option) { 678 if (!dict.GetInteger(kDpiHorizontal, &option->horizontal) || 679 !dict.GetInteger(kDpiVertical, &option->vertical)) { 680 return false; 681 } 682 return true; 683 } 684 685 static void Save(const Dpi& option, base::DictionaryValue* dict) { 686 dict->SetInteger(kDpiHorizontal, option.horizontal); 687 dict->SetInteger(kDpiVertical, option.vertical); 688 } 689 }; 690 691 class FitToPageTraits : public NoValueValidation, 692 public ItemsTraits<kOptionFitToPage> { 693 public: 694 static bool Load(const base::DictionaryValue& dict, FitToPageType* option) { 695 std::string type_str; 696 return dict.GetString(kKeyType, &type_str) && 697 TypeFromString(kFitToPageNames, type_str, option); 698 } 699 700 static void Save(FitToPageType option, base::DictionaryValue* dict) { 701 dict->SetString(kKeyType, TypeToString(kFitToPageNames, option)); 702 } 703 }; 704 705 class PageRangeTraits : public ItemsTraits<kOptionPageRange> { 706 public: 707 static bool IsValid(const PageRange& option) { 708 for (size_t i = 0; i < option.size(); ++i) { 709 if (option[i].start < 1 || option[i].end < 1) { 710 return false; 711 } 712 } 713 return true; 714 } 715 716 static bool Load(const base::DictionaryValue& dict, PageRange* option) { 717 const base::ListValue* list = NULL; 718 if (!dict.GetList(kPageRangeInterval, &list)) 719 return false; 720 for (size_t i = 0; i < list->GetSize(); ++i) { 721 const base::DictionaryValue* interval = NULL; 722 if (!list->GetDictionary(i, &interval)) 723 return false; 724 Interval new_interval(1, kMaxPageNumber); 725 interval->GetInteger(kPageRangeStart, &new_interval.start); 726 interval->GetInteger(kPageRangeEnd, &new_interval.end); 727 option->push_back(new_interval); 728 } 729 return true; 730 } 731 732 static void Save(const PageRange& option, base::DictionaryValue* dict) { 733 if (!option.empty()) { 734 base::ListValue* list = new base::ListValue; 735 dict->Set(kPageRangeInterval, list); 736 for (size_t i = 0; i < option.size(); ++i) { 737 base::DictionaryValue* interval = new base::DictionaryValue; 738 list->Append(interval); 739 interval->SetInteger(kPageRangeStart, option[i].start); 740 if (option[i].end < kMaxPageNumber) 741 interval->SetInteger(kPageRangeEnd, option[i].end); 742 } 743 } 744 } 745 }; 746 747 class MediaTraits : public ItemsTraits<kOptionMediaSize> { 748 public: 749 static bool IsValid(const Media& option) { return option.IsValid(); } 750 751 static bool Load(const base::DictionaryValue& dict, Media* option) { 752 std::string type_str; 753 if (dict.GetString(kKeyName, &type_str)) { 754 if (!TypeFromString(kMediaDefinitions, type_str, &option->type)) 755 return false; 756 } 757 758 dict.GetInteger(kMediaWidth, &option->width_um); 759 dict.GetInteger(kMediaHeight, &option->height_um); 760 dict.GetBoolean(kMediaIsContinuous, &option->is_continuous_feed); 761 dict.GetString(kCustomName, &option->custom_display_name); 762 dict.GetString(kKeyVendorId, &option->vendor_id); 763 return true; 764 } 765 766 static void Save(const Media& option, base::DictionaryValue* dict) { 767 if (option.type != CUSTOM_MEDIA) 768 dict->SetString(kKeyName, TypeToString(kMediaDefinitions, option.type)); 769 if (!option.custom_display_name.empty() || option.type == CUSTOM_MEDIA) 770 dict->SetString(kCustomName, option.custom_display_name); 771 if (!option.vendor_id.empty()) 772 dict->SetString(kKeyVendorId, option.vendor_id); 773 if (option.width_um > 0) 774 dict->SetInteger(kMediaWidth, option.width_um); 775 if (option.height_um > 0) 776 dict->SetInteger(kMediaHeight, option.height_um); 777 if (option.is_continuous_feed) 778 dict->SetBoolean(kMediaIsContinuous, true); 779 } 780 }; 781 782 class CollateTraits : public NoValueValidation, 783 public ItemsTraits<kOptionCollate> { 784 public: 785 static const bool kDefault = true; 786 787 static bool Load(const base::DictionaryValue& dict, bool* option) { 788 return dict.GetBoolean(kOptionCollate, option); 789 } 790 791 static void Save(bool option, base::DictionaryValue* dict) { 792 dict->SetBoolean(kOptionCollate, option); 793 } 794 }; 795 796 class ReverseTraits : public NoValueValidation, 797 public ItemsTraits<kOptionReverse> { 798 public: 799 static const bool kDefault = false; 800 801 static bool Load(const base::DictionaryValue& dict, bool* option) { 802 return dict.GetBoolean(kOptionReverse, option); 803 } 804 805 static void Save(bool option, base::DictionaryValue* dict) { 806 dict->SetBoolean(kOptionReverse, option); 807 } 808 }; 809 810 } // namespace printer 811 812 using namespace printer; 813 814 template class ListCapability<ContentType, ContentTypeTraits>; 815 template class ValueCapability<PwgRasterConfig, PwgRasterConfigTraits>; 816 template class SelectionCapability<Color, ColorTraits>; 817 template class SelectionCapability<DuplexType, DuplexTraits>; 818 template class SelectionCapability<OrientationType, OrientationTraits>; 819 template class SelectionCapability<Margins, MarginsTraits>; 820 template class SelectionCapability<Dpi, DpiTraits>; 821 template class SelectionCapability<FitToPageType, FitToPageTraits>; 822 template class SelectionCapability<Media, MediaTraits>; 823 template class EmptyCapability<class CopiesTraits>; 824 template class EmptyCapability<class PageRangeTraits>; 825 template class BooleanCapability<class CollateTraits>; 826 template class BooleanCapability<class ReverseTraits>; 827 828 template class TicketItem<PwgRasterConfig, PwgRasterConfigTraits>; 829 template class TicketItem<Color, ColorTraits>; 830 template class TicketItem<DuplexType, DuplexTraits>; 831 template class TicketItem<OrientationType, OrientationTraits>; 832 template class TicketItem<Margins, MarginsTraits>; 833 template class TicketItem<Dpi, DpiTraits>; 834 template class TicketItem<FitToPageType, FitToPageTraits>; 835 template class TicketItem<Media, MediaTraits>; 836 template class TicketItem<int32, CopiesTraits>; 837 template class TicketItem<PageRange, PageRangeTraits>; 838 template class TicketItem<bool, CollateTraits>; 839 template class TicketItem<bool, ReverseTraits>; 840 841 } // namespace cloud_devices 842