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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/renderer/print_web_view_helper.cc
diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc
index 1735d90b7e661e1a46a8eebc778efd4688d310ab..68c235c92d91630f7ef235bfa198e4732620bbda 100644
--- a/chrome/renderer/print_web_view_helper.cc
+++ b/chrome/renderer/print_web_view_helper.cc
@@ -4,6 +4,10 @@
#include "chrome/renderer/print_web_view_helper.h"
+#if defined(USE_SKIA)
+#include <algorithm>
+#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
+#endif
#include <string>
#include "base/command_line.h"
@@ -36,8 +40,20 @@
#include "content/common/view_messages.h"
#endif
+#if defined(USE_SKIA)
+#include "base/i18n/time_formatting.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+#include "skia/ext/vector_canvas.h"
+#include "skia/ext/vector_platform_device_skia.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "ui/base/text/text_elider.h"
+#endif // USE_SKIA
+
+using base::Time;
using printing::ConvertPixelsToPoint;
using printing::ConvertPixelsToPointDouble;
+using printing::ConvertPointsToPixelDouble;
using printing::ConvertUnit;
using printing::ConvertUnitDouble;
using WebKit::WebConsoleMessage;
@@ -87,6 +103,8 @@ bool PrintMsg_Print_Params_IsEqual(
oldParams.params.supports_alpha_blend ==
newParams.params.supports_alpha_blend &&
oldParams.pages.size() == newParams.pages.size() &&
+ oldParams.params.display_header_footer ==
+ newParams.params.display_header_footer &&
std::equal(oldParams.pages.begin(), oldParams.pages.end(),
newParams.pages.begin());
}
@@ -101,8 +119,225 @@ void CalculatePrintCanvasSize(const PrintMsg_Print_Params& print_params,
print_params.desired_dpi));
}
+#if defined(USE_SKIA)
+// Splits the horizontal width equally into segments with an interstice
+// 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.
+SkScalar GetSegmentWidth(const PageSizeMargins& page_layout) {
+ SkScalar page_width = page_layout.margin_left +
+ 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.
+ page_layout.margin_right;
+ // Interstice is left at both ends of the page as well as between
+ // each region, so 1 is added.
+ SkScalar total_interstice_width =
+ (printing::kSettingHeaderFooterHorizontalRegions + 1) *
+ printing::kSettingHeaderFooterInterstice;
+ return (page_width - total_interstice_width) /
+ printing::kSettingHeaderFooterHorizontalRegions;
+}
+
+// Given a text, the positions, and the paint object, this method gets the
+// coordinates and prints the text at those coordinates on the canvas.
+void PrintHeaderFooterText(
+ string16 text,
+ SkPaint paint,
+ skia::VectorCanvas* canvas,
+ printing::HorizontalHeaderFooterPosition horizontal_position,
+ printing::VerticalHeaderFooterPosition vertical_position,
+ float webkit_scale_factor,
+ const PageSizeMargins& page_layout,
+ SkScalar max_text_width,
+ const gfx::Font& font,
+ SkScalar height_to_baseline) {
+ text = ui::ElideText(text, font, ConvertPointsToPixelDouble(max_text_width),
+ false);
+
+ size_t text_byte_length = text.length() * sizeof(char16);
+ // Get the (x, y) coordinate from where printing of the current text should
+ // start depending on the horizontal alignment (LEFT, RIGHT, CENTER) and
+ // vertical alignment (TOP, BOTTOM).
+ SkScalar text_width_in_points = paint.measureText(text.c_str(),
+ text_byte_length);
+ SkScalar x = 0;
+ switch (horizontal_position) {
+ case printing::LEFT: {
+ x = printing::kSettingHeaderFooterInterstice - page_layout.margin_left;
+ break;
+ }
+ case printing::RIGHT: {
+ x = page_layout.content_width + page_layout.margin_right -
+ printing::kSettingHeaderFooterInterstice - text_width_in_points;
+ break;
+ }
+ case printing::CENTER: {
+ SkScalar available_width = GetSegmentWidth(page_layout);
+ x = available_width - page_layout.margin_left +
+ (available_width - text_width_in_points) / 2;
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+
+ SkScalar y = 0;
+ switch (vertical_position) {
+ case printing::TOP: {
+ y = printing::kSettingHeaderFooterInterstice -
+ page_layout.margin_top - height_to_baseline;
+ break;
+ }
+ case printing::BOTTOM: {
+ y = page_layout.margin_bottom + page_layout.content_height -
+ printing::kSettingHeaderFooterInterstice - height_to_baseline;
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+
+ x = x / webkit_scale_factor;
+ y = y / webkit_scale_factor;
+ paint.setTextSize(paint.getTextSize() / webkit_scale_factor);
+ canvas->drawText(text.c_str(), text_byte_length, x, y, paint);
+}
+
+// Prints the headers onto the |canvas| if there is enough space to print them.
+void PrintHeaders(skia::VectorCanvas* canvas,
+ const DictionaryValue& header_footer_info,
+ SkPaint paint,
+ const PageSizeMargins& page_layout,
+ float webkit_scale_factor,
+ const gfx::Font& font) {
+ string16 date = base::TimeFormatShortDateNumeric(Time::Now());
+ string16 title;
+ if (!header_footer_info.GetString(printing::kSettingHeaderFooterTitle,
+ &title)) {
+ NOTREACHED();
+ }
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.
+
+ string16 header_text = date + title;
+ SkRect header_bounds;
+ paint.measureText(header_text.c_str(), header_text.length() * sizeof(char16),
+ &header_bounds, 0);
+
+ SkScalar text_height =
+ printing::kSettingHeaderFooterInterstice + header_bounds.height();
+
+ if (text_height > page_layout.margin_top)
+ return;
+
+ SkScalar segment_width = GetSegmentWidth(page_layout);
+ PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP,
+ webkit_scale_factor, page_layout, segment_width, font,
+ header_bounds.top());
+
+ 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.
+ date.length() * sizeof(char16));
+ // Calculate the available title width. If the date string is not long
+ // 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.
+ // Assumes there is no header text to RIGHT of title.
+ SkScalar max_title_width = std::min(2 * segment_width,
+ 2 * (segment_width - date_width) +
+ segment_width);
+ PrintHeaderFooterText(title, paint, canvas, printing::CENTER,
+ printing::TOP, webkit_scale_factor, page_layout,
+ max_title_width, font, header_bounds.top());
+}
+
+// Prints the footers onto the |canvas| if there is enough space to print them.
+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.
+ const DictionaryValue& header_footer_info,
+ SkPaint paint,
+ const PageSizeMargins& page_layout,
+ float webkit_scale_factor,
+ const gfx::Font& font,
+ int page_number,
+ int total_pages) {
+ string16 page_of_total_pages = base::IntToString16(page_number) +
+ UTF8ToUTF16("/") +
+ base::IntToString16(total_pages);
+ std::string url;
+ if (!header_footer_info.GetString(printing::kSettingHeaderFooterURL,
+ &url)) {
+ NOTREACHED();
+ }
+
+ string16 footer_text = page_of_total_pages + UTF8ToUTF16(url);
+ SkRect footer_bounds;
+ paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16),
+ &footer_bounds, 0);
+
+ SkScalar text_height =
+ printing::kSettingHeaderFooterInterstice + footer_bounds.height();
+
+ if (text_height > page_layout.margin_bottom)
+ return;
+
+ SkScalar segment_width = GetSegmentWidth(page_layout);
+ PrintHeaderFooterText(page_of_total_pages, paint, canvas, printing::RIGHT,
+ printing::BOTTOM, webkit_scale_factor, page_layout,
+ segment_width, font, footer_bounds.bottom());
+
+ GURL gurl(url);
+ SkScalar page_width = paint.measureText(
+ page_of_total_pages.c_str(),
+ page_of_total_pages.length() * sizeof(char16));
+
+ // Calculate the available URL width. We increase the available URL width
+ // if the |page_of_total_pages| string isn't long enough.
+ // Assumes no footer text being printed in the CENTER.
+ SkScalar max_url_width =
+ (page_layout.content_width + page_layout.margin_left +
+ 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.
+ max_url_width = std::min(max_url_width,
+ 2 * (segment_width - page_width) + segment_width);
+ string16 url_elided = ui::ElideUrl(gurl, font,
+ ConvertPointsToPixelDouble(max_url_width),
+ std::string());
+ PrintHeaderFooterText(url_elided, paint, canvas, printing::LEFT,
+ printing::BOTTOM, webkit_scale_factor, page_layout,
+ max_url_width, font, footer_bounds.bottom());
+}
+#endif // USE_SKIA
+
} // namespace
+#if defined(USE_SKIA)
+// static - Not anonymous so that platform implementations can use it.
+void PrintWebViewHelper::PrintHeaderAndFooter(
+ SkDevice* device,
+ skia::VectorCanvas* canvas,
+ int page_number,
+ int total_pages,
+ float webkit_scale_factor,
+ const PageSizeMargins& page_layout,
+ const DictionaryValue& header_footer_info) {
+ static_cast<skia::VectorPlatformDeviceSkia*>(device)->setDrawingArea(
+ SkPDFDevice::kMargin_DrawingArea);
+
+ // 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.
+ SkPaint paint;
+ paint.setColor(SK_ColorBLACK);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ paint.setTextSize(printing::kSettingHeaderFooterFontSize);
+ gfx::Font font(UTF8ToUTF16(printing::kSettingHeaderFooterFontName),
+ ceil(ConvertPointsToPixelDouble(
+ printing::kSettingHeaderFooterFontSize)));
+ paint.setTypeface(SkTypeface::CreateFromName(
+ UTF16ToUTF8(font.GetFontName()).c_str(), SkTypeface::kNormal));
+
+ PrintHeaders(canvas, header_footer_info, paint, page_layout,
+ webkit_scale_factor, font);
+
vandebo (ex-Chrome) 2011/08/04 20:46:22 nit: extra space.
Aayush Kumar 2011/08/04 23:00:30 Done.
+ PrintFooters(canvas, header_footer_info, paint, page_layout,
+ webkit_scale_factor, font, page_number, total_pages);
+
+ static_cast<skia::VectorPlatformDeviceSkia*>(device)->setDrawingArea(
+ SkPDFDevice::kContent_DrawingArea);
+}
+#endif // USE_SKIA
+
PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
const PrintMsg_Print_Params& print_params,
WebFrame* frame,
@@ -765,8 +1000,9 @@ bool PrintWebViewHelper::UpdatePrintSettings(
PrintMsg_PrintPages_Params settings;
Send(new PrintHostMsg_UpdatePrintSettings(routing_id(),
- print_pages_params_->params.document_cookie, job_settings, &settings));
+ print_pages_params_->params.document_cookie, job_settings, &settings));
+ 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! :)
if (settings.params.dpi < kMinDpi || !settings.params.document_cookie)
return false;
@@ -774,6 +1010,26 @@ bool PrintWebViewHelper::UpdatePrintSettings(
return false;
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
+ // Getting Header and Footer settings.
+ bool display_header_footer = false;
+ if (!job_settings.GetBoolean(printing::kSettingHeaderFooterEnabled,
+ &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.
+ NOTREACHED();
+ }
+ print_pages_params_->params.display_header_footer = display_header_footer;
+
+ if (display_header_footer) {
+ string16 title;
+ std::string url;
+ if (!job_settings.GetString(printing::kSettingHeaderFooterTitle, &title) ||
+ !job_settings.GetString(printing::kSettingHeaderFooterURL, &url)) {
+ NOTREACHED();
+ }
+ header_footer_info_.reset(new DictionaryValue());
+ header_footer_info_->SetString(printing::kSettingHeaderFooterURL, url);
+ header_footer_info_->SetString(printing::kSettingHeaderFooterTitle, title);
+ }
+
Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
settings.params.document_cookie));
return true;
« 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