Skip to content

Commit

Permalink
Add N-up feature support to pdfium_engine.
Browse files Browse the repository at this point in the history
In printing, 2-up, 3-up, or more generally N-up refers to a page
layout strategy in which multiple pages are composited onto a
single page.

1. Added ability to pass the N-up feature UI settings(which will be
   added in the next CL) to the print preview workflow, so that the
   PDF plugin can take action based on user's input.
2. Added N-up feature support to pdfium_engine, so that when the
   source is PDF, pdf plugin will generate the N-up output doc based
   on user's input.

These changes have been reviewed in:
https://chromium-review.googlesource.com/c/chromium/src/+/1014628.

Bug: 775999
Change-Id: I552c9c91e32af0faa6ffaa8c42ac0652f470f791
Reviewed-on: https://chromium-review.googlesource.com/1028992
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Jochen Eisinger <jochen@chromium.org>
Commit-Queue: Shirleen Lou <xlou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554188}
  • Loading branch information
xlou authored and Commit Bot committed Apr 26, 2018
1 parent 2a9b438 commit 1942075
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 21 deletions.
1 change: 1 addition & 0 deletions components/printing/browser/print_manager_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void RenderParamsFromPrintSettings(const PrintSettings& settings,
params->url = settings.url();
params->printed_doc_type =
IsOopifEnabled() ? SkiaDocumentType::MSKP : SkiaDocumentType::PDF;
params->num_pages_per_sheet = settings.num_pages_per_sheet();
}

} // namespace printing
4 changes: 3 additions & 1 deletion components/printing/common/print_messages.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ PrintMsg_Print_Params::PrintMsg_Print_Params()
footer_template(),
should_print_backgrounds(false),
printed_doc_type(printing::SkiaDocumentType::PDF),
prefer_css_page_size(false) {}
prefer_css_page_size(false),
num_pages_per_sheet(1) {}

PrintMsg_Print_Params::PrintMsg_Print_Params(
const PrintMsg_Print_Params& other) = default;
Expand Down Expand Up @@ -128,6 +129,7 @@ void PrintMsg_Print_Params::Reset() {
should_print_backgrounds = false;
printed_doc_type = printing::SkiaDocumentType::PDF;
prefer_css_page_size = false;
num_pages_per_sheet = 1;
}

PrintMsg_PrintPages_Params::PrintMsg_PrintPages_Params()
Expand Down
6 changes: 6 additions & 0 deletions components/printing/common/print_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct PrintMsg_Print_Params {
bool should_print_backgrounds;
printing::SkiaDocumentType printed_doc_type;
bool prefer_css_page_size;
int num_pages_per_sheet;
};

struct PrintMsg_PrintPages_Params {
Expand Down Expand Up @@ -191,6 +192,11 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)

// True if page size defined by css should be preferred.
IPC_STRUCT_TRAITS_MEMBER(prefer_css_page_size)

// Number of pages per sheet. This parameter is for N-up mode.
// Defaults to 1 if the feature is disabled, and some number greater
// than 1 otherwise. See printing::NupParameters for supported values.
IPC_STRUCT_TRAITS_MEMBER(num_pages_per_sheet)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(printing::PageRange)
Expand Down
3 changes: 3 additions & 0 deletions components/printing/renderer/print_render_frame_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ void ComputeWebKitPrintParamsInDesiredDpi(
ConvertUnit(print_params.page_size.width(), dpi, kPointsPerInch);
webkit_print_params->paper_size.height =
ConvertUnit(print_params.page_size.height(), dpi, kPointsPerInch);

// The following settings is for N-up mode.
webkit_print_params->num_pages_per_sheet = print_params.num_pages_per_sheet;
}

