From 957b445184639d1c6d141a6eca7bed8c89b142de Mon Sep 17 00:00:00 2001 From: thestig Date: Wed, 11 Mar 2015 15:20:54 -0700 Subject: [PATCH] Printing: PDFs should only be fit to page if there is a size mismatch. BUG=158752 Review URL: https://codereview.chromium.org/981843003 Cr-Commit-Position: refs/heads/master@{#320167} --- .../renderer/print_web_view_helper.cc | 67 ++++++++++++++----- .../printing/renderer/print_web_view_helper.h | 4 +- .../pepper/pepper_plugin_instance_impl.cc | 4 ++ pdf/instance.cc | 4 ++ pdf/out_of_process_instance.cc | 4 ++ pdf/pdf_engine.h | 2 + pdf/pdfium/pdfium_engine.cc | 18 +++++ pdf/pdfium/pdfium_engine.h | 1 + ppapi/c/private/ppp_pdf.h | 8 ++- ppapi/proxy/ppapi_messages.h | 5 +- 10 files changed, 94 insertions(+), 23 deletions(-) diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index 820dfe1cf07753..d38516af9fe0bf 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc @@ -35,7 +35,6 @@ #include "third_party/WebKit/public/web/WebPluginDocument.h" #include "third_party/WebKit/public/web/WebPrintParams.h" #include "third_party/WebKit/public/web/WebPrintPresetOptions.h" -#include "third_party/WebKit/public/web/WebPrintScalingOption.h" #include "third_party/WebKit/public/web/WebSandboxFlags.h" #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebSettings.h" @@ -312,12 +311,41 @@ bool PrintingFrameHasPageSizeStyle(blink::WebFrame* frame, return frame_has_custom_page_size_style; } -MarginType GetMarginsForPdf(blink::WebFrame* frame, - const blink::WebNode& node) { - if (frame->isPrintScalingDisabledForPlugin(node)) - return NO_MARGINS; - else - return PRINTABLE_AREA_MARGINS; +// Disable scaling when either: +// - The PDF specifies disabling scaling. +// - All the pages in the PDF are the same size, and that size is the same as +// the paper size. +bool PDFShouldDisableScalingBasedOnPreset( + const blink::WebPrintPresetOptions& options, + const PrintMsg_Print_Params& params) { + if (options.isScalingDisabled) + return true; + + if (!options.isPageSizeUniform) + return false; + + int dpi = GetDPI(¶ms); + blink::WebSize page_size( + ConvertUnit(params.page_size.width(), dpi, kPointsPerInch), + ConvertUnit(params.page_size.height(), dpi, kPointsPerInch)); + return options.uniformPageSize == page_size; +} + +bool PDFShouldDisableScaling(blink::WebLocalFrame* frame, + const blink::WebNode& node, + const PrintMsg_Print_Params& params) { + const bool kDefaultPDFShouldDisableScalingSetting = true; + blink::WebPrintPresetOptions preset_options; + if (!frame->getPrintPresetOptionsForPlugin(node, &preset_options)) + return kDefaultPDFShouldDisableScalingSetting; + return PDFShouldDisableScalingBasedOnPreset(preset_options, params); +} + +MarginType GetMarginsForPdf(blink::WebLocalFrame* frame, + const blink::WebNode& node, + const PrintMsg_Print_Params& params) { + return PDFShouldDisableScaling(frame, node, params) ? + NO_MARGINS : PRINTABLE_AREA_MARGINS; } bool FitToPageEnabled(const base::DictionaryValue& job_settings) { @@ -343,7 +371,7 @@ bool FitToPageEnabled(const base::DictionaryValue& job_settings) { // // In all other cases, we scale the source page to fit the printable area. blink::WebPrintScalingOption GetPrintScalingOption( - blink::WebFrame* frame, + blink::WebLocalFrame* frame, const blink::WebNode& node, bool source_is_html, const base::DictionaryValue& job_settings, @@ -355,8 +383,7 @@ blink::WebPrintScalingOption GetPrintScalingOption( if (!FitToPageEnabled(job_settings)) return blink::WebPrintScalingOptionNone; - bool no_plugin_scaling = frame->isPrintScalingDisabledForPlugin(node); - + bool no_plugin_scaling = PDFShouldDisableScaling(frame, node, params); if (params.is_first_request && no_plugin_scaling) return blink::WebPrintScalingOptionNone; } @@ -1017,8 +1044,8 @@ void PrintWebViewHelper::OnPrintPreview(const base::DictionaryValue& settings) { if (print_pages_params_->params.is_first_request && !print_preview_context_.IsModifiable()) { PrintHostMsg_SetOptionsFromDocument_Params options; - SetOptionsFromPdfDocument(&options); - Send(new PrintHostMsg_SetOptionsFromDocument(routing_id(), options)); + if (SetOptionsFromPdfDocument(&options)) + Send(new PrintHostMsg_SetOptionsFromDocument(routing_id(), options)); } is_print_ready_metafile_sent_ = false; @@ -1443,7 +1470,7 @@ bool PrintWebViewHelper::CalculateNumberOfPages(blink::WebLocalFrame* frame, return true; } -void PrintWebViewHelper::SetOptionsFromPdfDocument( +bool PrintWebViewHelper::SetOptionsFromPdfDocument( PrintHostMsg_SetOptionsFromDocument_Params* options) { blink::WebLocalFrame* source_frame = print_preview_context_.source_frame(); const blink::WebNode& source_node = print_preview_context_.source_node(); @@ -1451,10 +1478,11 @@ void PrintWebViewHelper::SetOptionsFromPdfDocument( blink::WebPrintPresetOptions preset_options; if (!source_frame->getPrintPresetOptionsForPlugin(source_node, &preset_options)) { - return; + return false; } - options->is_scaling_disabled = preset_options.isScalingDisabled; + options->is_scaling_disabled = PDFShouldDisableScalingBasedOnPreset( + preset_options, print_pages_params_->params); options->copies = preset_options.copies; // TODO(thestig) This should be a straight pass-through, but print preview @@ -1470,6 +1498,7 @@ void PrintWebViewHelper::SetOptionsFromPdfDocument( options->duplex = UNKNOWN_DUPLEX_MODE; break; } + return true; } bool PrintWebViewHelper::UpdatePrintSettings( @@ -1550,7 +1579,7 @@ bool PrintWebViewHelper::UpdatePrintSettings( return true; } -bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebFrame* frame, +bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebLocalFrame* frame, const blink::WebNode& node, int expected_pages_count, bool is_scripted) { @@ -1561,8 +1590,10 @@ bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebFrame* frame, params.has_selection = frame->hasSelection(); params.expected_pages_count = expected_pages_count; MarginType margin_type = DEFAULT_MARGINS; - if (PrintingNodeOrPdfFrame(frame, node)) - margin_type = GetMarginsForPdf(frame, node); + if (PrintingNodeOrPdfFrame(frame, node)) { + margin_type = + GetMarginsForPdf(frame, node, print_pages_params_->params); + } params.margin_type = margin_type; params.is_scripted = is_scripted; diff --git a/components/printing/renderer/print_web_view_helper.h b/components/printing/renderer/print_web_view_helper.h index a36b943029b059..3ffdf21d93793a 100644 --- a/components/printing/renderer/print_web_view_helper.h +++ b/components/printing/renderer/print_web_view_helper.h @@ -221,7 +221,7 @@ class PrintWebViewHelper int* number_of_pages); // Set options for print preset from source PDF document. - void SetOptionsFromPdfDocument( + bool SetOptionsFromPdfDocument( PrintHostMsg_SetOptionsFromDocument_Params* options); // Update the current print settings with new |passed_job_settings|. @@ -233,7 +233,7 @@ class PrintWebViewHelper // Get final print settings from the user. // Return false if the user cancels or on error. - bool GetPrintSettingsFromUser(blink::WebFrame* frame, + bool GetPrintSettingsFromUser(blink::WebLocalFrame* frame, const blink::WebNode& node, int expected_pages_count, bool is_scripted); diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 4e051349df677d..ecbd59cc640269 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -1837,6 +1837,10 @@ bool PepperPluginInstanceImpl::GetPrintPresetOptionsFromDocument( break; } preset_options->copies = options.copies; + preset_options->isPageSizeUniform = PP_ToBool(options.is_page_size_uniform); + preset_options->uniformPageSize = + blink::WebSize(options.uniform_page_size.width, + options.uniform_page_size.height); return true; } diff --git a/pdf/instance.cc b/pdf/instance.cc index 724f7d664c2f1a..f32129163c8a78 100644 --- a/pdf/instance.cc +++ b/pdf/instance.cc @@ -677,6 +677,10 @@ void Instance::GetPrintPresetOptionsFromDocument( options->duplex = static_cast(engine_->GetDuplexType()); options->copies = engine_->GetCopiesToPrint(); + pp::Size uniform_page_size; + options->is_page_size_uniform = + PP_FromBool(engine_->GetPageSizeAndUniformity(&uniform_page_size)); + options->uniform_page_size = PP_Size(uniform_page_size); } pp::Var Instance::GetLinkAtPosition(const pp::Point& point) { diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index f40582d65dcd6e..87d45aa2cf0730 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc @@ -610,6 +610,10 @@ void OutOfProcessInstance::GetPrintPresetOptionsFromDocument( options->duplex = static_cast(engine_->GetDuplexType()); options->copies = engine_->GetCopiesToPrint(); + pp::Size uniform_page_size; + options->is_page_size_uniform = + PP_FromBool(engine_->GetPageSizeAndUniformity(&uniform_page_size)); + options->uniform_page_size = uniform_page_size; } pp::Var OutOfProcessInstance::GetLinkAtPosition( diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index bcfa7e6475e907..e99ab47ed878b6 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h @@ -252,6 +252,8 @@ class PDFEngine { virtual int GetCopiesToPrint() = 0; // Returns the duplex setting. virtual int GetDuplexType() = 0; + // Returns true if all the pages are the same size. + virtual bool GetPageSizeAndUniformity(pp::Size* size) = 0; // Returns a VarArray of Bookmarks, each a VarDictionary containing the // following key/values: diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index ddc1696857d5d3..76a5c27732126f 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc @@ -2461,6 +2461,24 @@ int PDFiumEngine::GetDuplexType() { return static_cast(FPDF_VIEWERREF_GetDuplex(doc_)); } +bool PDFiumEngine::GetPageSizeAndUniformity(pp::Size* size) { + if (pages_.empty()) + return false; + + pp::Size page_size = GetPageSize(0); + for (size_t i = 1; i < pages_.size(); ++i) { + if (page_size != GetPageSize(i)) + return false; + } + + // Convert |page_size| back to points. + size->set_width( + ConvertUnit(page_size.width(), kPixelsPerInch, kPointsPerInch)); + size->set_height( + ConvertUnit(page_size.height(), kPixelsPerInch, kPointsPerInch)); + return true; +} + void PDFiumEngine::AppendBlankPages(int num_pages) { DCHECK(num_pages != 0); diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index 2dc65b4100f438..d3a9a14150316a 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h @@ -94,6 +94,7 @@ class PDFiumEngine : public PDFEngine, virtual bool GetPrintScaling(); virtual int GetCopiesToPrint(); virtual int GetDuplexType(); + virtual bool GetPageSizeAndUniformity(pp::Size* size); virtual void AppendBlankPages(int num_pages); virtual void AppendPage(PDFEngine* engine, int index); virtual pp::Point GetScrollPosition(); diff --git a/ppapi/c/private/ppp_pdf.h b/ppapi/c/private/ppp_pdf.h index c3678e43d9f070..2a761b8618aaac 100644 --- a/ppapi/c/private/ppp_pdf.h +++ b/ppapi/c/private/ppp_pdf.h @@ -40,8 +40,14 @@ struct PP_PdfPrintPresetOptions_Dev { // DuplexMode to be used for printing. PP_PrivateDuplexMode_Dev duplex; + + // True if all the pages in the PDF are the same size. + PP_Bool is_page_size_uniform; + + // Only valid if |is_page_size_uniform| is true. The page size. + PP_Size uniform_page_size; }; -PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_PdfPrintPresetOptions_Dev, 12); +PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_PdfPrintPresetOptions_Dev, 24); struct PPP_Pdf_1_1 { // Returns an absolute URL if the position is over a link. diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index ce4db8939178e1..4347649753e3b9 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -113,8 +113,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(PP_NetworkList_Type, PP_NETWORKLIST_TYPE_CELLULAR) IPC_ENUM_TRAITS(PP_PrintOrientation_Dev) IPC_ENUM_TRAITS(PP_PrintOutputFormat_Dev) IPC_ENUM_TRAITS(PP_PrintScalingOption_Dev) -IPC_ENUM_TRAITS_MAX_VALUE(PP_PrivateDuplexMode_Dev, - PP_PRIVATEDUPLEXMODE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(PP_PrivateDuplexMode_Dev, PP_PRIVATEDUPLEXMODE_LAST) IPC_ENUM_TRAITS(PP_PrivateFontCharset) IPC_ENUM_TRAITS(PP_ResourceImage) IPC_ENUM_TRAITS(PP_ResourceString) @@ -216,6 +215,8 @@ IPC_STRUCT_TRAITS_BEGIN(PP_PdfPrintPresetOptions_Dev) IPC_STRUCT_TRAITS_MEMBER(is_scaling_disabled) IPC_STRUCT_TRAITS_MEMBER(copies) IPC_STRUCT_TRAITS_MEMBER(duplex) + IPC_STRUCT_TRAITS_MEMBER(is_page_size_uniform) + IPC_STRUCT_TRAITS_MEMBER(uniform_page_size) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(PP_URLComponent_Dev)