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

Side by Side Diff: chrome/renderer/print_web_view_helper.cc

Issue 7348010: Added Header and Footer support using Skia (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Now we print either headers or footers (if we have space to print any). Created 9 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « chrome/renderer/print_web_view_helper.h ('k') | chrome/renderer/print_web_view_helper_linux.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #if defined(USE_SKIA)
8 #include <algorithm>
9 #include <cmath>
vandebo (ex-Chrome) 2011/08/04 20:46:22 what's cmath for?
Aayush Kumar 2011/08/04 23:00:30 I use ceil (while declaring gfx::font), as gfx::fo
10 #endif
7 #include <string> 11 #include <string>
8 12
9 #include "base/command_line.h" 13 #include "base/command_line.h"
10 #include "base/logging.h" 14 #include "base/logging.h"
11 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
12 #include "base/process_util.h" 16 #include "base/process_util.h"
13 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
14 #include "chrome/common/chrome_switches.h" 18 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/print_messages.h" 19 #include "chrome/common/print_messages.h"
16 #include "chrome/common/render_messages.h" 20 #include "chrome/common/render_messages.h"
(...skipping 12 matching lines...) Expand all
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" 34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
33 #include "ui/base/l10n/l10n_util.h" 37 #include "ui/base/l10n/l10n_util.h"
34 38
35 #if defined(OS_POSIX) 39 #if defined(OS_POSIX)
36 #include "content/common/view_messages.h" 40 #include "content/common/view_messages.h"
37 #endif 41 #endif
38 42
43 #if defined(USE_SKIA)
44 #include "base/i18n/time_formatting.h"
45 #include "base/string_number_conversions.h"
46 #include "base/time.h"
47 #include "skia/ext/vector_canvas.h"
48 #include "skia/ext/vector_platform_device_skia.h"
49 #include "third_party/skia/include/core/SkTypeface.h"
50 #include "ui/base/text/text_elider.h"
51 #endif // USE_SKIA
52
53 using base::Time;
39 using printing::ConvertPixelsToPoint; 54 using printing::ConvertPixelsToPoint;
40 using printing::ConvertPixelsToPointDouble; 55 using printing::ConvertPixelsToPointDouble;
56 using printing::ConvertPointsToPixelDouble;
41 using printing::ConvertUnit; 57 using printing::ConvertUnit;
42 using printing::ConvertUnitDouble; 58 using printing::ConvertUnitDouble;
43 using WebKit::WebConsoleMessage; 59 using WebKit::WebConsoleMessage;
44 using WebKit::WebDocument; 60 using WebKit::WebDocument;
45 using WebKit::WebElement; 61 using WebKit::WebElement;
46 using WebKit::WebFrame; 62 using WebKit::WebFrame;
47 using WebKit::WebNode; 63 using WebKit::WebNode;
48 using WebKit::WebSize; 64 using WebKit::WebSize;
49 using WebKit::WebString; 65 using WebKit::WebString;
50 using WebKit::WebURLRequest; 66 using WebKit::WebURLRequest;
(...skipping 29 matching lines...) Expand all
80 oldParams.params.min_shrink == newParams.params.min_shrink && 96 oldParams.params.min_shrink == newParams.params.min_shrink &&
81 oldParams.params.dpi == newParams.params.dpi && 97 oldParams.params.dpi == newParams.params.dpi &&
82 oldParams.params.printable_size == newParams.params.printable_size && 98 oldParams.params.printable_size == newParams.params.printable_size &&
83 oldParams.params.selection_only == newParams.params.selection_only && 99 oldParams.params.selection_only == newParams.params.selection_only &&
84 oldParams.params.page_size == newParams.params.page_size && 100 oldParams.params.page_size == newParams.params.page_size &&
85 oldParams.params.margin_top == newParams.params.margin_top && 101 oldParams.params.margin_top == newParams.params.margin_top &&
86 oldParams.params.margin_left == newParams.params.margin_left && 102 oldParams.params.margin_left == newParams.params.margin_left &&
87 oldParams.params.supports_alpha_blend == 103 oldParams.params.supports_alpha_blend ==
88 newParams.params.supports_alpha_blend && 104 newParams.params.supports_alpha_blend &&
89 oldParams.pages.size() == newParams.pages.size() && 105 oldParams.pages.size() == newParams.pages.size() &&
106 oldParams.params.display_header_footer ==
107 newParams.params.display_header_footer &&
90 std::equal(oldParams.pages.begin(), oldParams.pages.end(), 108 std::equal(oldParams.pages.begin(), oldParams.pages.end(),
91 newParams.pages.begin()); 109 newParams.pages.begin());
92 } 110 }
93 111
94 void CalculatePrintCanvasSize(const PrintMsg_Print_Params& print_params, 112 void CalculatePrintCanvasSize(const PrintMsg_Print_Params& print_params,
95 gfx::Size* result) { 113 gfx::Size* result) {
96 int dpi = GetDPI(&print_params); 114 int dpi = GetDPI(&print_params);
97 result->set_width(ConvertUnit(print_params.printable_size.width(), dpi, 115 result->set_width(ConvertUnit(print_params.printable_size.width(), dpi,
98 print_params.desired_dpi)); 116 print_params.desired_dpi));
99 117
100 result->set_height(ConvertUnit(print_params.printable_size.height(), dpi, 118 result->set_height(ConvertUnit(print_params.printable_size.height(), dpi,
101 print_params.desired_dpi)); 119 print_params.desired_dpi));
102 } 120 }
103 121
122 #if defined(USE_SKIA)
123 // Splits the horizontal width equally into segments with an interstice
124 // between each segment. Returns the width of this segment.
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: "...of this segment." => of a segment.
Aayush Kumar 2011/08/04 23:00:30 Done.
125 SkScalar GetSegmentWidth(const PageSizeMargins& page_layout) {
126 SkScalar page_width = page_layout.margin_left +
127 page_layout.content_width +
kmadhusu 2011/08/04 19:15:15 style nit: 4 space indentation is not required her
vandebo (ex-Chrome) 2011/08/04 20:46:22 Oops, Mea culpa
Aayush Kumar 2011/08/04 23:00:30 Done.
128 page_layout.margin_right;
129 // Interstice is left at both ends of the page as well as between
130 // each region, so 1 is added.
131 SkScalar total_interstice_width =
132 (printing::kSettingHeaderFooterHorizontalRegions + 1) *
133 printing::kSettingHeaderFooterInterstice;
134 return (page_width - total_interstice_width) /
135 printing::kSettingHeaderFooterHorizontalRegions;
136 }
137
138 // Given a text, the positions, and the paint object, this method gets the
139 // coordinates and prints the text at those coordinates on the canvas.
140 void PrintHeaderFooterText(
141 string16 text,
142 SkPaint paint,
143 skia::VectorCanvas* canvas,
144 printing::HorizontalHeaderFooterPosition horizontal_position,
145 printing::VerticalHeaderFooterPosition vertical_position,
146 float webkit_scale_factor,
147 const PageSizeMargins& page_layout,
148 SkScalar max_text_width,
149 const gfx::Font& font,
150 SkScalar height_to_baseline) {
151 text = ui::ElideText(text, font, ConvertPointsToPixelDouble(max_text_width),
152 false);
153
154 size_t text_byte_length = text.length() * sizeof(char16);
155 // Get the (x, y) coordinate from where printing of the current text should
156 // start depending on the horizontal alignment (LEFT, RIGHT, CENTER) and
157 // vertical alignment (TOP, BOTTOM).
158 SkScalar text_width_in_points = paint.measureText(text.c_str(),
159 text_byte_length);
160 SkScalar x = 0;
161 switch (horizontal_position) {
162 case printing::LEFT: {
163 x = printing::kSettingHeaderFooterInterstice - page_layout.margin_left;
164 break;
165 }
166 case printing::RIGHT: {
167 x = page_layout.content_width + page_layout.margin_right -
168 printing::kSettingHeaderFooterInterstice - text_width_in_points;
169 break;
170 }
171 case printing::CENTER: {
172 SkScalar available_width = GetSegmentWidth(page_layout);
173 x = available_width - page_layout.margin_left +
174 (available_width - text_width_in_points) / 2;
175 break;
176 }
177 default: {
178 NOTREACHED();
179 }
180 }
181
182 SkScalar y = 0;
183 switch (vertical_position) {
184 case printing::TOP: {
185 y = printing::kSettingHeaderFooterInterstice -
186 page_layout.margin_top - height_to_baseline;
187 break;
188 }
189 case printing::BOTTOM: {
190 y = page_layout.margin_bottom + page_layout.content_height -
191 printing::kSettingHeaderFooterInterstice - height_to_baseline;
192 break;
193 }
194 default: {
195 NOTREACHED();
196 }
197 }
198
199 x = x / webkit_scale_factor;
200 y = y / webkit_scale_factor;
201 paint.setTextSize(paint.getTextSize() / webkit_scale_factor);
202 canvas->drawText(text.c_str(), text_byte_length, x, y, paint);
203 }
204
205 // Prints the headers onto the |canvas| if there is enough space to print them.
206 void PrintHeaders(skia::VectorCanvas* canvas,
207 const DictionaryValue& header_footer_info,
208 SkPaint paint,
209 const PageSizeMargins& page_layout,
210 float webkit_scale_factor,
211 const gfx::Font& font) {
212 string16 date = base::TimeFormatShortDateNumeric(Time::Now());
213 string16 title;
214 if (!header_footer_info.GetString(printing::kSettingHeaderFooterTitle,
215 &title)) {
216 NOTREACHED();
217 }
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: I don't follow your code sectioning. I sugge
Aayush Kumar 2011/08/04 23:00:30 Done.
218
219 string16 header_text = date + title;
220 SkRect header_bounds;
221 paint.measureText(header_text.c_str(), header_text.length() * sizeof(char16),
222 &header_bounds, 0);
223
224 SkScalar text_height =
225 printing::kSettingHeaderFooterInterstice + header_bounds.height();
226
227 if (text_height > page_layout.margin_top)
228 return;
229
230 SkScalar segment_width = GetSegmentWidth(page_layout);
231 PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP,
232 webkit_scale_factor, page_layout, segment_width, font,
233 header_bounds.top());
234
235 SkScalar date_width = paint.measureText(date.c_str(),
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: Push this below the comment (240).
Aayush Kumar 2011/08/04 23:00:30 Done.
236 date.length() * sizeof(char16));
237 // Calculate the available title width. If the date string is not long
238 // enough, then, we increase the available space we have for the title.
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: ", then, we " => ", " "we have " => ""
Aayush Kumar 2011/08/04 23:00:30 Done.
239 // Assumes there is no header text to RIGHT of title.
240 SkScalar max_title_width = std::min(2 * segment_width,
241 2 * (segment_width - date_width) +
242 segment_width);
243 PrintHeaderFooterText(title, paint, canvas, printing::CENTER,
244 printing::TOP, webkit_scale_factor, page_layout,
245 max_title_width, font, header_bounds.top());
246 }
247
248 // Prints the footers onto the |canvas| if there is enough space to print them.
249 void PrintFooters(skia::VectorCanvas* canvas,
vandebo (ex-Chrome) 2011/08/04 20:46:22 Same comments as PrintHeaders
Aayush Kumar 2011/08/04 23:00:30 Done.
250 const DictionaryValue& header_footer_info,
251 SkPaint paint,
252 const PageSizeMargins& page_layout,
253 float webkit_scale_factor,
254 const gfx::Font& font,
255 int page_number,
256 int total_pages) {
257 string16 page_of_total_pages = base::IntToString16(page_number) +
258 UTF8ToUTF16("/") +
259 base::IntToString16(total_pages);
260 std::string url;
261 if (!header_footer_info.GetString(printing::kSettingHeaderFooterURL,
262 &url)) {
263 NOTREACHED();
264 }
265
266 string16 footer_text = page_of_total_pages + UTF8ToUTF16(url);
267 SkRect footer_bounds;
268 paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16),
269 &footer_bounds, 0);
270
271 SkScalar text_height =
272 printing::kSettingHeaderFooterInterstice + footer_bounds.height();
273
274 if (text_height > page_layout.margin_bottom)
275 return;
276
277 SkScalar segment_width = GetSegmentWidth(page_layout);
278 PrintHeaderFooterText(page_of_total_pages, paint, canvas, printing::RIGHT,
279 printing::BOTTOM, webkit_scale_factor, page_layout,
280 segment_width, font, footer_bounds.bottom());
281
282 GURL gurl(url);
283 SkScalar page_width = paint.measureText(
284 page_of_total_pages.c_str(),
285 page_of_total_pages.length() * sizeof(char16));
286
287 // Calculate the available URL width. We increase the available URL width
288 // if the |page_of_total_pages| string isn't long enough.
289 // Assumes no footer text being printed in the CENTER.
290 SkScalar max_url_width =
291 (page_layout.content_width + page_layout.margin_left +
292 page_layout.margin_right) * 3 / 4;
kmadhusu 2011/08/04 19:15:15 style nit: 4 space indentation is not required her
Aayush Kumar 2011/08/04 23:00:30 Done.
293 max_url_width = std::min(max_url_width,
294 2 * (segment_width - page_width) + segment_width);
295 string16 url_elided = ui::ElideUrl(gurl, font,
296 ConvertPointsToPixelDouble(max_url_width),
297 std::string());
298 PrintHeaderFooterText(url_elided, paint, canvas, printing::LEFT,
299 printing::BOTTOM, webkit_scale_factor, page_layout,
300 max_url_width, font, footer_bounds.bottom());
301 }
302 #endif // USE_SKIA
303
104 } // namespace 304 } // namespace
105 305
306 #if defined(USE_SKIA)
307 // static - Not anonymous so that platform implementations can use it.
308 void PrintWebViewHelper::PrintHeaderAndFooter(
309 SkDevice* device,
310 skia::VectorCanvas* canvas,
311 int page_number,
312 int total_pages,
313 float webkit_scale_factor,
314 const PageSizeMargins& page_layout,
315 const DictionaryValue& header_footer_info) {
316 static_cast<skia::VectorPlatformDeviceSkia*>(device)->setDrawingArea(
317 SkPDFDevice::kMargin_DrawingArea);
318
319 // Setting up styles for the headers and footers text.
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: comment seems unnecessary.
Aayush Kumar 2011/08/04 23:00:30 Done.
320 SkPaint paint;
321 paint.setColor(SK_ColorBLACK);
322 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
323 paint.setTextSize(printing::kSettingHeaderFooterFontSize);
324 gfx::Font font(UTF8ToUTF16(printing::kSettingHeaderFooterFontName),
325 ceil(ConvertPointsToPixelDouble(
326 printing::kSettingHeaderFooterFontSize)));
327 paint.setTypeface(SkTypeface::CreateFromName(
328 UTF16ToUTF8(font.GetFontName()).c_str(), SkTypeface::kNormal));
329
330 PrintHeaders(canvas, header_footer_info, paint, page_layout,
331 webkit_scale_factor, font);
332
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: extra space.
Aayush Kumar 2011/08/04 23:00:30 Done.
333 PrintFooters(canvas, header_footer_info, paint, page_layout,
334 webkit_scale_factor, font, page_number, total_pages);
335
336 static_cast<skia::VectorPlatformDeviceSkia*>(device)->setDrawingArea(
337 SkPDFDevice::kContent_DrawingArea);
338 }
339 #endif // USE_SKIA
340
106 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint( 341 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
107 const PrintMsg_Print_Params& print_params, 342 const PrintMsg_Print_Params& print_params,
108 WebFrame* frame, 343 WebFrame* frame,
109 WebNode* node) 344 WebNode* node)
110 : frame_(frame), 345 : frame_(frame),
111 web_view_(frame->view()), 346 web_view_(frame->view()),
112 dpi_(static_cast<int>(print_params.dpi)), 347 dpi_(static_cast<int>(print_params.dpi)),
113 expected_pages_count_(0), 348 expected_pages_count_(0),
114 use_browser_overlays_(true), 349 use_browser_overlays_(true),
115 finished_(false) { 350 finished_(false) {
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 return false; 993 return false;
759 } 994 }
760 return true; 995 return true;
761 } 996 }
762 997
763 bool PrintWebViewHelper::UpdatePrintSettings( 998 bool PrintWebViewHelper::UpdatePrintSettings(
764 const DictionaryValue& job_settings) { 999 const DictionaryValue& job_settings) {
765 PrintMsg_PrintPages_Params settings; 1000 PrintMsg_PrintPages_Params settings;
766 1001
767 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(), 1002 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(),
768 print_pages_params_->params.document_cookie, job_settings, &settings)); 1003 print_pages_params_->params.document_cookie, job_settings, &settings));
769 1004
1005 settings.params.margin_top = 0;
kmadhusu 2011/08/04 19:49:17 Why are you resetting the margin top to zero?
Aayush Kumar 2011/08/04 23:00:30 sorry about that! :)
770 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie) 1006 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie)
771 return false; 1007 return false;
772 1008
773 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) 1009 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params)))
774 return false; 1010 return false;
775 1011
776 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); 1012 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
1013 // Getting Header and Footer settings.
1014 bool display_header_footer = false;
1015 if (!job_settings.GetBoolean(printing::kSettingHeaderFooterEnabled,
1016 &display_header_footer)) {
kmadhusu 2011/08/04 19:15:15 Fix indentation. Remove a blank space in front of
Aayush Kumar 2011/08/04 23:00:30 Done.
1017 NOTREACHED();
1018 }
1019 print_pages_params_->params.display_header_footer = display_header_footer;
1020
1021 if (display_header_footer) {
1022 string16 title;
1023 std::string url;
1024 if (!job_settings.GetString(printing::kSettingHeaderFooterTitle, &title) ||
1025 !job_settings.GetString(printing::kSettingHeaderFooterURL, &url)) {
1026 NOTREACHED();
1027 }
1028 header_footer_info_.reset(new DictionaryValue());
1029 header_footer_info_->SetString(printing::kSettingHeaderFooterURL, url);
1030 header_footer_info_->SetString(printing::kSettingHeaderFooterTitle, title);
1031 }
1032
777 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), 1033 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
778 settings.params.document_cookie)); 1034 settings.params.document_cookie));
779 return true; 1035 return true;
780 } 1036 }
781 1037
782 bool PrintWebViewHelper::GetPrintSettingsFromUser(WebKit::WebFrame* frame, 1038 bool PrintWebViewHelper::GetPrintSettingsFromUser(WebKit::WebFrame* frame,
783 int expected_pages_count, 1039 int expected_pages_count,
784 bool use_browser_overlays) { 1040 bool use_browser_overlays) {
785 PrintHostMsg_ScriptedPrint_Params params; 1041 PrintHostMsg_ScriptedPrint_Params params;
786 PrintMsg_PrintPages_Params print_settings; 1042 PrintMsg_PrintPages_Params print_settings;
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 const gfx::Size& 1372 const gfx::Size&
1117 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const { 1373 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const {
1118 return prep_frame_view_->GetPrintCanvasSize(); 1374 return prep_frame_view_->GetPrintCanvasSize();
1119 } 1375 }
1120 1376
1121 void PrintWebViewHelper::PrintPreviewContext::ClearContext() { 1377 void PrintWebViewHelper::PrintPreviewContext::ClearContext() {
1122 prep_frame_view_.reset(); 1378 prep_frame_view_.reset();
1123 metafile_.reset(); 1379 metafile_.reset();
1124 rendered_pages_.clear(); 1380 rendered_pages_.clear();
1125 } 1381 }
OLDNEW
« no previous file with comments | « chrome/renderer/print_web_view_helper.h ('k') | chrome/renderer/print_web_view_helper_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698