| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "pdf/pdf_transform.h" |
| |
| #include "pdf/pdf_rect.h" |
| #include "printing/units.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size_f.h" |
| #include "ui/gfx/geometry/vector2d_f.h" |
| |
| namespace chrome_pdf { |
| |
| namespace { |
| |
| constexpr float kDefaultWidth = 8.5 * printing::kPointsPerInch; |
| constexpr float kDefaultHeight = 11.0 * printing::kPointsPerInch; |
| constexpr float kDefaultRatio = kDefaultWidth / kDefaultHeight; |
| constexpr float kTolerance = 0.0001f; |
| |
| void ExpectDefaultPortraitBox(const PdfRect& box) { |
| EXPECT_FLOAT_EQ(0, box.left()); |
| EXPECT_FLOAT_EQ(0, box.bottom()); |
| EXPECT_FLOAT_EQ(kDefaultWidth, box.right()); |
| EXPECT_FLOAT_EQ(kDefaultHeight, box.top()); |
| } |
| |
| void ExpectDefaultLandscapeBox(const PdfRect& box) { |
| EXPECT_FLOAT_EQ(0, box.left()); |
| EXPECT_FLOAT_EQ(0, box.bottom()); |
| EXPECT_FLOAT_EQ(kDefaultHeight, box.right()); |
| EXPECT_FLOAT_EQ(kDefaultWidth, box.top()); |
| } |
| |
| void ExpectBoxesAreEqual(const PdfRect& expected, const PdfRect& actual) { |
| EXPECT_FLOAT_EQ(expected.left(), actual.left()); |
| EXPECT_FLOAT_EQ(expected.bottom(), actual.bottom()); |
| EXPECT_FLOAT_EQ(expected.right(), actual.right()); |
| EXPECT_FLOAT_EQ(expected.top(), actual.top()); |
| } |
| |
| void InitializeBoxToInvalidValues(PdfRect* box) { |
| *box = PdfRect(-1, -1, -1, -1); |
| } |
| |
| void InitializeBoxToDefaultPortraitValues(PdfRect* box) { |
| *box = PdfRect(0, 0, kDefaultWidth, kDefaultHeight); |
| } |
| |
| void InitializeBoxToDefaultLandscapeValue(PdfRect* box) { |
| *box = PdfRect(0, 0, kDefaultHeight, kDefaultWidth); |
| } |
| |
| } // namespace |
| |
| TEST(PdfTransformTest, CalculateScaleFactor) { |
| static constexpr gfx::SizeF kSize(kDefaultWidth, kDefaultHeight); |
| gfx::Rect rect(kDefaultWidth, kDefaultHeight); |
| float scale; |
| |
| // 1:1 |
| scale = CalculateScaleFactor(rect, kSize, false); |
| EXPECT_NEAR(1.0f, scale, kTolerance); |
| scale = CalculateScaleFactor(rect, kSize, true); |
| EXPECT_NEAR(kDefaultRatio, scale, kTolerance); |
| |
| // 1:2 |
| rect = gfx::Rect(kDefaultWidth / 2, kDefaultHeight / 2); |
| scale = CalculateScaleFactor(rect, kSize, false); |
| EXPECT_NEAR(0.5f, scale, kTolerance); |
| scale = CalculateScaleFactor(rect, kSize, true); |
| EXPECT_NEAR(kDefaultRatio / 2, scale, kTolerance); |
| |
| // 3:1 |
| rect = gfx::Rect(kDefaultWidth * 3, kDefaultHeight * 3); |
| scale = CalculateScaleFactor(rect, kSize, false); |
| EXPECT_NEAR(3.0f, scale, kTolerance); |
| scale = CalculateScaleFactor(rect, kSize, true); |
| EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance); |
| |
| // 3:1, rotated. |
| rect = gfx::Rect(kDefaultHeight * 3, kDefaultWidth * 3); |
| scale = CalculateScaleFactor(rect, kSize, false); |
| EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance); |
| scale = CalculateScaleFactor(rect, kSize, true); |
| EXPECT_NEAR(3.0f, scale, kTolerance); |
| |
| // Odd size |
| rect = gfx::Rect(10, 1000); |
| scale = CalculateScaleFactor(rect, kSize, false); |
| EXPECT_NEAR(0.01634f, scale, kTolerance); |
| scale = CalculateScaleFactor(rect, kSize, true); |
| EXPECT_NEAR(0.01263f, scale, kTolerance); |
| } |
| |
| TEST(PdfTransformTest, CalculateMediaBoxAndCropBox) { |
| PdfRect media_box; |
| PdfRect crop_box; |
| |
| // Assume both boxes are there. |
| InitializeBoxToDefaultPortraitValues(&media_box); |
| InitializeBoxToDefaultLandscapeValue(&crop_box); |
| CalculateMediaBoxAndCropBox(true, true, true, &media_box, &crop_box); |
| ExpectDefaultPortraitBox(media_box); |
| ExpectDefaultLandscapeBox(crop_box); |
| |
| // Assume both boxes are missing. |
| InitializeBoxToInvalidValues(&media_box); |
| InitializeBoxToInvalidValues(&crop_box); |
| CalculateMediaBoxAndCropBox(false, false, false, &media_box, &crop_box); |
| ExpectDefaultPortraitBox(media_box); |
| ExpectDefaultPortraitBox(crop_box); |
| CalculateMediaBoxAndCropBox(true, false, false, &media_box, &crop_box); |
| ExpectDefaultLandscapeBox(media_box); |
| ExpectDefaultLandscapeBox(crop_box); |
| |
| // Assume crop box is missing. |
| constexpr PdfRect kExpctedBox(0, 0, 42, 420); |
| media_box = kExpctedBox; |
| InitializeBoxToInvalidValues(&crop_box); |
| CalculateMediaBoxAndCropBox(false, true, false, &media_box, &crop_box); |
| ExpectBoxesAreEqual(kExpctedBox, media_box); |
| ExpectBoxesAreEqual(kExpctedBox, crop_box); |
| |
| // Assume media box is missing. |
| InitializeBoxToInvalidValues(&media_box); |
| CalculateMediaBoxAndCropBox(false, false, true, &media_box, &crop_box); |
| ExpectBoxesAreEqual(kExpctedBox, media_box); |
| ExpectBoxesAreEqual(kExpctedBox, crop_box); |
| } |
| |
| TEST(PdfTransformTest, CalculateClipBoxBoundary) { |
| PdfRect media_box; |
| PdfRect crop_box; |
| PdfRect result; |
| |
| // media box and crop box are the same. |
| InitializeBoxToDefaultPortraitValues(&media_box); |
| InitializeBoxToDefaultPortraitValues(&crop_box); |
| result = CalculateClipBoxBoundary(media_box, crop_box); |
| ExpectDefaultPortraitBox(result); |
| |
| // media box is portrait and crop box is landscape. |
| InitializeBoxToDefaultLandscapeValue(&crop_box); |
| result = CalculateClipBoxBoundary(media_box, crop_box); |
| EXPECT_FLOAT_EQ(0, result.left()); |
| EXPECT_FLOAT_EQ(0, result.bottom()); |
| EXPECT_FLOAT_EQ(kDefaultWidth, result.right()); |
| EXPECT_FLOAT_EQ(kDefaultWidth, result.top()); |
| |
| // crop box is smaller than media box. |
| crop_box = PdfRect( |
| /*left=*/0, |
| /*bottom=*/0, |
| /*right=*/100, |
| /*top=*/200); |
| result = CalculateClipBoxBoundary(media_box, crop_box); |
| EXPECT_FLOAT_EQ(0, result.left()); |
| EXPECT_FLOAT_EQ(0, result.bottom()); |
| EXPECT_FLOAT_EQ(100, result.right()); |
| EXPECT_FLOAT_EQ(200, result.top()); |
| |
| // crop box is smaller than the media box in one dimension and longer in the |
| // other. |
| crop_box = PdfRect( |
| /*left=*/0, |
| /*bottom=*/0, |
| /*right=*/100, |
| /*top=*/2000); |
| result = CalculateClipBoxBoundary(media_box, crop_box); |
| EXPECT_FLOAT_EQ(0, result.left()); |
| EXPECT_FLOAT_EQ(0, result.bottom()); |
| EXPECT_FLOAT_EQ(100, result.right()); |
| EXPECT_FLOAT_EQ(kDefaultHeight, result.top()); |
| } |
| |
| TEST(PdfTransformTest, CalculateScaledClipBoxOffset) { |
| constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight); |
| |
| // `rect` and `clip_box` are the same size. |
| PdfRect clip_box; |
| InitializeBoxToDefaultPortraitValues(&clip_box); |
| gfx::Vector2dF offset = CalculateScaledClipBoxOffset(rect, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| |
| // `rect` is larger than `clip_box`. |
| *clip_box.writable_top() /= 2; |
| *clip_box.writable_right() /= 4; |
| offset = CalculateScaledClipBoxOffset(rect, clip_box); |
| EXPECT_FLOAT_EQ(229.5f, offset.x()); |
| EXPECT_FLOAT_EQ(198, offset.y()); |
| } |
| |
| TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) { |
| int page_width = kDefaultWidth; |
| int page_height = kDefaultHeight; |
| |
| // `rect`, page size and `clip_box` are the same. |
| PdfRect clip_box; |
| InitializeBoxToDefaultPortraitValues(&clip_box); |
| gfx::Vector2dF offset = |
| CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(180, offset.x()); |
| EXPECT_FLOAT_EQ(-180, offset.y()); |
| |
| // Smaller `clip_box`. |
| *clip_box.writable_top() /= 4; |
| *clip_box.writable_right() /= 2; |
| offset = |
| CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(594, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(306, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(486, offset.x()); |
| EXPECT_FLOAT_EQ(414, offset.y()); |
| |
| // Larger page size. |
| InitializeBoxToDefaultPortraitValues(&clip_box); |
| page_width += 10; |
| page_height += 20; |
| offset = |
| CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(20, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(10, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| offset = |
| CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(200, offset.x()); |
| EXPECT_FLOAT_EQ(-170, offset.y()); |
| } |
| |
| // https://crbug.com/491160 and https://crbug.com/588757 |
| TEST(PdfTransformTest, ReversedMediaBox) { |
| int page_width = kDefaultWidth; |
| int page_height = kDefaultHeight; |
| constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight); |
| |
| constexpr PdfRect expected_media_box_b491160 = {0, -792, 612, 0}; |
| PdfRect media_box_b491160 = {0, 0, 612, -792}; |
| PdfRect clip_box; |
| CalculateMediaBoxAndCropBox(false, true, false, &media_box_b491160, |
| &clip_box); |
| ExpectBoxesAreEqual(expected_media_box_b491160, media_box_b491160); |
| ExpectBoxesAreEqual(expected_media_box_b491160, clip_box); |
| |
| gfx::Vector2dF offset = CalculateScaledClipBoxOffset(rect, media_box_b491160); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(792, offset.y()); |
| |
| offset = CalculateNonScaledClipBoxOffset(0, page_width, page_height, |
| media_box_b491160); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(792, offset.y()); |
| |
| PdfRect media_box_b588757 = {0, 792, 612, 0}; |
| CalculateMediaBoxAndCropBox(false, true, false, &media_box_b588757, |
| &clip_box); |
| ExpectDefaultPortraitBox(media_box_b588757); |
| ExpectDefaultPortraitBox(clip_box); |
| |
| offset = CalculateScaledClipBoxOffset(rect, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| |
| offset = |
| CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| |
| PdfRect media_box_left_right_flipped = {612, 792, 0, 0}; |
| CalculateMediaBoxAndCropBox(false, true, false, &media_box_left_right_flipped, |
| &clip_box); |
| ExpectDefaultPortraitBox(media_box_left_right_flipped); |
| ExpectDefaultPortraitBox(clip_box); |
| |
| offset = CalculateScaledClipBoxOffset(rect, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| |
| offset = |
| CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); |
| EXPECT_FLOAT_EQ(0, offset.x()); |
| EXPECT_FLOAT_EQ(0, offset.y()); |
| } |
| |
| } // namespace chrome_pdf |