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

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: Updated as per Chris' comments. Created 9 years, 5 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
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 1edc892a397aef33dd43754b5eb070d0da326bc5..f8ef3dd98727b55899bda4d5243e73c60ac91e17 100644
--- a/chrome/renderer/print_web_view_helper.cc
+++ b/chrome/renderer/print_web_view_helper.cc
@@ -4,12 +4,17 @@
#include "chrome/renderer/print_web_view_helper.h"
+#include <algorithm>
+#include <cmath>
#include <string>
#include "base/command_line.h"
+#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/process_util.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/print_messages.h"
@@ -21,6 +26,9 @@
#include "printing/metafile_impl.h"
#include "printing/print_job_constants.h"
#include "printing/units.h"
+#include "skia/ext/vector_canvas.h"
+#include "skia/ext/vector_platform_device_skia.h"
+#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
@@ -32,13 +40,16 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
#if defined(OS_POSIX)
#include "content/common/view_messages.h"
#endif
+using base::Time;
using printing::ConvertPixelsToPoint;
using printing::ConvertPixelsToPointDouble;
+using printing::ConvertPointsToPixelDouble;
using printing::ConvertUnit;
using printing::ConvertUnitDouble;
using WebKit::WebConsoleMessage;
@@ -88,12 +99,210 @@ 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());
}
+// Splits the horizontal width equally into segments with an interstice
+// between each segment. Returns the width of this segment.
+SkScalar GetSegmentWidth(const PageSizeMargins& page_layout) {
+ return (page_layout.margin_left +
+ page_layout.content_width +
vandebo (ex-Chrome) 2011/07/26 06:11:37 nit: indent
Aayush Kumar 2011/07/26 07:37:33 Done.
+ page_layout.margin_right -
+ // Interstice is left at both ends of the page as well as between each
+ // region, so 1 is added.
+ (printing::kSettingHeaderFooterHorizontalRegions + 1) *
+ printing::kSettingHeaderFooterInterstice) /
+ 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,
+ gfx::Font font,
+ SkScalar height_to_baseline) {
+ text = ui::ElideText(text, font, ConvertPointsToPixelDouble(max_text_width),
+ false);
+
+ SkPoint text_location;
+ 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).
+ {
vandebo (ex-Chrome) 2011/07/26 06:11:37 Don't use an extra scope.
Aayush Kumar 2011/07/26 07:37:33 Done.
+ SkScalar text_width_in_points = paint.measureText(text.c_str(),
+ text_byte_length);
+
+ SkScalar x = 0;
+ switch (horizontal_position) {
+ case printing::LEFT: {
+ x = -page_layout.margin_left +
+ printing::kSettingHeaderFooterInterstice;
+ 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 = -page_layout.margin_top - height_to_baseline +
+ printing::kSettingHeaderFooterInterstice;
+ break;
+ }
+ case printing::BOTTOM: {
+ y = page_layout.margin_bottom + page_layout.content_height -
+ printing::kSettingHeaderFooterInterstice - height_to_baseline;
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+
+ text_location.set(x / webkit_scale_factor, y / webkit_scale_factor);
+ }
+
+ paint.setTextSize(paint.getTextSize() / webkit_scale_factor);
+ canvas.drawText(text.c_str(), text_byte_length, text_location.x(),
+ text_location.y(), paint);
+}
+
} // namespace
+void PrintHeaderAndFooter(skia::VectorPlatformDeviceSkia* device,
+ skia::VectorCanvas& canvas,
+ int page_number, int total_pages,
+ float webkit_scale_factor,
+ const PageSizeMargins& page_layout,
+ const DictionaryValue* header_footer_info) {
+ // Set the drawing area to draw in the margins.
+ device->setDrawingArea(SkPDFDevice::kMargin_DrawingArea);
+
+ // Setting up styles for the headers and footers text.
+ 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));
+
+ // Ensure we have enough space to print above and below the page to print
+ // headers.
+ string16 date = base::TimeFormatShortDateNumeric(Time::Now());
+ string16 title;
+ if (!header_footer_info->GetString(printing::kSettingHeaderFooterTitle,
+ &title)) {
+ NOTREACHED();
+ }
+
+ SkRect header_bounds;
+ string16 header_text = date + title;
+ paint.measureText(header_text.c_str(), header_text.length() * sizeof(char16),
+ &header_bounds, 0);
+ SkScalar text_height = printing::kSettingHeaderFooterInterstice +
vandebo (ex-Chrome) 2011/07/26 06:11:37 nit: = <newline>
Aayush Kumar 2011/07/26 07:37:33 Done.
+ header_bounds.height();
+
+ if (text_height > page_layout.margin_top)
+ return;
+
+ // Ensure we have enough space to print above and below the page to print
+ // footers.
+ string16 page_on_page_total = base::IntToString16(page_number) +
vandebo (ex-Chrome) 2011/07/26 06:11:37 page_of_total_pages ?
Aayush Kumar 2011/07/26 07:37:33 Done.
+ UTF8ToUTF16("/") +
+ base::IntToString16(total_pages);
+ std::string url;
+ if (!header_footer_info->GetString(printing::kSettingHeaderFooterURL,
+ &url)) {
+ NOTREACHED();
+ }
+
+ SkRect footer_bounds;
+ string16 footer_text = page_on_page_total + UTF8ToUTF16(url);
+ paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16),
+ &footer_bounds, 0);
+ text_height = printing::kSettingHeaderFooterInterstice +
vandebo (ex-Chrome) 2011/07/26 06:11:37 nit: = <newline>
Aayush Kumar 2011/07/26 07:37:33 Done.
+ footer_bounds.height();
+
+ if (text_height > page_layout.margin_bottom)
+ return;
+
+ SkScalar segment_width = GetSegmentWidth(page_layout);
+ // Print the Date.
+ PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP,
+ webkit_scale_factor, page_layout, segment_width,
+ font, header_bounds.top());
+
+ // Print the title.
+ SkScalar date_width = paint.measureText(date.c_str(),
+ 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.
+ // 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());
+
+ // Print the page numbers at the bottom right corner of page.
+ PrintHeaderFooterText(page_on_page_total, paint, canvas, printing::RIGHT,
+ printing::BOTTOM, webkit_scale_factor,
+ page_layout, segment_width, font,
+ footer_bounds.bottom());
+
+ // Print the URL.
+ GURL gurl(url);
+ SkScalar page_width = paint.measureText(
+ page_on_page_total.c_str(),
+ page_on_page_total.length() * sizeof(char16));
+
+ // Calculate the available URL width. We increase the available URL width
+ // if the |page_on_page_total| string isn't long enough.
+ // Assumes no footer text being printed in the CENTER.
+ SkScalar max_url_width = 3 * (page_layout.content_width +
vandebo (ex-Chrome) 2011/07/26 06:11:37 nit: newline foo = (foo + bar + baz) * 3
Aayush Kumar 2011/07/26 07:37:33 Done.
+ page_layout.margin_left + page_layout.margin_right) / 4;
+ 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());
+
+ // Restore the drawing area to draw in the content area.
+ device->setDrawingArea(SkPDFDevice::kContent_DrawingArea);
+}
+
PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint(
const PrintMsg_Print_Params& print_params,
WebFrame* frame,
@@ -156,6 +365,7 @@ PrintWebViewHelper::PrintWebViewHelper(RenderView* render_view)
user_cancelled_scripted_print_count_(0),
notify_browser_of_print_failure_(true) {
is_preview_ = switches::IsPrintPreviewEnabled();
+ header_footer_info_ = new DictionaryValue();
vandebo (ex-Chrome) 2011/07/26 06:11:37 put in init list
Aayush Kumar 2011/07/26 07:37:33 Done.
}
PrintWebViewHelper::~PrintWebViewHelper() {}
@@ -734,6 +944,7 @@ bool PrintWebViewHelper::UpdatePrintSettingsCloud(
settings.params.desired_dpi = 72;
settings.params.selection_only = false;
settings.params.supports_alpha_blend = false;
+ settings.params.display_header_footer = false;
if (!UpdatePrintSettingsRequestId(job_settings, &(settings.params)))
return false;
// TODO(abodenha@chromium.org) Parse page ranges from the job_settings.
@@ -755,6 +966,22 @@ bool PrintWebViewHelper::UpdatePrintSettingsLocal(
return false;
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
+ // Getting Header and Footer settings.
vandebo (ex-Chrome) 2011/07/26 06:11:37 Should this go into UpdatePrintSettings?
Aayush Kumar 2011/07/26 07:37:33 I just rebased and it seems that UpdatePrintSettin
+ bool display_header_footer;
+ if (!job_settings.GetBoolean(printing::kSettingHeaderFooter,
+ &display_header_footer)) {
+ NOTREACHED();
+ }
+ print_pages_params_->params.display_header_footer = display_header_footer;
+ std::string url;
+ if (!job_settings.GetString(printing::kSettingHeaderFooterURL, &url))
+ NOTREACHED();
+ header_footer_info_->SetString(printing::kSettingHeaderFooterURL, url);
+ string16 title;
+ if (!job_settings.GetString(printing::kSettingHeaderFooterTitle, &title))
+ NOTREACHED();
+ header_footer_info_->SetString(printing::kSettingHeaderFooterTitle, title);
+
Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
settings.params.document_cookie));
return true;

Powered by Google App Engine
This is Rietveld 408576698