OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/print_web_view_helper.h" | 5 #include "chrome/renderer/print_web_view_helper.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 #include <cmath> |
7 #include <string> | 9 #include <string> |
8 | 10 |
9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/i18n/time_formatting.h" |
10 #include "base/logging.h" | 13 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
12 #include "base/process_util.h" | 15 #include "base/process_util.h" |
| 16 #include "base/string_number_conversions.h" |
| 17 #include "base/time.h" |
13 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
14 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
15 #include "chrome/common/print_messages.h" | 20 #include "chrome/common/print_messages.h" |
16 #include "chrome/common/render_messages.h" | 21 #include "chrome/common/render_messages.h" |
17 #include "chrome/common/url_constants.h" | 22 #include "chrome/common/url_constants.h" |
18 #include "chrome/renderer/prerender/prerender_helper.h" | 23 #include "chrome/renderer/prerender/prerender_helper.h" |
19 #include "content/renderer/render_view.h" | 24 #include "content/renderer/render_view.h" |
20 #include "grit/generated_resources.h" | 25 #include "grit/generated_resources.h" |
21 #include "printing/metafile_impl.h" | 26 #include "printing/metafile_impl.h" |
22 #include "printing/print_job_constants.h" | 27 #include "printing/print_job_constants.h" |
23 #include "printing/units.h" | 28 #include "printing/units.h" |
| 29 #include "skia/ext/vector_canvas.h" |
| 30 #include "skia/ext/vector_platform_device_skia.h" |
| 31 #include "third_party/skia/include/core/SkTypeface.h" |
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" | 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" | 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" | 38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" |
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" | 39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" |
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" | 40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" |
33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
34 #include "ui/base/l10n/l10n_util.h" | 42 #include "ui/base/l10n/l10n_util.h" |
| 43 #include "ui/base/text/text_elider.h" |
35 | 44 |
36 #if defined(OS_POSIX) | 45 #if defined(OS_POSIX) |
37 #include "content/common/view_messages.h" | 46 #include "content/common/view_messages.h" |
38 #endif | 47 #endif |
39 | 48 |
| 49 using base::Time; |
40 using printing::ConvertPixelsToPoint; | 50 using printing::ConvertPixelsToPoint; |
41 using printing::ConvertPixelsToPointDouble; | 51 using printing::ConvertPixelsToPointDouble; |
| 52 using printing::ConvertPointsToPixelDouble; |
42 using printing::ConvertUnit; | 53 using printing::ConvertUnit; |
43 using printing::ConvertUnitDouble; | 54 using printing::ConvertUnitDouble; |
44 using WebKit::WebConsoleMessage; | 55 using WebKit::WebConsoleMessage; |
45 using WebKit::WebDocument; | 56 using WebKit::WebDocument; |
46 using WebKit::WebElement; | 57 using WebKit::WebElement; |
47 using WebKit::WebFrame; | 58 using WebKit::WebFrame; |
48 using WebKit::WebNode; | 59 using WebKit::WebNode; |
49 using WebKit::WebSize; | 60 using WebKit::WebSize; |
50 using WebKit::WebString; | 61 using WebKit::WebString; |
51 using WebKit::WebURLRequest; | 62 using WebKit::WebURLRequest; |
(...skipping 29 matching lines...) Expand all Loading... |
81 oldParams.params.min_shrink == newParams.params.min_shrink && | 92 oldParams.params.min_shrink == newParams.params.min_shrink && |
82 oldParams.params.dpi == newParams.params.dpi && | 93 oldParams.params.dpi == newParams.params.dpi && |
83 oldParams.params.printable_size == newParams.params.printable_size && | 94 oldParams.params.printable_size == newParams.params.printable_size && |
84 oldParams.params.selection_only == newParams.params.selection_only && | 95 oldParams.params.selection_only == newParams.params.selection_only && |
85 oldParams.params.page_size == newParams.params.page_size && | 96 oldParams.params.page_size == newParams.params.page_size && |
86 oldParams.params.margin_top == newParams.params.margin_top && | 97 oldParams.params.margin_top == newParams.params.margin_top && |
87 oldParams.params.margin_left == newParams.params.margin_left && | 98 oldParams.params.margin_left == newParams.params.margin_left && |
88 oldParams.params.supports_alpha_blend == | 99 oldParams.params.supports_alpha_blend == |
89 newParams.params.supports_alpha_blend && | 100 newParams.params.supports_alpha_blend && |
90 oldParams.pages.size() == newParams.pages.size() && | 101 oldParams.pages.size() == newParams.pages.size() && |
| 102 oldParams.params.display_header_footer == |
| 103 newParams.params.display_header_footer && |
91 std::equal(oldParams.pages.begin(), oldParams.pages.end(), | 104 std::equal(oldParams.pages.begin(), oldParams.pages.end(), |
92 newParams.pages.begin()); | 105 newParams.pages.begin()); |
93 } | 106 } |
94 | 107 |
| 108 // Splits the horizontal width equally into three segments with an interstice |
| 109 // between each segment. Returns the width of this segment. |
| 110 SkScalar GetSegmentWidth(PageSizeMargins& page_layout) { |
| 111 return (page_layout.margin_left + |
| 112 page_layout.content_width + |
| 113 page_layout.margin_right - |
| 114 (printing::kSettingHeaderFooterHorizontalRegions + 1) * |
| 115 printing::kSettingHeaderFooterInterstice) / |
| 116 printing::kSettingHeaderFooterHorizontalRegions; |
| 117 } |
| 118 |
| 119 // Given a text, the positions and the paint object, this method gets the |
| 120 // coordinates and prints the text at those co-ordinates on the canvas. |
| 121 void PrintHeaderFooterText( |
| 122 string16 text, |
| 123 SkPaint paint, |
| 124 const SkRefPtr<skia::VectorCanvas>& canvas, |
| 125 printing::HorizontalHeaderFooterPosition hor_pos, |
| 126 printing::VerticalHeaderFooterPosition ver_pos, |
| 127 float webkit_scale_factor, |
| 128 PageSizeMargins& page_layout, |
| 129 SkScalar max_text_width, |
| 130 gfx::Font font, |
| 131 SkScalar height_to_baseline) { |
| 132 text = ui::ElideText(text, font, ConvertPointsToPixelDouble(max_text_width), |
| 133 false); |
| 134 |
| 135 SkPoint text_location; |
| 136 size_t text_byte_length = text.length() * sizeof(char16); |
| 137 // Gets the (x, y) coordinate from where we want to start printing the current |
| 138 // text depending on the alignment horizontal alignment (LEFT, RIGHT, CENTER) |
| 139 // and vertical alignment (TOP, BOTTOM). |
| 140 { |
| 141 SkScalar text_width_in_points = paint.measureText(text.c_str(), |
| 142 text_byte_length); |
| 143 |
| 144 SkScalar x = 0; |
| 145 switch (hor_pos) { |
| 146 case printing::LEFT: { |
| 147 x = page_layout.margin_left * (-1) + |
| 148 printing::kSettingHeaderFooterInterstice; |
| 149 break; |
| 150 } |
| 151 case printing::RIGHT: { |
| 152 x = (page_layout.content_width + page_layout.margin_right - |
| 153 (printing::kSettingHeaderFooterInterstice + text_width_in_points)); |
| 154 break; |
| 155 } |
| 156 case printing::CENTER: { |
| 157 SkScalar available_width = GetSegmentWidth(page_layout); |
| 158 x = (available_width - page_layout.margin_left + |
| 159 (available_width - text_width_in_points) / 2); |
| 160 break; |
| 161 } |
| 162 default: { |
| 163 NOTREACHED(); |
| 164 } |
| 165 } |
| 166 |
| 167 SkScalar y = 0; |
| 168 switch (ver_pos) { |
| 169 case printing::TOP: { |
| 170 y = page_layout.margin_top * (-1) + |
| 171 printing::kSettingHeaderFooterInterstice - height_to_baseline; |
| 172 break; |
| 173 } |
| 174 case printing::BOTTOM: { |
| 175 y = page_layout.margin_bottom + page_layout.content_height - |
| 176 printing::kSettingHeaderFooterInterstice - height_to_baseline; |
| 177 break; |
| 178 } |
| 179 default: { |
| 180 NOTREACHED(); |
| 181 } |
| 182 } |
| 183 |
| 184 text_location.set(x / webkit_scale_factor, y / webkit_scale_factor); |
| 185 } |
| 186 |
| 187 paint.setTextSize(paint.getTextSize()/webkit_scale_factor); |
| 188 canvas->drawText(text.c_str(), text_byte_length, text_location.x(), |
| 189 text_location.y(), paint); |
| 190 } |
| 191 |
95 } // namespace | 192 } // namespace |
96 | 193 |
| 194 void PrintHeaderAndFooter(skia::VectorPlatformDeviceSkia* device, |
| 195 const SkRefPtr<skia::VectorCanvas>& canvas, |
| 196 int page_number, int total_pages, |
| 197 float webkit_scale_factor, |
| 198 PageSizeMargins& page_layout, |
| 199 const DictionaryValue* header_footer_info) { |
| 200 // Set the drawing area to draw in the margins. |
| 201 device->setDrawingArea(SkPDFDevice::kMargin_DrawingArea); |
| 202 |
| 203 // Setting up styles for the headers and footers text. |
| 204 SkPaint paint; |
| 205 paint.setColor(SK_ColorBLACK); |
| 206 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); |
| 207 paint.setTextSize(printing::kSettingHeaderFooterFontSize); |
| 208 gfx::Font font(UTF8ToUTF16(printing::kSettingHeaderFooterFontName), |
| 209 ceil(ConvertPointsToPixelDouble( |
| 210 printing::kSettingHeaderFooterFontSize))); |
| 211 paint.setTypeface(SkTypeface::CreateFromName( |
| 212 UTF16ToUTF8(font.GetFontName()).c_str(), |
| 213 SkTypeface::kNormal)); |
| 214 |
| 215 // Ensuring we have enough space to print above and below the page to print |
| 216 // headers. |
| 217 string16 date = base::TimeFormatShortDateNumeric(Time::Now()); |
| 218 string16 title; |
| 219 if (!header_footer_info->GetString(printing::kSettingHeaderFooterTitle, |
| 220 &title)) { |
| 221 NOTREACHED(); |
| 222 } |
| 223 |
| 224 SkRect header_bounds; |
| 225 string16 header_text = date + title; |
| 226 paint.measureText(header_text.c_str(), header_text.length() * sizeof(char16), |
| 227 &header_bounds, 0); |
| 228 SkScalar text_height = printing::kSettingHeaderFooterInterstice + |
| 229 header_bounds.height(); |
| 230 |
| 231 if (text_height > page_layout.margin_top) |
| 232 return; |
| 233 |
| 234 // Ensuring we have enough space to print above and below the page to print |
| 235 // footers. |
| 236 string16 page_on_page_total = base::IntToString16(page_number) + |
| 237 UTF8ToUTF16("/") + |
| 238 base::IntToString16(total_pages); |
| 239 std::string url; |
| 240 if (!header_footer_info->GetString(printing::kSettingHeaderFooterURL, |
| 241 &url)) { |
| 242 NOTREACHED(); |
| 243 } |
| 244 |
| 245 SkRect footer_bounds; |
| 246 string16 footer_text = page_on_page_total + UTF8ToUTF16(url); |
| 247 paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16), |
| 248 &footer_bounds, 0); |
| 249 text_height = printing::kSettingHeaderFooterInterstice + |
| 250 footer_bounds.height(); |
| 251 |
| 252 if (text_height > page_layout.margin_bottom) |
| 253 return; |
| 254 |
| 255 SkScalar segment_width = GetSegmentWidth(page_layout); |
| 256 // Printing the Date. |
| 257 PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP, |
| 258 webkit_scale_factor, page_layout, segment_width, |
| 259 font, header_bounds.top()); |
| 260 |
| 261 // Printing the title. |
| 262 SkScalar date_width = paint.measureText(date.c_str(), |
| 263 date.length() * sizeof(char16)); |
| 264 // Calculating the available title width. If the date string is not long |
| 265 // enough, then, we increase the available space we have for the title. |
| 266 // Assumes there is no header text to RIGHT of title. |
| 267 SkScalar max_title_width = std::min(2 * segment_width, |
| 268 2 * (segment_width - date_width) + |
| 269 segment_width); |
| 270 PrintHeaderFooterText(title, paint, canvas, printing::CENTER, |
| 271 printing::TOP, webkit_scale_factor, page_layout, |
| 272 max_title_width, font, header_bounds.top()); |
| 273 |
| 274 // Printing the page numbers at the bottom right corner of page. |
| 275 PrintHeaderFooterText(page_on_page_total, paint, canvas, printing::RIGHT, |
| 276 printing::BOTTOM, webkit_scale_factor, |
| 277 page_layout, segment_width, font, |
| 278 footer_bounds.bottom()); |
| 279 |
| 280 // Printing the URL. |
| 281 GURL gurl(url); |
| 282 SkScalar page_width = paint.measureText( |
| 283 page_on_page_total.c_str(), |
| 284 page_on_page_total.length() * sizeof(char16)); |
| 285 |
| 286 // Calculating the available URL width. We increase the available URL width |
| 287 // if the |page_on_page_total| string isn't long enough. |
| 288 // Assumes no footer text being printed in the CENTER. |
| 289 SkScalar max_url_width = 3 * (page_layout.content_width + |
| 290 page_layout.margin_left + page_layout.margin_right) / 4; |
| 291 max_url_width = std::min(max_url_width, |
| 292 2 * (segment_width - page_width) + segment_width); |
| 293 string16 url_elided = ui::ElideUrl(gurl, font, |
| 294 ConvertPointsToPixelDouble(max_url_width), |
| 295 std::string()); |
| 296 PrintHeaderFooterText(url_elided, paint, canvas, printing::LEFT, |
| 297 printing::BOTTOM, webkit_scale_factor, |
| 298 page_layout, max_url_width, font, |
| 299 footer_bounds.bottom()); |
| 300 |
| 301 // Restore the drawing area to draw in the content area. |
| 302 device->setDrawingArea(SkPDFDevice::kContent_DrawingArea); |
| 303 } |
| 304 |
97 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint( | 305 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint( |
98 const PrintMsg_Print_Params& print_params, | 306 const PrintMsg_Print_Params& print_params, |
99 WebFrame* frame, | 307 WebFrame* frame, |
100 WebNode* node) | 308 WebNode* node) |
101 : frame_(frame), | 309 : frame_(frame), |
102 web_view_(frame->view()), | 310 web_view_(frame->view()), |
103 expected_pages_count_(0), | 311 expected_pages_count_(0), |
104 use_browser_overlays_(true), | 312 use_browser_overlays_(true), |
105 finished_(false) { | 313 finished_(false) { |
106 int dpi = GetDPI(&print_params); | 314 int dpi = GetDPI(&print_params); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 if (!node) { | 481 if (!node) { |
274 Print(frame, NULL); | 482 Print(frame, NULL); |
275 } else { | 483 } else { |
276 // Make a copy of the node, because |print_preview_context_| will reset its | 484 // Make a copy of the node, because |print_preview_context_| will reset its |
277 // copy when the print preview tab closes. | 485 // copy when the print preview tab closes. |
278 WebNode duplicate_node(*node); | 486 WebNode duplicate_node(*node); |
279 Print(frame, &duplicate_node); | 487 Print(frame, &duplicate_node); |
280 } | 488 } |
281 } | 489 } |
282 | 490 |
283 void PrintWebViewHelper::OnPrintPreview(const DictionaryValue& settings) { | 491 void PrintWebViewHelper::OnPrintPreview( |
| 492 const DictionaryValue& settings, |
| 493 const DictionaryValue& header_footer_info) { |
284 DCHECK(is_preview_); | 494 DCHECK(is_preview_); |
285 print_preview_context_.OnPrintPreview(); | 495 print_preview_context_.OnPrintPreview(); |
| 496 header_footer_info_ = header_footer_info.DeepCopy(); |
286 | 497 |
287 if (!InitPrintSettings(print_preview_context_.frame(), | 498 if (!InitPrintSettings(print_preview_context_.frame(), |
288 print_preview_context_.node())) { | 499 print_preview_context_.node())) { |
289 NOTREACHED(); | 500 NOTREACHED(); |
290 return; | 501 return; |
291 } | 502 } |
292 | 503 |
293 if (!UpdatePrintSettings(settings)) { | 504 if (!UpdatePrintSettings(settings)) { |
294 DidFinishPrinting(FAIL_PREVIEW); | 505 DidFinishPrinting(FAIL_PREVIEW); |
295 return; | 506 return; |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 settings.params.dpi = 300.0; | 942 settings.params.dpi = 300.0; |
732 settings.params.min_shrink = 1.25; | 943 settings.params.min_shrink = 1.25; |
733 settings.params.max_shrink = 2.0; | 944 settings.params.max_shrink = 2.0; |
734 settings.params.desired_dpi = 72; | 945 settings.params.desired_dpi = 72; |
735 settings.params.selection_only = false; | 946 settings.params.selection_only = false; |
736 settings.params.supports_alpha_blend = false; | 947 settings.params.supports_alpha_blend = false; |
737 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) | 948 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) |
738 return false; | 949 return false; |
739 // TODO(abodenha@chromium.org) Parse page ranges from the job_settings. | 950 // TODO(abodenha@chromium.org) Parse page ranges from the job_settings. |
740 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); | 951 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); |
| 952 print_pages_params_->params.display_header_footer = false; |
741 return true; | 953 return true; |
742 } | 954 } |
743 | 955 |
744 bool PrintWebViewHelper::UpdatePrintSettingsLocal( | 956 bool PrintWebViewHelper::UpdatePrintSettingsLocal( |
745 const DictionaryValue& job_settings) { | 957 const DictionaryValue& job_settings) { |
746 PrintMsg_PrintPages_Params settings; | 958 PrintMsg_PrintPages_Params settings; |
747 | 959 |
748 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(), | 960 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(), |
749 print_pages_params_->params.document_cookie, job_settings, &settings)); | 961 print_pages_params_->params.document_cookie, job_settings, &settings)); |
750 | 962 |
751 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie) | 963 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie) |
752 return false; | 964 return false; |
753 | 965 |
754 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) | 966 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) |
755 return false; | 967 return false; |
756 | 968 |
757 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); | 969 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); |
| 970 bool header_footer; |
| 971 if (!job_settings.GetBoolean(printing::kSettingHeaderFooter, &header_footer)) |
| 972 NOTREACHED(); |
| 973 print_pages_params_->params.display_header_footer = header_footer; |
| 974 |
758 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), | 975 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), |
759 settings.params.document_cookie)); | 976 settings.params.document_cookie)); |
760 return true; | 977 return true; |
761 } | 978 } |
762 | 979 |
763 bool PrintWebViewHelper::UpdatePrintSettings( | 980 bool PrintWebViewHelper::UpdatePrintSettings( |
764 const DictionaryValue& job_settings) { | 981 const DictionaryValue& job_settings) { |
765 if (job_settings.HasKey(printing::kSettingCloudPrintId)) { | 982 if (job_settings.HasKey(printing::kSettingCloudPrintId)) { |
766 return UpdatePrintSettingsCloud(job_settings); | 983 return UpdatePrintSettingsCloud(job_settings); |
767 } else { | 984 } else { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 const gfx::Size& | 1286 const gfx::Size& |
1070 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const { | 1287 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const { |
1071 return prep_frame_view_->GetPrintCanvasSize(); | 1288 return prep_frame_view_->GetPrintCanvasSize(); |
1072 } | 1289 } |
1073 | 1290 |
1074 void PrintWebViewHelper::PrintPreviewContext::ClearContext() { | 1291 void PrintWebViewHelper::PrintPreviewContext::ClearContext() { |
1075 prep_frame_view_.reset(); | 1292 prep_frame_view_.reset(); |
1076 metafile_.reset(); | 1293 metafile_.reset(); |
1077 rendered_pages_.clear(); | 1294 rendered_pages_.clear(); |
1078 } | 1295 } |
OLD | NEW |