blink::WebPlugin* GetPlugin(const blink::WebLocalFrame* frame) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ PepperPrintSettingsManager::Result ComputeDefaultPrintSettings() {
settings.paper_size =
PrintSizeToPPPrintSize(page_setup.physical_size(), device_units_per_inch);
settings.dpi = print_settings.dpi();
settings.num_pages_per_sheet = print_settings.num_pages_per_sheet();

// The remainder of the attributes are hard-coded to the defaults as set
// elsewhere.
Expand Down
3 changes: 3 additions & 0 deletions content/renderer/pepper/pepper_plugin_instance_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,9 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
print_settings.print_scaling_option =
static_cast<PP_PrintScalingOption_Dev>(print_params.print_scaling_option);
print_settings.format = format;

print_settings.num_pages_per_sheet = print_params.num_pages_per_sheet;

num_pages = plugin_print_interface_->Begin(pp_instance(), &print_settings);
if (!num_pages)
return 0;
Expand Down
1 change: 1 addition & 0 deletions pdf/pdfium/DEPS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include_rules = [
"+gin/array_buffer.h",
"+gin/public",
"+printing/nup_parameters.h",
"+third_party/pdfium/public",
"+ui/gfx/codec/jpeg_codec.h",
]
106 changes: 92 additions & 14 deletions pdf/pdfium/pdfium_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "ppapi/cpp/url_response_info.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_dictionary.h"
#include "printing/nup_parameters.h"
#include "printing/units.h"
#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
#include "third_party/pdfium/public/fpdf_annot.h"
Expand Down Expand Up @@ -709,6 +710,30 @@ std::string ConvertViewIntToViewString(unsigned long view_int) {
}
}

// UI should have done parameter sanity check, when execution
// reaches here, |num_pages_per_sheet| should be a positive integer.
bool ShouldDoNup(int num_pages_per_sheet) {
return num_pages_per_sheet > 1;
}

// Check the source doc orientation. Returns true if the doc is landscape.
// For now the orientation of the doc is determined by its first page's
// orientation. Improvement can be added in the future to better determine the
// orientation of the source docs that have mixed orientation.
// TODO(xlou): rotate pages if the source doc has mixed orientation. So that
// the orientation of all pages of the doc are uniform. Pages of square size
// will not be rotated.
bool IsSourcePdfLandscape(FPDF_DOCUMENT doc) {
DCHECK(doc);

ScopedFPDFPage pdf_page(FPDF_LoadPage(doc, 0));
DCHECK(pdf_page);

bool is_source_landscape =
FPDF_GetPageWidth(pdf_page.get()) > FPDF_GetPageHeight(pdf_page.get());
return is_source_landscape;
}

} // namespace

