android_webview
apps
ash
base
blink
build
build_overrides
cc
chrome
chrome_elf
chromecast
chromeos
cloud_print
components
content
courgette
crypto
dbus
device
docs
extensions
gin
google_apis
google_update
gpu
headless
infra
ios
ipc
jingle
mash
media
mojo
native_client_sdk
net
pdf
pdfium
test
BUILD.gn
DEPS
OWNERS
chunk_stream.h
chunk_stream_unittest.cc
document_loader.h
document_loader_impl.cc
document_loader_impl.h
document_loader_impl_unittest.cc
draw_utils.cc
draw_utils.h
features.gni
out_of_process_instance.cc
out_of_process_instance.h
paint_aggregator.cc
paint_aggregator.h
paint_manager.cc
paint_manager.h
pdf.cc
pdf.h
pdf_engine.cc
pdf_engine.h
pdf_ppapi.cc
pdf_ppapi.h
pdf_transform.cc
pdf_transform.h
pdf_transform_unittest.cc
preview_mode_client.cc
preview_mode_client.h
range_set.cc
range_set.h
range_set_unittest.cc
run_all_unittests.cc
url_loader_wrapper.h
url_loader_wrapper_impl.cc
url_loader_wrapper_impl.h
ppapi
printing
remoting
rlz
sandbox
services
skia
sql
storage
styleguide
testing
third_party
tools
ui
url
webrunner
.clang-format
.eslintrc.js
.git-blame-ignore-revs
.gitattributes
.gitignore
.gn
.vpython
AUTHORS
BUILD.gn
CODE_OF_CONDUCT.md
DEPS
ENG_REVIEW_OWNERS
LICENSE
LICENSE.chromium_os
OWNERS
PRESUBMIT.py
PRESUBMIT_test.py
PRESUBMIT_test_mocks.py
README.md
WATCHLISTS
codereview.settings

