1 // Copyright 2019 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/document_layout.h"
7 #include "base/i18n/rtl.h"
8 #include "base/test/values_test_util.h"
9 #include "base/values.h"
10 #include "pdf/page_orientation.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gfx/geometry/rect.h"
14 #include "ui/gfx/geometry/size.h"
16 namespace chrome_pdf {
20 class DocumentLayoutOptionsTest : public testing::Test {
22 DocumentLayout::Options options_;
25 TEST_F(DocumentLayoutOptionsTest, DefaultConstructor) {
26 EXPECT_EQ(options_.direction(), base::i18n::UNKNOWN_DIRECTION);
27 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kOriginal);
28 EXPECT_EQ(options_.page_spread(), DocumentLayout::PageSpread::kOneUp);
31 TEST_F(DocumentLayoutOptionsTest, CopyConstructor) {
32 options_.set_direction(base::i18n::RIGHT_TO_LEFT);
33 options_.RotatePagesClockwise();
34 options_.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
36 DocumentLayout::Options copy(options_);
37 EXPECT_EQ(copy.direction(), base::i18n::RIGHT_TO_LEFT);
38 EXPECT_EQ(copy.default_page_orientation(), PageOrientation::kClockwise90);
39 EXPECT_EQ(copy.page_spread(), DocumentLayout::PageSpread::kTwoUpOdd);
41 options_.set_direction(base::i18n::LEFT_TO_RIGHT);
42 options_.RotatePagesClockwise();
43 options_.set_page_spread(DocumentLayout::PageSpread::kOneUp);
44 EXPECT_EQ(copy.direction(), base::i18n::RIGHT_TO_LEFT);
45 EXPECT_EQ(copy.default_page_orientation(), PageOrientation::kClockwise90);
46 EXPECT_EQ(copy.page_spread(), DocumentLayout::PageSpread::kTwoUpOdd);
49 TEST_F(DocumentLayoutOptionsTest, CopyAssignment) {
50 options_.set_direction(base::i18n::RIGHT_TO_LEFT);
51 options_.RotatePagesClockwise();
52 options_.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
54 DocumentLayout::Options copy = options_;
55 EXPECT_EQ(copy.direction(), base::i18n::RIGHT_TO_LEFT);
56 EXPECT_EQ(copy.default_page_orientation(), PageOrientation::kClockwise90);
57 EXPECT_EQ(copy.page_spread(), DocumentLayout::PageSpread::kTwoUpOdd);
59 options_.set_direction(base::i18n::LEFT_TO_RIGHT);
60 options_.RotatePagesClockwise();
61 options_.set_page_spread(DocumentLayout::PageSpread::kOneUp);
62 EXPECT_EQ(copy.direction(), base::i18n::RIGHT_TO_LEFT);
63 EXPECT_EQ(copy.default_page_orientation(), PageOrientation::kClockwise90);
64 EXPECT_EQ(copy.page_spread(), DocumentLayout::PageSpread::kTwoUpOdd);
67 TEST_F(DocumentLayoutOptionsTest, Equals) {
68 EXPECT_TRUE(options_ == options_);
70 DocumentLayout::Options copy;
71 EXPECT_TRUE(copy == options_);
73 options_.set_direction(base::i18n::RIGHT_TO_LEFT);
74 EXPECT_FALSE(copy == options_);
76 copy.set_direction(base::i18n::RIGHT_TO_LEFT);
77 EXPECT_TRUE(copy == options_);
79 options_.RotatePagesClockwise();
80 EXPECT_FALSE(copy == options_);
82 copy.RotatePagesClockwise();
83 EXPECT_TRUE(copy == options_);
85 options_.RotatePagesCounterclockwise();
86 EXPECT_FALSE(copy == options_);
88 copy.RotatePagesCounterclockwise();
89 EXPECT_TRUE(copy == options_);
91 options_.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
92 EXPECT_FALSE(copy == options_);
94 copy.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
95 EXPECT_TRUE(copy == options_);
98 TEST_F(DocumentLayoutOptionsTest, NotEquals) {
99 // Given that "!=" is defined as "!(==)", minimal tests should be sufficient
101 EXPECT_FALSE(options_ != options_);
103 DocumentLayout::Options copy;
104 EXPECT_FALSE(copy != options_);
106 options_.RotatePagesClockwise();
107 EXPECT_TRUE(copy != options_);
109 copy.RotatePagesClockwise();
110 EXPECT_FALSE(copy != options_);
113 TEST_F(DocumentLayoutOptionsTest, ToValueDefault) {
114 base::Value value(options_.ToValue());
116 EXPECT_THAT(value, base::test::IsJson(R"({
118 "defaultPageOrientation": 0,
119 "twoUpViewEnabled": false,
123 TEST_F(DocumentLayoutOptionsTest, ToValueModified) {
124 options_.set_direction(base::i18n::LEFT_TO_RIGHT);
125 options_.RotatePagesClockwise();
126 options_.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
127 base::Value value(options_.ToValue());
129 EXPECT_THAT(value, base::test::IsJson(R"({
131 "defaultPageOrientation": 1,
132 "twoUpViewEnabled": true,
136 TEST_F(DocumentLayoutOptionsTest, FromValueDefault) {
137 base::Value value = base::test::ParseJson(R"({
139 "defaultPageOrientation": 0,
140 "twoUpViewEnabled": false,
142 options_.FromValue(value.GetDict());
144 EXPECT_EQ(options_, DocumentLayout::Options());
147 TEST_F(DocumentLayoutOptionsTest, FromValueModified) {
148 base::Value value = base::test::ParseJson(R"({
150 "defaultPageOrientation": 1,
151 "twoUpViewEnabled": true,
153 options_.FromValue(value.GetDict());
155 EXPECT_EQ(options_.direction(), base::i18n::LEFT_TO_RIGHT);
156 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kClockwise90);
157 EXPECT_EQ(options_.page_spread(), DocumentLayout::PageSpread::kTwoUpOdd);
160 TEST_F(DocumentLayoutOptionsTest, RotatePagesClockwise) {
161 options_.RotatePagesClockwise();
162 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kClockwise90);
164 options_.RotatePagesClockwise();
165 EXPECT_EQ(options_.default_page_orientation(),
166 PageOrientation::kClockwise180);
168 options_.RotatePagesClockwise();
169 EXPECT_EQ(options_.default_page_orientation(),
170 PageOrientation::kClockwise270);
172 options_.RotatePagesClockwise();
173 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kOriginal);
176 TEST_F(DocumentLayoutOptionsTest, RotatePagesCounterclockwise) {
177 options_.RotatePagesCounterclockwise();
178 EXPECT_EQ(options_.default_page_orientation(),
179 PageOrientation::kClockwise270);
181 options_.RotatePagesCounterclockwise();
182 EXPECT_EQ(options_.default_page_orientation(),
183 PageOrientation::kClockwise180);
185 options_.RotatePagesCounterclockwise();
186 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kClockwise90);
188 options_.RotatePagesCounterclockwise();
189 EXPECT_EQ(options_.default_page_orientation(), PageOrientation::kOriginal);
192 class DocumentLayoutTest : public testing::Test {
194 void SetPageSpread(DocumentLayout::PageSpread page_spread) {
195 DocumentLayout::Options options;
196 options.set_page_spread(page_spread);
197 layout_.SetOptions(options);
200 DocumentLayout layout_;
203 TEST_F(DocumentLayoutTest, DefaultConstructor) {
204 EXPECT_EQ(layout_.options().default_page_orientation(),
205 PageOrientation::kOriginal);
206 EXPECT_EQ(layout_.options().page_spread(),
207 DocumentLayout::PageSpread::kOneUp);
208 EXPECT_FALSE(layout_.dirty());
209 EXPECT_EQ(layout_.size(), gfx::Size(0, 0));
210 EXPECT_EQ(layout_.page_count(), 0u);
213 TEST_F(DocumentLayoutTest, SetOptionsDoesNotRecomputeLayout) {
214 layout_.ComputeLayout({{100, 200}});
215 EXPECT_EQ(layout_.size(), gfx::Size(100, 200));
217 DocumentLayout::Options options;
218 options.RotatePagesClockwise();
219 layout_.SetOptions(options);
220 EXPECT_EQ(layout_.options().default_page_orientation(),
221 PageOrientation::kClockwise90);
222 EXPECT_EQ(layout_.size(), gfx::Size(100, 200));
225 TEST_F(DocumentLayoutTest, DirtySetOnOptionsChange) {
226 DocumentLayout::Options options;
227 layout_.SetOptions(options);
228 EXPECT_FALSE(layout_.dirty());
230 options.RotatePagesClockwise();
231 layout_.SetOptions(options);
232 EXPECT_TRUE(layout_.dirty());
234 layout_.clear_dirty();
236 options.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
237 layout_.SetOptions(options);
238 EXPECT_TRUE(layout_.dirty());
241 TEST_F(DocumentLayoutTest, DirtyNotSetOnSameOptions) {
242 DocumentLayout::Options options;
243 options.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
244 layout_.SetOptions(options);
245 EXPECT_TRUE(layout_.dirty());
247 layout_.clear_dirty();
249 options.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
250 layout_.SetOptions(options);
251 EXPECT_FALSE(layout_.dirty());
254 TEST_F(DocumentLayoutTest, ComputeLayoutOneUp) {
255 SetPageSpread(DocumentLayout::PageSpread::kOneUp);
257 std::vector<gfx::Size> page_sizes{
258 {300, 400}, {400, 500}, {300, 400}, {200, 300}};
259 layout_.ComputeLayout(page_sizes);
260 ASSERT_EQ(4u, layout_.page_count());
261 EXPECT_EQ(gfx::Rect(50, 0, 300, 400), layout_.page_rect(0));
262 EXPECT_EQ(gfx::Rect(0, 404, 400, 500), layout_.page_rect(1));
263 EXPECT_EQ(gfx::Rect(50, 908, 300, 400), layout_.page_rect(2));
264 EXPECT_EQ(gfx::Rect(100, 1312, 200, 300), layout_.page_rect(3));
265 EXPECT_EQ(gfx::Rect(55, 3, 290, 390), layout_.page_bounds_rect(0));
266 EXPECT_EQ(gfx::Rect(5, 407, 390, 490), layout_.page_bounds_rect(1));
267 EXPECT_EQ(gfx::Rect(55, 911, 290, 390), layout_.page_bounds_rect(2));
268 EXPECT_EQ(gfx::Rect(105, 1315, 190, 290), layout_.page_bounds_rect(3));
269 EXPECT_EQ(gfx::Size(400, 1612), layout_.size());
271 page_sizes = {{240, 300}, {320, 400}, {250, 360}, {300, 600}, {270, 555}};
272 layout_.ComputeLayout(page_sizes);
273 ASSERT_EQ(5u, layout_.page_count());
274 EXPECT_EQ(gfx::Rect(40, 0, 240, 300), layout_.page_rect(0));
275 EXPECT_EQ(gfx::Rect(0, 304, 320, 400), layout_.page_rect(1));
276 EXPECT_EQ(gfx::Rect(35, 708, 250, 360), layout_.page_rect(2));
277 EXPECT_EQ(gfx::Rect(10, 1072, 300, 600), layout_.page_rect(3));
278 EXPECT_EQ(gfx::Rect(25, 1676, 270, 555), layout_.page_rect(4));
279 EXPECT_EQ(gfx::Rect(45, 3, 230, 290), layout_.page_bounds_rect(0));
280 EXPECT_EQ(gfx::Rect(5, 307, 310, 390), layout_.page_bounds_rect(1));
281 EXPECT_EQ(gfx::Rect(40, 711, 240, 350), layout_.page_bounds_rect(2));
282 EXPECT_EQ(gfx::Rect(15, 1075, 290, 590), layout_.page_bounds_rect(3));
283 EXPECT_EQ(gfx::Rect(30, 1679, 260, 545), layout_.page_bounds_rect(4));
284 EXPECT_EQ(gfx::Size(320, 2231), layout_.size());
287 TEST_F(DocumentLayoutTest, ComputeLayoutOneUpWithNoPages) {
288 SetPageSpread(DocumentLayout::PageSpread::kOneUp);
290 layout_.ComputeLayout({});
291 ASSERT_EQ(0u, layout_.page_count());
294 TEST_F(DocumentLayoutTest, DirtySetOnLayoutInputChangeOneUp) {
295 SetPageSpread(DocumentLayout::PageSpread::kOneUp);
297 layout_.ComputeLayout({{100, 200}});
298 EXPECT_TRUE(layout_.dirty());
299 layout_.clear_dirty();
300 EXPECT_FALSE(layout_.dirty());
302 layout_.ComputeLayout({{100, 200}});
303 EXPECT_FALSE(layout_.dirty());
305 layout_.ComputeLayout({{200, 100}});
306 EXPECT_TRUE(layout_.dirty());
307 layout_.clear_dirty();
309 layout_.ComputeLayout({{200, 100}, {300, 300}});
310 EXPECT_TRUE(layout_.dirty());
311 layout_.clear_dirty();
313 layout_.ComputeLayout({{200, 100}});
314 EXPECT_TRUE(layout_.dirty());
317 TEST_F(DocumentLayoutTest, ComputeLayoutTwoUpOdd) {
318 SetPageSpread(DocumentLayout::PageSpread::kTwoUpOdd);
320 // Test case where the widest page is on the right.
321 std::vector<gfx::Size> page_sizes{
322 {826, 1066}, {1066, 826}, {826, 1066}, {826, 900}};
323 layout_.ComputeLayout(page_sizes);
324 ASSERT_EQ(4u, layout_.page_count());
325 EXPECT_EQ(gfx::Rect(240, 0, 826, 1066), layout_.page_rect(0));
326 EXPECT_EQ(gfx::Rect(1066, 0, 1066, 826), layout_.page_rect(1));
327 EXPECT_EQ(gfx::Rect(240, 1066, 826, 1066), layout_.page_rect(2));
328 EXPECT_EQ(gfx::Rect(1066, 1066, 826, 900), layout_.page_rect(3));
329 EXPECT_EQ(gfx::Rect(245, 3, 820, 1056), layout_.page_bounds_rect(0));
330 EXPECT_EQ(gfx::Rect(1067, 3, 1060, 816), layout_.page_bounds_rect(1));
331 EXPECT_EQ(gfx::Rect(245, 1069, 820, 1056), layout_.page_bounds_rect(2));
332 EXPECT_EQ(gfx::Rect(1067, 1069, 820, 890), layout_.page_bounds_rect(3));
333 EXPECT_EQ(gfx::Size(2132, 2132), layout_.size());
335 // Test case where the widest page is on the left.
336 page_sizes = {{1066, 826}, {820, 1056}, {820, 890}, {826, 1066}};
337 layout_.ComputeLayout(page_sizes);
338 ASSERT_EQ(4u, layout_.page_count());
339 EXPECT_EQ(gfx::Rect(0, 0, 1066, 826), layout_.page_rect(0));
340 EXPECT_EQ(gfx::Rect(1066, 0, 820, 1056), layout_.page_rect(1));
341 EXPECT_EQ(gfx::Rect(246, 1056, 820, 890), layout_.page_rect(2));
342 EXPECT_EQ(gfx::Rect(1066, 1056, 826, 1066), layout_.page_rect(3));
343 EXPECT_EQ(gfx::Rect(5, 3, 1060, 816), layout_.page_bounds_rect(0));
344 EXPECT_EQ(gfx::Rect(1067, 3, 814, 1046), layout_.page_bounds_rect(1));
345 EXPECT_EQ(gfx::Rect(251, 1059, 814, 880), layout_.page_bounds_rect(2));
346 EXPECT_EQ(gfx::Rect(1067, 1059, 820, 1056), layout_.page_bounds_rect(3));
347 EXPECT_EQ(gfx::Size(2132, 2122), layout_.size());
349 // Test case where there's an odd # of pages.
350 page_sizes = {{200, 300}, {400, 200}, {300, 600}, {250, 500}, {300, 400}};
351 layout_.ComputeLayout(page_sizes);
352 ASSERT_EQ(5u, layout_.page_count());
353 EXPECT_EQ(gfx::Rect(200, 0, 200, 300), layout_.page_rect(0));
354 EXPECT_EQ(gfx::Rect(400, 0, 400, 200), layout_.page_rect(1));
355 EXPECT_EQ(gfx::Rect(100, 300, 300, 600), layout_.page_rect(2));
356 EXPECT_EQ(gfx::Rect(400, 300, 250, 500), layout_.page_rect(3));
357 EXPECT_EQ(gfx::Rect(100, 900, 300, 400), layout_.page_rect(4));
358 EXPECT_EQ(gfx::Rect(205, 3, 194, 290), layout_.page_bounds_rect(0));
359 EXPECT_EQ(gfx::Rect(401, 3, 394, 190), layout_.page_bounds_rect(1));
360 EXPECT_EQ(gfx::Rect(105, 303, 294, 590), layout_.page_bounds_rect(2));
361 EXPECT_EQ(gfx::Rect(401, 303, 244, 490), layout_.page_bounds_rect(3));
362 EXPECT_EQ(gfx::Rect(105, 903, 290, 390), layout_.page_bounds_rect(4));
363 EXPECT_EQ(gfx::Size(800, 1300), layout_.size());
366 TEST_F(DocumentLayoutTest, ComputeLayoutTwoUpOddWithNoPages) {
367 SetPageSpread(DocumentLayout::PageSpread::kTwoUpOdd);
369 layout_.ComputeLayout({});
370 ASSERT_EQ(0u, layout_.page_count());
373 TEST_F(DocumentLayoutTest, DirtySetOnLayoutInputChangeTwoUpOdd) {
374 SetPageSpread(DocumentLayout::PageSpread::kTwoUpOdd);
376 layout_.ComputeLayout({{100, 200}, {200, 100}});
377 EXPECT_TRUE(layout_.dirty());
378 layout_.clear_dirty();
379 EXPECT_FALSE(layout_.dirty());
381 layout_.ComputeLayout({{100, 200}, {200, 100}});
382 EXPECT_FALSE(layout_.dirty());
384 layout_.ComputeLayout({{200, 100}, {100, 200}});
385 EXPECT_TRUE(layout_.dirty());
386 layout_.clear_dirty();
388 layout_.ComputeLayout({{200, 100}, {100, 200}, {300, 300}});
389 EXPECT_TRUE(layout_.dirty());
390 layout_.clear_dirty();
392 layout_.ComputeLayout({{200, 100}, {100, 200}});
393 EXPECT_TRUE(layout_.dirty());
398 } // namespace chrome_pdf