bool InitializeSDK() {
Expand Down Expand Up @@ -1707,16 +1732,21 @@ pp::Buffer_Dev PDFiumEngine::PrintPagesAsRasterPDF(
pp::Buffer_Dev buffer;
if (i == pages_to_print.size()) {
FPDF_CopyViewerPreferences(output_doc, doc_);
FitContentsToPrintableAreaIfRequired(output_doc, print_settings);
// Now flatten all the output pages.
buffer = GetFlattenedPrintData(output_doc);
if (ShouldDoNup(print_settings.num_pages_per_sheet)) {
buffer = NupPdfToPdf(output_doc, print_settings);
} else {
FitContentsToPrintableAreaIfRequired(output_doc, print_settings);
buffer = GetPrintData(output_doc);
}
}

FPDF_CloseDocument(output_doc);
return buffer;
}

pp::Buffer_Dev PDFiumEngine::GetFlattenedPrintData(FPDF_DOCUMENT doc) {
pp::Buffer_Dev buffer;
bool PDFiumEngine::FlattenPrintData(FPDF_DOCUMENT doc) {
DCHECK(doc);

ScopedSubstFont scoped_subst_font(this);
int page_count = FPDF_GetPageCount(doc);
for (int i = 0; i < page_count; ++i) {
Expand All @@ -1725,9 +1755,15 @@ pp::Buffer_Dev PDFiumEngine::GetFlattenedPrintData(FPDF_DOCUMENT doc) {
int flatten_ret = FPDFPage_Flatten(page, FLAT_PRINT);
FPDF_ClosePage(page);
if (flatten_ret == FLATTEN_FAIL)
return buffer;
return false;
}
return true;
}

pp::Buffer_Dev PDFiumEngine::GetPrintData(FPDF_DOCUMENT doc) {
DCHECK(doc);

pp::Buffer_Dev buffer;
PDFiumMemBufferFileWrite output_file_write;
if (FPDF_SaveAsCopy(doc, &output_file_write, 0)) {
size_t size = output_file_write.size();
Expand All @@ -1738,6 +1774,41 @@ pp::Buffer_Dev PDFiumEngine::GetFlattenedPrintData(FPDF_DOCUMENT doc) {
return buffer;
}

pp::Buffer_Dev PDFiumEngine::GetFlattenedPrintData(FPDF_DOCUMENT doc) {
DCHECK(doc);

pp::Buffer_Dev buffer;
if (FlattenPrintData(doc))
buffer = GetPrintData(doc);
return buffer;
}

pp::Buffer_Dev PDFiumEngine::NupPdfToPdf(
FPDF_DOCUMENT doc,
const PP_PrintSettings_Dev& print_settings) {
DCHECK(doc);

PP_Size page_size = print_settings.paper_size;

printing::NupParameters nup_params;
bool is_landscape = IsSourcePdfLandscape(doc);
nup_params.SetParameters(print_settings.num_pages_per_sheet, is_landscape);

// Import n pages to one.
bool paper_is_landscape = page_size.width > page_size.height;
if (nup_params.landscape() != paper_is_landscape)
std::swap(page_size.width, page_size.height);

ScopedFPDFDocument output_doc_nup(FPDF_ImportNPagesToOne(
doc, page_size.width, page_size.height, nup_params.num_pages_on_x_axis(),
nup_params.num_pages_on_y_axis()));
if (!output_doc_nup)
return pp::Buffer_Dev();

FitContentsToPrintableAreaIfRequired(output_doc_nup.get(), print_settings);
return GetPrintData(output_doc_nup.get());
}

pp::Buffer_Dev PDFiumEngine::PrintPagesAsPDF(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
Expand All @@ -1746,7 +1817,7 @@ pp::Buffer_Dev PDFiumEngine::PrintPagesAsPDF(
return pp::Buffer_Dev();

DCHECK(doc_);
FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
if (!output_doc)
return pp::Buffer_Dev();

Expand All @@ -1772,17 +1843,24 @@ pp::Buffer_Dev PDFiumEngine::PrintPagesAsPDF(
pages_[page_number]->Unload();
}

FPDF_CopyViewerPreferences(output_doc, doc_);
if (!FPDF_ImportPages(output_doc, doc_, page_number_str.c_str(), 0)) {
FPDF_CloseDocument(output_doc);
FPDF_CopyViewerPreferences(output_doc.get(), doc_);
if (!FPDF_ImportPages(output_doc.get(), doc_, page_number_str.c_str(), 0)) {
return pp::Buffer_Dev();
}

FitContentsToPrintableAreaIfRequired(output_doc, print_settings);

// Now flatten all the output pages.
pp::Buffer_Dev buffer = GetFlattenedPrintData(output_doc);
FPDF_CloseDocument(output_doc);
if (!FlattenPrintData(output_doc.get())) {
return pp::Buffer_Dev();
}

pp::Buffer_Dev buffer;
if (ShouldDoNup(print_settings.num_pages_per_sheet)) {
buffer = NupPdfToPdf(output_doc.get(), print_settings);
} else {
FitContentsToPrintableAreaIfRequired(output_doc.get(), print_settings);
buffer = GetPrintData(output_doc.get());
}

return buffer;
}

Expand Down
9 changes: 9 additions & 0 deletions pdf/pdfium/pdfium_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,16 @@ class PDFiumEngine : public PDFEngine,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings);

bool FlattenPrintData(FPDF_DOCUMENT doc);
pp::Buffer_Dev GetPrintData(FPDF_DOCUMENT doc);
pp::Buffer_Dev GetFlattenedPrintData(FPDF_DOCUMENT doc);

// Perform N-up PDF generation from |doc| based on the parameters in
// |print_settings|. On success, the returned buffer contains the N-up version
// of |doc|. On failure, the returned buffer is empty.
pp::Buffer_Dev NupPdfToPdf(FPDF_DOCUMENT doc,
const PP_PrintSettings_Dev& print_settings);

void FitContentsToPrintableAreaIfRequired(
FPDF_DOCUMENT doc,
const PP_PrintSettings_Dev& print_settings);
Expand Down
4 changes: 3 additions & 1 deletion ppapi/api/dev/pp_print_settings_dev.idl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum PP_PrintScalingOption_Dev {
PP_PRINTSCALINGOPTION_LAST = PP_PRINTSCALINGOPTION_SOURCE_SIZE
};

[assert_size(60)]
[assert_size(64)]
struct PP_PrintSettings_Dev {
/** This is the size of the printable area in points (1/72 of an inch). */
PP_Rect printable_area;
Expand All @@ -44,4 +44,6 @@ struct PP_PrintSettings_Dev {
PP_Bool grayscale;
/** Note that Chrome currently only supports PDF printing. */
PP_PrintOutputFormat_Dev format;
/** Note the following parameter is for N-up mode. */
uint32_t num_pages_per_sheet;
};
4 changes: 3 additions & 1 deletion ppapi/c/dev/pp_print_settings_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ struct PP_PrintSettings_Dev {
PP_Bool grayscale;
/** Note that Chrome currently only supports PDF printing. */
PP_PrintOutputFormat_Dev format;
/** Note the following parameter is for N-up mode. */
uint32_t num_pages_per_sheet;
};
PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_PrintSettings_Dev, 60);
PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_PrintSettings_Dev, 64);
/**
* @}
*/
Expand Down
1 change: 1 addition & 0 deletions ppapi/proxy/ppapi_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ IPC_STRUCT_TRAITS_BEGIN(PP_PrintSettings_Dev)
IPC_STRUCT_TRAITS_MEMBER(print_scaling_option)
IPC_STRUCT_TRAITS_MEMBER(grayscale)
IPC_STRUCT_TRAITS_MEMBER(format)
IPC_STRUCT_TRAITS_MEMBER(num_pages_per_sheet)
IPC_STRUCT_TRAITS_END()

IPC_STRUCT_TRAITS_BEGIN(PP_PdfPrintPresetOptions_Dev)
Expand Down
1 change: 1 addition & 0 deletions printing/print_settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ void PrintSettings::Clear() {
printer_type_ = PrintSettings::PrinterType::TYPE_NONE;
#endif
is_modifiable_ = true;
num_pages_per_sheet_ = 1;
}

void PrintSettings::SetPrinterPrintableArea(
Expand Down
8 changes: 8 additions & 0 deletions printing/print_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ class PRINTING_EXPORT PrintSettings {
void set_is_modifiable(bool is_modifiable) { is_modifiable_ = is_modifiable; }
bool is_modifiable() const { return is_modifiable_; }

int num_pages_per_sheet() const { return num_pages_per_sheet_; }
void set_num_pages_per_sheet(int num_pages_per_sheet) {
num_pages_per_sheet_ = num_pages_per_sheet;
}

// Cookie generator. It is used to initialize PrintedDocument with its
// associated PrintSettings, to be sure that each generated PrintedPage is
// correctly associated with its corresponding PrintedDocument.
Expand Down Expand Up @@ -262,6 +267,9 @@ class PRINTING_EXPORT PrintSettings {

// If margin type is custom, this is what was requested.
PageMargins requested_custom_margins_in_points_;

// Number of pages per sheet.
int num_pages_per_sheet_;
};

} // namespace printing
Expand Down
4 changes: 4 additions & 0 deletions printing/print_settings_conversion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings,
int copies = 1;
int scale_factor = 100;
bool rasterize_pdf = false;
int num_pages_per_sheet = 1;

if (!job_settings.GetBoolean(kSettingCollate, &collate) ||
!job_settings.GetInteger(kSettingCopies, &copies) ||
Expand Down Expand Up @@ -216,6 +217,9 @@ bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings,
#endif
}

// TODO(xlou): Add logic to get |num_pages_per_sheet| from |job_settings|.
settings->set_num_pages_per_sheet(num_pages_per_sheet);

return true;
}

Expand Down
15 changes: 11 additions & 4 deletions third_party/blink/public/web/web_print_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ struct WebPrintParams {
// Specifies whether printing layout needs to be applied.
bool use_printing_layout;

// Specifies how many pages per sheet. This parameter is for N-up mode.
size_t num_pages_per_sheet;

WebPrintParams()
: printer_dpi(72),
print_scaling_option(kWebPrintScalingOptionFitToPrintableArea),
use_printing_layout(true) {}
use_printing_layout(true),
num_pages_per_sheet(1) {}

WebPrintParams(const WebSize& paper_size)
: WebPrintParams(paper_size, true) {}
Expand All @@ -75,20 +79,23 @@ struct WebPrintParams {
paper_size(paper_size),
printer_dpi(72),
print_scaling_option(kWebPrintScalingOptionSourceSize),
use_printing_layout(use_printing_layout) {}
use_printing_layout(use_printing_layout),
num_pages_per_sheet(1) {}

WebPrintParams(const WebRect& print_content_area,
const WebRect& printable_area,
const WebSize& paper_size,
int printer_dpi,
WebPrintScalingOption print_scaling_option,
bool use_printing_layout)
bool use_printing_layout,
int num_pages_per_sheet)
: print_content_area(print_content_area),
printable_area(printable_area),
paper_size(paper_size),
printer_dpi(printer_dpi),
print_scaling_option(print_scaling_option),
use_printing_layout(use_printing_layout) {}
use_printing_layout(use_printing_layout),
num_pages_per_sheet(num_pages_per_sheet) {}
};

} // namespace blink
Expand Down

0 comments on commit 1942075

Please sign in to comment.