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

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: style changes as per demetrios 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 f55fc3b100bcb0c9aa9b4ab9c894bcaba0761b24..1eb2176bb34a72115ae7374ac81f2258ab7c8de8 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,8 @@
#include "printing/metafile_impl.h"
#include "printing/print_job_constants.h"
#include "printing/units.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 +39,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 +98,217 @@ 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());
}
+// Gets the byte length of the |text|.
+size_t GetString16ByteLength(string16 text) {
vandebo (ex-Chrome) 2011/07/22 22:58:33 I don't think this needs to be a function, go ahea
Aayush Kumar 2011/07/24 02:09:02 Done.
+ return text.length() * sizeof(char16);
+}
+
+// Splits the horizontal width equally into three segments with an interstice
+// between each segment. Returns the width of this segment.
+SkScalar GetSegmentWidth(PageSizeMargins& page_size_margins) {
+ return (page_size_margins.margin_left +
+ page_size_margins.content_width +
+ page_size_margins.margin_right -
+ (printing::kSettingHeaderFooterHorizontalRegions + 1) *
+ printing::kSettingHeaderFooterInterstice) /
+ printing::kSettingHeaderFooterHorizontalRegions;
+}
+
+// Given a SkPaint object, gets the maximum possible height of any glyph.
+SkScalar GetMaxTextHeight(SkPaint paint) {
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ return metrics.fBottom - metrics.fTop;
+}
+
+// Gets the (x, y) coordinate from where we want to start printing the current
+// text depending on the alignment horizontal alignment (LEFT, RIGHT, CENTER)
+// and vertical alignment (TOP, BOTTOM).
+SkPoint GetHeaderFooterPosition(
+ string16 text,
+ SkPaint paint,
+ printing::HorizontalHeaderFooterPosition hor_pos,
+ printing::VerticalHeaderFooterPosition ver_pos,
+ PageSizeMargins& page_size_margins) {
+
+ SkScalar text_width_in_points = paint.measureText(
+ text.c_str(), GetString16ByteLength(text));
+
+ SkScalar x = 0;
+ switch (hor_pos) {
+ case printing::LEFT: {
+ x = page_size_margins.margin_left * (-1) +
+ printing::kSettingHeaderFooterInterstice;
+ break;
+ }
+ case printing::RIGHT: {
+ x = ((page_size_margins.content_width + page_size_margins.margin_right) -
+ (printing::kSettingHeaderFooterInterstice + text_width_in_points));
+ break;
+ }
+ case printing::CENTER: {
+ SkScalar available_width = GetSegmentWidth(page_size_margins);
+ x = (available_width - page_size_margins.margin_left +
+ (available_width - text_width_in_points) / 2);
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+
+ SkScalar y = 0;
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ switch (ver_pos) {
+ case printing::TOP: {
+ y = page_size_margins.margin_top * (-1) +
+ printing::kSettingHeaderFooterInterstice - metrics.fTop;
+ break;
+ }
+ case printing::BOTTOM: {
+ y = page_size_margins.margin_bottom + page_size_margins.content_height -
+ printing::kSettingHeaderFooterInterstice - metrics.fBottom;
+ break;
+ }
+ default: {
+ NOTREACHED();
+ }
+ }
+
+ SkPoint point;
+ point.set(x, y);
+ return point;
+}
+
+// Given a text, the positions and the paint object, this method gets the
+// coordinates and prints the text at those co-ordinates on the canvas.
+void PrintHeaderFooterText(
+ string16 text,
+ SkPaint paint,
+ const SkRefPtr<skia::VectorCanvas>& canvas,
+ printing::HorizontalHeaderFooterPosition hor_pos,
+ printing::VerticalHeaderFooterPosition ver_pos,
+ float webkit_scale_factor,
+ PageSizeMargins& page_size_margins) {
+ SkPoint point = GetHeaderFooterPosition(text, paint, hor_pos, ver_pos,
vandebo (ex-Chrome) 2011/07/22 22:58:33 Maybe just inline getheaderfooterposition here, si
Aayush Kumar 2011/07/24 02:09:02 Done.
+ page_size_margins);
+ point.set(point.x() / webkit_scale_factor, point.y() / webkit_scale_factor);
+ size_t byte_length = GetString16ByteLength(text);
+
+ canvas->drawText(text.c_str(), byte_length, point.x(), point.y(), paint);
+}
+
} // namespace
+void PrintHeaderAndFooter(skia::VectorPlatformDeviceSkia* device,
+ const SkRefPtr<skia::VectorCanvas>& canvas,
+ int page_number, int total_pages,
+ float webkit_scale_factor,
+ PageSizeMargins& page_size_margins,
+ 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);
+
+ SkScalar font_size = printing::kSettingHeaderFooterFontSize /
+ webkit_scale_factor;
+ paint.setTextSize(font_size);
+ gfx::Font font(UTF8ToUTF16(printing::kSettingHeaderFooterFontName),
+ ceil(ConvertPointsToPixelDouble(font_size)));
+ paint.setTypeface(SkTypeface::CreateFromName(
+ UTF16ToUTF8(font.GetFontName()).c_str(),
+ SkTypeface::kNormal));
+
+ // Ensuring we have enough space to print above and below the page to print
+ // headers and footers.
+ SkScalar text_height = printing::kSettingHeaderFooterInterstice +
+ GetMaxTextHeight(paint);
vandebo (ex-Chrome) 2011/07/22 22:58:33 Why not measure the actual text height here, inste
Aayush Kumar 2011/07/24 02:09:02 Done.
+ if (text_height > page_size_margins.margin_top ||
+ text_height > page_size_margins.margin_bottom) {
+ return;
+ }
+
+ SkScalar segment_width = GetSegmentWidth(page_size_margins);
+ // Printing the Date.
+ string16 date = base::TimeFormatShortDateNumeric(Time::Now());
+ date = date;
+ date = ui::ElideText(date, font, ConvertPointsToPixelDouble(segment_width),
vandebo (ex-Chrome) 2011/07/22 22:58:33 Can you pull the ElideText into the PrintHeaderFoo
Aayush Kumar 2011/07/24 02:09:02 Done.
+ false);
+ PrintHeaderFooterText(date, paint, canvas, printing::LEFT, printing::TOP,
+ webkit_scale_factor, page_size_margins);
+
+ // Printing the title.
+ string16 title;
+ if (!header_footer_info->GetString(printing::kSettingHeaderFooterTitle,
+ &title)) {
+ NOTREACHED();
+ }
+
+ SkScalar date_width = paint.measureText(date.c_str(),
+ GetString16ByteLength(date));
+ // Calculating 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);
+ title = ui::ElideText(title, font,
+ ConvertPointsToPixelDouble(max_title_width), false);
+ PrintHeaderFooterText(title, paint, canvas, printing::CENTER,
+ printing::TOP, webkit_scale_factor,
+ page_size_margins);
+
+ // Printing the page numbers at the bottom right corner of page.
+ string16 page_on_page_total = base::IntToString16(page_number) +
+ UTF8ToUTF16("/") +
+ base::IntToString16(total_pages);
+ page_on_page_total = ui::ElideText(page_on_page_total, font,
+ ConvertPointsToPixelDouble(segment_width),
+ false);
+ PrintHeaderFooterText(page_on_page_total, paint, canvas, printing::RIGHT,
+ printing::BOTTOM, webkit_scale_factor,
+ page_size_margins);
+
+ // Printing the URL.
+ std::string url;
+ if (!header_footer_info->GetString(printing::kSettingHeaderFooterURL,
+ &url)) {
+ NOTREACHED();
+ }
+ GURL gurl(url);
+ SkScalar page_width = paint.measureText(
+ page_on_page_total.c_str(),
+ GetString16ByteLength(page_on_page_total));
+
+ // Calculating 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_size_margins.content_width +
+ page_size_margins.margin_left + page_size_margins.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_size_margins);
+
+ // 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,
@@ -261,9 +476,12 @@ void PrintWebViewHelper::OnPrintPages() {
Print(frame, NULL);
}
-void PrintWebViewHelper::OnPrintPreview(const DictionaryValue& settings) {
+void PrintWebViewHelper::OnPrintPreview(
+ const DictionaryValue& settings,
+ const DictionaryValue& header_footer_info) {
DCHECK(is_preview_);
print_preview_context_.OnPrintPreview();
+ header_footer_info_ = header_footer_info.DeepCopy();
if (!InitPrintSettings(print_preview_context_.frame(),
print_preview_context_.node())) {
@@ -552,16 +770,10 @@ void PrintWebViewHelper::didStopLoading() {
PrintPages(*params, print_web_view_->mainFrame(), NULL);
}
-void PrintWebViewHelper::GetPageSizeAndMarginsInPoints(
+PageSizeMargins PrintWebViewHelper::GetPageSizeAndMarginsInPoints(
WebFrame* frame,
int page_index,
- const PrintMsg_Print_Params& default_params,
- double* content_width_in_points,
- double* content_height_in_points,
- double* margin_top_in_points,
- double* margin_right_in_points,
- double* margin_bottom_in_points,
- double* margin_left_in_points) {
+ const PrintMsg_Print_Params& default_params) {
int dpi = GetDPI(&default_params);
WebSize page_size_in_pixels(
@@ -593,67 +805,53 @@ void PrintWebViewHelper::GetPageSizeAndMarginsInPoints(
margin_left_in_pixels);
}
- *content_width_in_points = ConvertPixelsToPoint(page_size_in_pixels.width -
- margin_left_in_pixels -
- margin_right_in_pixels);
- *content_height_in_points = ConvertPixelsToPoint(page_size_in_pixels.height -
- margin_top_in_pixels -
- margin_bottom_in_pixels);
+ PageSizeMargins page_size_margins_in_points;
+ page_size_margins_in_points.content_width = ConvertPixelsToPoint(
+ page_size_in_pixels.width - margin_left_in_pixels -
+ margin_right_in_pixels);
+ page_size_margins_in_points.content_height = ConvertPixelsToPoint(
+ page_size_in_pixels.height - margin_top_in_pixels -
+ margin_bottom_in_pixels);
// Invalid page size and/or margins. We just use the default setting.
- if (*content_width_in_points < 1.0 || *content_height_in_points < 1.0) {
- GetPageSizeAndMarginsInPoints(NULL,
- page_index,
- default_params,
- content_width_in_points,
- content_height_in_points,
- margin_top_in_points,
- margin_right_in_points,
- margin_bottom_in_points,
- margin_left_in_points);
- return;
+ if (page_size_margins_in_points.content_width < 1.0 ||
+ page_size_margins_in_points.content_height < 1.0) {
+ return GetPageSizeAndMarginsInPoints(NULL, page_index, default_params);
}
- if (margin_top_in_points)
- *margin_top_in_points =
- ConvertPixelsToPointDouble(margin_top_in_pixels);
- if (margin_right_in_points)
- *margin_right_in_points =
- ConvertPixelsToPointDouble(margin_right_in_pixels);
- if (margin_bottom_in_points)
- *margin_bottom_in_points =
- ConvertPixelsToPointDouble(margin_bottom_in_pixels);
- if (margin_left_in_points)
- *margin_left_in_points =
- ConvertPixelsToPointDouble(margin_left_in_pixels);
+ page_size_margins_in_points.margin_top =
+ ConvertPixelsToPointDouble(margin_top_in_pixels);
+ page_size_margins_in_points.margin_right =
+ ConvertPixelsToPointDouble(margin_right_in_pixels);
+ page_size_margins_in_points.margin_bottom =
+ ConvertPixelsToPointDouble(margin_bottom_in_pixels);
+ page_size_margins_in_points.margin_left =
+ ConvertPixelsToPointDouble(margin_left_in_pixels);
+ return page_size_margins_in_points;
}
void PrintWebViewHelper::UpdatePrintableSizeInPrintParameters(
WebFrame* frame,
WebNode* node,
PrintMsg_Print_Params* params) {
- double content_width_in_points;
- double content_height_in_points;
- double margin_top_in_points;
- double margin_right_in_points;
- double margin_bottom_in_points;
- double margin_left_in_points;
PrepareFrameAndViewForPrint prepare(*params, frame, node);
- PrintWebViewHelper::GetPageSizeAndMarginsInPoints(frame, 0, *params,
- &content_width_in_points, &content_height_in_points,
- &margin_top_in_points, &margin_right_in_points,
- &margin_bottom_in_points, &margin_left_in_points);
+ PageSizeMargins page_size_margins_in_points =
+ PrintWebViewHelper::GetPageSizeAndMarginsInPoints(frame, 0, *params);
int dpi = GetDPI(params);
params->printable_size = gfx::Size(
- static_cast<int>(ConvertUnitDouble(content_width_in_points,
+ static_cast<int>(ConvertUnitDouble(
+ page_size_margins_in_points.content_width,
printing::kPointsPerInch, dpi)),
- static_cast<int>(ConvertUnitDouble(content_height_in_points,
+ static_cast<int>(ConvertUnitDouble(
+ page_size_margins_in_points.content_height,
printing::kPointsPerInch, dpi)));
- double page_width_in_points = content_width_in_points +
- margin_left_in_points + margin_right_in_points;
- double page_height_in_points = content_height_in_points +
- margin_top_in_points + margin_bottom_in_points;
+ double page_width_in_points = page_size_margins_in_points.content_width +
+ page_size_margins_in_points.margin_left +
+ page_size_margins_in_points.margin_right;
+ double page_height_in_points = page_size_margins_in_points.content_height +
+ page_size_margins_in_points.margin_top +
+ page_size_margins_in_points.margin_bottom;
params->page_size = gfx::Size(
static_cast<int>(ConvertUnitDouble(
@@ -662,9 +860,9 @@ void PrintWebViewHelper::UpdatePrintableSizeInPrintParameters(
page_height_in_points, printing::kPointsPerInch, dpi)));
params->margin_top = static_cast<int>(ConvertUnitDouble(
- margin_top_in_points, printing::kPointsPerInch, dpi));
+ page_size_margins_in_points.margin_top, printing::kPointsPerInch, dpi));
params->margin_left = static_cast<int>(ConvertUnitDouble(
- margin_left_in_points, printing::kPointsPerInch, dpi));
+ page_size_margins_in_points.margin_left, printing::kPointsPerInch, dpi));
}
bool PrintWebViewHelper::InitPrintSettings(WebKit::WebFrame* frame,
@@ -720,6 +918,7 @@ bool PrintWebViewHelper::UpdatePrintSettingsCloud(
settings.params.supports_alpha_blend = false;
// TODO(abodenha@chromium.org) Parse page ranges from the job_settings.
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
+ print_pages_params_->params.display_header_footer = false;
return true;
}
@@ -740,6 +939,11 @@ bool PrintWebViewHelper::UpdatePrintSettingsLocal(
}
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
+ bool header_footer;
+ if (!job_settings.GetBoolean(printing::kSettingHeaderFooter, &header_footer))
+ NOTREACHED();
+ print_pages_params_->params.display_header_footer = header_footer;
+
Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
settings.params.document_cookie));
return true;

Powered by Google App Engine
This is Rietveld 408576698