1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "pdf/pdf_transform.h"
7 #include "printing/units.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/gfx/geometry/point_f.h"
10 #include "ui/gfx/geometry/rect.h"
11 #include "ui/gfx/geometry/size_f.h"
13 namespace chrome_pdf {
17 constexpr float kDefaultWidth = 8.5 * printing::kPointsPerInch;
18 constexpr float kDefaultHeight = 11.0 * printing::kPointsPerInch;
19 constexpr float kDefaultRatio = kDefaultWidth / kDefaultHeight;
20 constexpr float kTolerance = 0.0001f;
22 void ExpectDefaultPortraitBox(const PdfRectangle& box) {
23 EXPECT_FLOAT_EQ(0, box.left);
24 EXPECT_FLOAT_EQ(0, box.bottom);
25 EXPECT_FLOAT_EQ(kDefaultWidth, box.right);
26 EXPECT_FLOAT_EQ(kDefaultHeight, box.top);
29 void ExpectDefaultLandscapeBox(const PdfRectangle& box) {
30 EXPECT_FLOAT_EQ(0, box.left);
31 EXPECT_FLOAT_EQ(0, box.bottom);
32 EXPECT_FLOAT_EQ(kDefaultHeight, box.right);
33 EXPECT_FLOAT_EQ(kDefaultWidth, box.top);
36 void ExpectBoxesAreEqual(const PdfRectangle& expected,
37 const PdfRectangle& actual) {
38 EXPECT_FLOAT_EQ(expected.left, actual.left);
39 EXPECT_FLOAT_EQ(expected.bottom, actual.bottom);
40 EXPECT_FLOAT_EQ(expected.right, actual.right);
41 EXPECT_FLOAT_EQ(expected.top, actual.top);
44 void InitializeBoxToInvalidValues(PdfRectangle* box) {
45 box->left = box->bottom = box->right = box->top = -1;
48 void InitializeBoxToDefaultPortraitValues(PdfRectangle* box) {
51 box->right = kDefaultWidth;
52 box->top = kDefaultHeight;
55 void InitializeBoxToDefaultLandscapeValue(PdfRectangle* box) {
58 box->right = kDefaultHeight;
59 box->top = kDefaultWidth;
64 TEST(PdfTransformTest, CalculateScaleFactor) {
65 static constexpr gfx::SizeF kSize(kDefaultWidth, kDefaultHeight);
66 gfx::Rect rect(kDefaultWidth, kDefaultHeight);
70 scale = CalculateScaleFactor(rect, kSize, false);
71 EXPECT_NEAR(1.0f, scale, kTolerance);
72 scale = CalculateScaleFactor(rect, kSize, true);
73 EXPECT_NEAR(kDefaultRatio, scale, kTolerance);
76 rect = gfx::Rect(kDefaultWidth / 2, kDefaultHeight / 2);
77 scale = CalculateScaleFactor(rect, kSize, false);
78 EXPECT_NEAR(0.5f, scale, kTolerance);
79 scale = CalculateScaleFactor(rect, kSize, true);
80 EXPECT_NEAR(kDefaultRatio / 2, scale, kTolerance);
83 rect = gfx::Rect(kDefaultWidth * 3, kDefaultHeight * 3);
84 scale = CalculateScaleFactor(rect, kSize, false);
85 EXPECT_NEAR(3.0f, scale, kTolerance);
86 scale = CalculateScaleFactor(rect, kSize, true);
87 EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance);
90 rect = gfx::Rect(kDefaultHeight * 3, kDefaultWidth * 3);
91 scale = CalculateScaleFactor(rect, kSize, false);
92 EXPECT_NEAR(kDefaultRatio * 3, scale, kTolerance);
93 scale = CalculateScaleFactor(rect, kSize, true);
94 EXPECT_NEAR(3.0f, scale, kTolerance);
97 rect = gfx::Rect(10, 1000);
98 scale = CalculateScaleFactor(rect, kSize, false);
99 EXPECT_NEAR(0.01634f, scale, kTolerance);
100 scale = CalculateScaleFactor(rect, kSize, true);
101 EXPECT_NEAR(0.01263f, scale, kTolerance);
104 TEST(PdfTransformTest, SetDefaultClipBox) {
107 SetDefaultClipBox(false, &box);
108 ExpectDefaultPortraitBox(box);
110 SetDefaultClipBox(true, &box);
111 ExpectDefaultLandscapeBox(box);
114 TEST(PdfTransformTest, CalculateMediaBoxAndCropBox) {
115 PdfRectangle media_box;
116 PdfRectangle crop_box;
118 // Assume both boxes are there.
119 InitializeBoxToDefaultPortraitValues(&media_box);
120 InitializeBoxToDefaultLandscapeValue(&crop_box);
121 CalculateMediaBoxAndCropBox(true, true, true, &media_box, &crop_box);
122 ExpectDefaultPortraitBox(media_box);
123 ExpectDefaultLandscapeBox(crop_box);
125 // Assume both boxes are missing.
126 InitializeBoxToInvalidValues(&media_box);
127 InitializeBoxToInvalidValues(&crop_box);
128 CalculateMediaBoxAndCropBox(false, false, false, &media_box, &crop_box);
129 ExpectDefaultPortraitBox(media_box);
130 ExpectDefaultPortraitBox(crop_box);
131 CalculateMediaBoxAndCropBox(true, false, false, &media_box, &crop_box);
132 ExpectDefaultLandscapeBox(media_box);
133 ExpectDefaultLandscapeBox(crop_box);
135 // Assume crop box is missing.
136 constexpr PdfRectangle expected_box = {0, 0, 42, 420};
137 media_box = expected_box;
138 InitializeBoxToInvalidValues(&crop_box);
139 CalculateMediaBoxAndCropBox(false, true, false, &media_box, &crop_box);
140 ExpectBoxesAreEqual(expected_box, media_box);
141 ExpectBoxesAreEqual(expected_box, crop_box);
143 // Assume media box is missing.
144 InitializeBoxToInvalidValues(&media_box);
145 CalculateMediaBoxAndCropBox(false, false, true, &media_box, &crop_box);
146 ExpectBoxesAreEqual(expected_box, media_box);
147 ExpectBoxesAreEqual(expected_box, crop_box);
150 TEST(PdfTransformTest, CalculateClipBoxBoundary) {
151 PdfRectangle media_box;
152 PdfRectangle crop_box;
155 // media box and crop box are the same.
156 InitializeBoxToDefaultPortraitValues(&media_box);
157 InitializeBoxToDefaultPortraitValues(&crop_box);
158 result = CalculateClipBoxBoundary(media_box, crop_box);
159 ExpectDefaultPortraitBox(result);
161 // media box is portrait and crop box is landscape.
162 InitializeBoxToDefaultLandscapeValue(&crop_box);
163 result = CalculateClipBoxBoundary(media_box, crop_box);
164 EXPECT_FLOAT_EQ(0, result.left);
165 EXPECT_FLOAT_EQ(0, result.bottom);
166 EXPECT_FLOAT_EQ(kDefaultWidth, result.right);
167 EXPECT_FLOAT_EQ(kDefaultWidth, result.top);
169 // crop box is smaller than media box.
172 crop_box.right = 100;
174 result = CalculateClipBoxBoundary(media_box, crop_box);
175 EXPECT_FLOAT_EQ(0, result.left);
176 EXPECT_FLOAT_EQ(0, result.bottom);
177 EXPECT_FLOAT_EQ(100, result.right);
178 EXPECT_FLOAT_EQ(200, result.top);
180 // crop box is smaller than the media box in one dimension and longer in the
184 crop_box.right = 100;
186 result = CalculateClipBoxBoundary(media_box, crop_box);
187 EXPECT_FLOAT_EQ(0, result.left);
188 EXPECT_FLOAT_EQ(0, result.bottom);
189 EXPECT_FLOAT_EQ(100, result.right);
190 EXPECT_FLOAT_EQ(kDefaultHeight, result.top);
193 TEST(PdfTransformTest, CalculateScaledClipBoxOffset) {
194 constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight);
195 PdfRectangle clip_box;
198 // `rect` and `clip_box` are the same size.
199 InitializeBoxToDefaultPortraitValues(&clip_box);
200 offset = CalculateScaledClipBoxOffset(rect, clip_box);
201 EXPECT_FLOAT_EQ(0, offset.x());
202 EXPECT_FLOAT_EQ(0, offset.y());
204 // `rect` is larger than `clip_box`.
207 offset = CalculateScaledClipBoxOffset(rect, clip_box);
208 EXPECT_FLOAT_EQ(229.5f, offset.x());
209 EXPECT_FLOAT_EQ(198, offset.y());
212 TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) {
213 int page_width = kDefaultWidth;
214 int page_height = kDefaultHeight;
215 PdfRectangle clip_box;
218 // `rect`, page size and `clip_box` are the same.
219 InitializeBoxToDefaultPortraitValues(&clip_box);
221 CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box);
222 EXPECT_FLOAT_EQ(0, offset.x());
223 EXPECT_FLOAT_EQ(0, offset.y());
225 CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box);
226 EXPECT_FLOAT_EQ(0, offset.x());
227 EXPECT_FLOAT_EQ(0, offset.y());
229 CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box);
230 EXPECT_FLOAT_EQ(0, offset.x());
231 EXPECT_FLOAT_EQ(0, offset.y());
233 CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box);
234 EXPECT_FLOAT_EQ(180, offset.x());
235 EXPECT_FLOAT_EQ(-180, offset.y());
237 // Smaller `clip_box`.
241 CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box);
242 EXPECT_FLOAT_EQ(0, offset.x());
243 EXPECT_FLOAT_EQ(594, offset.y());
245 CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box);
246 EXPECT_FLOAT_EQ(0, offset.x());
247 EXPECT_FLOAT_EQ(0, offset.y());
249 CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box);
250 EXPECT_FLOAT_EQ(306, offset.x());
251 EXPECT_FLOAT_EQ(0, offset.y());
253 CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box);
254 EXPECT_FLOAT_EQ(486, offset.x());
255 EXPECT_FLOAT_EQ(414, offset.y());
258 InitializeBoxToDefaultPortraitValues(&clip_box);
262 CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box);
263 EXPECT_FLOAT_EQ(0, offset.x());
264 EXPECT_FLOAT_EQ(20, offset.y());
266 CalculateNonScaledClipBoxOffset(1, page_width, page_height, clip_box);
267 EXPECT_FLOAT_EQ(0, offset.x());
268 EXPECT_FLOAT_EQ(0, offset.y());
270 CalculateNonScaledClipBoxOffset(2, page_width, page_height, clip_box);
271 EXPECT_FLOAT_EQ(10, offset.x());
272 EXPECT_FLOAT_EQ(0, offset.y());
274 CalculateNonScaledClipBoxOffset(3, page_width, page_height, clip_box);
275 EXPECT_FLOAT_EQ(200, offset.x());
276 EXPECT_FLOAT_EQ(-170, offset.y());
279 // https://crbug.com/491160 and https://crbug.com/588757
280 TEST(PdfTransformTest, ReversedMediaBox) {
281 int page_width = kDefaultWidth;
282 int page_height = kDefaultHeight;
283 constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight);
284 PdfRectangle clip_box;
287 constexpr PdfRectangle expected_media_box_b491160 = {0, -792, 612, 0};
288 PdfRectangle media_box_b491160 = {0, 0, 612, -792};
289 CalculateMediaBoxAndCropBox(false, true, false, &media_box_b491160,
291 ExpectBoxesAreEqual(expected_media_box_b491160, media_box_b491160);
292 ExpectBoxesAreEqual(expected_media_box_b491160, clip_box);
294 offset = CalculateScaledClipBoxOffset(rect, media_box_b491160);
295 EXPECT_FLOAT_EQ(0, offset.x());
296 EXPECT_FLOAT_EQ(792, offset.y());
298 offset = CalculateNonScaledClipBoxOffset(0, page_width, page_height,
300 EXPECT_FLOAT_EQ(0, offset.x());
301 EXPECT_FLOAT_EQ(792, offset.y());
303 PdfRectangle media_box_b588757 = {0, 792, 612, 0};
304 CalculateMediaBoxAndCropBox(false, true, false, &media_box_b588757,
306 ExpectDefaultPortraitBox(media_box_b588757);
307 ExpectDefaultPortraitBox(clip_box);
309 offset = CalculateScaledClipBoxOffset(rect, clip_box);
310 EXPECT_FLOAT_EQ(0, offset.x());
311 EXPECT_FLOAT_EQ(0, offset.y());
314 CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box);
315 EXPECT_FLOAT_EQ(0, offset.x());
316 EXPECT_FLOAT_EQ(0, offset.y());
318 PdfRectangle media_box_left_right_flipped = {612, 792, 0, 0};
319 CalculateMediaBoxAndCropBox(false, true, false, &media_box_left_right_flipped,
321 ExpectDefaultPortraitBox(media_box_left_right_flipped);
322 ExpectDefaultPortraitBox(clip_box);
324 offset = CalculateScaledClipBoxOffset(rect, clip_box);
325 EXPECT_FLOAT_EQ(0, offset.x());
326 EXPECT_FLOAT_EQ(0, offset.y());
329 CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box);
330 EXPECT_FLOAT_EQ(0, offset.x());
331 EXPECT_FLOAT_EQ(0, offset.y());
334 } // namespace chrome_pdf