Chromium Code Reviews| 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..611f95ed011241eae9faed199649acf2d9d45c79 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; |
|
dpapad
2011/07/21 23:18:51
Nit: alphabetical order.
Aayush Kumar
2011/07/21 23:30:47
Am I missing something? Isn't it already?
On 2011
dpapad
2011/07/21 23:47:49
You are right, never mind.
|
| 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) { |
| + 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 paint object, gets the maximum possible height of any glyph. |
|
dpapad
2011/07/21 23:18:51
Nit: There is no "paint" class, you mean "Given a
Aayush Kumar
2011/07/21 23:30:47
Done.
|
| +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, |
| + 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); |
| + 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), |
| + 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; |