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

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: Freeing header_footer_info_ memory 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 #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"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" 32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" 34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" 35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 37 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
34 #include "ui/base/l10n/l10n_util.h" 39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/text/text_elider.h"
35 41
36 #if defined(OS_POSIX) 42 #if defined(OS_POSIX)
37 #include "content/common/view_messages.h" 43 #include "content/common/view_messages.h"
38 #endif 44 #endif
39 45
46 #if defined(USE_SKIA)
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 #endif
51
52 using base::Time;
40 using printing::ConvertPixelsToPoint; 53 using printing::ConvertPixelsToPoint;
41 using printing::ConvertPixelsToPointDouble; 54 using printing::ConvertPixelsToPointDouble;
55 using printing::ConvertPointsToPixelDouble;
42 using printing::ConvertUnit; 56 using printing::ConvertUnit;
43 using printing::ConvertUnitDouble; 57 using printing::ConvertUnitDouble;
44 using WebKit::WebConsoleMessage; 58 using WebKit::WebConsoleMessage;
45 using WebKit::WebDocument; 59 using WebKit::WebDocument;
46 using WebKit::WebElement; 60 using WebKit::WebElement;
47 using WebKit::WebFrame; 61 using WebKit::WebFrame;
48 using WebKit::WebNode; 62 using WebKit::WebNode;
49 using WebKit::WebSize; 63 using WebKit::WebSize;
50 using WebKit::WebString; 64 using WebKit::WebString;
51 using WebKit::WebURLRequest; 65 using WebKit::WebURLRequest;
(...skipping 29 matching lines...) Expand all
81 oldParams.params.min_shrink == newParams.params.min_shrink && 95 oldParams.params.min_shrink == newParams.params.min_shrink &&
82 oldParams.params.dpi == newParams.params.dpi && 96 oldParams.params.dpi == newParams.params.dpi &&
83 oldParams.params.printable_size == newParams.params.printable_size && 97 oldParams.params.printable_size == newParams.params.printable_size &&
84 oldParams.params.selection_only == newParams.params.selection_only && 98 oldParams.params.selection_only == newParams.params.selection_only &&
85 oldParams.params.page_size == newParams.params.page_size && 99 oldParams.params.page_size == newParams.params.page_size &&
86 oldParams.params.margin_top == newParams.params.margin_top && 100 oldParams.params.margin_top == newParams.params.margin_top &&
87 oldParams.params.margin_left == newParams.params.margin_left && 101 oldParams.params.margin_left == newParams.params.margin_left &&
88 oldParams.params.supports_alpha_blend == 102 oldParams.params.supports_alpha_blend ==
89 newParams.params.supports_alpha_blend && 103 newParams.params.supports_alpha_blend &&
90 oldParams.pages.size() == newParams.pages.size() && 104 oldParams.pages.size() == newParams.pages.size() &&
105 oldParams.params.display_header_footer ==
106 newParams.params.display_header_footer &&
91 std::equal(oldParams.pages.begin(), oldParams.pages.end(), 107 std::equal(oldParams.pages.begin(), oldParams.pages.end(),
92 newParams.pages.begin()); 108 newParams.pages.begin());
93 } 109 }
94 110
111 #if defined(USE_SKIA)
112 // Splits the horizontal width equally into segments with an interstice
113 // between each segment. Returns the width of this segment.
114 SkScalar GetSegmentWidth(const PageSizeMargins& page_layout) {
115 return (page_layout.margin_left +
116 page_layout.content_width +
117 page_layout.margin_right -
118 // Interstice is left at both ends of the page as well as between
vandebo (ex-Chrome) 2011/07/26 08:08:55 Put the comment outside
Aayush Kumar 2011/07/26 08:52:28 Done.
119 // each region, so 1 is added.
120 (printing::kSettingHeaderFooterHorizontalRegions + 1) *
vandebo (ex-Chrome) 2011/07/26 08:08:55 Indent the () block one more.
Aayush Kumar 2011/07/26 08:52:28 Done.
121 printing::kSettingHeaderFooterInterstice) /
122 printing::kSettingHeaderFooterHorizontalRegions;
123 }
124
125 // Given a text, the positions, and the paint object, this method gets the
126 // coordinates and prints the text at those coordinates on the canvas.
127 void PrintHeaderFooterText(
128 string16 text,
129 SkPaint paint,
130 skia::VectorCanvas& canvas,
131 printing::HorizontalHeaderFooterPosition horizontal_position,
132 printing::VerticalHeaderFooterPosition vertical_position,
133 float webkit_scale_factor,
134 const PageSizeMargins& page_layout,
135 SkScalar max_text_width,
136 gfx::Font font,
137 SkScalar height_to_baseline) {
138 text = ui::ElideText(text, font, ConvertPointsToPixelDouble(max_text_width),
139 false);
140
141 SkPoint text_location;
142 size_t text_byte_length = text.length() * sizeof(char16);
143 // Get the (x, y) coordinate from where printing of the current text should
144 // start depending on the horizontal alignment (LEFT, RIGHT, CENTER) and
145 // vertical alignment (TOP, BOTTOM).
146 SkScalar text_width_in_points = paint.measureText(text.c_str(),
147 text_byte_length);
148 SkScalar x = 0;
149 switch (horizontal_position) {
150 case printing::LEFT: {
151 x = -page_layout.margin_left +
152 printing::kSettingHeaderFooterInterstice;
153 break;
154 }
155 case printing::RIGHT: {
156 x = (page_layout.content_width + page_layout.margin_right -
157 (printing::kSettingHeaderFooterInterstice + text_width_in_points));
158 break;
159 }
160 case printing::CENTER: {
161 SkScalar available_width = GetSegmentWidth(page_layout);
162 x = available_width - page_layout.margin_left +
163 (available_width - text_width_in_points) / 2;
164 break;
165 }
166 default: {
167 NOTREACHED();
168 }
169 }
170
171 SkScalar y = 0;
172 switch (vertical_position) {
173 case printing::TOP: {
174 y = -page_layout.margin_top - height_to_baseline +
175 printing::kSettingHeaderFooterInterstice;
176 break;
177 }
178 case printing::BOTTOM: {
179 y = page_layout.margin_bottom + page_layout.content_height -
180 printing::kSettingHeaderFooterInterstice - height_to_baseline;
181 break;
182 }
183 default: {
184 NOTREACHED();
185 }
186 }
187
188 text_location.set(x / webkit_scale_factor, y / webkit_scale_factor);
189 paint.setTextSize(paint.getTextSize() / webkit_scale_factor);
190 canvas.drawText(text.c_str(), text_byte_length, text_location.x(),
191 text_location.y(), paint);
192 }
193 #endif
95 } // namespace 194 } // namespace
96 195
196 #if defined(USE_SKIA)
197 void PrintHeaderAndFooter(SkDevice* device,
198 skia::VectorCanvas& canvas,
199 int page_number, int total_pages,
200 float webkit_scale_factor,
201 const PageSizeMargins& page_layout,
202 const DictionaryValue* header_footer_info) {
203 // Set the drawing area to draw in the margins.
204 static_cast<skia::VectorPlatformDeviceSkia*>(device)->
205 setDrawingArea(SkPDFDevice::kMargin_DrawingArea);
vandebo (ex-Chrome) 2011/07/26 08:08:55 wrap the argument foo->bar(<newline>
Aayush Kumar 2011/07/26 08:52:28 Done.
206
207 // Setting up styles for the headers and footers text.
208 SkPaint paint;
209 paint.setColor(SK_ColorBLACK);
210 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
211 paint.setTextSize(printing::kSettingHeaderFooterFontSize);
212 gfx::Font font(UTF8ToUTF16(printing::kSettingHeaderFooterFontName),
213 ceil(ConvertPointsToPixelDouble(
214 printing::kSettingHeaderFooterFontSize)));
vandebo (ex-Chrome) 2011/07/26 08:08:55 one more space
Aayush Kumar 2011/07/26 08:52:28 Done.
215 paint.setTypeface(SkTypeface::CreateFromName(
216 UTF16ToUTF8(font.GetFontName()).c_str(), SkTypeface::kNormal));
217
218 // Ensure we have enough space to print above and below the page to print
219 // headers.
220 string16 date = base::TimeFormatShortDateNumeric(Time::Now());
221 string16 title;
222 if (!header_footer_info->GetString(printing::kSettingHeaderFooterTitle,
223 &title)) {
224 NOTREACHED();
225 }
226
227 SkRect header_bounds;
228 string16 header_text = date + title;
229 paint.measureText(header_text.c_str(), header_text.length() * sizeof(char16),
230 &header_bounds, 0);
231
232 SkScalar text_height =
233 printing::kSettingHeaderFooterInterstice + header_bounds.height();
234
235 if (text_height > page_layout.margin_top)
236 return;
237
238 // Ensure we have enough space to print above and below the page to print
239 // footers.
240 string16 page_of_total_pages = base::IntToString16(page_number) +
241 UTF8ToUTF16("/") +
242 base::IntToString16(total_pages);
243 std::string url;
244 if (!header_footer_info->GetString(printing::kSettingHeaderFooterURL,
245 &url)) {
246 NOTREACHED();
247 }
248
249 SkRect footer_bounds;
250 string16 footer_text = page_of_total_pages + UTF8ToUTF16(url);
251 paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16),
252 &footer_bounds, 0);
253
254 text_height =
255 printing::kSettingHeaderFooterInterstice + footer_bounds.height();
256
257 if (text_height > page_layout.margin_bottom)
258 return;
259
260 SkScalar segment_width = GetSegmentWidth(page_layout);
261 // Print the Date.
262 PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP,
263 webkit_scale_factor, page_layout, segment_width,
264 font, header_bounds.top());
265
266 // Print the title.
267 SkScalar date_width = paint.measureText(date.c_str(),
268 date.length() * sizeof(char16));
269 // Calculate the available title width. If the date string is not long
270 // enough, then, we increase the available space we have for the title.
271 // Assumes there is no header text to RIGHT of title.
272 SkScalar max_title_width = std::min(2 * segment_width,
273 2 * (segment_width - date_width) +
274 segment_width);
275 PrintHeaderFooterText(title, paint, canvas, printing::CENTER,
276 printing::TOP, webkit_scale_factor, page_layout,
277 max_title_width, font, header_bounds.top());
278
279 // Print the page numbers at the bottom right corner of page.
280 PrintHeaderFooterText(page_of_total_pages, paint, canvas, printing::RIGHT,
281 printing::BOTTOM, webkit_scale_factor,
282 page_layout, segment_width, font,
283 footer_bounds.bottom());
284
285 // Print the URL.
286 GURL gurl(url);
287 SkScalar page_width = paint.measureText(
288 page_of_total_pages.c_str(),
289 page_of_total_pages.length() * sizeof(char16));
290
291 // Calculate the available URL width. We increase the available URL width
292 // if the |page_of_total_pages| string isn't long enough.
293 // Assumes no footer text being printed in the CENTER.
294 SkScalar max_url_width =
295 (page_layout.content_width + page_layout.margin_left +
296 page_layout.margin_right) * 3 / 4;
297 max_url_width = std::min(max_url_width,
298 2 * (segment_width - page_width) + segment_width);
299 string16 url_elided = ui::ElideUrl(gurl, font,
300 ConvertPointsToPixelDouble(max_url_width),
301 std::string());
302 PrintHeaderFooterText(url_elided, paint, canvas, printing::LEFT,
303 printing::BOTTOM, webkit_scale_factor,
304 page_layout, max_url_width, font,
305 footer_bounds.bottom());
306
307 // Restore the drawing area to draw in the content area.
308 static_cast<skia::VectorPlatformDeviceSkia*>(device)->
vandebo (ex-Chrome) 2011/07/26 08:08:55 Here too
Aayush Kumar 2011/07/26 08:52:28 Done.
309 setDrawingArea(SkPDFDevice::kContent_DrawingArea);
310 }
311 #endif
312
97 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint( 313 PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
98 const PrintMsg_Print_Params& print_params, 314 const PrintMsg_Print_Params& print_params,
99 WebFrame* frame, 315 WebFrame* frame,
100 WebNode* node) 316 WebNode* node)
101 : frame_(frame), 317 : frame_(frame),
102 web_view_(frame->view()), 318 web_view_(frame->view()),
103 expected_pages_count_(0), 319 expected_pages_count_(0),
104 use_browser_overlays_(true), 320 use_browser_overlays_(true),
105 finished_(false) { 321 finished_(false) {
106 int dpi = GetDPI(&print_params); 322 int dpi = GetDPI(&print_params);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 if (WebFrame* web_frame = web_view_->mainFrame()) 363 if (WebFrame* web_frame = web_view_->mainFrame())
148 web_frame->setScrollOffset(prev_scroll_offset_); 364 web_frame->setScrollOffset(prev_scroll_offset_);
149 } 365 }
150 } 366 }
151 367
152 PrintWebViewHelper::PrintWebViewHelper(RenderView* render_view) 368 PrintWebViewHelper::PrintWebViewHelper(RenderView* render_view)
153 : RenderViewObserver(render_view), 369 : RenderViewObserver(render_view),
154 RenderViewObserverTracker<PrintWebViewHelper>(render_view), 370 RenderViewObserverTracker<PrintWebViewHelper>(render_view),
155 print_web_view_(NULL), 371 print_web_view_(NULL),
156 user_cancelled_scripted_print_count_(0), 372 user_cancelled_scripted_print_count_(0),
157 notify_browser_of_print_failure_(true) { 373 notify_browser_of_print_failure_(true),
374 header_footer_info_(NULL) {
158 is_preview_ = switches::IsPrintPreviewEnabled(); 375 is_preview_ = switches::IsPrintPreviewEnabled();
159 } 376 }
160 377
161 PrintWebViewHelper::~PrintWebViewHelper() {} 378 PrintWebViewHelper::~PrintWebViewHelper() {
379 if (header_footer_info_)
380 delete header_footer_info_;
vandebo (ex-Chrome) 2011/07/26 08:08:55 use a scoped_ptr instead
Aayush Kumar 2011/07/26 08:52:28 Done.
381 }
162 382
163 // Prints |frame| which called window.print(). 383 // Prints |frame| which called window.print().
164 void PrintWebViewHelper::PrintPage(WebKit::WebFrame* frame) { 384 void PrintWebViewHelper::PrintPage(WebKit::WebFrame* frame) {
165 DCHECK(frame); 385 DCHECK(frame);
166 386
167 // Allow Prerendering to cancel this print request if necessary. 387 // Allow Prerendering to cancel this print request if necessary.
168 if (prerender::PrerenderHelper::IsPrerendering(render_view())) { 388 if (prerender::PrerenderHelper::IsPrerendering(render_view())) {
169 Send(new ViewHostMsg_CancelPrerenderForPrinting(routing_id())); 389 Send(new ViewHostMsg_CancelPrerenderForPrinting(routing_id()));
170 return; 390 return;
171 } 391 }
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(), 939 Send(new PrintHostMsg_UpdatePrintSettings(routing_id(),
720 print_pages_params_->params.document_cookie, job_settings, &settings)); 940 print_pages_params_->params.document_cookie, job_settings, &settings));
721 941
722 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie) 942 if (settings.params.dpi < kMinDpi || !settings.params.document_cookie)
723 return false; 943 return false;
724 944
725 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params))) 945 if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params)))
726 return false; 946 return false;
727 947
728 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); 948 print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
949 // Getting Header and Footer settings.
950 bool display_header_footer;
951 if (!job_settings.GetBoolean(printing::kSettingHeaderFooter,
952 &display_header_footer)) {
953 NOTREACHED();
954 }
955 print_pages_params_->params.display_header_footer = display_header_footer;
956 std::string url;
957 if (!job_settings.GetString(printing::kSettingHeaderFooterURL, &url))
958 NOTREACHED();
959
960 if (!header_footer_info_)
961 header_footer_info_ = new DictionaryValue();
962 header_footer_info_->SetString(printing::kSettingHeaderFooterURL, url);
963 string16 title;
964 if (!job_settings.GetString(printing::kSettingHeaderFooterTitle, &title))
965 NOTREACHED();
966 header_footer_info_->SetString(printing::kSettingHeaderFooterTitle, title);
967
729 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), 968 Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
730 settings.params.document_cookie)); 969 settings.params.document_cookie));
731 return true; 970 return true;
732 } 971 }
733 972
734 bool PrintWebViewHelper::GetPrintSettingsFromUser(WebKit::WebFrame* frame, 973 bool PrintWebViewHelper::GetPrintSettingsFromUser(WebKit::WebFrame* frame,
735 int expected_pages_count, 974 int expected_pages_count,
736 bool use_browser_overlays) { 975 bool use_browser_overlays) {
737 PrintHostMsg_ScriptedPrint_Params params; 976 PrintHostMsg_ScriptedPrint_Params params;
738 PrintMsg_PrintPages_Params print_settings; 977 PrintMsg_PrintPages_Params print_settings;
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 const gfx::Size& 1270 const gfx::Size&
1032 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const { 1271 PrintWebViewHelper::PrintPreviewContext::GetPrintCanvasSize() const {
1033 return prep_frame_view_->GetPrintCanvasSize(); 1272 return prep_frame_view_->GetPrintCanvasSize();
1034 } 1273 }
1035 1274
1036 void PrintWebViewHelper::PrintPreviewContext::ClearContext() { 1275 void PrintWebViewHelper::PrintPreviewContext::ClearContext() {
1037 prep_frame_view_.reset(); 1276 prep_frame_view_.reset();
1038 metafile_.reset(); 1277 metafile_.reset();
1039 rendered_pages_.clear(); 1278 rendered_pages_.clear();
1040 } 1279 }
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