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.
5 #include "printing/print_settings_conversion.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "base/values.h"
19 #include "build/build_config.h"
20 #include "printing/print_job_constants.h"
21 #include "printing/print_settings.h"
22 #include "printing/units.h"
28 void GetCustomMarginsFromJobSettings(const base::Value& settings,
29 PageMargins* page_size_margins) {
30 const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom);
31 if (!custom_margins) {
35 page_size_margins->top =
36 custom_margins->FindKey(kSettingMarginTop)->GetDouble();
37 page_size_margins->bottom =
38 custom_margins->FindKey(kSettingMarginBottom)->GetDouble();
39 page_size_margins->left =
40 custom_margins->FindKey(kSettingMarginLeft)->GetDouble();
41 page_size_margins->right =
42 custom_margins->FindKey(kSettingMarginRight)->GetDouble();
45 void SetMarginsToJobSettings(const std::string& json_path,
46 const PageMargins& margins,
47 base::DictionaryValue* job_settings) {
48 auto dict = std::make_unique<base::DictionaryValue>();
49 dict->SetInteger(kSettingMarginTop, margins.top);
50 dict->SetInteger(kSettingMarginBottom, margins.bottom);
51 dict->SetInteger(kSettingMarginLeft, margins.left);
52 dict->SetInteger(kSettingMarginRight, margins.right);
53 job_settings->Set(json_path, std::move(dict));
56 void SetSizeToJobSettings(const std::string& json_path,
57 const gfx::Size& size,
58 base::DictionaryValue* job_settings) {
59 auto dict = std::make_unique<base::DictionaryValue>();
60 dict->SetInteger("width", size.width());
61 dict->SetInteger("height", size.height());
62 job_settings->Set(json_path, std::move(dict));
65 void SetRectToJobSettings(const std::string& json_path,
66 const gfx::Rect& rect,
67 base::DictionaryValue* job_settings) {
68 auto dict = std::make_unique<base::DictionaryValue>();
69 dict->SetInteger("x", rect.x());
70 dict->SetInteger("y", rect.y());
71 dict->SetInteger("width", rect.width());
72 dict->SetInteger("height", rect.height());
73 job_settings->Set(json_path, std::move(dict));
78 bool PrintSettingsFromJobSettings(const base::Value& job_settings,
79 PrintSettings* settings) {
80 base::Optional<bool> display_header_footer =
81 job_settings.FindBoolKey(kSettingHeaderFooterEnabled);
82 if (!display_header_footer.has_value())
85 settings->set_display_header_footer(display_header_footer.value());
86 if (settings->display_header_footer()) {
87 const std::string* title =
88 job_settings.FindStringKey(kSettingHeaderFooterTitle);
89 const std::string* url =
90 job_settings.FindStringKey(kSettingHeaderFooterURL);
94 settings->set_title(base::UTF8ToUTF16(*title));
95 settings->set_url(base::UTF8ToUTF16(*url));
98 base::Optional<bool> backgrounds =
99 job_settings.FindBoolKey(kSettingShouldPrintBackgrounds);
100 base::Optional<bool> selection_only =
101 job_settings.FindBoolKey(kSettingShouldPrintSelectionOnly);
102 if (!backgrounds.has_value() || !selection_only.has_value())
105 settings->set_should_print_backgrounds(backgrounds.value());
106 settings->set_selection_only(selection_only.value());
108 PrintSettings::RequestedMedia requested_media;
109 const base::Value* media_size_value = job_settings.FindKeyOfType(
110 kSettingMediaSize, base::Value::Type::DICTIONARY);
111 if (media_size_value) {
112 base::Optional<int> width_microns =
113 media_size_value->FindIntKey(kSettingMediaSizeWidthMicrons);
114 base::Optional<int> height_microns =
115 media_size_value->FindIntKey(kSettingMediaSizeHeightMicrons);
116 if (width_microns.has_value() && height_microns.has_value()) {
117 requested_media.size_microns =
118 gfx::Size(width_microns.value(), height_microns.value());
121 const std::string* vendor_id =
122 media_size_value->FindStringKey(kSettingMediaSizeVendorId);
123 if (vendor_id && !vendor_id->empty())
124 requested_media.vendor_id = *vendor_id;
126 settings->set_requested_media(requested_media);
129 job_settings.FindIntKey(kSettingMarginsType).value_or(DEFAULT_MARGINS);
130 if (margin_type != DEFAULT_MARGINS && margin_type != NO_MARGINS &&
131 margin_type != CUSTOM_MARGINS && margin_type != PRINTABLE_AREA_MARGINS) {
132 margin_type = DEFAULT_MARGINS;
134 settings->set_margin_type(static_cast<MarginType>(margin_type));
136 if (margin_type == CUSTOM_MARGINS) {
137 PageMargins margins_in_points;
138 margins_in_points.Clear();
139 GetCustomMarginsFromJobSettings(job_settings, &margins_in_points);
140 settings->SetCustomMargins(margins_in_points);
143 PageRanges new_ranges;
144 const base::Value* page_range_array =
145 job_settings.FindKeyOfType(kSettingPageRange, base::Value::Type::LIST);
146 if (page_range_array) {
147 for (const base::Value& value : page_range_array->GetList()) {
148 if (!value.is_dict())
151 base::Optional<int> from = value.FindIntKey(kSettingPageRangeFrom);
152 base::Optional<int> to = value.FindIntKey(kSettingPageRangeTo);
153 if (!from.has_value() || !to.has_value())
156 // Page numbers are 1-based in the dictionary.
157 // Page numbers are 0-based for the printing context.
158 new_ranges.push_back(PageRange{from.value() - 1, to.value() - 1});
161 settings->set_ranges(new_ranges);
163 base::Optional<bool> collate = job_settings.FindBoolKey(kSettingCollate);
164 base::Optional<int> copies = job_settings.FindIntKey(kSettingCopies);
165 base::Optional<int> color = job_settings.FindIntKey(kSettingColor);
166 base::Optional<int> duplex_mode = job_settings.FindIntKey(kSettingDuplexMode);
167 base::Optional<bool> landscape = job_settings.FindBoolKey(kSettingLandscape);
168 const std::string* device_name =
169 job_settings.FindStringKey(kSettingDeviceName);
170 base::Optional<int> scale_factor =
171 job_settings.FindIntKey(kSettingScaleFactor);
172 base::Optional<bool> rasterize_pdf =
173 job_settings.FindBoolKey(kSettingRasterizePdf);
174 base::Optional<int> pages_per_sheet =
175 job_settings.FindIntKey(kSettingPagesPerSheet);
177 if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
178 !duplex_mode.has_value() || !landscape.has_value() || !device_name ||
179 !scale_factor.has_value() || !rasterize_pdf.has_value() ||
180 !pages_per_sheet.has_value()) {
184 base::Optional<int> dpi_horizontal =
185 job_settings.FindIntKey(kSettingDpiHorizontal);
186 base::Optional<int> dpi_vertical =
187 job_settings.FindIntKey(kSettingDpiVertical);
188 if (!dpi_horizontal.has_value() || !dpi_vertical.has_value())
191 settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());
194 settings->set_collate(collate.value());
195 settings->set_copies(copies.value());
196 settings->SetOrientation(landscape.value());
197 settings->set_device_name(base::UTF8ToUTF16(*device_name));
198 settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode.value()));
199 settings->set_color(static_cast<ColorModel>(color.value()));
200 settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0);
201 settings->set_rasterize_pdf(rasterize_pdf.value());
202 settings->set_pages_per_sheet(pages_per_sheet.value());
203 base::Optional<bool> is_modifiable =
204 job_settings.FindBoolKey(kSettingPreviewModifiable);
205 if (is_modifiable.has_value()) {
206 settings->set_is_modifiable(is_modifiable.value());
208 settings->set_print_text_with_gdi(is_modifiable.value());
214 void PrintSettingsToJobSettingsDebug(const PrintSettings& settings,
215 base::DictionaryValue* job_settings) {
216 job_settings->SetBoolean(kSettingHeaderFooterEnabled,
217 settings.display_header_footer());
218 job_settings->SetString(kSettingHeaderFooterTitle, settings.title());
219 job_settings->SetString(kSettingHeaderFooterURL, settings.url());
220 job_settings->SetBoolean(kSettingShouldPrintBackgrounds,
221 settings.should_print_backgrounds());
222 job_settings->SetBoolean(kSettingShouldPrintSelectionOnly,
223 settings.selection_only());
224 job_settings->SetInteger(kSettingMarginsType, settings.margin_type());
225 if (!settings.ranges().empty()) {
226 auto page_range_array = std::make_unique<base::ListValue>();
227 for (size_t i = 0; i < settings.ranges().size(); ++i) {
228 auto dict = std::make_unique<base::DictionaryValue>();
229 dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1);
230 dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1);
231 page_range_array->Append(std::move(dict));
233 job_settings->Set(kSettingPageRange, std::move(page_range_array));
236 job_settings->SetBoolean(kSettingCollate, settings.collate());
237 job_settings->SetInteger(kSettingCopies, settings.copies());
238 job_settings->SetInteger(kSettingColor, settings.color());
239 job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode());
240 job_settings->SetBoolean(kSettingLandscape, settings.landscape());
241 job_settings->SetString(kSettingDeviceName, settings.device_name());
242 job_settings->SetInteger(kSettingPagesPerSheet, settings.pages_per_sheet());
244 // Following values are not read form JSON by InitSettings, so do not have
245 // common public constants. So just serialize in "debug" section.
246 auto debug = std::make_unique<base::DictionaryValue>();
247 debug->SetInteger("dpi", settings.dpi());
248 debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch());
249 debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds());
250 debug->SetString("media_vendor_id", settings.requested_media().vendor_id);
251 SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
253 SetMarginsToJobSettings("requested_custom_margins_in_points",
254 settings.requested_custom_margins_in_points(),
256 const PageSetup& page_setup = settings.page_setup_device_units();
257 SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
259 SetSizeToJobSettings("physical_size", page_setup.physical_size(),
261 SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug.get());
262 SetRectToJobSettings("content_area", page_setup.content_area(), debug.get());
263 SetRectToJobSettings("printable_area", page_setup.printable_area(),
265 job_settings->Set("debug", std::move(debug));
268 } // namespace printing