diff options
author | kmadhusu@chromium.org <kmadhusu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 23:17:32 +0000 |
---|---|---|
committer | kmadhusu@chromium.org <kmadhusu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 23:17:32 +0000 |
commit | 732b813ab60ebaad3cd2a60e19154e2c29b5a144 (patch) | |
tree | 9ed80f722ccf2e478ec771614193e88f9126e419 /chrome/renderer | |
parent | 66122f44aec56f163aed88a673f062f035619bc2 (diff) | |
download | chromium_src-732b813ab60ebaad3cd2a60e19154e2c29b5a144.zip chromium_src-732b813ab60ebaad3cd2a60e19154e2c29b5a144.tar.gz chromium_src-732b813ab60ebaad3cd2a60e19154e2c29b5a144.tar.bz2 |
PrintPreview: Honor the print media page size and margin values.
BUG=104210, 100819
TEST=Added PrintWebViewHelperPreviewTests.
Review URL: http://codereview.chromium.org/8585017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117102 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/chrome_mock_render_thread.cc | 6 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.cc | 37 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.h | 6 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.cc | 390 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.h | 52 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_browsertest.cc | 187 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_linux.cc | 33 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_mac.mm | 66 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_win.cc | 104 |
9 files changed, 659 insertions, 222 deletions
diff --git a/chrome/renderer/chrome_mock_render_thread.cc b/chrome/renderer/chrome_mock_render_thread.cc index 027998d..d3abcab 100644 --- a/chrome/renderer/chrome_mock_render_thread.cc +++ b/chrome/renderer/chrome_mock_render_thread.cc @@ -145,6 +145,7 @@ void ChromeMockRenderThread::OnUpdatePrintSettings( // Check and make sure the required settings are all there. // We don't actually care about the values. std::string dummy_string; + int margins_type = 0; if (!job_settings.GetBoolean(printing::kSettingLandscape, NULL) || !job_settings.GetBoolean(printing::kSettingCollate, NULL) || !job_settings.GetInteger(printing::kSettingColor, NULL) || @@ -154,7 +155,8 @@ void ChromeMockRenderThread::OnUpdatePrintSettings( !job_settings.GetInteger(printing::kSettingDuplexMode, NULL) || !job_settings.GetInteger(printing::kSettingCopies, NULL) || !job_settings.GetString(printing::kPreviewUIAddr, &dummy_string) || - !job_settings.GetInteger(printing::kPreviewRequestID, NULL)) { + !job_settings.GetInteger(printing::kPreviewRequestID, NULL) || + !job_settings.GetInteger(printing::kSettingMarginsType, &margins_type)) { return; } @@ -180,7 +182,7 @@ void ChromeMockRenderThread::OnUpdatePrintSettings( } } std::vector<int> pages(printing::PageRange::GetPages(new_ranges)); - printer_->UpdateSettings(document_cookie, params, pages); + printer_->UpdateSettings(document_cookie, params, pages, margins_type); } } diff --git a/chrome/renderer/mock_printer.cc b/chrome/renderer/mock_printer.cc index 28708df..8546d61 100644 --- a/chrome/renderer/mock_printer.cc +++ b/chrome/renderer/mock_printer.cc @@ -15,6 +15,29 @@ #include "printing/units.h" #include "testing/gtest/include/gtest/gtest.h" +namespace { + +void UpdateMargins(int margins_type, int dpi, PrintMsg_Print_Params* params) { + if (margins_type == printing::NO_MARGINS) { + params->content_size.SetSize(static_cast<int>((8.5 * dpi)), + static_cast<int>((11.0 * dpi))); + params->margin_left = 0; + params->margin_top = 0; + } else if (margins_type == printing::PRINTABLE_AREA_MARGINS) { + params->content_size.SetSize(static_cast<int>((8.0 * dpi)), + static_cast<int>((10.5 * dpi))); + params->margin_left = static_cast<int>(0.25 * dpi); + params->margin_top = static_cast<int>(0.25 * dpi); + } else if (margins_type == printing::CUSTOM_MARGINS) { + params->content_size.SetSize(static_cast<int>((7.9 * dpi)), + static_cast<int>((10.4 * dpi))); + params->margin_left = static_cast<int>(0.30 * dpi); + params->margin_top = static_cast<int>(0.30 * dpi); + } +} + +} // end + MockPrinterPage::MockPrinterPage(const void* source_data, uint32 source_size, const printing::Image& image) @@ -40,6 +63,7 @@ MockPrinter::MockPrinter() number_pages_(0), page_number_(0), is_first_request_(true), + print_to_pdf_(false), preview_request_id_(0), display_header_footer_(false), date_(ASCIIToUTF16("date")), @@ -51,6 +75,10 @@ MockPrinter::MockPrinter() content_size_.SetSize(static_cast<int>((7.5 * dpi_)), static_cast<int>((10.0 * dpi_))); margin_left_ = margin_top_ = static_cast<int>(0.5 * dpi_); + printable_area_.SetRect(static_cast<int>(0.25 * dpi_), + static_cast<int>(0.25 *dpi_), + static_cast<int>(8 * dpi_), + static_cast<int>(10.5 * dpi_)); } MockPrinter::~MockPrinter() { @@ -80,6 +108,7 @@ void MockPrinter::SetDefaultPrintSettings(const PrintMsg_Print_Params& params) { selection_only_ = params.selection_only; page_size_ = params.page_size; content_size_ = params.content_size; + printable_area_ = params.printable_area; margin_left_ = params.margin_left; margin_top_ = params.margin_top; display_header_footer_ = params.display_header_footer; @@ -111,7 +140,9 @@ void MockPrinter::ScriptedPrint(int cookie, settings->params.document_cookie = document_cookie_; settings->params.page_size = page_size_; settings->params.content_size = content_size_; + settings->params.printable_area = printable_area_; settings->params.is_first_request = is_first_request_; + settings->params.print_to_pdf = print_to_pdf_; settings->params.preview_request_id = preview_request_id_; settings->params.display_header_footer = display_header_footer_; settings->params.date = date_; @@ -122,13 +153,15 @@ void MockPrinter::ScriptedPrint(int cookie, void MockPrinter::UpdateSettings(int cookie, PrintMsg_PrintPages_Params* params, - const std::vector<int>& pages) { + const std::vector<int>& pages, + int margins_type) { if (document_cookie_ == -1) { document_cookie_ = CreateDocumentCookie(); } params->Reset(); params->pages = pages; SetPrintParams(&(params->params)); + UpdateMargins(margins_type, dpi_, &(params->params)); printer_status_ = PRINTER_PRINTING; } @@ -258,9 +291,11 @@ void MockPrinter::SetPrintParams(PrintMsg_Print_Params* params) { params->document_cookie = document_cookie_; params->page_size = page_size_; params->content_size = content_size_; + params->printable_area = printable_area_; params->margin_left = margin_left_; params->margin_top = margin_top_; params->is_first_request = is_first_request_; + params->print_to_pdf = print_to_pdf_; params->preview_request_id = preview_request_id_; params->display_header_footer = display_header_footer_; params->date = date_; diff --git a/chrome/renderer/mock_printer.h b/chrome/renderer/mock_printer.h index c73ac87..75e151f 100644 --- a/chrome/renderer/mock_printer.h +++ b/chrome/renderer/mock_printer.h @@ -14,6 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "printing/image.h" +#include "ui/gfx/rect.h" #include "ui/gfx/size.h" struct PrintMsg_Print_Params; @@ -78,7 +79,8 @@ class MockPrinter { bool has_selection, PrintMsg_PrintPages_Params* settings); void UpdateSettings(int cookie, PrintMsg_PrintPages_Params* params, - const std::vector<int>& page_range_array); + const std::vector<int>& page_range_array, + int margins_type); void SetPrintedPagesCount(int cookie, int number_pages); void PrintPage(const PrintHostMsg_DidPrintPage_Params& params); @@ -110,6 +112,7 @@ class MockPrinter { gfx::Size content_size_; int margin_left_; int margin_top_; + gfx::Rect printable_area_; // Specifies dots per inch. double dpi_; @@ -135,6 +138,7 @@ class MockPrinter { // Used only in the preview sequence. bool is_first_request_; + bool print_to_pdf_; int preview_request_id_; // Used for displaying headers and footers. diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc index 499b1fd..be0e3b2 100644 --- a/chrome/renderer/print_web_view_helper.cc +++ b/chrome/renderer/print_web_view_helper.cc @@ -109,6 +109,7 @@ bool PrintMsg_Print_Params_IsEmpty(const PrintMsg_Print_Params& params) { bool PageLayoutIsEqual(const PrintMsg_PrintPages_Params& oldParams, const PrintMsg_PrintPages_Params& newParams) { return oldParams.params.content_size == newParams.params.content_size && + oldParams.params.printable_area == newParams.params.printable_area && oldParams.params.page_size == newParams.params.page_size && oldParams.params.margin_top == newParams.params.margin_top && oldParams.params.margin_left == newParams.params.margin_left && @@ -126,6 +127,7 @@ bool PrintMsg_Print_Params_IsEqual( oldParams.params.supports_alpha_blend == newParams.params.supports_alpha_blend && oldParams.pages.size() == newParams.pages.size() && + oldParams.params.print_to_pdf == newParams.params.print_to_pdf && oldParams.params.display_header_footer == newParams.params.display_header_footer && oldParams.params.date == newParams.params.date && @@ -135,6 +137,140 @@ bool PrintMsg_Print_Params_IsEqual( newParams.pages.begin()); } +PrintMsg_Print_Params GetCssPrintParams( + WebFrame* frame, + int page_index, + const PrintMsg_Print_Params& page_params) { + PrintMsg_Print_Params page_css_params = page_params; + int dpi = GetDPI(&page_params); + WebSize page_size_in_pixels( + ConvertUnit(page_params.page_size.width(), + dpi, printing::kPixelsPerInch), + ConvertUnit(page_params.page_size.height(), + dpi, printing::kPixelsPerInch)); + int margin_top_in_pixels = ConvertUnit( + page_params.margin_top, + dpi, printing::kPixelsPerInch); + int margin_right_in_pixels = ConvertUnit( + page_params.page_size.width() - + page_params.content_size.width() - page_params.margin_left, + dpi, printing::kPixelsPerInch); + int margin_bottom_in_pixels = ConvertUnit( + page_params.page_size.height() - + page_params.content_size.height() - page_params.margin_top, + dpi, printing::kPixelsPerInch); + int margin_left_in_pixels = ConvertUnit( + page_params.margin_left, + dpi, printing::kPixelsPerInch); + + if (frame) { + frame->pageSizeAndMarginsInPixels(page_index, + page_size_in_pixels, + margin_top_in_pixels, + margin_right_in_pixels, + margin_bottom_in_pixels, + margin_left_in_pixels); + } + + int new_content_width = page_size_in_pixels.width - + margin_left_in_pixels - margin_right_in_pixels; + int new_content_height = 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 (new_content_width < 1 || new_content_height < 1) { + CHECK(frame != NULL); + page_css_params = GetCssPrintParams(NULL, page_index, page_params); + return page_css_params; + } + + page_css_params.content_size = gfx::Size( + static_cast<int>(ConvertUnit(new_content_width, + printing::kPixelsPerInch, dpi)), + static_cast<int>(ConvertUnit(new_content_height, + printing::kPixelsPerInch, dpi))); + + page_css_params.page_size = gfx::Size( + static_cast<int>(ConvertUnit(page_size_in_pixels.width, + printing::kPixelsPerInch, dpi)), + static_cast<int>(ConvertUnit(page_size_in_pixels.height, + printing::kPixelsPerInch, dpi))); + + page_css_params.margin_top = + static_cast<int>(ConvertUnit(margin_top_in_pixels, + printing::kPixelsPerInch, dpi)); + + page_css_params.margin_left = + static_cast<int>(ConvertUnit(margin_left_in_pixels, + printing::kPixelsPerInch, dpi)); + return page_css_params; +} + +double FitPrintParamsToPage(const PrintMsg_Print_Params& page_params, + PrintMsg_Print_Params* params_to_fit) { + double content_width = + static_cast<double>(params_to_fit->content_size.width()); + double content_height = + static_cast<double>(params_to_fit->content_size.height()); + int default_page_size_height = page_params.page_size.height(); + int default_page_size_width = page_params.page_size.width(); + int css_page_size_height = params_to_fit->page_size.height(); + int css_page_size_width = params_to_fit->page_size.width(); + + double scale_factor = 1.0f; + if (page_params.page_size == params_to_fit->page_size) + return scale_factor; + + if (default_page_size_width < css_page_size_width || + default_page_size_height < css_page_size_height) { + double ratio_width = + static_cast<double>(page_params.printable_area.width()) / + css_page_size_width; + double ratio_height = + static_cast<double>(page_params.printable_area.height()) / + css_page_size_height; + scale_factor = ratio_width < ratio_height ? ratio_width : ratio_height; + content_width *= scale_factor; + content_height *= scale_factor; + } + params_to_fit->margin_top = static_cast<int>( + (default_page_size_height - css_page_size_height * scale_factor) / 2 + + (params_to_fit->margin_top * scale_factor)); + params_to_fit->margin_left = static_cast<int>( + (default_page_size_width - css_page_size_width * scale_factor) / 2 + + (params_to_fit->margin_left * scale_factor)); + params_to_fit->content_size = gfx::Size( + static_cast<int>(content_width), static_cast<int>(content_height)); + params_to_fit->page_size = page_params.page_size; + return scale_factor; +} + +void CalculatePageLayoutFromPrintParams( + const PrintMsg_Print_Params& params, + PageSizeMargins* page_layout_in_points) { + int dpi = GetDPI(¶ms); + int content_width = params.content_size.width(); + int content_height = params.content_size.height(); + + int margin_bottom = params.page_size.height() - + content_height - params.margin_top; + int margin_right = params.page_size.width() - + content_width - params.margin_left; + + page_layout_in_points->content_width = ConvertUnit( + content_width, dpi, printing::kPointsPerInch); + page_layout_in_points->content_height = ConvertUnit( + content_height, dpi, printing::kPointsPerInch); + page_layout_in_points->margin_top = ConvertUnit( + params.margin_top, dpi, printing::kPointsPerInch); + page_layout_in_points->margin_right = ConvertUnit( + margin_right, dpi, printing::kPointsPerInch); + page_layout_in_points->margin_bottom = ConvertUnit( + margin_bottom, dpi, printing::kPointsPerInch); + page_layout_in_points->margin_left = ConvertUnit( + params.margin_left, dpi, printing::kPointsPerInch); +} + void CalculatePrintCanvasSize(const PrintMsg_Print_Params& print_params, gfx::Size* result) { int dpi = GetDPI(&print_params); @@ -152,6 +288,19 @@ bool PrintingNodeOrPdfFrame(const WebFrame* frame, const WebNode& node) { return mime == "application/pdf"; } +bool PrintingFrameHasPageSizeStyle(WebFrame* frame, int total_page_count) { + if (!frame) + return false; + bool frame_has_custom_page_size_style = false; + for (int i = 0; i < total_page_count; ++i) { + if (frame->hasCustomPageSizeStyle(i)) { + frame_has_custom_page_size_style = true; + break; + } + } + return frame_has_custom_page_size_style; +} + printing::MarginType GetMarginsForPdf(WebFrame* frame, const WebNode& node) { if (frame->isPrintScalingDisabledForPlugin(node)) return printing::NO_MARGINS; @@ -253,6 +402,43 @@ void PrintHeaderFooterText( #endif } +PrintMsg_Print_Params CalculatePrintParamsForCss( + WebFrame* frame, + int page_index, + const PrintMsg_Print_Params& page_params, + bool ignore_css_margins, + bool fit_to_page, + double* scale_factor) { + if (ignore_css_margins && fit_to_page) + return page_params; + + PrintMsg_Print_Params params = GetCssPrintParams(frame, page_index, + page_params); + + if (ignore_css_margins) { + params.margin_top = page_params.margin_top; + params.margin_left = page_params.margin_left; + + DCHECK(!fit_to_page); + // Since we are ignoring the margins, the css page size is no longer + // valid. + int default_margin_right = page_params.page_size.width() - + page_params.content_size.width() - page_params.margin_left; + int default_margin_bottom = page_params.page_size.height() - + page_params.content_size.height() - page_params.margin_top; + params.content_size = gfx::Size( + params.page_size.width() - params.margin_left - default_margin_right, + params.page_size.height() - params.margin_top - default_margin_bottom); + } + + if (fit_to_page) { + double factor = FitPrintParamsToPage(page_params, ¶ms); + if (scale_factor) + *scale_factor = factor; + } + return params; +} + } // namespace // static - Not anonymous so that platform implementations can use it. @@ -440,6 +626,8 @@ PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view) print_web_view_(NULL), is_preview_enabled_(switches::IsPrintPreviewEnabled()), is_print_ready_metafile_sent_(false), + ignore_css_margins_(false), + fit_to_page_(true), user_cancelled_scripted_print_count_(0), notify_browser_of_print_failure_(true) { } @@ -560,6 +748,39 @@ void PrintWebViewHelper::OnPrintForSystemDialog() { Print(frame, print_preview_context_.node()); } +void PrintWebViewHelper::GetPageSizeAndContentAreaFromPageLayout( + const printing::PageSizeMargins& page_layout_in_points, + gfx::Size* page_size, + gfx::Rect* content_area) { + *page_size = gfx::Size( + page_layout_in_points.content_width + + page_layout_in_points.margin_right + + page_layout_in_points.margin_left, + page_layout_in_points.content_height + + page_layout_in_points.margin_top + + page_layout_in_points.margin_bottom); + *content_area = gfx::Rect(page_layout_in_points.margin_left, + page_layout_in_points.margin_top, + page_layout_in_points.content_width, + page_layout_in_points.content_height); +} + +void PrintWebViewHelper::UpdateFrameMarginsCssInfo( + const DictionaryValue& settings) { + int margins_type = 0; + if (!settings.GetInteger(printing::kSettingMarginsType, &margins_type)) + margins_type = printing::DEFAULT_MARGINS; + ignore_css_margins_ = margins_type != printing::DEFAULT_MARGINS; +} + +bool PrintWebViewHelper::IsPrintToPdfRequested( + const DictionaryValue& job_settings) { + bool print_to_pdf = false; + if (!job_settings.GetBoolean(printing::kSettingPrintToPDF, &print_to_pdf)) + NOTREACHED(); + return print_to_pdf; +} + void PrintWebViewHelper::OnPrintPreview(const DictionaryValue& settings) { DCHECK(is_preview_enabled_); print_preview_context_.OnPrintPreview(); @@ -620,8 +841,27 @@ void PrintWebViewHelper::OnPrintPreview(const DictionaryValue& settings) { bool PrintWebViewHelper::CreatePreviewDocument() { PrintMsg_Print_Params print_params = print_pages_params_->params; const std::vector<int>& pages = print_pages_params_->pages; - if (!print_preview_context_.CreatePreviewDocument(&print_params, pages)) + if (!print_preview_context_.CreatePreviewDocument(&print_params, pages, + ignore_css_margins_, + fit_to_page_)) { return false; + } + + PageSizeMargins default_page_layout; + ComputePageLayoutInPointsForCss(print_preview_context_.frame(), 0, + print_params, ignore_css_margins_, + fit_to_page_, NULL, &default_page_layout); + if (!old_print_pages_params_.get() || + !PageLayoutIsEqual(*old_print_pages_params_, *print_pages_params_)) { + bool has_page_size_style = PrintingFrameHasPageSizeStyle( + print_preview_context_.frame(), + print_preview_context_.total_page_count()); + // Margins: Send default page layout to browser process. + Send(new PrintHostMsg_DidGetDefaultPageLayout(routing_id(), + default_page_layout, + has_page_size_style)); + } + PrintHostMsg_DidGetPreviewPageCount_Params params; params.page_count = print_preview_context_.total_page_count(); params.is_modifiable = print_preview_context_.IsModifiable(); @@ -841,8 +1081,9 @@ bool PrintWebViewHelper::PrintPages(const PrintMsg_PrintPages_Params& params, const WebNode& node) { PrintMsg_Print_Params print_params = params.params; PrepareFrameAndViewForPrint prep_frame_view(print_params, frame, node); - UpdatePrintableSizeInPrintParameters(frame, node, &prep_frame_view, - &print_params); + UpdateFrameAndViewFromCssPageLayout(frame, node, &prep_frame_view, + print_params, ignore_css_margins_, + fit_to_page_); int page_count = prep_frame_view.GetExpectedPageCount(); if (!page_count) @@ -878,111 +1119,36 @@ void PrintWebViewHelper::didStopLoading() { } // static - Not anonymous so that platform implementations can use it. -void PrintWebViewHelper::GetPageSizeAndMarginsInPoints( +void PrintWebViewHelper::ComputePageLayoutInPointsForCss( WebFrame* frame, int page_index, - const PrintMsg_Print_Params& default_params, + const PrintMsg_Print_Params& page_params, + bool ignore_css_margins, + bool fit_to_page, + double* scale_factor, PageSizeMargins* page_layout_in_points) { - int dpi = GetDPI(&default_params); - - WebSize page_size_in_pixels( - ConvertUnit(default_params.page_size.width(), - dpi, printing::kPixelsPerInch), - ConvertUnit(default_params.page_size.height(), - dpi, printing::kPixelsPerInch)); - int margin_top_in_pixels = ConvertUnit( - default_params.margin_top, - dpi, printing::kPixelsPerInch); - int margin_right_in_pixels = ConvertUnit( - default_params.page_size.width() - - default_params.content_size.width() - default_params.margin_left, - dpi, printing::kPixelsPerInch); - int margin_bottom_in_pixels = ConvertUnit( - default_params.page_size.height() - - default_params.content_size.height() - default_params.margin_top, - dpi, printing::kPixelsPerInch); - int margin_left_in_pixels = ConvertUnit( - default_params.margin_left, - dpi, printing::kPixelsPerInch); - - if (frame) { - frame->pageSizeAndMarginsInPixels(page_index, - page_size_in_pixels, - margin_top_in_pixels, - margin_right_in_pixels, - margin_bottom_in_pixels, - margin_left_in_pixels); - } - - page_layout_in_points->content_width = - ConvertPixelsToPoint(page_size_in_pixels.width - - margin_left_in_pixels - - margin_right_in_pixels); - page_layout_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 (page_layout_in_points->content_width < 1.0 || - page_layout_in_points->content_height < 1.0) { - CHECK(frame != NULL); - GetPageSizeAndMarginsInPoints(NULL, page_index, default_params, - page_layout_in_points); - return; - } - - page_layout_in_points->margin_top = - ConvertPixelsToPointDouble(margin_top_in_pixels); - page_layout_in_points->margin_right = - ConvertPixelsToPointDouble(margin_right_in_pixels); - page_layout_in_points->margin_bottom = - ConvertPixelsToPointDouble(margin_bottom_in_pixels); - page_layout_in_points->margin_left = - ConvertPixelsToPointDouble(margin_left_in_pixels); + PrintMsg_Print_Params params = CalculatePrintParamsForCss(frame, page_index, + page_params, + ignore_css_margins, + fit_to_page, + scale_factor); + CalculatePageLayoutFromPrintParams(params, page_layout_in_points); } // static - Not anonymous so that platform implementations can use it. -void PrintWebViewHelper::UpdatePrintableSizeInPrintParameters( +void PrintWebViewHelper::UpdateFrameAndViewFromCssPageLayout( WebFrame* frame, const WebNode& node, PrepareFrameAndViewForPrint* prepare, - PrintMsg_Print_Params* params) { + const PrintMsg_Print_Params& params, + bool ignore_css_margins, + bool fit_to_page) { if (PrintingNodeOrPdfFrame(frame, node)) return; - PageSizeMargins page_layout_in_points; - PrintWebViewHelper::GetPageSizeAndMarginsInPoints(frame, 0, *params, - &page_layout_in_points); - int dpi = GetDPI(params); - params->content_size = gfx::Size( - static_cast<int>(ConvertUnitDouble( - page_layout_in_points.content_width, - printing::kPointsPerInch, dpi)), - static_cast<int>(ConvertUnitDouble( - page_layout_in_points.content_height, - printing::kPointsPerInch, dpi))); - - double page_width_in_points = - page_layout_in_points.content_width + - page_layout_in_points.margin_left + - page_layout_in_points.margin_right; - double page_height_in_points = - page_layout_in_points.content_height + - page_layout_in_points.margin_top + - page_layout_in_points.margin_bottom; - - params->page_size = gfx::Size( - static_cast<int>(ConvertUnitDouble( - page_width_in_points, printing::kPointsPerInch, dpi)), - static_cast<int>(ConvertUnitDouble( - page_height_in_points, printing::kPointsPerInch, dpi))); - - params->margin_top = static_cast<int>(ConvertUnitDouble( - page_layout_in_points.margin_top, printing::kPointsPerInch, dpi)); - params->margin_left = static_cast<int>(ConvertUnitDouble( - page_layout_in_points.margin_left, printing::kPointsPerInch, dpi)); - - prepare->UpdatePrintParams(*params); + PrintMsg_Print_Params print_params = CalculatePrintParamsForCss( + frame, 0, params, ignore_css_margins, ignore_css_margins && fit_to_page, + NULL); + prepare->UpdatePrintParams(print_params); } bool PrintWebViewHelper::InitPrintSettings(WebKit::WebFrame* frame, @@ -990,6 +1156,10 @@ bool PrintWebViewHelper::InitPrintSettings(WebKit::WebFrame* frame, DCHECK(frame); PrintMsg_PrintPages_Params settings; + // Reset to default values. + ignore_css_margins_ = false; + fit_to_page_ = true; + Send(new PrintHostMsg_GetDefaultPrintSettings(routing_id(), &settings.params)); // Check if the printer returned any settings, if the settings is empty, we @@ -1025,8 +1195,9 @@ bool PrintWebViewHelper::InitPrintSettingsAndPrepareFrame( DCHECK(!prepare->get()); prepare->reset(new PrepareFrameAndViewForPrint(print_pages_params_->params, frame, node)); - UpdatePrintableSizeInPrintParameters(frame, node, prepare->get(), - &print_pages_params_->params); + UpdateFrameAndViewFromCssPageLayout(frame, node, prepare->get(), + print_pages_params_->params, + ignore_css_margins_, fit_to_page_); Send(new PrintHostMsg_DidGetDocumentCookie( routing_id(), print_pages_params_->params.document_cookie)); return true; @@ -1127,15 +1298,9 @@ bool PrintWebViewHelper::UpdatePrintSettings( return false; } - // Margins: Send default page layout to browser process. - PageSizeMargins default_page_layout; - GetPageSizeAndMarginsInPoints(NULL, -1, settings.params, - &default_page_layout); - if (!old_print_pages_params_.get() || - !PageLayoutIsEqual(*old_print_pages_params_, settings)) { - Send(new PrintHostMsg_DidGetDefaultPageLayout(routing_id(), - default_page_layout)); - } + settings.params.print_to_pdf = IsPrintToPdfRequested(*job_settings); + UpdateFrameMarginsCssInfo(*job_settings); + fit_to_page_ = source_is_html && !IsPrintToPdfRequested(*job_settings); // Header/Footer: Set |header_footer_info_|. if (settings.params.display_header_footer) { @@ -1373,7 +1538,9 @@ void PrintWebViewHelper::PrintPreviewContext::OnPrintPreview() { bool PrintWebViewHelper::PrintPreviewContext::CreatePreviewDocument( PrintMsg_Print_Params* print_params, - const std::vector<int>& pages) { + const std::vector<int>& pages, + bool ignore_css_margins, + bool fit_to_page) { DCHECK_EQ(INITIALIZED, state_); state_ = RENDERING; @@ -1387,8 +1554,9 @@ bool PrintWebViewHelper::PrintPreviewContext::CreatePreviewDocument( // Need to make sure old object gets destroyed first. prep_frame_view_.reset(new PrepareFrameAndViewForPrint(*print_params, frame(), node())); - UpdatePrintableSizeInPrintParameters(frame_, node_, - prep_frame_view_.get(), print_params); + UpdateFrameAndViewFromCssPageLayout(frame_, node_, prep_frame_view_.get(), + *print_params, ignore_css_margins, + fit_to_page); print_params_.reset(new PrintMsg_Print_Params(*print_params)); diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h index 24de40e..984a52c 100644 --- a/chrome/renderer/print_web_view_helper.h +++ b/chrome/renderer/print_web_view_helper.h @@ -117,6 +117,19 @@ class PrintWebViewHelper // Print the document with the print preview frame/node. void OnPrintForSystemDialog(); + // Get |page_size| and |content_area| information from + // |page_layout_in_points|. + void GetPageSizeAndContentAreaFromPageLayout( + const printing::PageSizeMargins& page_layout_in_points, + gfx::Size* page_size, + gfx::Rect* content_area); + + // Update |ignore_css_margins_| based on settings. + void UpdateFrameMarginsCssInfo(const base::DictionaryValue& settings); + + // Returns true if the current destination printer is PRINT_TO_PDF. + bool IsPrintToPdfRequested(const base::DictionaryValue& settings); + // Initiate print preview. void OnInitiatePrintPreview(); @@ -216,14 +229,18 @@ class PrintWebViewHelper // |metafile| or a new one. In either case, the caller owns both |metafile| // and the result. printing::Metafile* RenderPage(const PrintMsg_Print_Params& params, - float* scale_factor, int page_number, - bool is_preview, WebKit::WebFrame* frame, - printing::Metafile* metafile); + int page_number, + WebKit::WebFrame* frame, + bool is_preview, + printing::Metafile* metafile, + double* scale_factor, + gfx::Size* page_size_in_dpi, + gfx::Rect* content_area_in_dpi); #elif defined(OS_MACOSX) - void RenderPage(const gfx::Size& page_size, const gfx::Rect& content_area, - const float& scale_factor, int page_number, + void RenderPage(const PrintMsg_Print_Params& params, int page_number, WebKit::WebFrame* frame, bool is_preview, - printing::Metafile* metafile); + printing::Metafile* metafile, gfx::Size* page_size, + gfx::Rect* content_rect); #elif defined(OS_POSIX) bool RenderPages(const PrintMsg_PrintPages_Params& params, WebKit::WebFrame* frame, const WebKit::WebNode& node, @@ -238,17 +255,25 @@ class PrintWebViewHelper bool CopyMetafileDataToSharedMem(printing::Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle); - static void GetPageSizeAndMarginsInPoints( + // Helper method to get page layout in points and fit to page if needed. + static void ComputePageLayoutInPointsForCss( WebKit::WebFrame* frame, int page_index, const PrintMsg_Print_Params& default_params, + bool ignore_css_margins, + bool fit_to_page, + double* scale_factor, printing::PageSizeMargins* page_layout_in_points); - static void UpdatePrintableSizeInPrintParameters( + // Prepare the frame and view for print and then call this function to honor + // the CSS page layout information. + static void UpdateFrameAndViewFromCssPageLayout( WebKit::WebFrame* frame, const WebKit::WebNode& node, PrepareFrameAndViewForPrint* prepare, - PrintMsg_Print_Params* params); + const PrintMsg_Print_Params& params, + bool ignore_css_margins, + bool fit_to_page); // Given the |device| and |canvas| to draw on, prints the appropriate headers // and footers using strings from |header_footer_info| on to the canvas. @@ -299,6 +324,11 @@ class PrintWebViewHelper scoped_ptr<PrintMsg_PrintPages_Params> print_pages_params_; bool is_preview_enabled_; bool is_print_ready_metafile_sent_; + bool ignore_css_margins_; + + // True if we need to auto fit to page else false. + // NOTE: When we print to pdf, we don't fit to page. + bool fit_to_page_; // Used for scripted initiated printing blocking. base::Time last_cancelled_script_print_; @@ -343,7 +373,9 @@ class PrintWebViewHelper // Create the print preview document. |pages| is empty to print all pages. bool CreatePreviewDocument(PrintMsg_Print_Params* params, - const std::vector<int>& pages); + const std::vector<int>& pages, + bool ignore_css_margins, + bool fit_to_page); // Called after a page gets rendered. |page_time| is how long the // rendering took. diff --git a/chrome/renderer/print_web_view_helper_browsertest.cc b/chrome/renderer/print_web_view_helper_browsertest.cc index 2b72538..5d4610c 100644 --- a/chrome/renderer/print_web_view_helper_browsertest.cc +++ b/chrome/renderer/print_web_view_helper_browsertest.cc @@ -26,6 +26,18 @@ namespace { // A simple web page. const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>"; +// A simple web page with print page size css. +const char kHTMLWithPageSizeCss[] = + "<html><head><style>" + "@media print {" + " @page {" + " size: 4in 4in;" + " }" + "}" + "</style></head>" + "<body>Lorem Ipsum:" + "</body></html>"; + // A simple webpage that prints itself. const char kPrintWithJSHTML[] = "<body>Hello<script>window.print()</script>World</body>"; @@ -242,7 +254,7 @@ const TestPageData kTestPages[] = { #if defined(OS_MACOSX) // Mac printing code compensates for the WebKit scale factor while generating // the metafile, so we expect smaller pages. - 1, 540, 720, + 1, 600, 780, #else 1, 675, 900, #endif @@ -389,6 +401,28 @@ class PrintWebViewHelperPreviewTest : public PrintWebViewHelperTestBase { ASSERT_EQ(generate_draft_pages, msg_found); } + void VerifyDefaultPageLayout(int content_width, int content_height, + int margin_top, int margin_bottom, + int margin_left, int margin_right, + bool page_has_print_css) { + const IPC::Message* default_page_layout_msg = + render_thread_->sink().GetUniqueMessageMatching( + PrintHostMsg_DidGetDefaultPageLayout::ID); + bool did_get_default_page_layout_msg = (NULL != default_page_layout_msg); + if (did_get_default_page_layout_msg) { + PrintHostMsg_DidGetDefaultPageLayout::Param param; + PrintHostMsg_DidGetDefaultPageLayout::Read(default_page_layout_msg, + ¶m); + EXPECT_EQ(content_width, param.a.content_width); + EXPECT_EQ(content_height, param.a.content_height); + EXPECT_EQ(margin_top, param.a.margin_top); + EXPECT_EQ(margin_right, param.a.margin_right); + EXPECT_EQ(margin_left, param.a.margin_left); + EXPECT_EQ(margin_bottom, param.a.margin_bottom); + EXPECT_EQ(page_has_print_css, param.b); + } + } + DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperPreviewTest); }; @@ -403,12 +437,163 @@ TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreview) { OnPrintPreview(dict); EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); + VerifyPrintPreviewGenerated(true); + VerifyPagesPrinted(false); +} + +TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewHTMLWithPageMarginsCss) { + // A simple web page with print margins css. + const char kHTMLWithPageMarginsCss[] = + "<html><head><style>" + "@media print {" + " @page {" + " margin: 3in 1in 2in 0.3in;" + " }" + "}" + "</style></head>" + "<body>Lorem Ipsum:" + "</body></html>"; + LoadHTML(kHTMLWithPageMarginsCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, false); + dict.SetInteger(printing::kSettingMarginsType, printing::DEFAULT_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + VerifyDefaultPageLayout(519, 432, 216, 144, 21, 72, false); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); + VerifyPrintPreviewGenerated(true); + VerifyPagesPrinted(false); +} + +// Test to verify that print preview ignores print media css when non-default +// margin is selected. +TEST_F(PrintWebViewHelperPreviewTest, NonDefaultMarginsSelectedIgnorePrintCss) { + LoadHTML(kHTMLWithPageSizeCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, false); + dict.SetInteger(printing::kSettingMarginsType, printing::NO_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + VerifyDefaultPageLayout(612, 792, 0, 0, 0, 0, true); VerifyPrintPreviewCancelled(false); VerifyPrintPreviewFailed(false); VerifyPrintPreviewGenerated(true); VerifyPagesPrinted(false); } +// Test to verify that print preview honor print media size css when +// PRINT_TO_PDF is selected and doesn't fit to printer default paper size. +TEST_F(PrintWebViewHelperPreviewTest, PrintToPDFSelectedHonorPrintCss) { + LoadHTML(kHTMLWithPageSizeCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, true); + dict.SetInteger(printing::kSettingMarginsType, + printing::PRINTABLE_AREA_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page + // size. + VerifyDefaultPageLayout(252, 252, 18, 18, 18, 18, true); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); +} + +// Test to verify that print preview honor print margin css when PRINT_TO_PDF +// is selected and doesn't fit to printer default paper size. +TEST_F(PrintWebViewHelperPreviewTest, PrintToPDFSelectedHonorPageMarginsCss) { + // A simple web page with print margins css. + const char kHTMLWithPageCss[] = + "<html><head><style>" + "@media print {" + " @page {" + " margin: 3in 1in 2in 0.3in;" + " size: 14in 14in;" + " }" + "}" + "</style></head>" + "<body>Lorem Ipsum:" + "</body></html>"; + LoadHTML(kHTMLWithPageCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, true); + dict.SetInteger(printing::kSettingMarginsType, printing::DEFAULT_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page + // size. + VerifyDefaultPageLayout(915, 648, 216, 144, 21, 72, true); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); +} + +// Test to verify that print preview workflow center the html page contents to +// fit the page size. +TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewCenterToFitPage) { + LoadHTML(kHTMLWithPageSizeCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, false); + dict.SetInteger(printing::kSettingMarginsType, printing::DEFAULT_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + VerifyDefaultPageLayout(288, 288, 252, 252, 162, 162, true); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); + VerifyPrintPreviewGenerated(true); +} + +// Test to verify that print preview workflow scale the html page contents to +// fit the page size. +TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewShrinkToFitPage) { + // A simple web page with print margins css. + const char kHTMLWithPageCss[] = + "<html><head><style>" + "@media print {" + " @page {" + " size: 15in 17in;" + " }" + "}" + "</style></head>" + "<body>Lorem Ipsum:" + "</body></html>"; + LoadHTML(kHTMLWithPageCss); + + // Fill in some dummy values. + DictionaryValue dict; + CreatePrintSettingsDictionary(&dict); + dict.SetBoolean(printing::kSettingPrintToPDF, false); + dict.SetInteger(printing::kSettingMarginsType, printing::DEFAULT_MARGINS); + OnPrintPreview(dict); + + EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining()); + VerifyDefaultPageLayout(576, 652, 69, 71, 18, 18, true); + VerifyPrintPreviewCancelled(false); + VerifyPrintPreviewFailed(false); +} + // Test to verify that complete metafile is generated for a subset of pages // without creating draft pages. TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreviewForSelectedPages) { diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc index 6b6d9e6..57b77c9 100644 --- a/chrome/renderer/print_web_view_helper_linux.cc +++ b/chrome/renderer/print_web_view_helper_linux.cc @@ -143,7 +143,8 @@ bool PrintWebViewHelper::RenderPages(const PrintMsg_PrintPages_Params& params, PrepareFrameAndViewForPrint* prepare, printing::Metafile* metafile) { PrintMsg_Print_Params print_params = params.params; - UpdatePrintableSizeInPrintParameters(frame, node, prepare, &print_params); + UpdateFrameAndViewFromCssPageLayout(frame, node, prepare, print_params, + ignore_css_margins_, fit_to_page_); *page_count = prepare->GetExpectedPageCount(); if (!*page_count) @@ -181,23 +182,16 @@ void PrintWebViewHelper::PrintPageInternal( WebFrame* frame, printing::Metafile* metafile) { printing::PageSizeMargins page_layout_in_points; - GetPageSizeAndMarginsInPoints(frame, params.page_number, params.params, - &page_layout_in_points); - - gfx::Size page_size( - page_layout_in_points.content_width + - page_layout_in_points.margin_right + - page_layout_in_points.margin_left, - page_layout_in_points.content_height + - page_layout_in_points.margin_top + - page_layout_in_points.margin_bottom); - gfx::Rect content_area(page_layout_in_points.margin_left, - page_layout_in_points.margin_top, - page_layout_in_points.content_width, - page_layout_in_points.content_height); - + double scale_factor = 1.0f; + ComputePageLayoutInPointsForCss(frame, params.page_number, params.params, + ignore_css_margins_, fit_to_page_, + &scale_factor, &page_layout_in_points); + gfx::Size page_size; + gfx::Rect content_area; + GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size, + &content_area); SkDevice* device = metafile->StartPageForVectorCanvas( - page_size, content_area, 1.0f); + page_size, content_area, scale_factor); if (!device) return; @@ -213,8 +207,9 @@ void PrintWebViewHelper::PrintPageInternal( // |page_number| is 0-based, so 1 is added. // The scale factor on Linux is 1. PrintHeaderAndFooter(canvas.get(), params.page_number + 1, - print_preview_context_.total_page_count(), 1, - page_layout_in_points, *header_footer_info_); + print_preview_context_.total_page_count(), + scale_factor, page_layout_in_points, + *header_footer_info_); } // Done printing. Close the device context to retrieve the compiled metafile. diff --git a/chrome/renderer/print_web_view_helper_mac.mm b/chrome/renderer/print_web_view_helper_mac.mm index 5962a1a..508fde2 100644 --- a/chrome/renderer/print_web_view_helper_mac.mm +++ b/chrome/renderer/print_web_view_helper_mac.mm @@ -32,25 +32,19 @@ void PrintWebViewHelper::PrintPageInternal( if (!metafile.Init()) return; - float scale_factor = frame->getPrintPageShrink(params.page_number); int page_number = params.page_number; - - // Render page for printing. - gfx::Rect content_area(params.params.content_size); - RenderPage(params.params.content_size, content_area, scale_factor, - page_number, frame, false, &metafile); + gfx::Size page_size_in_dpi; + gfx::Rect content_area_in_dpi; + RenderPage(print_pages_params_->params, page_number, frame, false, &metafile, + &page_size_in_dpi, &content_area_in_dpi); metafile.FinishDocument(); PrintHostMsg_DidPrintPage_Params page_params; page_params.data_size = metafile.GetDataSize(); page_params.page_number = page_number; page_params.document_cookie = params.params.document_cookie; - page_params.actual_shrink = scale_factor; - page_params.page_size = params.params.page_size; - page_params.content_area = gfx::Rect(params.params.margin_left, - params.params.margin_top, - params.params.content_size.width(), - params.params.content_size.height()); + page_params.page_size = page_size_in_dpi; + page_params.content_area = content_area_in_dpi; // Ask the browser to create the shared memory for us. if (!CopyMetafileDataToSharedMem(&metafile, @@ -62,12 +56,7 @@ void PrintWebViewHelper::PrintPageInternal( } bool PrintWebViewHelper::RenderPreviewPage(int page_number) { - float scale_factor = print_preview_context_.frame()->getPrintPageShrink(0); PrintMsg_Print_Params printParams = print_preview_context_.print_params(); - gfx::Rect content_area(printParams.margin_left, printParams.margin_top, - printParams.content_size.width(), - printParams.content_size.height()); - scoped_ptr<printing::Metafile> draft_metafile; printing::Metafile* initial_render_metafile = print_preview_context_.metafile(); @@ -96,8 +85,9 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) { } base::TimeTicks begin_time = base::TimeTicks::Now(); - RenderPage(printParams.page_size, content_area, scale_factor, page_number, - print_preview_context_.frame(), true, initial_render_metafile); + gfx::Size page_size; + RenderPage(printParams, page_number, print_preview_context_.frame(), true, + initial_render_metafile, &page_size, NULL); print_preview_context_.RenderedPreviewPage( base::TimeTicks::Now() - begin_time); @@ -111,13 +101,13 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) { // drawing. printing::Metafile* print_ready_metafile = print_preview_context_.metafile(); - bool success = print_ready_metafile->StartPage( - printParams.page_size, gfx::Rect(printParams.page_size), 1.0); + bool success = print_ready_metafile->StartPage(page_size, + gfx::Rect(page_size), 1.0); DCHECK(success); // StartPage unconditionally flips the content over, flip it back since it // was already flipped in |draft_metafile|. CGContextTranslateCTM(print_ready_metafile->context(), 0, - printParams.page_size.height()); + page_size.height()); CGContextScaleCTM(print_ready_metafile->context(), 1.0, -1.0); draft_metafile->RenderPage(1, print_ready_metafile->context(), @@ -143,14 +133,27 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) { } void PrintWebViewHelper::RenderPage( - const gfx::Size& page_size, const gfx::Rect& content_area, - const float& scale_factor, int page_number, WebFrame* frame, - bool is_preview, printing::Metafile* metafile) { - + const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, + bool is_preview, printing::Metafile* metafile, gfx::Size* page_size, + gfx::Rect* content_rect) { + double scale_factor = 1.0f; + double webkit_shrink_factor = frame->getPrintPageShrink(page_number); + printing::PageSizeMargins page_layout_in_points; + gfx::Rect content_area; + + ComputePageLayoutInPointsForCss(frame, page_number, params, + ignore_css_margins_, fit_to_page_, + &scale_factor, &page_layout_in_points); + GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, page_size, + &content_area); + if (content_rect) + *content_rect = content_area; + + scale_factor *= webkit_shrink_factor; { #if defined(USE_SKIA) SkDevice* device = metafile->StartPageForVectorCanvas( - page_size, content_area, scale_factor); + *page_size, content_area, scale_factor); if (!device) return; @@ -161,7 +164,7 @@ void PrintWebViewHelper::RenderPage( skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); skia::SetIsPreviewMetafile(*canvas, is_preview); #else - bool success = metafile->StartPage(page_size, content_area, scale_factor); + bool success = metafile->StartPage(*page_size, content_area, scale_factor); DCHECK(success); // printPage can create autoreleased references to |context|. PDF contexts // don't write all their data until they are destroyed, so we need to make @@ -169,14 +172,7 @@ void PrintWebViewHelper::RenderPage( base::mac::ScopedNSAutoreleasePool pool; CGContextRef cgContext = metafile->context(); CGContextRef canvas_ptr = cgContext; -#endif - - printing::PageSizeMargins page_layout_in_points; - GetPageSizeAndMarginsInPoints(frame, page_number, - print_pages_params_->params, - &page_layout_in_points); -#if !defined(USE_SKIA) // For CoreGraphics, print in the margins before printing in the content // area so that we don't spill over. Webkit draws a white background in the // content area and this acts as a clip. diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc index 4ee351b..648f219 100644 --- a/chrome/renderer/print_web_view_helper_win.cc +++ b/chrome/renderer/print_web_view_helper_win.cc @@ -109,12 +109,15 @@ void PrintWebViewHelper::PrintPageInternal( int page_number = params.page_number; // Calculate the dpi adjustment. - float scale_factor = static_cast<float>(params.params.desired_dpi / - params.params.dpi); + double actual_shrink = static_cast<float>(params.params.desired_dpi / + params.params.dpi); + gfx::Size page_size_in_dpi; + gfx::Rect content_area_in_dpi; // Render page for printing. - metafile.reset(RenderPage(params.params, &scale_factor, page_number, false, - frame, metafile.get())); + metafile.reset(RenderPage(params.params, page_number, frame, false, + metafile.get(), &actual_shrink, &page_size_in_dpi, + &content_area_in_dpi)); // Close the device context to retrieve the compiled metafile. if (!metafile->FinishDocument()) @@ -129,11 +132,9 @@ void PrintWebViewHelper::PrintPageInternal( page_params.metafile_data_handle = NULL; page_params.page_number = page_number; page_params.document_cookie = params.params.document_cookie; - page_params.actual_shrink = scale_factor; - page_params.page_size = params.params.page_size; - page_params.content_area = gfx::Rect(params.params.margin_left, - params.params.margin_top, params.params.content_size.width(), - params.params.content_size.height()); + page_params.actual_shrink = actual_shrink; + page_params.page_size = page_size_in_dpi; + page_params.content_area = content_area_in_dpi; if (!CopyMetafileDataToSharedMem(metafile.get(), &(page_params.metafile_data_handle))) { @@ -146,8 +147,8 @@ void PrintWebViewHelper::PrintPageInternal( bool PrintWebViewHelper::RenderPreviewPage(int page_number) { PrintMsg_Print_Params print_params = print_preview_context_.print_params(); // Calculate the dpi adjustment. - float scale_factor = static_cast<float>(print_params.desired_dpi / - print_params.dpi); + double actual_shrink = static_cast<float>(print_params.desired_dpi / + print_params.dpi); scoped_ptr<Metafile> draft_metafile; printing::Metafile* initial_render_metafile = print_preview_context_.metafile(); @@ -159,8 +160,8 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) { base::TimeTicks begin_time = base::TimeTicks::Now(); printing::Metafile* render_page_result = - RenderPage(print_params, &scale_factor, page_number, true, - print_preview_context_.frame(), initial_render_metafile); + RenderPage(print_params, page_number, print_preview_context_.frame(), + true, initial_render_metafile, &actual_shrink, NULL, NULL); // In the preview flow, RenderPage will never return a new metafile. DCHECK_EQ(render_page_result, initial_render_metafile); print_preview_context_.RenderedPreviewPage( @@ -178,37 +179,54 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) { } Metafile* PrintWebViewHelper::RenderPage( - const PrintMsg_Print_Params& params, float* scale_factor, int page_number, - bool is_preview, WebFrame* frame, Metafile* metafile) { + const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, + bool is_preview, Metafile* metafile, double* actual_shrink, + gfx::Size* page_size_in_dpi, gfx::Rect* content_area_in_dpi) { printing::PageSizeMargins page_layout_in_points; - GetPageSizeAndMarginsInPoints(frame, page_number, params, - &page_layout_in_points); + double css_scale_factor = 1.0f; + ComputePageLayoutInPointsForCss(frame, page_number, params, + ignore_css_margins_, fit_to_page_, + &css_scale_factor, &page_layout_in_points); + gfx::Size page_size; + gfx::Rect content_area; + GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size, + &content_area); + int dpi = static_cast<int>(params.dpi); + // Calculate the actual page size and content area in dpi. + if (page_size_in_dpi) { + *page_size_in_dpi = gfx::Size( + static_cast<int>(ConvertUnitDouble( + page_size.width(), printing::kPointsPerInch, dpi)), + static_cast<int>(ConvertUnitDouble( + page_size.height(), printing::kPointsPerInch, dpi))); + } - int width; - int height; - if (is_preview) { - int dpi = static_cast<int>(params.dpi); - int desired_dpi = printing::kPointsPerInch; - width = ConvertUnit(params.page_size.width(), dpi, desired_dpi); - height = ConvertUnit(params.page_size.height(), dpi, desired_dpi); - } else { + if (content_area_in_dpi) { + *content_area_in_dpi = gfx::Rect( + static_cast<int>(ConvertUnitDouble(content_area.x(), + printing::kPointsPerInch, dpi)), + static_cast<int>(ConvertUnitDouble(content_area.y(), + printing::kPointsPerInch, dpi)), + static_cast<int>(ConvertUnitDouble(content_area.width(), + printing::kPointsPerInch, dpi)), + static_cast<int>(ConvertUnitDouble(content_area.height(), + printing::kPointsPerInch, dpi))); + } + + if (!is_preview) { // Since WebKit extends the page width depending on the magical scale factor // we make sure the canvas covers the worst case scenario (x2.0 currently). // PrintContext will then set the correct clipping region. - width = static_cast<int>(page_layout_in_points.content_width * - params.max_shrink); - height = static_cast<int>(page_layout_in_points.content_height * - params.max_shrink); + page_size = gfx::Size( + static_cast<int>(page_layout_in_points.content_width * + params.max_shrink), + static_cast<int>(page_layout_in_points.content_height * + params.max_shrink)); } - gfx::Size page_size(width, height); - gfx::Rect content_area( - static_cast<int>(page_layout_in_points.margin_left), - static_cast<int>(page_layout_in_points.margin_top), - static_cast<int>(page_layout_in_points.content_width), - static_cast<int>(page_layout_in_points.content_height)); + float webkit_page_shrink_factor = frame->getPrintPageShrink(page_number); SkDevice* device = metafile->StartPageForVectorCanvas( - page_size, content_area, frame->getPrintPageShrink(page_number)); + page_size, content_area, css_scale_factor * webkit_page_shrink_factor); DCHECK(device); // The printPage method may take a reference to the canvas we pass down, so it // can't be a stack object. @@ -226,16 +244,17 @@ Metafile* PrintWebViewHelper::RenderPage( // |page_number| is 0-based, so 1 is added. PrintHeaderAndFooter(canvas.get(), page_number + 1, print_preview_context_.total_page_count(), - webkit_scale_factor, page_layout_in_points, + css_scale_factor * webkit_page_shrink_factor, + page_layout_in_points, *header_footer_info_); } - if (*scale_factor <= 0 || webkit_scale_factor <= 0) { + if (*actual_shrink <= 0 || webkit_scale_factor <= 0) { NOTREACHED() << "Printing page " << page_number << " failed."; } else { - // Update the dpi adjustment with the "page |scale_factor|" calculated in + // Update the dpi adjustment with the "page |actual_shrink|" calculated in // webkit. - *scale_factor /= webkit_scale_factor; + *actual_shrink /= (webkit_scale_factor * css_scale_factor); } bool result = metafile->FinishPage(); @@ -264,14 +283,15 @@ Metafile* PrintWebViewHelper::RenderPage( SetGraphicsMode(bitmap_dc, GM_ADVANCED); void* bits = NULL; BITMAPINFO hdr; - gfx::CreateBitmapHeader(width, height, &hdr.bmiHeader); + gfx::CreateBitmapHeader(page_size.width(), page_size.height(), + &hdr.bmiHeader); base::win::ScopedBitmap hbitmap(CreateDIBSection( bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0)); if (!hbitmap) NOTREACHED() << "Raster bitmap creation for printing failed"; base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap); - RECT rect = {0, 0, width, height }; + RECT rect = { 0, 0, page_size.width(), page_size.height() }; HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); FillRect(bitmap_dc, &rect, whiteBrush); |