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

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: Fix comment. 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 <map>
11 #include <string>
12 #include <vector>
13
14 #include "base/logging.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 const std::map<const base::StringPiece, ColorModel> kColorMap{
Lei Zhang 2016/07/19 22:26:39 Can't do this. It adds a static initializer. Given
skau 2016/07/20 23:58:22 Thanks. That works well.
45 {CUPS_PRINT_COLOR_MODE_COLOR, COLORMODE_COLOR},
46 {CUPS_PRINT_COLOR_MODE_MONOCHROME, COLORMODE_MONOCHROME},
47 };
48
49 ColorModel ColorModelFromIppColor(base::StringPiece ippColor) {
50 auto found = kColorMap.find(ippColor);
51 return found == kColorMap.end() ? UNKNOWN_COLOR_MODEL : found->second;
52 }
53
54 bool PrinterSupportsValue(const CupsPrinter& printer,
55 base::StringPiece name,
56 base::StringPiece value) {
57 std::vector<base::StringPiece> values =
58 printer.GetSupportedOptionValueStrings(name);
59 auto iter = std::find(values.begin(), values.end(), value);
60 return iter != values.end();
61 }
62
63 DuplexMode PrinterDefaultDuplex(const CupsPrinter& printer) {
64 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppDuplex);
65 if (!attr)
66 return UNKNOWN_DUPLEX_MODE;
67
68 const char* value = ippGetString(attr, 0, nullptr);
69 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_ONE_SIDED))
70 return SIMPLEX;
71 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_PORTRAIT))
72 return LONG_EDGE;
73 if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_LANDSCAPE))
74 return SHORT_EDGE;
75
76 return UNKNOWN_DUPLEX_MODE;
77 }
78
79 gfx::Size DimensionsToMicrons(base::StringPiece value) {
80 Unit unit;
81 base::StringPiece dims;
82 size_t unit_position;
83 if ((unit_position = value.find("mm")) != base::StringPiece::npos) {
84 unit = MILLIMETERS;
85 dims = value.substr(0, unit_position);
86 } else if ((unit_position = value.find("in")) != base::StringPiece::npos) {
87 unit = INCHES;
88 dims = value.substr(0, unit_position);
89 } else {
90 LOG(WARNING) << "Could not parse paper dimensions";
91 return {0, 0};
92 }
93
94 std::vector<std::string> pieces = base::SplitString(
95 dims, "x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
96 double width;
97 double height;
98
99 if (pieces.size() != 2 || !base::StringToDouble(pieces[0], &width) ||
100 !base::StringToDouble(pieces[1], &height)) {
101 return {0, 0};
102 }
103
104 int width_microns;
105 int height_microns;
106
107 switch (unit) {
108 case MILLIMETERS:
109 width_microns = width * kMicronsPerMM;
110 height_microns = height * kMicronsPerMM;
111 break;
112 case INCHES:
113 width_microns = width * kMicronsPerInch;
114 height_microns = height * kMicronsPerInch;
115 break;
116 default:
117 NOTREACHED();
118 break;
119 }
120
121 return gfx::Size{width_microns, height_microns};
122 }
123
124 PrinterSemanticCapsAndDefaults::Paper ParsePaper(base::StringPiece value) {
125 // <name>_<width>x<height>{in,mm}
126 // e.g. na_letter_8.5x11in, iso_a4_210x297mm
127
128 std::vector<base::StringPiece> pieces = base::SplitStringPiece(
129 value, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
130 if (pieces.size() < 2) {
131 // we expect at least a display string and a dimension string
132 return PrinterSemanticCapsAndDefaults::Paper();
133 }
134
135 base::StringPiece dimensions = pieces.back();
136
137 std::string display = pieces[0].as_string();
138 for (size_t i = 1; i <= pieces.size() - 2; ++i) {
139 display.append(" ");
140 pieces[i].AppendToString(&display);
141 }
142
143 PrinterSemanticCapsAndDefaults::Paper paper;
144 paper.display_name = display;
145 paper.vendor_id = value.as_string();
146 paper.size_um = DimensionsToMicrons(dimensions);
147
148 return paper;
149 }
150
151 void ExtractColor(const CupsPrinter& printer,
152 PrinterSemanticCapsAndDefaults* printer_info) {
153 printer_info->bw_model = UNKNOWN_COLOR_MODEL;
154 printer_info->color_model = UNKNOWN_COLOR_MODEL;
155
156 // color and b&w
157 std::vector<ColorModel> color_models = SupportedColorModels(printer);
158 for (ColorModel color : color_models) {
159 switch (color) {
160 case COLORMODE_COLOR:
161 printer_info->color_model = COLORMODE_COLOR;
162 break;
163 case COLORMODE_MONOCHROME:
164 printer_info->bw_model = COLORMODE_MONOCHROME;
165 break;
166 default:
167 // value not needed
168 break;
169 }
170 }
171
172 // changeable
173 printer_info->color_changeable =
174 (printer_info->color_model != UNKNOWN_COLOR_MODEL &&
175 printer_info->bw_model != UNKNOWN_COLOR_MODEL);
176
177 // default color
178 printer_info->color_default = DefaultColorModel(printer);
179 }
180
181 void ExtractCopies(const CupsPrinter& printer,
182 PrinterSemanticCapsAndDefaults* printer_info) {
183 // copies
184 int upper_bound;
185 int lower_bound;
186 CopiesRange(printer, &lower_bound, &upper_bound);
187 printer_info->copies_capable = (lower_bound != -1) && (upper_bound >= 2);
188 }
189
190 } // anonymous namespace
Lei Zhang 2016/07/19 22:26:39 no "anonymous "
skau 2016/07/20 23:58:22 Done.
191
192 ColorModel DefaultColorModel(const CupsPrinter& printer) {
193 // default color
194 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppColor);
195 if (!attr)
196 return UNKNOWN_COLOR_MODEL;
197
198 const char* value = ippGetString(attr, 0, nullptr);
Lei Zhang 2016/07/19 22:26:39 Just combine with the next line and drop |value|.
skau 2016/07/20 23:58:23 Done.
199 return ColorModelFromIppColor(value);
200 }
201
202 std::vector<ColorModel> SupportedColorModels(const CupsPrinter& printer) {
203 std::vector<ColorModel> colors;
204
205 std::vector<base::StringPiece> color_modes =
206 printer.GetSupportedOptionValueStrings(kIppColor);
207
208 for (base::StringPiece color : color_modes) {
209 ColorModel color_model = ColorModelFromIppColor(color);
210 if (color_model != UNKNOWN_COLOR_MODEL) {
211 colors.push_back(color_model);
212 }
213 }
214
215 return colors;
216 }
217
218 PrinterSemanticCapsAndDefaults::Paper DefaultPaper(const CupsPrinter& printer) {
219 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppMedia);
220 if (!attr)
221 return PrinterSemanticCapsAndDefaults::Paper();
222
223 const char* value = ippGetString(attr, 0, nullptr);
224 return ParsePaper(value);
225 }
226
227 std::vector<PrinterSemanticCapsAndDefaults::Paper> SupportedPapers(
228 const CupsPrinter& printer) {
229 std::vector<base::StringPiece> papers =
230 printer.GetSupportedOptionValueStrings(kIppMedia);
231 std::vector<PrinterSemanticCapsAndDefaults::Paper> parsed_papers;
232 for (base::StringPiece paper : papers) {
233 PrinterSemanticCapsAndDefaults::Paper p = ParsePaper(paper);
Lei Zhang 2016/07/19 22:26:39 Also less wordy if it's just combined with the nex
skau 2016/07/20 23:58:23 Done.
234 parsed_papers.push_back(p);
235 }
236
237 return parsed_papers;
238 }
239
240 void CopiesRange(const CupsPrinter& printer,
241 int* lower_bound,
242 int* upper_bound) {
243 ipp_attribute_t* attr = printer.GetSupportedOptionValues(kIppCopies);
244 if (attr) {
Lei Zhang 2016/07/19 22:26:39 If |attr| is nullptr, what happens? Does |lower_bo
skau 2016/07/20 23:58:22 Whoops. I'll write some unit tests.
245 *lower_bound = -1;
246 *upper_bound = -1;
247 }
248
249 *lower_bound = ippGetRange(attr, 0, upper_bound);
250 }
251
252 bool CollateCapable(const CupsPrinter& printer) {
253 std::vector<base::StringPiece> values =
254 printer.GetSupportedOptionValueStrings(kIppCollate);
255 auto iter = std::find(values.begin(), values.end(), kCollated);
Lei Zhang 2016/07/19 22:26:39 Just: return ContainsValue(values, kCollated); Sa
skau 2016/07/20 23:58:22 Thanks. I didn't know we had that.
256 return iter != values.end();
257 }
258
259 bool CollateDefault(const CupsPrinter& printer) {
260 ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppCollate);
261 if (!attr)
262 return false;
263
264 base::StringPiece name = ippGetString(attr, 0, nullptr);
265 return name.compare(kCollated) == 0;
266 }
267
268 void CapsAndDefaultsFromPrinter(const CupsPrinter& printer,
269 PrinterSemanticCapsAndDefaults* printer_info) {
270 // duplex
271 printer_info->duplex_default = PrinterDefaultDuplex(printer);
272 printer_info->duplex_capable =
273 PrinterSupportsValue(printer, kIppDuplex, CUPS_SIDES_TWO_SIDED_PORTRAIT);
274
275 // collate
276 printer_info->collate_default = CollateDefault(printer);
277 printer_info->collate_capable = CollateCapable(printer);
278
279 // paper
280 printer_info->default_paper = DefaultPaper(printer);
281 printer_info->papers = SupportedPapers(printer);
282
283 ExtractCopies(printer, printer_info);
284 ExtractColor(printer, printer_info);
285
286 // TODO(skau): Add dpi and default_dpi
287 }
288
289 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698