Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: printing/backend/cups_ipp_util.cc

Issue 2105463002: Create a new print backend for the updated CUPS APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Really done Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "printing/backend/cups_ipp_util.h"
6
7 #include <cups/cups.h>
8
9 #include <algorithm>
10 #include <string>
11 #include <vector>
12
13 #include "base/logging.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "printing/backend/cups_printer.h"
20 #include "printing/backend/print_backend_consts.h"
21 #include "printing/units.h"
22
23 namespace printing {
24
25 namespace {
26
27 const char kIppCollate[] = "sheet-collate"; // RFC 3381
28 const char kIppCopies[] = CUPS_COPIES;
29 const char kIppColor[] = CUPS_PRINT_COLOR_MODE;
30 const char kIppMedia[] = CUPS_MEDIA;
31 const char kIppDuplex[] = CUPS_SIDES;
32
33 const char kCollated[] = "collated";
34
35 const int kMicronsPerMM = 1000;
36 const double kMMPerInch = 25.4;
37 const double kMicronsPerInch = kMMPerInch * kMicronsPerMM;
38
39 enum Unit {
40 INCHES,
41 MILLIMETERS,
42 };
43
44 struct ColorMap {
45 const char* color;
46 ColorModel model;
47 };
48
49 const ColorMap kColorList[]{
50 {CUPS_PRINT_COLOR_MODE_COLOR, COLORMODE_COLOR},
51 {CUPS_PRINT_COLOR_MODE_MONOCHROME, COLORMODE_MONOCHROME},
52 };
53
54 ColorModel ColorModelFromIppColor(base::StringPiece ippColor) {
55 for (const ColorMap& color : kColorList) {
56 if (ippColor.compare(color.color) == 0) {
57 return color.model;
58 }
59 }
60
61 return UNKNOWN_COLOR_MODEL;
62 }
63
64 bool PrinterSupportsValue(const CupsOptionProvider& printer,
65 base::StringPiece name,
66 base::StringPiece value) {
67 std::vector<base::StringPiece> values =
68 printer.GetSupportedOptionValueStrings(name);
69 return ContainsValue(values, value);
70 }
71
72 DuplexMode PrinterDefaultDuplex(const CupsOptionProvider& printer) {
73 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppDuplex);
74 if (!attr)
75 return UNKNOWN_DUPLEX_MODE;
76
77 const char* value = ippGetString(attr, 0, nullptr);
78 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_ONE_SIDED))
79 return SIMPLEX;
80
81 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_PORTRAIT))
82 return LONG_EDGE;
83
84 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_LANDSCAPE))
85 return SHORT_EDGE;
86
87 return UNKNOWN_DUPLEX_MODE;
88 }
89
90 gfx::Size DimensionsToMicrons(base::StringPiece value) {
91 Unit unit;
92 base::StringPiece dims;
93 size_t unit_position;
94 if ((unit_position = value.find("mm")) != base::StringPiece::npos) {
95 unit = MILLIMETERS;
96 dims = value.substr(0, unit_position);
97 } else if ((unit_position = value.find("in")) != base::StringPiece::npos) {
98 unit = INCHES;
99 dims = value.substr(0, unit_position);
100 } else {
101 LOG(WARNING) << "Could not parse paper dimensions";
102 return {0, 0};
103 }
104
105 std::vector<std::string> pieces = base::SplitString(
106 dims, "x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
107 double width;
108 double height;
109
110 if (pieces.size() != 2 || !base::StringToDouble(pieces[0], &width) ||
111 !base::StringToDouble(pieces[1], &height)) {
112 return {0, 0};
113 }
114
115 int width_microns;
116 int height_microns;
117
118 switch (unit) {
119 case MILLIMETERS:
120 width_microns = width * kMicronsPerMM;
121 height_microns = height * kMicronsPerMM;
122 break;
123 case INCHES:
124 width_microns = width * kMicronsPerInch;
125 height_microns = height * kMicronsPerInch;
126 break;
127 default:
128 NOTREACHED();
129 break;
130 }
131
132 return gfx::Size{width_microns, height_microns};
133 }
134
135 PrinterSemanticCapsAndDefaults::Paper ParsePaper(base::StringPiece value) {
136 // <name>_<width>x<height>{in,mm}
137 // e.g. na_letter_8.5x11in, iso_a4_210x297mm
138
139 std::vector<base::StringPiece> pieces = base::SplitStringPiece(
140 value, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
141 // we expect at least a display string and a dimension string
142 if (pieces.size() < 2)
143 return PrinterSemanticCapsAndDefaults::Paper();
144
145 base::StringPiece dimensions = pieces.back();
146
147 std::string display = pieces[0].as_string();
148 for (size_t i = 1; i <= pieces.size() - 2; ++i) {
149 display.append(" ");
150 pieces[i].AppendToString(&display);
151 }
152
153 PrinterSemanticCapsAndDefaults::Paper paper;
154 paper.display_name = display;
155 paper.vendor_id = value.as_string();
156 paper.size_um = DimensionsToMicrons(dimensions);
157
158 return paper;
159 }
160
161 void ExtractColor(const CupsOptionProvider& printer,
162 PrinterSemanticCapsAndDefaults* printer_info) {
163 printer_info->bw_model = UNKNOWN_COLOR_MODEL;
164 printer_info->color_model = UNKNOWN_COLOR_MODEL;
165
166 // color and b&w
167 std::vector<ColorModel> color_models = SupportedColorModels(printer);
168 for (ColorModel color : color_models) {
169 switch (color) {
170 case COLORMODE_COLOR:
171 printer_info->color_model = COLORMODE_COLOR;
172 break;
173 case COLORMODE_MONOCHROME:
174 printer_info->bw_model = COLORMODE_MONOCHROME;
175 break;
176 default:
177 // value not needed
178 break;
179 }
180 }
181
182 // changeable
183 printer_info->color_changeable =
184 (printer_info->color_model != UNKNOWN_COLOR_MODEL &&
185 printer_info->bw_model != UNKNOWN_COLOR_MODEL);
186
187 // default color
188 printer_info->color_default = DefaultColorModel(printer) == COLORMODE_COLOR;
189 }
190
191 void ExtractCopies(const CupsOptionProvider& printer,
192 PrinterSemanticCapsAndDefaults* printer_info) {
193 // copies
194 int upper_bound;
195 int lower_bound;
196 CopiesRange(printer, &lower_bound, &upper_bound);
197 printer_info->copies_capable = (lower_bound != -1) && (upper_bound >= 2);
198 }
199
200 } // namespace
201
202 ColorModel DefaultColorModel(const CupsOptionProvider& printer) {
203 // default color
204 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppColor);
205 if (!attr)
206 return UNKNOWN_COLOR_MODEL;
207
208 return ColorModelFromIppColor(ippGetString(attr, 0, nullptr));
209 }
210
211 std::vector<ColorModel> SupportedColorModels(
212 const CupsOptionProvider& printer) {
213 std::vector<ColorModel> colors;
214
215 std::vector<base::StringPiece> color_modes =
216 printer.GetSupportedOptionValueStrings(kIppColor);
217
218 for (base::StringPiece color : color_modes) {
219 ColorModel color_model = ColorModelFromIppColor(color);
220 if (color_model != UNKNOWN_COLOR_MODEL) {
221 colors.push_back(color_model);
222 }
223 }
224
225 return colors;
226 }
227
228 PrinterSemanticCapsAndDefaults::Paper DefaultPaper(
229 const CupsOptionProvider& printer) {
230 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppMedia);
231 if (!attr)
232 return PrinterSemanticCapsAndDefaults::Paper();
233
234 return ParsePaper(ippGetString(attr, 0, nullptr));
235 }
236
237 std::vector<PrinterSemanticCapsAndDefaults::Paper> SupportedPapers(
238 const CupsOptionProvider& printer) {
239 std::vector<base::StringPiece> papers =
240 printer.GetSupportedOptionValueStrings(kIppMedia);
241 std::vector<PrinterSemanticCapsAndDefaults::Paper> parsed_papers;
242 for (base::StringPiece paper : papers) {
243 parsed_papers.push_back(ParsePaper(paper));
244 }
245
246 return parsed_papers;
247 }
248
249 void CopiesRange(const CupsOptionProvider& printer,
250 int* lower_bound,
251 int* upper_bound) {
252 ipp_attribute_t* attr = printer.GetSupportedOptionValues(kIppCopies);
253 if (!attr) {
254 *lower_bound = -1;
255 *upper_bound = -1;
256 }
257
258 *lower_bound = ippGetRange(attr, 0, upper_bound);
259 }
260
261 bool CollateCapable(const CupsOptionProvider& printer) {
262 std::vector<base::StringPiece> values =
263 printer.GetSupportedOptionValueStrings(kIppCollate);
264 auto iter = std::find(values.begin(), values.end(), kCollated);
265 return iter != values.end();
266 }
267
268 bool CollateDefault(const CupsOptionProvider& printer) {
269 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppCollate);
270 if (!attr)
271 return false;
272
273 base::StringPiece name = ippGetString(attr, 0, nullptr);
274 return name.compare(kCollated) == 0;
275 }
276
277 void CapsAndDefaultsFromPrinter(const CupsOptionProvider& printer,
278 PrinterSemanticCapsAndDefaults* printer_info) {
279 // duplex
280 printer_info->duplex_default = PrinterDefaultDuplex(printer);
281 printer_info->duplex_capable =
282 PrinterSupportsValue(printer, kIppDuplex, CUPS_SIDES_TWO_SIDED_PORTRAIT);
283
284 // collate
285 printer_info->collate_default = CollateDefault(printer);
286 printer_info->collate_capable = CollateCapable(printer);
287
288 // paper
289 printer_info->default_paper = DefaultPaper(printer);
290 printer_info->papers = SupportedPapers(printer);
291
292 ExtractCopies(printer, printer_info);
293 ExtractColor(printer, printer_info);
294
295 // TODO(skau): Add dpi and default_dpi
296 }
297
298 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698