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 "printing/print_settings_conversion.h" 6 7 #include <algorithm> 8 #include <cmath> 9 #include <string> 10 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/time/time.h" 14 #include "base/values.h" 15 #include "printing/page_size_margins.h" 16 #include "printing/print_job_constants.h" 17 #include "printing/print_settings.h" 18 #include "printing/units.h" 19 20 namespace printing { 21 22 namespace { 23 24 void GetCustomMarginsFromJobSettings(const base::DictionaryValue& settings, 25 PageSizeMargins* page_size_margins) { 26 const base::DictionaryValue* custom_margins; 27 if (!settings.GetDictionary(kSettingMarginsCustom, &custom_margins) || 28 !custom_margins->GetDouble(kSettingMarginTop, 29 &page_size_margins->margin_top) || 30 !custom_margins->GetDouble(kSettingMarginBottom, 31 &page_size_margins->margin_bottom) || 32 !custom_margins->GetDouble(kSettingMarginLeft, 33 &page_size_margins->margin_left) || 34 !custom_margins->GetDouble(kSettingMarginRight, 35 &page_size_margins->margin_right)) { 36 NOTREACHED(); 37 } 38 } 39 40 void SetMarginsToJobSettings(const std::string& json_path, 41 const PageMargins& margins, 42 base::DictionaryValue* job_settings) { 43 base::DictionaryValue* dict = new base::DictionaryValue; 44 job_settings->Set(json_path, dict); 45 dict->SetInteger(kSettingMarginTop, margins.top); 46 dict->SetInteger(kSettingMarginBottom, margins.bottom); 47 dict->SetInteger(kSettingMarginLeft, margins.left); 48 dict->SetInteger(kSettingMarginRight, margins.right); 49 } 50 51 void SetSizeToJobSettings(const std::string& json_path, 52 const gfx::Size& size, 53 base::DictionaryValue* job_settings) { 54 base::DictionaryValue* dict = new base::DictionaryValue; 55 job_settings->Set(json_path, dict); 56 dict->SetInteger("width", size.width()); 57 dict->SetInteger("height", size.height()); 58 } 59 60 void SetRectToJobSettings(const std::string& json_path, 61 const gfx::Rect& rect, 62 base::DictionaryValue* job_settings) { 63 base::DictionaryValue* dict = new base::DictionaryValue; 64 job_settings->Set(json_path, dict); 65 dict->SetInteger("x", rect.x()); 66 dict->SetInteger("y", rect.y()); 67 dict->SetInteger("width", rect.width()); 68 dict->SetInteger("height", rect.height()); 69 } 70 71 } // namespace 72 73 bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings, 74 PrintSettings* settings) { 75 bool display_header_footer = false; 76 if (!job_settings.GetBoolean(kSettingHeaderFooterEnabled, 77 &display_header_footer)) { 78 return false; 79 } 80 settings->set_display_header_footer(display_header_footer); 81 82 if (settings->display_header_footer()) { 83 base::string16 title; 84 base::string16 url; 85 if (!job_settings.GetString(kSettingHeaderFooterTitle, &title) || 86 !job_settings.GetString(kSettingHeaderFooterURL, &url)) { 87 return false; 88 } 89 settings->set_title(title); 90 settings->set_url(url); 91 } 92 93 bool backgrounds = false; 94 bool selection_only = false; 95 if (!job_settings.GetBoolean(kSettingShouldPrintBackgrounds, &backgrounds) || 96 !job_settings.GetBoolean(kSettingShouldPrintSelectionOnly, 97 &selection_only)) { 98 return false; 99 } 100 settings->set_should_print_backgrounds(backgrounds); 101 settings->set_selection_only(selection_only); 102 103 PrintSettings::RequestedMedia requested_media; 104 const base::DictionaryValue* media_size_value = NULL; 105 if (job_settings.GetDictionary(kSettingMediaSize, &media_size_value)) { 106 int width_microns = 0; 107 int height_microns = 0; 108 if (media_size_value->GetInteger(kSettingMediaSizeWidthMicrons, 109 &width_microns) && 110 media_size_value->GetInteger(kSettingMediaSizeHeightMicrons, 111 &height_microns)) { 112 requested_media.size_microns = gfx::Size(width_microns, height_microns); 113 } 114 std::string vendor_id; 115 if (media_size_value->GetString(kSettingMediaSizeVendorId, &vendor_id) && 116 !vendor_id.empty()) { 117 requested_media.vendor_id = vendor_id; 118 } 119 } 120 settings->set_requested_media(requested_media); 121 122 int margin_type = DEFAULT_MARGINS; 123 if (!job_settings.GetInteger(kSettingMarginsType, &margin_type) || 124 (margin_type != DEFAULT_MARGINS && 125 margin_type != NO_MARGINS && 126 margin_type != CUSTOM_MARGINS && 127 margin_type != PRINTABLE_AREA_MARGINS)) { 128 margin_type = DEFAULT_MARGINS; 129 } 130 settings->set_margin_type(static_cast<MarginType>(margin_type)); 131 132 if (margin_type == CUSTOM_MARGINS) { 133 PageSizeMargins page_size_margins; 134 GetCustomMarginsFromJobSettings(job_settings, &page_size_margins); 135 136 PageMargins margins_in_points; 137 margins_in_points.Clear(); 138 margins_in_points.top = page_size_margins.margin_top; 139 margins_in_points.bottom = page_size_margins.margin_bottom; 140 margins_in_points.left = page_size_margins.margin_left; 141 margins_in_points.right = page_size_margins.margin_right; 142 143 settings->SetCustomMargins(margins_in_points); 144 } 145 146 PageRanges new_ranges; 147 const base::ListValue* page_range_array = NULL; 148 if (job_settings.GetList(kSettingPageRange, &page_range_array)) { 149 for (size_t index = 0; index < page_range_array->GetSize(); ++index) { 150 const base::DictionaryValue* dict; 151 if (!page_range_array->GetDictionary(index, &dict)) 152 continue; 153 154 PageRange range; 155 if (!dict->GetInteger(kSettingPageRangeFrom, &range.from) || 156 !dict->GetInteger(kSettingPageRangeTo, &range.to)) { 157 continue; 158 } 159 160 // Page numbers are 1-based in the dictionary. 161 // Page numbers are 0-based for the printing context. 162 range.from--; 163 range.to--; 164 new_ranges.push_back(range); 165 } 166 } 167 settings->set_ranges(new_ranges); 168 169 int color = 0; 170 bool landscape = false; 171 int duplex_mode = 0; 172 base::string16 device_name; 173 bool collate = false; 174 int copies = 1; 175 176 if (!job_settings.GetBoolean(kSettingCollate, &collate) || 177 !job_settings.GetInteger(kSettingCopies, &copies) || 178 !job_settings.GetInteger(kSettingColor, &color) || 179 !job_settings.GetInteger(kSettingDuplexMode, &duplex_mode) || 180 !job_settings.GetBoolean(kSettingLandscape, &landscape) || 181 !job_settings.GetString(kSettingDeviceName, &device_name)) { 182 return false; 183 } 184 185 settings->set_collate(collate); 186 settings->set_copies(copies); 187 settings->SetOrientation(landscape); 188 settings->set_device_name(device_name); 189 settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode)); 190 settings->set_color(static_cast<ColorModel>(color)); 191 192 return true; 193 } 194 195 void PrintSettingsToJobSettingsDebug(const PrintSettings& settings, 196 base::DictionaryValue* job_settings) { 197 job_settings->SetBoolean(kSettingHeaderFooterEnabled, 198 settings.display_header_footer()); 199 job_settings->SetString(kSettingHeaderFooterTitle, settings.title()); 200 job_settings->SetString(kSettingHeaderFooterURL, settings.url()); 201 job_settings->SetBoolean(kSettingShouldPrintBackgrounds, 202 settings.should_print_backgrounds()); 203 job_settings->SetBoolean(kSettingShouldPrintSelectionOnly, 204 settings.selection_only()); 205 job_settings->SetInteger(kSettingMarginsType, settings.margin_type()); 206 if (!settings.ranges().empty()) { 207 base::ListValue* page_range_array = new base::ListValue; 208 job_settings->Set(kSettingPageRange, page_range_array); 209 for (size_t i = 0; i < settings.ranges().size(); ++i) { 210 base::DictionaryValue* dict = new base::DictionaryValue; 211 page_range_array->Append(dict); 212 dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1); 213 dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1); 214 } 215 } 216 217 job_settings->SetBoolean(kSettingCollate, settings.collate()); 218 job_settings->SetInteger(kSettingCopies, settings.copies()); 219 job_settings->SetInteger(kSettingColor, settings.color()); 220 job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode()); 221 job_settings->SetBoolean(kSettingLandscape, settings.landscape()); 222 job_settings->SetString(kSettingDeviceName, settings.device_name()); 223 224 // Following values are not read form JSON by InitSettings, so do not have 225 // common public constants. So just serialize in "debug" section. 226 base::DictionaryValue* debug = new base::DictionaryValue; 227 job_settings->Set("debug", debug); 228 debug->SetDouble("minShrink", settings.min_shrink()); 229 debug->SetDouble("maxShrink", settings.max_shrink()); 230 debug->SetInteger("desiredDpi", settings.desired_dpi()); 231 debug->SetInteger("dpi", settings.dpi()); 232 debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch()); 233 debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds()); 234 debug->SetString("media_vendor_od", settings.requested_media().vendor_id); 235 SetSizeToJobSettings( 236 "media_size", settings.requested_media().size_microns, debug); 237 SetMarginsToJobSettings("requested_custom_margins_in_points", 238 settings.requested_custom_margins_in_points(), 239 debug); 240 const PageSetup& page_setup = settings.page_setup_device_units(); 241 SetMarginsToJobSettings( 242 "effective_margins", page_setup.effective_margins(), debug); 243 SetSizeToJobSettings("physical_size", page_setup.physical_size(), debug); 244 SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug); 245 SetRectToJobSettings("content_area", page_setup.content_area(), debug); 246 SetRectToJobSettings("printable_area", page_setup.printable_area(), debug); 247 } 248 249 } // namespace printing 250