0

Add PrintWithReducedRasterization feature.

Add an off by default base::Feature for controlling how much
rasterization to do when printing in EMF mode on Windows. This will
reduce print job sizes in some cases. Since the feature caused printing
regressions in the past, having a base::Feature toggle will allow the
feature to be rolled out in a controlled manner.

This CL includes:
- Plumbing for the browser to tell the PdfToEmfConverter service to use
  the new printing modes.
- New Printing.ConversionSize metrics to see how the new printing modes
  perform size-wise. Along the way, all Printing.ConversionSize metrics
  have been updated with secondary owners and actual expiration dates.
- A very basic sanity test.

Bug: 674771
Change-Id: I7ccd8d4c9320eb1c42f3c3040814ed41027f36bc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2194797
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Rebekah Potter <rbpotter@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Alexei Svitkine <asvitkine@chromium.org>
Cr-Commit-Position: refs/heads/master@{#768459}
This commit is contained in:
Lei Zhang
2020-05-13 22:32:36 +00:00
committed by Commit Bot
parent 9c87548793
commit 92eadbb0cc
12 changed files with 155 additions and 36 deletions

@ -408,6 +408,16 @@ void PdfConverterImpl::RecordConversionMetrics() {
UMA_HISTOGRAM_MEMORY_KB("Printing.ConversionSize.PostScript3",
average_page_size_in_kb);
return;
case PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION:
UMA_HISTOGRAM_MEMORY_KB(
"Printing.ConversionSize.EmfWithReducedRasterization",
average_page_size_in_kb);
return;
case PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT:
UMA_HISTOGRAM_MEMORY_KB(
"Printing.ConversionSize.EmfWithReducedRasterizationAndGdiText",
average_page_size_in_kb);
return;
default:
NOTREACHED();
return;

@ -266,6 +266,26 @@ IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest, EmfBasic) {
}
}
IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest,
EmfWithReducedRasterizationBasic) {
const PdfRenderSettings pdf_settings(
kLetter200DpiRect, gfx::Point(0, 0), k200DpiSize,
/*autorotate=*/false,
/*use_color=*/true,
PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION);
constexpr int kNumberOfPages = 3;
ASSERT_TRUE(GetTestInput("pdf_converter_basic.pdf"));
ASSERT_TRUE(StartPdfConverter(pdf_settings, kNumberOfPages));
for (int i = 0; i < kNumberOfPages; ++i) {
ASSERT_TRUE(GetPage(i));
ASSERT_TRUE(GetPageExpectedEmfData(
GetFileNameForPageNumber("pdf_converter_basic_emf_page_", i)));
ComparePageEmfHeader();
// TODO(thestig): Check if ComparePageEmfPayload() works on bots.
}
}
IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest, PostScriptLevel2Basic) {
const PdfRenderSettings pdf_settings(
kLetter200DpiRect, gfx::Point(0, 0), k200DpiSize,

@ -29,17 +29,29 @@
#include "chrome/common/chrome_features.h"
#include "printing/pdf_render_settings.h"
#include "printing/printed_page_win.h"
#include "printing/printing_features.h"
#endif
using base::TimeDelta;
namespace printing {
namespace {
// Helper function to ensure |job| is valid until at least |callback| returns.
void HoldRefCallback(scoped_refptr<PrintJob> job, base::OnceClosure callback) {
std::move(callback).Run();
}
#if defined(OS_WIN)
bool PrintWithReducedRasterization() {
// TODO(crbug.com/674771): Support setting via policy.
return base::FeatureList::IsEnabled(features::kPrintWithReducedRasterization);
}
#endif
} // namespace
PrintJob::PrintJob() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
@ -319,11 +331,21 @@ void PrintJob::StartPdfToEmfConversion(
bool print_text_with_gdi =
settings.print_text_with_gdi() && !settings.printer_is_xps() &&
base::FeatureList::IsEnabled(::features::kGdiTextPrinting);
bool print_with_reduced_rasterization = PrintWithReducedRasterization();
using RenderMode = PdfRenderSettings::Mode;
RenderMode mode;
if (print_with_reduced_rasterization) {
mode = print_text_with_gdi
? RenderMode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT
: RenderMode::EMF_WITH_REDUCED_RASTERIZATION;
} else {
mode = print_text_with_gdi ? RenderMode::GDI_TEXT : RenderMode::NORMAL;
}
PdfRenderSettings render_settings(
content_area, gfx::Point(0, 0), settings.dpi_size(),
/*autorotate=*/true, settings.color() == COLOR,
print_text_with_gdi ? PdfRenderSettings::Mode::GDI_TEXT
: PdfRenderSettings::Mode::NORMAL);
/*autorotate=*/true, settings.color() == COLOR, mode);
pdf_conversion_state_->Start(
bytes, render_settings,
base::BindOnce(&PrintJob::OnPdfConversionStarted, this));
@ -581,4 +603,5 @@ PrintedDocument* JobEventDetails::document() const { return document_.get(); }
#if defined(OS_WIN)
PrintedPage* JobEventDetails::page() const { return page_.get(); }
#endif
} // namespace printing

@ -80,8 +80,12 @@ PdfToEmfConverter::PdfToEmfConverter(
PdfToEmfConverter::~PdfToEmfConverter() = default;
void PdfToEmfConverter::SetPrintMode() {
chrome_pdf::SetPDFUseGDIPrinting(pdf_render_settings_.mode ==
PdfRenderSettings::Mode::GDI_TEXT);
bool use_gdi_printing =
pdf_render_settings_.mode == PdfRenderSettings::Mode::GDI_TEXT ||
pdf_render_settings_.mode ==
PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT;
chrome_pdf::SetPDFUseGDIPrinting(use_gdi_printing);
int printing_mode;
switch (pdf_render_settings_.mode) {
case PdfRenderSettings::Mode::TEXTONLY:
@ -93,8 +97,11 @@ void PdfToEmfConverter::SetPrintMode() {
case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3:
printing_mode = chrome_pdf::PrintingMode::kPostScript3;
break;
case PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION:
case PdfRenderSettings::Mode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT:
printing_mode = chrome_pdf::PrintingMode::kEmfWithReducedRasterization;
break;
default:
// Not using postscript or text only.
printing_mode = chrome_pdf::PrintingMode::kEmf;
}
chrome_pdf::SetPDFUsePrintMode(printing_mode);

@ -17,7 +17,11 @@ struct PdfRenderSettings {
[EnableIf=is_win]
POSTSCRIPT_LEVEL2,
[EnableIf=is_win]
POSTSCRIPT_LEVEL3
POSTSCRIPT_LEVEL3,
[EnableIf=is_win]
EMF_WITH_REDUCED_RASTERIZATION,
[EnableIf=is_win]
EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT
};
gfx.mojom.Rect area;

@ -16,18 +16,24 @@ struct EnumTraits<printing::mojom::PdfRenderSettings::Mode,
printing::PdfRenderSettings::Mode> {
static printing::mojom::PdfRenderSettings::Mode ToMojom(
printing::PdfRenderSettings::Mode mode) {
using MojomMode = printing::mojom::PdfRenderSettings::Mode;
using PrintMode = printing::PdfRenderSettings::Mode;
switch (mode) {
case printing::PdfRenderSettings::Mode::NORMAL:
return printing::mojom::PdfRenderSettings::Mode::NORMAL;
case PrintMode::NORMAL:
return MojomMode::NORMAL;
#if defined(OS_WIN)
case printing::PdfRenderSettings::Mode::TEXTONLY:
return printing::mojom::PdfRenderSettings::Mode::TEXTONLY;
case printing::PdfRenderSettings::Mode::GDI_TEXT:
return printing::mojom::PdfRenderSettings::Mode::GDI_TEXT;
case printing::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2:
return printing::mojom::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2;
case printing::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3:
return printing::mojom::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3;
case PrintMode::TEXTONLY:
return MojomMode::TEXTONLY;
case PrintMode::GDI_TEXT:
return MojomMode::GDI_TEXT;
case PrintMode::POSTSCRIPT_LEVEL2:
return MojomMode::POSTSCRIPT_LEVEL2;
case PrintMode::POSTSCRIPT_LEVEL3:
return MojomMode::POSTSCRIPT_LEVEL3;
case PrintMode::EMF_WITH_REDUCED_RASTERIZATION:
return MojomMode::EMF_WITH_REDUCED_RASTERIZATION;
case PrintMode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT:
return MojomMode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT;
#endif
}
NOTREACHED() << "Unknown mode " << static_cast<int>(mode);
@ -36,22 +42,30 @@ struct EnumTraits<printing::mojom::PdfRenderSettings::Mode,
static bool FromMojom(printing::mojom::PdfRenderSettings::Mode input,
printing::PdfRenderSettings::Mode* output) {
using MojomMode = printing::mojom::PdfRenderSettings::Mode;
using PrintMode = printing::PdfRenderSettings::Mode;
switch (input) {
case printing::mojom::PdfRenderSettings::Mode::NORMAL:
*output = printing::PdfRenderSettings::Mode::NORMAL;
case MojomMode::NORMAL:
*output = PrintMode::NORMAL;
return true;
#if defined(OS_WIN)
case printing::mojom::PdfRenderSettings::Mode::TEXTONLY:
*output = printing::PdfRenderSettings::Mode::TEXTONLY;
case MojomMode::TEXTONLY:
*output = PrintMode::TEXTONLY;
return true;
case printing::mojom::PdfRenderSettings::Mode::GDI_TEXT:
*output = printing::PdfRenderSettings::Mode::GDI_TEXT;
case MojomMode::GDI_TEXT:
*output = PrintMode::GDI_TEXT;
return true;
case printing::mojom::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2:
*output = printing::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2;
case MojomMode::POSTSCRIPT_LEVEL2:
*output = PrintMode::POSTSCRIPT_LEVEL2;
return true;
case printing::mojom::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3:
*output = printing::PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3;
case MojomMode::POSTSCRIPT_LEVEL3:
*output = PrintMode::POSTSCRIPT_LEVEL3;
return true;
case MojomMode::EMF_WITH_REDUCED_RASTERIZATION:
*output = PrintMode::EMF_WITH_REDUCED_RASTERIZATION;
return true;
case MojomMode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT:
*output = PrintMode::EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT;
return true;
#endif
}

@ -37,12 +37,16 @@ std::vector<uint8_t> CreateFlattenedPdf(base::span<const uint8_t> input_buffer);
#endif // defined(OS_CHROMEOS)
#if defined(OS_WIN)
// Printing modes - type to convert PDF to for printing
// Printing modes - type to convert PDF to for printing. See PDFium's
// FPDF_SetPrintMode() for details.
enum PrintingMode {
kEmf = 0,
kTextOnly = 1,
kPostScript2 = 2,
kPostScript3 = 3,
// Values 4 and 5 are similar to |kPostScript2| and |kPostScript3|, but are
// not intended for use in sandboxed environments like Chromium's.
kEmfWithReducedRasterization = 6,
};
// |pdf_buffer| is the buffer that contains the entire PDF document to be

@ -234,4 +234,6 @@ STATIC_ASSERT_ENUM(chrome_pdf::kEmf, FPDF_PRINTMODE_EMF);
STATIC_ASSERT_ENUM(chrome_pdf::kTextOnly, FPDF_PRINTMODE_TEXTONLY);
STATIC_ASSERT_ENUM(chrome_pdf::kPostScript2, FPDF_PRINTMODE_POSTSCRIPT2);
STATIC_ASSERT_ENUM(chrome_pdf::kPostScript3, FPDF_PRINTMODE_POSTSCRIPT3);
STATIC_ASSERT_ENUM(chrome_pdf::kEmfWithReducedRasterization,
FPDF_PRINTMODE_EMF_IMAGE_MASKS);
#endif

@ -21,9 +21,11 @@ struct PdfRenderSettings {
GDI_TEXT,
POSTSCRIPT_LEVEL2,
POSTSCRIPT_LEVEL3,
LAST = POSTSCRIPT_LEVEL3,
EMF_WITH_REDUCED_RASTERIZATION,
EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT,
LAST = EMF_WITH_REDUCED_RASTERIZATION_AND_GDI_TEXT
#else
LAST = NORMAL,
LAST = NORMAL
#endif
};

@ -24,6 +24,10 @@ const base::Feature kEnableCustomMacPaperSizes{
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
// When using GDI printing, avoid rasterization if possible.
const base::Feature kPrintWithReducedRasterization{
"PrintWithReducedRasterization", base::FEATURE_DISABLED_BY_DEFAULT};
// Use XPS for printing instead of GDI.
const base::Feature kUseXpsForPrinting{"UseXpsForPrinting",
base::FEATURE_DISABLED_BY_DEFAULT};

@ -25,6 +25,7 @@ PRINTING_EXPORT extern const base::Feature kEnableCustomMacPaperSizes;
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
PRINTING_EXPORT extern const base::Feature kPrintWithReducedRasterization;
PRINTING_EXPORT extern const base::Feature kUseXpsForPrinting;
PRINTING_EXPORT extern const base::Feature kUseXpsForPrintingFromPdf;

@ -130821,25 +130821,50 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.Emf" units="KB" expires_after="M90">
<histogram name="Printing.ConversionSize.Emf" units="KB"
expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to EMF.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.EmfWithGdiText" units="KB"
expires_after="M90">
expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to EMF with
the GDI Text experiment turned on.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.PostScript2" units="KB"
expires_after="M90">
<histogram name="Printing.ConversionSize.EmfWithReducedRasterization"
units="KB" expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to EMF with
the reduced rasterization feature turned on.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.EmfWithReducedRasterizationAndGdiText"
units="KB" expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to EMF with
the reduced rasterization feature turned on and the GDI Text experiment
turned on.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.PostScript2" units="KB"
expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to level 2
PostScript.
@ -130847,16 +130872,19 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</histogram>
<histogram name="Printing.ConversionSize.PostScript3" units="KB"
expires_after="M90">
expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On Windows, the average size of a printed page after converting to level 3
PostScript.
</summary>
</histogram>
<histogram name="Printing.ConversionSize.Pwg" units="KB" expires_after="M90">
<histogram name="Printing.ConversionSize.Pwg" units="KB"
expires_after="2021-04-30">
<owner>thestig@chromium.org</owner>
<owner>awscreen@chromium.org</owner>
<summary>
On desktop, the average size of a printed page after converting to PWG
Raster format.