From d6fd27ce86e82f6f1b782e9398dbbb7343f883bd Mon Sep 17 00:00:00 2001 From: Jeremy Chinsen Date: Tue, 6 Aug 2019 00:40:17 +0000 Subject: [PATCH] Add DocumentLayout::GetTwoUpViewLayout() and PDFiumEngine::LoadPagesInTwoUpView(). Currently PDFiumEngine can only generate a single-view layout for documents. This CL adds DocumentLayout::GetTwoUpViewLayout() which takes a vector of pages and returns the pages formatted for two-up view, as well as updates the size of the layout. This helper function makes the two-up view layout testable. This CL also adds PDFiumEngine::LoadPagesInTwoUpView() which calls DocumentLayout::GetTwoUpViewLayout() to format pages in two-up view and appends them to |pages_|. This allows PDFiumEngine to render documents in two-up view. Bug: 51472 Change-Id: I6b65210f32efc205376d53abaeaa0c6eab84ac2d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1733737 Commit-Queue: Jeremy Chinsen Reviewed-by: Lei Zhang Cr-Commit-Position: refs/heads/master@{#684197} --- pdf/document_layout.cc | 30 +++++++++++++++++++ pdf/document_layout.h | 11 +++++-- pdf/document_layout_unittest.cc | 53 +++++++++++++++++++++++++++++++++ pdf/pdfium/pdfium_engine.cc | 16 +++++++++- pdf/pdfium/pdfium_engine.h | 4 +++ 5 files changed, 111 insertions(+), 3 deletions(-) diff --git a/pdf/document_layout.cc b/pdf/document_layout.cc index 1508e1a99ab5f8..604a2e3fd1cf57 100644 --- a/pdf/document_layout.cc +++ b/pdf/document_layout.cc @@ -27,6 +27,36 @@ void DocumentLayout::RotatePagesCounterclockwise() { default_page_orientation_ = (default_page_orientation_ - 1) % 4; } +std::vector DocumentLayout::GetTwoUpViewLayout( + const std::vector& page_rects) { + std::vector formatted_rects(page_rects.size()); + // Reset the current layout's height for new two-up view layout. + size_.set_height(0); + + for (size_t i = 0; i < page_rects.size(); ++i) { + draw_utils::PageInsetSizes page_insets = + draw_utils::GetPageInsetsForTwoUpView( + i, page_rects.size(), kSingleViewInsets, kHorizontalSeparator); + const pp::Size& page_size = page_rects[i].size(); + + if (i % 2 == 0) { + formatted_rects[i] = draw_utils::GetLeftRectForTwoUpView( + page_size, {size_.width(), size_.height()}, page_insets); + } else { + formatted_rects[i] = draw_utils::GetRightRectForTwoUpView( + page_size, {size_.width(), size_.height()}, page_insets); + EnlargeHeight( + std::max(page_size.height(), page_rects[i - 1].size().height())); + } + } + + if (page_rects.size() % 2 == 1) { + EnlargeHeight(page_rects.back().size().height()); + } + + return formatted_rects; +} + void DocumentLayout::EnlargeHeight(int height) { DCHECK_GE(height, 0); size_.Enlarge(0, height); diff --git a/pdf/document_layout.h b/pdf/document_layout.h index 8b1c91f16dd49c..117d8a72e89623 100644 --- a/pdf/document_layout.h +++ b/pdf/document_layout.h @@ -5,7 +5,10 @@ #ifndef PDF_DOCUMENT_LAYOUT_H_ #define PDF_DOCUMENT_LAYOUT_H_ +#include + #include "pdf/draw_utils/coordinates.h" +#include "ppapi/cpp/rect.h" #include "ppapi/cpp/size.h" namespace chrome_pdf { @@ -14,8 +17,6 @@ namespace chrome_pdf { // (possibly rotated) in a non-overlapping vertical sequence. // // All layout units are pixels. -// -// TODO(crbug.com/51472): Support multiple columns. class DocumentLayout final { public: static const draw_utils::PageInsetSizes kSingleViewInsets; @@ -50,6 +51,12 @@ class DocumentLayout final { // Sets the layout's total size. void set_size(const pp::Size& size) { size_ = size; } + // Given |page_rects| and the layout's size is set to a single-view layout, + // return |page_rects| formatted for two-up view and update the layout's size + // to the size of the new two-up view layout. + std::vector GetTwoUpViewLayout( + const std::vector& page_rects); + // Increases the layout's total height by |height|. void EnlargeHeight(int height); diff --git a/pdf/document_layout_unittest.cc b/pdf/document_layout_unittest.cc index 8185464d54ea60..1d7d0a807248f5 100644 --- a/pdf/document_layout_unittest.cc +++ b/pdf/document_layout_unittest.cc @@ -25,6 +25,10 @@ inline bool PpSizeEq(const pp::Size& lhs, const pp::Size& rhs) { return lhs == rhs; } +inline bool PpRectEq(const pp::Rect& lhs, const pp::Rect& rhs) { + return lhs == rhs; +} + TEST_F(DocumentLayoutTest, DefaultConstructor) { EXPECT_EQ(layout_.default_page_orientation(), 0); EXPECT_PRED2(PpSizeEq, layout_.size(), pp::Size(0, 0)); @@ -108,6 +112,55 @@ TEST_F(DocumentLayoutTest, EnlargeHeight) { EXPECT_PRED2(PpSizeEq, layout_.size(), pp::Size(0, 16)); } +TEST_F(DocumentLayoutTest, GetTwoUpViewLayout) { + std::vector two_up_view_layout; + + // Test case where the widest page is on the right. + std::vector page_rects{{0, 10, 826, 1066}, + {0, 1076, 1066, 826}, + {0, 1902, 826, 1066}, + {0, 2968, 826, 900}}; + layout_.set_size({1066, 0}); + two_up_view_layout = layout_.GetTwoUpViewLayout(page_rects); + ASSERT_EQ(4u, two_up_view_layout.size()); + EXPECT_PRED2(PpRectEq, pp::Rect(245, 3, 820, 1056), two_up_view_layout[0]); + EXPECT_PRED2(PpRectEq, pp::Rect(1067, 3, 1060, 816), two_up_view_layout[1]); + EXPECT_PRED2(PpRectEq, pp::Rect(245, 1069, 820, 1056), two_up_view_layout[2]); + EXPECT_PRED2(PpRectEq, pp::Rect(1067, 1069, 820, 890), two_up_view_layout[3]); + EXPECT_PRED2(PpSizeEq, pp::Size(1066, 2132), layout_.size()); + + // Test case where the widest page is on the left. + page_rects = {{0, 5, 1066, 826}, + {0, 831, 820, 1056}, + {0, 1887, 820, 890}, + {0, 2777, 826, 1066}}; + layout_.set_size({1066, 0}); + two_up_view_layout = layout_.GetTwoUpViewLayout(page_rects); + ASSERT_EQ(4u, two_up_view_layout.size()); + EXPECT_PRED2(PpRectEq, pp::Rect(5, 3, 1060, 816), two_up_view_layout[0]); + EXPECT_PRED2(PpRectEq, pp::Rect(1067, 3, 814, 1046), two_up_view_layout[1]); + EXPECT_PRED2(PpRectEq, pp::Rect(251, 1059, 814, 880), two_up_view_layout[2]); + EXPECT_PRED2(PpRectEq, pp::Rect(1067, 1059, 820, 1056), + two_up_view_layout[3]); + EXPECT_PRED2(PpSizeEq, pp::Size(1066, 2122), layout_.size()); + + // Test case where there's an odd # of pages. + page_rects = {{0, 5, 200, 300}, + {0, 305, 400, 200}, + {0, 505, 300, 600}, + {0, 1105, 250, 500}, + {0, 1605, 300, 400}}; + layout_.set_size({400, 0}); + two_up_view_layout = layout_.GetTwoUpViewLayout(page_rects); + ASSERT_EQ(5u, two_up_view_layout.size()); + EXPECT_PRED2(PpRectEq, pp::Rect(205, 3, 194, 290), two_up_view_layout[0]); + EXPECT_PRED2(PpRectEq, pp::Rect(401, 3, 394, 190), two_up_view_layout[1]); + EXPECT_PRED2(PpRectEq, pp::Rect(105, 303, 294, 590), two_up_view_layout[2]); + EXPECT_PRED2(PpRectEq, pp::Rect(401, 303, 244, 490), two_up_view_layout[3]); + EXPECT_PRED2(PpRectEq, pp::Rect(105, 903, 290, 390), two_up_view_layout[4]); + EXPECT_PRED2(PpSizeEq, pp::Size(400, 1300), layout_.size()); +} + TEST_F(DocumentLayoutDeathTest, EnlargeHeightNegativeIncrement) { EXPECT_DCHECK_DEATH(layout_.EnlargeHeight(-5)); } diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index c166788910f432..272d97c70ac848 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc @@ -2400,6 +2400,16 @@ void PDFiumEngine::LoadPagesInSingleView(std::vector page_rects, } } +void PDFiumEngine::LoadPagesInTwoUpView(std::vector page_rects, + bool reload) { + std::vector two_up_view_layout = + layout_.GetTwoUpViewLayout(page_rects); + + for (size_t i = 0; i < two_up_view_layout.size(); ++i) { + AppendPageRectToPages(two_up_view_layout[i], i, reload); + } +} + void PDFiumEngine::LoadPageInfo(bool reload) { if (!doc_loader_) return; @@ -2445,7 +2455,11 @@ void PDFiumEngine::LoadPageInfo(bool reload) { layout_.AppendPageRect(size); } - LoadPagesInSingleView(std::move(page_rects), reload); + if (two_up_view_) { + LoadPagesInTwoUpView(std::move(page_rects), reload); + } else { + LoadPagesInSingleView(std::move(page_rects), reload); + } // Remove pages that do not exist anymore. if (pages_.size() > new_page_count) { diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index ee8c7e0dc87e3b..c45a3d5b687ade 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h @@ -243,6 +243,10 @@ class PDFiumEngine : public PDFEngine, // |pages_|. void LoadPagesInSingleView(std::vector page_rects, bool reload); + // Formats the pages of |page_rects| for two-up view and appends them to + // |pages_|. + void LoadPagesInTwoUpView(std::vector page_rects, bool reload); + // Loads information about the pages in the document and calculate the // document size. void LoadPageInfo(bool reload);