1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "printing/print_settings.h"
7 #include "base/atomic_sequence_num.h"
8 #include "base/notreached.h"
9 #include "build/build_config.h"
10 #include "printing/units.h"
12 #if defined(USE_CUPS) && (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS))
13 #include <cups/cups.h>
17 #include "printing/mojom/print.mojom.h"
22 mojom::ColorModel ColorModeToColorModel(int color_mode) {
23 if (color_mode < static_cast<int>(mojom::ColorModel::kUnknownColorModel) ||
24 color_mode > static_cast<int>(mojom::ColorModel::kColorModelLast))
25 return mojom::ColorModel::kUnknownColorModel;
26 return static_cast<mojom::ColorModel>(color_mode);
30 void GetColorModelForModel(mojom::ColorModel color_model,
31 std::string* color_setting_name,
32 std::string* color_value) {
34 constexpr char kCUPSColorMode[] = "ColorMode";
35 constexpr char kCUPSColorModel[] = "ColorModel";
36 constexpr char kCUPSPrintoutMode[] = "PrintoutMode";
37 constexpr char kCUPSProcessColorModel[] = "ProcessColorModel";
38 constexpr char kCUPSBrotherMonoColor[] = "BRMonoColor";
39 constexpr char kCUPSBrotherPrintQuality[] = "BRPrintQuality";
40 constexpr char kCUPSEpsonInk[] = "Ink";
41 constexpr char kCUPSSharpARCMode[] = "ARCMode";
42 constexpr char kCUPSXeroxXRXColor[] = "XRXColor";
44 constexpr char kCUPSColorMode[] = "cups-ColorMode";
45 constexpr char kCUPSColorModel[] = "cups-ColorModel";
46 constexpr char kCUPSPrintoutMode[] = "cups-PrintoutMode";
47 constexpr char kCUPSProcessColorModel[] = "cups-ProcessColorModel";
48 constexpr char kCUPSBrotherMonoColor[] = "cups-BRMonoColor";
49 constexpr char kCUPSBrotherPrintQuality[] = "cups-BRPrintQuality";
50 constexpr char kCUPSEpsonInk[] = "cups-Ink";
51 constexpr char kCUPSSharpARCMode[] = "cups-ARCMode";
52 constexpr char kCUPSXeroxXRXColor[] = "cups-XRXColor";
53 #endif // BUILDFLAG(IS_MAC)
55 *color_setting_name = kCUPSColorModel;
57 switch (color_model) {
58 case mojom::ColorModel::kUnknownColorModel:
59 *color_value = kGrayscale;
61 case mojom::ColorModel::kGray:
64 case mojom::ColorModel::kColor:
65 *color_value = kColor;
67 case mojom::ColorModel::kCMYK:
70 case mojom::ColorModel::kCMY:
73 case mojom::ColorModel::kKCMY:
76 case mojom::ColorModel::kCMYPlusK:
77 *color_value = kCMY_K;
79 case mojom::ColorModel::kBlack:
80 *color_value = kBlack;
82 case mojom::ColorModel::kGrayscale:
83 *color_value = kGrayscale;
85 case mojom::ColorModel::kRGB:
88 case mojom::ColorModel::kRGB16:
89 *color_value = kRGB16;
91 case mojom::ColorModel::kRGBA:
94 case mojom::ColorModel::kColorModeColor:
95 *color_setting_name = kCUPSColorMode;
96 *color_value = kColor;
98 case mojom::ColorModel::kColorModeMonochrome:
99 *color_setting_name = kCUPSColorMode;
100 *color_value = kMonochrome;
102 case mojom::ColorModel::kHPColorColor:
103 *color_setting_name = kColor;
104 *color_value = kColor;
106 case mojom::ColorModel::kHPColorBlack:
107 *color_setting_name = kColor;
108 *color_value = kBlack;
110 case mojom::ColorModel::kPrintoutModeNormal:
111 *color_setting_name = kCUPSPrintoutMode;
112 *color_value = kNormal;
114 case mojom::ColorModel::kPrintoutModeNormalGray:
115 *color_setting_name = kCUPSPrintoutMode;
116 *color_value = kNormalGray;
118 case mojom::ColorModel::kProcessColorModelCMYK:
119 *color_setting_name = kCUPSProcessColorModel;
120 *color_value = kCMYK;
122 case mojom::ColorModel::kProcessColorModelGreyscale:
123 *color_setting_name = kCUPSProcessColorModel;
124 *color_value = kGreyscale;
126 case mojom::ColorModel::kProcessColorModelRGB:
127 *color_setting_name = kCUPSProcessColorModel;
130 case mojom::ColorModel::kBrotherCUPSColor:
131 *color_setting_name = kCUPSBrotherMonoColor;
132 *color_value = kFullColor;
134 case mojom::ColorModel::kBrotherCUPSMono:
135 *color_setting_name = kCUPSBrotherMonoColor;
136 *color_value = kMono;
138 case mojom::ColorModel::kBrotherBRScript3Color:
139 *color_setting_name = kCUPSBrotherPrintQuality;
140 *color_value = kColor;
142 case mojom::ColorModel::kBrotherBRScript3Black:
143 *color_setting_name = kCUPSBrotherPrintQuality;
144 *color_value = kBlack;
146 case mojom::ColorModel::kEpsonInkColor:
147 *color_setting_name = kCUPSEpsonInk;
148 *color_value = kEpsonColor;
150 case mojom::ColorModel::kEpsonInkMono:
151 *color_setting_name = kCUPSEpsonInk;
152 *color_value = kEpsonMono;
154 case mojom::ColorModel::kSharpARCModeCMColor:
155 *color_setting_name = kCUPSSharpARCMode;
156 *color_value = kSharpCMColor;
158 case mojom::ColorModel::kSharpARCModeCMBW:
159 *color_setting_name = kCUPSSharpARCMode;
160 *color_value = kSharpCMBW;
162 case mojom::ColorModel::kXeroxXRXColorAutomatic:
163 *color_setting_name = kCUPSXeroxXRXColor;
164 *color_value = kXeroxAutomatic;
166 case mojom::ColorModel::kXeroxXRXColorBW:
167 *color_setting_name = kCUPSXeroxXRXColor;
168 *color_value = kXeroxBW;
171 // The default case is excluded from the above switch statement to ensure that
172 // all ColorModel values are determinantly handled.
175 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
176 std::string GetIppColorModelForModel(mojom::ColorModel color_model) {
177 // Accept `kUnknownColorModel` for consistency with GetColorModelForModel().
178 if (color_model == mojom::ColorModel::kUnknownColorModel)
179 return CUPS_PRINT_COLOR_MODE_MONOCHROME;
181 absl::optional<bool> is_color = IsColorModelSelected(color_model);
182 if (!is_color.has_value()) {
184 return std::string();
187 return is_color.value() ? CUPS_PRINT_COLOR_MODE_COLOR
188 : CUPS_PRINT_COLOR_MODE_MONOCHROME;
190 #endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
191 #endif // defined(USE_CUPS)
193 absl::optional<bool> IsColorModelSelected(mojom::ColorModel color_model) {
194 switch (color_model) {
195 case mojom::ColorModel::kColor:
196 case mojom::ColorModel::kCMYK:
197 case mojom::ColorModel::kCMY:
198 case mojom::ColorModel::kKCMY:
199 case mojom::ColorModel::kCMYPlusK:
200 case mojom::ColorModel::kRGB:
201 case mojom::ColorModel::kRGB16:
202 case mojom::ColorModel::kRGBA:
203 case mojom::ColorModel::kColorModeColor:
204 case mojom::ColorModel::kHPColorColor:
205 case mojom::ColorModel::kPrintoutModeNormal:
206 case mojom::ColorModel::kProcessColorModelCMYK:
207 case mojom::ColorModel::kProcessColorModelRGB:
208 case mojom::ColorModel::kBrotherCUPSColor:
209 case mojom::ColorModel::kBrotherBRScript3Color:
210 case mojom::ColorModel::kEpsonInkColor:
211 case mojom::ColorModel::kSharpARCModeCMColor:
212 case mojom::ColorModel::kXeroxXRXColorAutomatic:
214 case mojom::ColorModel::kGray:
215 case mojom::ColorModel::kBlack:
216 case mojom::ColorModel::kGrayscale:
217 case mojom::ColorModel::kColorModeMonochrome:
218 case mojom::ColorModel::kHPColorBlack:
219 case mojom::ColorModel::kPrintoutModeNormalGray:
220 case mojom::ColorModel::kProcessColorModelGreyscale:
221 case mojom::ColorModel::kBrotherCUPSMono:
222 case mojom::ColorModel::kBrotherBRScript3Black:
223 case mojom::ColorModel::kEpsonInkMono:
224 case mojom::ColorModel::kSharpARCModeCMBW:
225 case mojom::ColorModel::kXeroxXRXColorBW:
227 case mojom::ColorModel::kUnknownColorModel:
229 return absl::nullopt;
231 // The default case is excluded from the above switch statement to ensure that
232 // all ColorModel values are determinantly handled.
235 // Global SequenceNumber used for generating unique cookie values.
236 static base::AtomicSequenceNumber cookie_seq;
238 PrintSettings::PrintSettings() {
242 PrintSettings::PrintSettings(const PrintSettings& settings) {
246 PrintSettings& PrintSettings::operator=(const PrintSettings& settings) {
247 if (this == &settings)
250 ranges_ = settings.ranges_;
251 selection_only_ = settings.selection_only_;
252 margin_type_ = settings.margin_type_;
253 title_ = settings.title_;
254 url_ = settings.url_;
255 display_header_footer_ = settings.display_header_footer_;
256 should_print_backgrounds_ = settings.should_print_backgrounds_;
257 collate_ = settings.collate_;
258 color_ = settings.color_;
259 copies_ = settings.copies_;
260 duplex_mode_ = settings.duplex_mode_;
261 device_name_ = settings.device_name_;
262 requested_media_ = settings.requested_media_;
263 page_setup_device_units_ = settings.page_setup_device_units_;
264 dpi_ = settings.dpi_;
265 scale_factor_ = settings.scale_factor_;
266 rasterize_pdf_ = settings.rasterize_pdf_;
267 rasterize_pdf_dpi_ = settings.rasterize_pdf_dpi_;
268 landscape_ = settings.landscape_;
269 supports_alpha_blend_ = settings.supports_alpha_blend_;
270 #if BUILDFLAG(IS_WIN)
271 printer_language_type_ = settings.printer_language_type_;
273 is_modifiable_ = settings.is_modifiable_;
274 pages_per_sheet_ = settings.pages_per_sheet_;
275 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
276 for (const auto& item : settings.advanced_settings_)
277 advanced_settings_.emplace(item.first, item.second.Clone());
278 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
279 #if BUILDFLAG(IS_CHROMEOS)
280 send_user_info_ = settings.send_user_info_;
281 username_ = settings.username_;
282 pin_value_ = settings.pin_value_;
283 #endif // BUILDFLAG(IS_CHROMEOS)
287 PrintSettings::~PrintSettings() = default;
289 void PrintSettings::Clear() {
291 selection_only_ = false;
292 margin_type_ = mojom::MarginType::kDefaultMargins;
295 display_header_footer_ = false;
296 should_print_backgrounds_ = false;
298 color_ = mojom::ColorModel::kUnknownColorModel;
300 duplex_mode_ = mojom::DuplexMode::kUnknownDuplexMode;
301 device_name_.clear();
302 requested_media_ = RequestedMedia();
303 page_setup_device_units_.Clear();
305 scale_factor_ = 1.0f;
306 rasterize_pdf_ = false;
307 rasterize_pdf_dpi_ = 0;
309 supports_alpha_blend_ = true;
310 #if BUILDFLAG(IS_WIN)
311 printer_language_type_ = mojom::PrinterLanguageType::kNone;
313 is_modifiable_ = true;
314 pages_per_sheet_ = 1;
315 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
316 advanced_settings_.clear();
317 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
318 #if BUILDFLAG(IS_CHROMEOS)
319 send_user_info_ = false;
322 #endif // BUILDFLAG(IS_CHROMEOS)
325 void PrintSettings::SetPrinterPrintableArea(
326 const gfx::Size& physical_size_device_units,
327 const gfx::Rect& printable_area_device_units,
328 bool landscape_needs_flip) {
329 int units_per_inch = device_units_per_inch();
330 int header_footer_text_height = 0;
331 if (display_header_footer_) {
332 // Hard-code text_height = 0.5cm = ~1/5 of inch.
333 header_footer_text_height = ConvertUnit(kSettingHeaderFooterInterstice,
334 kPointsPerInch, units_per_inch);
338 bool small_paper_size = false;
339 switch (margin_type_) {
340 case mojom::MarginType::kDefaultMargins: {
341 // Default margins 1.0cm = ~2/5 of an inch, unless a page dimension is
342 // less than 2.54 cm = ~1 inch, in which case set the margins in that
344 static constexpr double kCmInMicrons = 10000;
345 int margin_printer_units =
346 ConvertUnit(kCmInMicrons, kMicronsPerInch, units_per_inch);
347 int min_size_printer_units = units_per_inch;
348 margins.header = header_footer_text_height;
349 margins.footer = header_footer_text_height;
350 if (physical_size_device_units.height() > min_size_printer_units) {
351 margins.top = margin_printer_units;
352 margins.bottom = margin_printer_units;
356 small_paper_size = true;
358 if (physical_size_device_units.width() > min_size_printer_units) {
359 margins.left = margin_printer_units;
360 margins.right = margin_printer_units;
364 small_paper_size = true;
368 case mojom::MarginType::kNoMargins:
369 case mojom::MarginType::kPrintableAreaMargins: {
378 case mojom::MarginType::kCustomMargins: {
381 margins.top = ConvertUnit(requested_custom_margins_in_points_.top,
382 kPointsPerInch, units_per_inch);
383 margins.bottom = ConvertUnit(requested_custom_margins_in_points_.bottom,
384 kPointsPerInch, units_per_inch);
385 margins.left = ConvertUnit(requested_custom_margins_in_points_.left,
386 kPointsPerInch, units_per_inch);
387 margins.right = ConvertUnit(requested_custom_margins_in_points_.right,
388 kPointsPerInch, units_per_inch);
396 if ((margin_type_ == mojom::MarginType::kDefaultMargins ||
397 margin_type_ == mojom::MarginType::kPrintableAreaMargins) &&
399 page_setup_device_units_.SetRequestedMargins(margins);
401 page_setup_device_units_.ForceRequestedMargins(margins);
403 page_setup_device_units_.Init(physical_size_device_units,
404 printable_area_device_units,
405 header_footer_text_height);
406 if (landscape_ && landscape_needs_flip)
407 page_setup_device_units_.FlipOrientation();
410 void PrintSettings::SetCustomMargins(
411 const PageMargins& requested_margins_in_points) {
412 requested_custom_margins_in_points_ = requested_margins_in_points;
413 margin_type_ = mojom::MarginType::kCustomMargins;
416 int PrintSettings::NewCookie() {
417 // A cookie of 0 is used to mark a document as unassigned, count from 1.
418 return cookie_seq.GetNext() + 1;
421 void PrintSettings::SetOrientation(bool landscape) {
422 if (landscape_ != landscape) {
423 landscape_ = landscape;
424 page_setup_device_units_.FlipOrientation();
428 } // namespace printing