blob: 16f56d41ae446e5c3761a5e81a78a9f9c44638f0 [file] [log] [blame]
K Moonbd80ce72019-07-26 19:27:501// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "pdf/document_layout.h"
6
Jeremy Apthorp17c873c2019-12-02 20:27:397#include <algorithm>
8
Hans Wennborg5078d102020-04-29 18:26:469#include "base/check_op.h"
Gouarb Kunduc4338a62020-07-30 21:30:4810#include "base/values.h"
Ankit Kumar 🌪️b8ba092f2020-08-21 20:07:4511#include "pdf/ppapi_migration/geometry_conversions.h"
K Moon6d326b92019-09-19 22:42:0712#include "ppapi/cpp/rect.h"
K Moon23d56442019-10-03 05:06:2313#include "ppapi/cpp/var.h"
14#include "ppapi/cpp/var_dictionary.h"
Ankit Kumar 🌪️aecc9f92020-08-18 19:11:2215#include "ui/gfx/geometry/point.h"
Ankit Kumar 🌪️b8ba092f2020-08-21 20:07:4516#include "ui/gfx/geometry/rect.h"
Ankit Kumar 🌪️e35101152020-07-30 09:57:5917#include "ui/gfx/geometry/size.h"
K Moonbd80ce72019-07-26 19:27:5018
19namespace chrome_pdf {
20
Jeremy Chinsene819dea2019-08-07 21:58:5921namespace {
22
K Moon23d56442019-10-03 05:06:2323constexpr char kDefaultPageOrientation[] = "defaultPageOrientation";
Hui Yingst28f9f5c2020-01-16 19:52:5624constexpr char kTwoUpViewEnabled[] = "twoUpViewEnabled";
K Moon23d56442019-10-03 05:06:2325
Ankit Kumar 🌪️e35101152020-07-30 09:57:5926int GetWidestPageWidth(const std::vector<gfx::Size>& page_sizes) {
Jeremy Chinsene819dea2019-08-07 21:58:5927 int widest_page_width = 0;
28 for (const auto& page_size : page_sizes) {
29 widest_page_width = std::max(widest_page_width, page_size.width());
30 }
31
32 return widest_page_width;
33}
34
K Moone4bd7522019-08-23 00:12:5635pp::Rect InsetRect(pp::Rect rect,
36 const draw_utils::PageInsetSizes& inset_sizes) {
37 rect.Inset(inset_sizes.left, inset_sizes.top, inset_sizes.right,
38 inset_sizes.bottom);
39 return rect;
40}
41
Jeremy Chinsene819dea2019-08-07 21:58:5942} // namespace
43
Lei Zhang4906c102019-08-06 00:28:0344const draw_utils::PageInsetSizes DocumentLayout::kSingleViewInsets{
45 /*left=*/5, /*top=*/3, /*right=*/5, /*bottom=*/7};
46
K Mooneb9e0002019-08-06 19:25:3247DocumentLayout::Options::Options() = default;
K Moonbd80ce72019-07-26 19:27:5048
K Mooneb9e0002019-08-06 19:25:3249DocumentLayout::Options::Options(const Options& other) = default;
50DocumentLayout::Options& DocumentLayout::Options::operator=(
51 const Options& other) = default;
K Moonbd80ce72019-07-26 19:27:5052
K Mooneb9e0002019-08-06 19:25:3253DocumentLayout::Options::~Options() = default;
K Moonbd80ce72019-07-26 19:27:5054
Gouarb Kunduc4338a62020-07-30 21:30:4855base::Value DocumentLayout::Options::ToValue() const {
56 base::Value dictionary(base::Value::Type::DICTIONARY);
57 dictionary.SetIntKey(kDefaultPageOrientation,
58 static_cast<int32_t>(default_page_orientation_));
59 dictionary.SetBoolKey(kTwoUpViewEnabled, two_up_view_enabled_);
K Moon23d56442019-10-03 05:06:2360 return dictionary;
61}
62
63void DocumentLayout::Options::FromVar(const pp::Var& var) {
64 pp::VarDictionary dictionary(var);
65
66 int32_t default_page_orientation =
67 dictionary.Get(kDefaultPageOrientation).AsInt();
68 DCHECK_GE(default_page_orientation,
69 static_cast<int32_t>(PageOrientation::kOriginal));
70 DCHECK_LE(default_page_orientation,
71 static_cast<int32_t>(PageOrientation::kLast));
72 default_page_orientation_ =
73 static_cast<PageOrientation>(default_page_orientation);
Hui Yingst28f9f5c2020-01-16 19:52:5674
75 two_up_view_enabled_ = dictionary.Get(kTwoUpViewEnabled).AsBool();
K Moon23d56442019-10-03 05:06:2376}
77
K Mooneb9e0002019-08-06 19:25:3278void DocumentLayout::Options::RotatePagesClockwise() {
K Moon9a62bf42019-08-07 20:05:3679 default_page_orientation_ = RotateClockwise(default_page_orientation_);
K Moonbd80ce72019-07-26 19:27:5080}
81
K Mooneb9e0002019-08-06 19:25:3282void DocumentLayout::Options::RotatePagesCounterclockwise() {
K Moon9a62bf42019-08-07 20:05:3683 default_page_orientation_ = RotateCounterclockwise(default_page_orientation_);
K Moonbd80ce72019-07-26 19:27:5084}
85
K Mooneb9e0002019-08-06 19:25:3286DocumentLayout::DocumentLayout() = default;
87
88DocumentLayout::~DocumentLayout() = default;
89
K Moon6d326b92019-09-19 22:42:0790void DocumentLayout::SetOptions(const Options& options) {
Hui Yingst28f9f5c2020-01-16 19:52:5691 // To be conservative, we want to consider the layout dirty for any layout
92 // option changes, even if the page rects don't necessarily change when
93 // layout options change.
K Moon6d326b92019-09-19 22:42:0794 //
Hui Yingst28f9f5c2020-01-16 19:52:5695 // We also probably don't want layout changes to actually kick in until
K Moon6d326b92019-09-19 22:42:0796 // the next call to ComputeLayout(). (In practice, we'll call ComputeLayout()
97 // shortly after calling SetOptions().)
Hui Yingst28f9f5c2020-01-16 19:52:5698 if (options_ != options) {
K Moon6d326b92019-09-19 22:42:0799 dirty_ = true;
100 }
101 options_ = options;
102}
103
K Moonff7ec672019-08-14 19:19:56104void DocumentLayout::ComputeSingleViewLayout(
Ankit Kumar 🌪️e35101152020-07-30 09:57:59105 const std::vector<gfx::Size>& page_sizes) {
106 gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);
Jeremy Chinsen08beb482019-08-07 01:58:54107
K Moon6d326b92019-09-19 22:42:07108 if (page_layouts_.size() != page_sizes.size()) {
109 // TODO(kmoon): May want to do less work when shrinking a layout.
110 page_layouts_.resize(page_sizes.size());
111 dirty_ = true;
112 }
113
Jeremy Chinsen08beb482019-08-07 01:58:54114 for (size_t i = 0; i < page_sizes.size(); ++i) {
115 if (i != 0) {
116 // Add space for bottom separator.
K Moon6d326b92019-09-19 22:42:07117 document_size.Enlarge(0, kBottomSeparator);
Jeremy Chinsen08beb482019-08-07 01:58:54118 }
119
Ankit Kumar 🌪️e35101152020-07-30 09:57:59120 const gfx::Size& page_size = page_sizes[i];
Ankit Kumar 🌪️b8ba092f2020-08-21 20:07:45121 pp::Rect page_rect = PPRectFromRect(
122 draw_utils::GetRectForSingleView(page_size, document_size));
K Moon6d326b92019-09-19 22:42:07123 CopyRectIfModified(page_rect, &page_layouts_[i].outer_rect);
124 CopyRectIfModified(InsetRect(page_rect, kSingleViewInsets),
125 &page_layouts_[i].inner_rect);
K Moone4bd7522019-08-23 00:12:56126
K Moon6d326b92019-09-19 22:42:07127 draw_utils::ExpandDocumentSize(page_size, &document_size);
128 }
129
130 if (size_ != document_size) {
131 size_ = document_size;
132 dirty_ = true;
Jeremy Chinsen08beb482019-08-07 01:58:54133 }
Jeremy Chinsen08beb482019-08-07 01:58:54134}
135
K Moonff7ec672019-08-14 19:19:56136void DocumentLayout::ComputeTwoUpViewLayout(
Ankit Kumar 🌪️e35101152020-07-30 09:57:59137 const std::vector<gfx::Size>& page_sizes) {
138 gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);
Jeremy Chinsend6fd27ce2019-08-06 00:40:17139
K Moon6d326b92019-09-19 22:42:07140 if (page_layouts_.size() != page_sizes.size()) {
141 // TODO(kmoon): May want to do less work when shrinking a layout.
142 page_layouts_.resize(page_sizes.size());
143 dirty_ = true;
144 }
145
Jeremy Chinsen4a65aad2019-08-07 00:14:33146 for (size_t i = 0; i < page_sizes.size(); ++i) {
Jeremy Chinsend6fd27ce2019-08-06 00:40:17147 draw_utils::PageInsetSizes page_insets =
148 draw_utils::GetPageInsetsForTwoUpView(
Jeremy Chinsen4a65aad2019-08-07 00:14:33149 i, page_sizes.size(), kSingleViewInsets, kHorizontalSeparator);
Ankit Kumar 🌪️e35101152020-07-30 09:57:59150 const gfx::Size& page_size = page_sizes[i];
Jeremy Chinsend6fd27ce2019-08-06 00:40:17151
K Moone4bd7522019-08-23 00:12:56152 pp::Rect page_rect;
Jeremy Chinsend6fd27ce2019-08-06 00:40:17153 if (i % 2 == 0) {
Ankit Kumar 🌪️b8ba092f2020-08-21 20:07:45154 page_rect = PPRectFromRect(draw_utils::GetLeftRectForTwoUpView(
155 page_size, {document_size.width(), document_size.height()}));
Jeremy Chinsend6fd27ce2019-08-06 00:40:17156 } else {
Ankit Kumar 🌪️b8ba092f2020-08-21 20:07:45157 page_rect = PPRectFromRect(draw_utils::GetRightRectForTwoUpView(
158 page_size, {document_size.width(), document_size.height()}));
K Moon6d326b92019-09-19 22:42:07159 document_size.Enlarge(
160 0, std::max(page_size.height(), page_sizes[i - 1].height()));
Jeremy Chinsend6fd27ce2019-08-06 00:40:17161 }
K Moon6d326b92019-09-19 22:42:07162 CopyRectIfModified(page_rect, &page_layouts_[i].outer_rect);
163 CopyRectIfModified(InsetRect(page_rect, page_insets),
164 &page_layouts_[i].inner_rect);
Jeremy Chinsend6fd27ce2019-08-06 00:40:17165 }
166
Jeremy Chinsen4a65aad2019-08-07 00:14:33167 if (page_sizes.size() % 2 == 1) {
K Moon6d326b92019-09-19 22:42:07168 document_size.Enlarge(0, page_sizes.back().height());
Jeremy Chinsend6fd27ce2019-08-06 00:40:17169 }
170
K Moon6d326b92019-09-19 22:42:07171 document_size.set_width(2 * document_size.width());
172
173 if (size_ != document_size) {
174 size_ = document_size;
175 dirty_ = true;
176 }
177}
178
179void DocumentLayout::CopyRectIfModified(const pp::Rect& source_rect,
180 pp::Rect* destination_rect) {
181 if (*destination_rect != source_rect) {
182 *destination_rect = source_rect;
183 dirty_ = true;
184 }
Jeremy Chinsend6fd27ce2019-08-06 00:40:17185}
186
K Moonbd80ce72019-07-26 19:27:50187} // namespace chrome_pdf