When the code was written, pdf_unittests did not exist, so the code ended up in printing/ since printing_unittests existed, and the code is used for printing PDFs. Change-Id: I31e01524904da6ded6dffa22f80d7c68580c58a9 Reviewed-on: https://chromium-review.googlesource.com/938852 Reviewed-by: dsinclair <dsinclair@chromium.org> Reviewed-by: danakj <danakj@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org> Cr-Commit-Position: refs/heads/master@{#540926}
336 lines
12 KiB
C++
336 lines
12 KiB
C++
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// 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 "printing/units.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "ui/gfx/geometry/rect.h"
|
|
|
|
namespace chrome_pdf {
|
|
|
|
namespace {
|
|
|
|
const float kDefaultWidth = 8.5 * printing::kPointsPerInch;
|
|
const float kDefaultHeight = 11.0 * printing::kPointsPerInch;
|
|
const float kDefaultRatio = kDefaultWidth / kDefaultHeight;
|
|
const double kTolerance = 0.0001;
|
|
|
|
void ExpectDefaultPortraitBox(const PdfRectangle& 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 PdfRectangle& 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 PdfRectangle& expected,
|
|
const PdfRectangle& 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(PdfRectangle* box) {
|
|
box->left = box->bottom = box->right = box->top = -1;
|
|
}
|
|
|
|
void InitializeBoxToDefaultPortraitValues(PdfRectangle* box) {
|
|
box->left = 0;
|
|
box->bottom = 0;
|
|
box->right = kDefaultWidth;
|
|
box->top = kDefaultHeight;
|
|
}
|
|
|
|
void InitializeBoxToDefaultLandscapeValue(PdfRectangle* box) {
|
|
box->left = 0;
|
|
box->bottom = 0;
|
|
box->right = kDefaultHeight;
|
|
box->top = kDefaultWidth;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(PdfTransformTest, CalculateScaleFactor) {
|
|
gfx::Rect rect(kDefaultWidth, kDefaultHeight);
|
|
double scale;
|
|
|
|
// 1:1
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, false);
|
|
EXPECT_NEAR(1, scale, kTolerance);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, true);
|
|
EXPECT_NEAR(kDefaultRatio, scale, kTolerance);
|
|
|
|
// 1:2
|
|
rect = gfx::Rect(kDefaultWidth / 2, kDefaultHeight / 2);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, false);
|
|
EXPECT_NEAR(0.5, scale, kTolerance);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, true);
|
|
EXPECT_NEAR(kDefaultRatio / 2, scale, kTolerance);
|
|
|
|
// 3:1
|
|
rect = gfx::Rect(kDefaultWidth * 3, kDefaultHeight * 3);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, false);
|
|
EXPECT_NEAR(3, scale, kTolerance);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, true);
|
|
EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance);
|
|
|
|
// 3:1, rotated.
|
|
rect = gfx::Rect(kDefaultHeight * 3, kDefaultWidth * 3);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, false);
|
|
EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, true);
|
|
EXPECT_NEAR(3, scale, kTolerance);
|
|
|
|
// Odd size
|
|
rect = gfx::Rect(10, 1000);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, false);
|
|
EXPECT_NEAR(0.01634, scale, kTolerance);
|
|
scale = CalculateScaleFactor(rect, kDefaultWidth, kDefaultHeight, true);
|
|
EXPECT_NEAR(0.01263, scale, kTolerance);
|
|
}
|
|
|
|
TEST(PdfTransformTest, SetDefaultClipBox) {
|
|
PdfRectangle box;
|
|
|
|
SetDefaultClipBox(false, &box);
|
|
ExpectDefaultPortraitBox(box);
|
|
|
|
SetDefaultClipBox(true, &box);
|
|
ExpectDefaultLandscapeBox(box);
|
|
}
|
|
|
|
TEST(PdfTransformTest, CalculateMediaBoxAndCropBox) {
|
|
PdfRectangle media_box;
|
|
PdfRectangle 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.
|
|
const PdfRectangle expected_box = {0, 0, 42, 420};
|
|
media_box = expected_box;
|
|
InitializeBoxToInvalidValues(&crop_box);
|
|
CalculateMediaBoxAndCropBox(false, true, false, &media_box, &crop_box);
|
|
ExpectBoxesAreEqual(expected_box, media_box);
|
|
ExpectBoxesAreEqual(expected_box, crop_box);
|
|
|
|
// Assume media box is missing.
|
|
InitializeBoxToInvalidValues(&media_box);
|
|
CalculateMediaBoxAndCropBox(false, false, true, &media_box, &crop_box);
|
|
ExpectBoxesAreEqual(expected_box, media_box);
|
|
ExpectBoxesAreEqual(expected_box, crop_box);
|
|
}
|
|
|
|
TEST(PdfTransformTest, CalculateClipBoxBoundary) {
|
|
PdfRectangle media_box;
|
|
PdfRectangle crop_box;
|
|
PdfRectangle 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.left = 0;
|
|
crop_box.bottom = 0;
|
|
crop_box.right = 100;
|
|
crop_box.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.left = 0;
|
|
crop_box.bottom = 0;
|
|
crop_box.right = 100;
|
|
crop_box.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) {
|
|
const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
|
|
PdfRectangle clip_box;
|
|
double offset_x;
|
|
double offset_y;
|
|
|
|
// |rect| and |clip_box| are the same size.
|
|
InitializeBoxToDefaultPortraitValues(&clip_box);
|
|
CalculateScaledClipBoxOffset(rect, clip_box, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
|
|
// |rect| is larger than |clip_box|.
|
|
clip_box.top /= 2;
|
|
clip_box.right /= 4;
|
|
CalculateScaledClipBoxOffset(rect, clip_box, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(229.5, offset_x);
|
|
EXPECT_DOUBLE_EQ(198, offset_y);
|
|
}
|
|
|
|
TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) {
|
|
int page_width = kDefaultWidth;
|
|
int page_height = kDefaultHeight;
|
|
const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
|
|
PdfRectangle clip_box;
|
|
double offset_x;
|
|
double offset_y;
|
|
|
|
// |rect|, page size and |clip_box| are the same.
|
|
InitializeBoxToDefaultPortraitValues(&clip_box);
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 1, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 2, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 3, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(180, offset_x);
|
|
EXPECT_DOUBLE_EQ(-180, offset_y);
|
|
|
|
// Smaller |clip_box|.
|
|
clip_box.top /= 4;
|
|
clip_box.right /= 2;
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(594, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 1, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 2, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(306, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 3, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(486, offset_x);
|
|
EXPECT_DOUBLE_EQ(414, offset_y);
|
|
|
|
// Larger page size.
|
|
InitializeBoxToDefaultPortraitValues(&clip_box);
|
|
page_width += 10;
|
|
page_height += 20;
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(20, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 1, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 2, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(10, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
CalculateNonScaledClipBoxOffset(rect, 3, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(200, offset_x);
|
|
EXPECT_DOUBLE_EQ(-170, offset_y);
|
|
}
|
|
|
|
// https://crbug.com/491160 and https://crbug.com/588757
|
|
TEST(PdfTransformTest, ReversedMediaBox) {
|
|
int page_width = kDefaultWidth;
|
|
int page_height = kDefaultHeight;
|
|
const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
|
|
PdfRectangle clip_box;
|
|
double offset_x;
|
|
double offset_y;
|
|
|
|
const PdfRectangle expected_media_box_b491160 = {0, -792, 612, 0};
|
|
PdfRectangle media_box_b491160 = {0, 0, 612, -792};
|
|
CalculateMediaBoxAndCropBox(false, true, false, &media_box_b491160,
|
|
&clip_box);
|
|
ExpectBoxesAreEqual(expected_media_box_b491160, media_box_b491160);
|
|
ExpectBoxesAreEqual(expected_media_box_b491160, clip_box);
|
|
|
|
CalculateScaledClipBoxOffset(rect, media_box_b491160, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(792, offset_y);
|
|
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height,
|
|
media_box_b491160, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(792, offset_y);
|
|
|
|
PdfRectangle media_box_b588757 = {0, 792, 612, 0};
|
|
CalculateMediaBoxAndCropBox(false, true, false, &media_box_b588757,
|
|
&clip_box);
|
|
ExpectDefaultPortraitBox(media_box_b588757);
|
|
ExpectDefaultPortraitBox(clip_box);
|
|
|
|
CalculateScaledClipBoxOffset(rect, clip_box, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
|
|
PdfRectangle 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);
|
|
|
|
CalculateScaledClipBoxOffset(rect, clip_box, &offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
|
|
CalculateNonScaledClipBoxOffset(rect, 0, page_width, page_height, clip_box,
|
|
&offset_x, &offset_y);
|
|
EXPECT_DOUBLE_EQ(0, offset_x);
|
|
EXPECT_DOUBLE_EQ(0, offset_y);
|
|
}
|
|
|
|
} // namespace chrome_pdf
|