diff options
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/mock_printer.cc | 92 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.h | 58 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.cc | 166 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.h | 22 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_browsertest.cc | 1 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_linux.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_mac.mm | 14 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_win.cc | 9 |
8 files changed, 364 insertions, 6 deletions
diff --git a/chrome/renderer/mock_printer.cc b/chrome/renderer/mock_printer.cc index ac2c779..0f82115 100644 --- a/chrome/renderer/mock_printer.cc +++ b/chrome/renderer/mock_printer.cc @@ -4,14 +4,78 @@ #include "chrome/renderer/mock_printer.h" +#include "base/basictypes.h" #include "base/file_util.h" #include "base/shared_memory.h" +#include "base/string16.h" +#include "base/utf_string_conversions.h" #include "chrome/common/print_messages.h" #include "ipc/ipc_message_utils.h" #include "printing/metafile_impl.h" #include "printing/units.h" #include "testing/gtest/include/gtest/gtest.h" +PrintMsg_Print_Params_Clone::PrintMsg_Print_Params_Clone() + : page_size_(), + printable_size_(), + margin_top_(0), + margin_left_(0), + dpi_(0), + min_shrink_(0), + max_shrink_(0), + desired_dpi_(0), + document_cookie_(0), + selection_only_(0), + supports_alpha_blend_(0), + preview_request_id_(0), + is_first_request_(0), + display_header_footer_(0), + date_(), + title_(), + url_() { +} + +PrintMsg_Print_Params_Clone::~PrintMsg_Print_Params_Clone(){} + +void PrintMsg_Print_Params_Clone::ResetParams(PrintMsg_Print_Params* params) { + params->dpi = dpi_; + params->max_shrink = max_shrink_; + params->min_shrink = min_shrink_; + params->desired_dpi = desired_dpi_; + params->selection_only = selection_only_; + params->document_cookie = document_cookie_; + params->page_size = page_size_; + params->printable_size = printable_size_; + params->margin_left = margin_left_; + params->margin_top = margin_top_; + params->is_first_request = is_first_request_; + params->preview_request_id = preview_request_id_; + params->display_header_footer = display_header_footer_; + params->date = date_; + params->title = title_; + params->url = url_; + + COMPILE_ASSERT(sizeof(PrintMsg_Print_Params_Clone) == + sizeof(PrintMsg_Print_Params), + PrintMsg_Print_Params); +} + +PrintMsg_PrintPages_Params_Clone::PrintMsg_PrintPages_Params_Clone() + : pages_(0) { +} + +PrintMsg_PrintPages_Params_Clone::~PrintMsg_PrintPages_Params_Clone(){} + +void PrintMsg_PrintPages_Params_Clone::ResetParams( + PrintMsg_PrintPages_Params* params) { + params_.ResetParams(¶ms->params); + params->pages = pages_; + + COMPILE_ASSERT(sizeof(PrintMsg_PrintPages_Params_Clone) == + sizeof(PrintMsg_PrintPages_Params_Clone), + PrintMsg_PrintPages_Params); +} + MockPrinterPage::MockPrinterPage(const void* source_data, uint32 source_size, const printing::Image& image) @@ -37,7 +101,11 @@ MockPrinter::MockPrinter() number_pages_(0), page_number_(0), is_first_request_(true), - preview_request_id_(0) { + preview_request_id_(0), + display_header_footer_(false), + date_(ASCIIToUTF16("date")), + title_(ASCIIToUTF16("title")), + url_(ASCIIToUTF16("url")) { page_size_.SetSize(static_cast<int>(8.5 * dpi_), static_cast<int>(11.0 * dpi_)); printable_size_.SetSize(static_cast<int>((7.5 * dpi_)), @@ -60,7 +128,8 @@ void MockPrinter::GetDefaultPrintSettings(PrintMsg_Print_Params* params) { // Assign a unit document cookie and set the print settings. document_cookie_ = CreateDocumentCookie(); - memset(params, 0, sizeof(PrintMsg_Print_Params)); + PrintMsg_Print_Params_Clone params_clone; + params_clone.ResetParams(params); SetPrintParams(params); } @@ -74,6 +143,10 @@ void MockPrinter::SetDefaultPrintSettings(const PrintMsg_Print_Params& params) { printable_size_ = params.printable_size; margin_left_ = params.margin_left; margin_top_ = params.margin_top; + display_header_footer_ = params.display_header_footer; + date_ = params.date; + title_ = params.title; + url_ = params.url; } void MockPrinter::ScriptedPrint(int cookie, @@ -83,7 +156,9 @@ void MockPrinter::ScriptedPrint(int cookie, // Verify the input parameters. EXPECT_EQ(document_cookie_, cookie); - memset(settings, 0, sizeof(PrintMsg_PrintPages_Params)); + PrintMsg_PrintPages_Params_Clone params_clone; + params_clone.ResetParams(settings); + settings->params.dpi = dpi_; settings->params.max_shrink = max_shrink_; settings->params.min_shrink = min_shrink_; @@ -94,6 +169,10 @@ void MockPrinter::ScriptedPrint(int cookie, settings->params.printable_size = printable_size_; settings->params.is_first_request = is_first_request_; settings->params.preview_request_id = preview_request_id_; + settings->params.display_header_footer = display_header_footer_; + settings->params.date = date_; + settings->params.title = title_; + settings->params.url = url_; printer_status_ = PRINTER_PRINTING; } @@ -101,7 +180,8 @@ void MockPrinter::UpdateSettings(int cookie, PrintMsg_PrintPages_Params* params) { EXPECT_EQ(document_cookie_, cookie); - memset(params, 0, sizeof(PrintMsg_PrintPages_Params)); + PrintMsg_PrintPages_Params_Clone params_clone; + params_clone.ResetParams(params); SetPrintParams(&(params->params)); printer_status_ = PRINTER_PRINTING; } @@ -236,4 +316,8 @@ void MockPrinter::SetPrintParams(PrintMsg_Print_Params* params) { params->margin_top = margin_top_; params->is_first_request = is_first_request_; params->preview_request_id = preview_request_id_; + params->display_header_footer = display_header_footer_; + params->date = date_; + params->title = title_; + params->url = url_; } diff --git a/chrome/renderer/mock_printer.h b/chrome/renderer/mock_printer.h index 0ae5687..326a50d 100644 --- a/chrome/renderer/mock_printer.h +++ b/chrome/renderer/mock_printer.h @@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/string16.h" #include "printing/image.h" #include "ui/gfx/size.h" @@ -134,9 +135,66 @@ class MockPrinter { bool is_first_request_; int preview_request_id_; + // Used for displaying headers and footers. + bool display_header_footer_; + string16 date_; + string16 title_; + string16 url_; + std::vector<scoped_refptr<MockPrinterPage> > pages_; DISALLOW_COPY_AND_ASSIGN(MockPrinter); }; +// A clone of PrintMsg_Print_Params struct. +class PrintMsg_Print_Params_Clone { + public: + PrintMsg_Print_Params_Clone(); + ~PrintMsg_Print_Params_Clone(); + + // Resets the members of |params| to 0. Checks to see if + // PrintMsg_Print_Params and PrintMsg_Print_Params_Clone have identical + // member variables. + void ResetParams(PrintMsg_Print_Params* params); + + private: + gfx::Size page_size_; + gfx::Size printable_size_; + int margin_top_; + int margin_left_; + double dpi_; + double min_shrink_; + double max_shrink_; + int desired_dpi_; + int document_cookie_; + bool selection_only_; + bool supports_alpha_blend_; + int preview_request_id_; + bool is_first_request_; + bool display_header_footer_; + string16 date_; + string16 title_; + string16 url_; + + DISALLOW_COPY_AND_ASSIGN(PrintMsg_Print_Params_Clone); +}; + +// A clone of PrintMsg_PrintPages_Params struct. +class PrintMsg_PrintPages_Params_Clone { + public: + PrintMsg_PrintPages_Params_Clone(); + ~PrintMsg_PrintPages_Params_Clone(); + + // Resets the members of |params| to 0. Checks to see if + // PrintMsg_PrintPages_Params and PrintMsg_PrintPages_Params_Clone have + // identical member variables. + void ResetParams(PrintMsg_PrintPages_Params* params); + + private: + PrintMsg_Print_Params_Clone params_; + std::vector<int> pages_; + + DISALLOW_COPY_AND_ASSIGN(PrintMsg_PrintPages_Params_Clone); +}; + #endif // CHROME_RENDERER_MOCK_PRINTER_H_ diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc index dbf1ca5..8d36b70 100644 --- a/chrome/renderer/print_web_view_helper.cc +++ b/chrome/renderer/print_web_view_helper.cc @@ -36,10 +36,19 @@ #include "content/common/view_messages.h" #endif +#if defined(USE_SKIA) +#include "base/string_number_conversions.h" +#include "skia/ext/vector_canvas.h" +#include "skia/ext/vector_platform_device_skia.h" +#include "third_party/skia/include/core/SkTypeface.h" +#endif // defined(USE_SKIA) + +using base::Time; using printing::ConvertPixelsToPoint; using printing::ConvertPixelsToPointDouble; using printing::ConvertUnit; using printing::ConvertUnitDouble; +using printing::GetHeaderFooterSegmentWidth; using WebKit::WebConsoleMessage; using WebKit::WebDocument; using WebKit::WebElement; @@ -87,6 +96,11 @@ 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 && + oldParams.params.date == newParams.params.date && + oldParams.params.title == newParams.params.title && + oldParams.params.url == newParams.params.url && std::equal(oldParams.pages.begin(), oldParams.pages.end(), newParams.pages.begin()); } @@ -101,8 +115,147 @@ void CalculatePrintCanvasSize(const PrintMsg_Print_Params& print_params, print_params.desired_dpi)); } +#if defined(USE_SKIA) +// 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, + skia::VectorCanvas* canvas, + SkPaint paint, + float webkit_scale_factor, + const PageSizeMargins& page_layout, + printing::HorizontalHeaderFooterPosition horizontal_position, + printing::VerticalHeaderFooterPosition vertical_position, + SkScalar offset_to_baseline) { + 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 = GetHeaderFooterSegmentWidth( + page_layout.margin_left + page_layout.margin_right + + page_layout.content_width); + 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 - offset_to_baseline; + break; + case printing::BOTTOM: + y = page_layout.margin_bottom + page_layout.content_height - + printing::kSettingHeaderFooterInterstice - offset_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); +} +#endif // defined(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); + + SkPaint paint; + paint.setColor(SK_ColorBLACK); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + paint.setTextSize(printing::kSettingHeaderFooterFontSize); + paint.setTypeface(SkTypeface::CreateFromName( + printing::kSettingHeaderFooterFontFamilyName, SkTypeface::kNormal)); + + // Print the headers onto the |canvas| if there is enough space to print + // them. + string16 date; + string16 title; + if (!header_footer_info.GetString(printing::kSettingHeaderFooterTitle, + &title) || + !header_footer_info.GetString(printing::kSettingHeaderFooterDate, + &date)) { + NOTREACHED(); + } + 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) { + PrintHeaderFooterText(date, canvas, paint, webkit_scale_factor, page_layout, + printing::LEFT, printing::TOP, header_bounds.top()); + PrintHeaderFooterText(title, canvas, paint, webkit_scale_factor, + page_layout, printing::CENTER, printing::TOP, + header_bounds.top()); + } + + // Prints the footers onto the |canvas| if there is enough space to print + // them. + string16 page_of_total_pages = base::IntToString16(page_number) + + UTF8ToUTF16("/") + + base::IntToString16(total_pages); + string16 url; + if (!header_footer_info.GetString(printing::kSettingHeaderFooterURL, + &url)) { + NOTREACHED(); + } + string16 footer_text = page_of_total_pages + url; + + SkRect footer_bounds; + paint.measureText(footer_text.c_str(), footer_text.length() * sizeof(char16), + &footer_bounds, 0); + text_height = + printing::kSettingHeaderFooterInterstice + footer_bounds.height(); + if (text_height <= page_layout.margin_bottom) { + PrintHeaderFooterText(page_of_total_pages, canvas, paint, + webkit_scale_factor, page_layout, printing::RIGHT, + printing::BOTTOM, footer_bounds.bottom()); + PrintHeaderFooterText(url, canvas, paint, webkit_scale_factor, page_layout, + printing::LEFT, printing::BOTTOM, + footer_bounds.bottom()); + } + + static_cast<skia::VectorPlatformDeviceSkia*>(device)->setDrawingArea( + SkPDFDevice::kContent_DrawingArea); +} +#endif // defined(USE_SKIA) + PrepareFrameAndViewForPrint::PrepareFrameAndViewForPrint( const PrintMsg_Print_Params& print_params, WebFrame* frame, @@ -766,7 +919,7 @@ 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)); if (settings.params.dpi < kMinDpi || !settings.params.document_cookie) return false; @@ -780,6 +933,17 @@ bool PrintWebViewHelper::UpdatePrintSettings( } print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); + + if (print_pages_params_->params.display_header_footer) { + header_footer_info_.reset(new DictionaryValue()); + header_footer_info_->SetString(printing::kSettingHeaderFooterDate, + print_pages_params_->params.date); + header_footer_info_->SetString(printing::kSettingHeaderFooterURL, + print_pages_params_->params.url); + header_footer_info_->SetString(printing::kSettingHeaderFooterTitle, + print_pages_params_->params.title); + } + Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), settings.params.document_cookie)); return true; diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h index 0407c85..cc04bd3 100644 --- a/chrome/renderer/print_web_view_helper.h +++ b/chrome/renderer/print_web_view_helper.h @@ -28,6 +28,11 @@ struct PrintMsg_PrintPages_Params; namespace base { class DictionaryValue; } +#if defined(USE_SKIA) +namespace skia { +class VectorCanvas; +} +#endif // Class that calls the Begin and End print functions on the frame and changes // the size of the view temporarily to support full page printing.. @@ -266,6 +271,19 @@ class PrintWebViewHelper : public RenderViewObserver, PrepareFrameAndViewForPrint* prepare, PrintMsg_Print_Params* params); +#if defined(USE_SKIA) + // Given the |device| and |canvas| to draw on, prints the appropriate headers + // and footers using strings from |header_footer_info| on to the canvas. + static void PrintHeaderAndFooter( + SkDevice* device, + skia::VectorCanvas* canvas, + int page_number, + int total_pages, + float webkit_scale_factor, + const PageSizeMargins& page_layout_in_points, + const base::DictionaryValue& header_footer_info); +#endif // defined(USE_SKIA) + bool GetPrintFrame(WebKit::WebFrame** frame); // This reports the current time - |start_time| as the time to render a page. @@ -309,6 +327,10 @@ class PrintWebViewHelper : public RenderViewObserver, scoped_ptr<PrintMsg_PrintPages_Params> old_print_pages_params_; + // Strings generated by the browser process to be printed as headers and + // footers if requested by the user. + scoped_ptr<base::DictionaryValue> header_footer_info_; + // Keeps track of the state of print preview between messages. class PrintPreviewContext { public: diff --git a/chrome/renderer/print_web_view_helper_browsertest.cc b/chrome/renderer/print_web_view_helper_browsertest.cc index a4e9a59..fb29845 100644 --- a/chrome/renderer/print_web_view_helper_browsertest.cc +++ b/chrome/renderer/print_web_view_helper_browsertest.cc @@ -43,6 +43,7 @@ void CreatePrintSettingsDictionary(DictionaryValue* dict) { dict->SetString(printing::kSettingDeviceName, "dummy"); dict->SetInteger(printing::kPreviewRequestID, 12345); dict->SetBoolean(printing::kIsFirstRequest, true); + dict->SetBoolean(printing::kSettingHeaderFooterEnabled, false); } } // namespace diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc index 0915681..c07f76b 100644 --- a/chrome/renderer/print_web_view_helper_linux.cc +++ b/chrome/renderer/print_web_view_helper_linux.cc @@ -209,7 +209,13 @@ void PrintWebViewHelper::PrintPageInternal( printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); frame->printPage(params.page_number, canvas.get()); - // TODO(myhuang): We should render the header and the footer. + if (params.params.display_header_footer) { + // |page_number| is 0-based, so 1 is added. + // The scale factor on Linux is 1. + PrintHeaderAndFooter(device, canvas.get(), params.page_number + 1, + print_preview_context_.total_page_count(), 1, + page_layout_in_points, *header_footer_info_); + } // Done printing. Close the device context to retrieve the compiled metafile. if (!metafile->FinishPage()) diff --git a/chrome/renderer/print_web_view_helper_mac.mm b/chrome/renderer/print_web_view_helper_mac.mm index 95ccb7e..b6d28cb 100644 --- a/chrome/renderer/print_web_view_helper_mac.mm +++ b/chrome/renderer/print_web_view_helper_mac.mm @@ -148,6 +148,20 @@ void PrintWebViewHelper::RenderPage( CGContextRef canvasPtr = cgContext; #endif frame->printPage(page_number, canvasPtr); +#if defined(USE_SKIA) + const PrintMsg_Print_Params& printParams = + print_preview_context_.print_params(); + if (printParams.display_header_footer) { + PageSizeMargins page_layout_in_points; + GetPageSizeAndMarginsInPoints(frame, page_number, printParams, + &page_layout_in_points); + // |page_number| is 0-based, so 1 is added. + PrintHeaderAndFooter(device, canvas.get(), page_number + 1, + print_preview_context_.total_page_count(), + scale_factor, page_layout_in_points, + *header_footer_info_); + } +#endif // defined(USE_SKIA) } // Done printing. Close the device context to retrieve the compiled metafile. diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc index b43c22f..cb70e43 100644 --- a/chrome/renderer/print_web_view_helper_win.cc +++ b/chrome/renderer/print_web_view_helper_win.cc @@ -187,6 +187,15 @@ Metafile* PrintWebViewHelper::RenderPage( printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); float webkit_scale_factor = frame->printPage(page_number, canvas.get()); + + if (params.display_header_footer) { + // |page_number| is 0-based, so 1 is added. + PrintHeaderAndFooter(device, canvas.get(), page_number + 1, + print_preview_context_.total_page_count(), + webkit_scale_factor, page_layout_in_points, + *header_footer_info_); + } + if (*scale_factor <= 0 || webkit_scale_factor <= 0) { NOTREACHED() << "Printing page " << page_number << " failed."; } else { |