From 500b41d1363441695d72c205b648d45450713524 Mon Sep 17 00:00:00 2001 From: Andy Phan Date: Fri, 5 May 2023 17:51:30 +0000 Subject: [PATCH] Scale size and area by max DPI value for non-square DPI PrintSettings PrintSettings stores paper size and printable area in device units. The device units for most platforms is the DPI multiplied by inches. For printers with non-square DPI, the largest DPI value should be used. When converting job settings to PrintSettings, the paper size and printable area were scaled by their respective dimension's DPI instead of the max DPI value. This meant that X and Y axes were represented differently in paper size and printable area. Print Preview does not support rendering different dpi settings in the X and Y axis, so this was causing incorrect renderings. Fix places where the paper size and printable area should be scaled by the max DPI. (cherry picked from commit feaa7f838d477fc71d02f0110449464b5c3480a2) Bug: 1442457 Change-Id: I113cc58611c99795afdf5076552d05406e2912df Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4508373 Reviewed-by: Lei Zhang Commit-Queue: Andy Phan Cr-Original-Commit-Position: refs/heads/main@{#1139921} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4509654 Owners-Override: Prudhvikumar Bommana Commit-Queue: Prudhvikumar Bommana Bot-Commit: Rubber Stamper Cr-Commit-Position: refs/branch-heads/5672_63@{#8} Cr-Branched-From: 0e1a4471d5ae5bf128b1bd8f4d627c8cbd55f70c-refs/branch-heads/5672@{#912} Cr-Branched-From: 5f2a72468eda1eb945b3b5a2298b5d1cd678521e-refs/heads/main@{#1121455} --- printing/print_settings.cc | 12 ++--- printing/print_settings_conversion.cc | 16 +++---- .../print_settings_conversion_unittest.cc | 48 +++++++++++++++++++ 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/printing/print_settings.cc b/printing/print_settings.cc index 7baa34db944ca8..32f669229118c0 100644 --- a/printing/print_settings.cc +++ b/printing/print_settings.cc @@ -454,13 +454,13 @@ void PrintSettings::SetPrinterPrintableArea( void PrintSettings::UpdatePrinterPrintableArea( const gfx::Rect& printable_area_um) { // Scale the page size and printable area to device units. - float x_scale = static_cast(device_units_per_inch_size().width()) / - kMicronsPerInch; - float y_scale = static_cast(device_units_per_inch_size().height()) / - kMicronsPerInch; - + // Blink doesn't support different dpi settings in X and Y axis. Because of + // this, printers with non-square DPIs still scale page size and printable + // area using device_units_per_inch() instead of their respective dimensions + // in device_units_per_inch_size(). + float scale = static_cast(device_units_per_inch()) / kMicronsPerInch; gfx::Rect printable_area_device_units = - gfx::ScaleToRoundedRect(printable_area_um, x_scale, y_scale); + gfx::ScaleToRoundedRect(printable_area_um, scale); // Protect against misbehaving drivers. We have observed some drivers return // incorrect values compared to page size. E.g., HP Business Inkjet 2300 PS. diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc index 3da01d4887bc99..8dec957471a708 100644 --- a/printing/print_settings_conversion.cc +++ b/printing/print_settings_conversion.cc @@ -101,20 +101,20 @@ void SetPrintableAreaIfValid(PrintSettings& settings, } // Scale the page size and printable area to device units. - float x_scale = - static_cast(settings.device_units_per_inch_size().width()) / - kMicronsPerInch; - float y_scale = - static_cast(settings.device_units_per_inch_size().height()) / - kMicronsPerInch; - gfx::Size page_size = gfx::ScaleToRoundedSize(size_microns, x_scale, y_scale); + // Blink doesn't support different dpi settings in X and Y axis. Because of + // this, printers with non-square DPIs still scale page size and printable + // area using device_units_per_inch() instead of their respective dimensions + // in device_units_per_inch_size(). + float scale = + static_cast(settings.device_units_per_inch()) / kMicronsPerInch; + gfx::Size page_size = gfx::ScaleToRoundedSize(size_microns, scale); // Flip the y-axis since the imageable area origin is at the bottom-left, // while the gfx::Rect origin is at the top-left. gfx::Rect printable_area = gfx::ScaleToRoundedRect( {left_microns.value(), size_microns.height() - top_microns.value(), right_microns.value() - left_microns.value(), top_microns.value() - bottom_microns.value()}, - x_scale, y_scale); + scale); // Sanity check that the printable area makes sense. if (printable_area.IsEmpty() || !gfx::Rect(page_size).Contains(printable_area)) { diff --git a/printing/print_settings_conversion_unittest.cc b/printing/print_settings_conversion_unittest.cc index db595a88a21a31..89f8f67c20a564 100644 --- a/printing/print_settings_conversion_unittest.cc +++ b/printing/print_settings_conversion_unittest.cc @@ -92,6 +92,35 @@ const char kPrinterSettingsWithImageableArea[] = R"({ "dpiVertical": 300, })"; +#if !BUILDFLAG(IS_MAC) +const char kPrinterSettingsWithNonSquareDpi[] = R"({ + "headerFooterEnabled": false, + "title": "Test Doc", + "url": "http://localhost/", + "shouldPrintBackgrounds": false, + "shouldPrintSelectionOnly": false, + "mediaSize": { + "height_microns": 297000, + "imageable_area_bottom_microns": 1000, + "imageable_area_left_microns": 0, + "imageable_area_right_microns": 180000, + "imageable_area_top_microns": 297000, + "width_microns": 210000 + }, + "collate": false, + "copies": 1, + "color": 2, + "duplex": 0, + "landscape": false, + "deviceName": "printer", + "scaleFactor": 100, + "rasterizePDF": false, + "pagesPerSheet": 1, + "dpiHorizontal": 800, + "dpiVertical": 50, +})"; +#endif // !BUILDFLAG(IS_MAC) + const char kCustomMargins[] = R"({ "marginBottom": 10, "marginLeft": 30, @@ -243,6 +272,25 @@ TEST(PrintSettingsConversionTest, WithCustomMarginsAndImageableArea) { EXPECT_EQ(page_setup.effective_margins(), kExpectedPageMargins); } +#if !BUILDFLAG(IS_MAC) +TEST(PrintSettingsConversionTest, WithNonSquareDpi) { + // Check that physical size and printable area are scaled by the max DPI + // value. Not needed for macOS, which always has a square DPI. + static constexpr gfx::Size kExpectedSize{6614, 9354}; + static constexpr gfx::Rect kExpectedPrintableArea{0, 0, 5669, 9323}; + + base::Value::Dict dict = + base::test::ParseJsonDict(kPrinterSettingsWithNonSquareDpi); + std::unique_ptr settings = PrintSettingsFromJobSettings(dict); + ASSERT_TRUE(settings); + EXPECT_EQ(settings->dpi_horizontal(), 800); + EXPECT_EQ(settings->dpi_vertical(), 50); + EXPECT_EQ(settings->page_setup_device_units().physical_size(), kExpectedSize); + EXPECT_EQ(settings->page_setup_device_units().printable_area(), + kExpectedPrintableArea); +} +#endif // !BUILDFLAG(IS_MAC) + TEST(PrintSettingsConversionTest, MissingDeviceName) { base::Value::Dict dict = base::test::ParseJsonDict(kPrinterSettings); EXPECT_TRUE(dict.Remove("deviceName"));