blob: b53da54e153b2078a2e18c9af38cfbbbae8da5b8 [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
K Moonbd80ce72019-07-26 19:27:509#include "base/logging.h"
K Moon6d326b92019-09-19 22:42:0710#include "ppapi/cpp/rect.h"
11#include "ppapi/cpp/size.h"
K Moon23d56442019-10-03 05:06:2312#include "ppapi/cpp/var.h"
13#include "ppapi/cpp/var_dictionary.h"
K Moonbd80ce72019-07-26 19:27:5014
15namespace chrome_pdf {
16
Jeremy Chinsene819dea2019-08-07 21:58:5917namespace {
18
K Moon23d56442019-10-03 05:06:2319constexpr char kDefaultPageOrientation[] = "defaultPageOrientation";
20
Jeremy Chinsene819dea2019-08-07 21:58:5921int GetWidestPageWidth(const std::vector<pp::Size>& page_sizes) {
22 int widest_page_width = 0;
23 for (const auto& page_size : page_sizes) {
24 widest_page_width = std::max(widest_page_width, page_size.width());
25 }
26
27 return widest_page_width;
28}
29
K Moone4bd7522019-08-23 00:12:5630pp::Rect InsetRect(pp::Rect rect,
31 const draw_utils::PageInsetSizes& inset_sizes) {
32 rect.Inset(inset_sizes.left, inset_sizes.top, inset_sizes.right,
33 inset_sizes.bottom);
34 return rect;
35}
36
Jeremy Chinsene819dea2019-08-07 21:58:5937} // namespace
38
Lei Zhang4906c102019-08-06 00:28:0339const draw_utils::PageInsetSizes DocumentLayout::kSingleViewInsets{
40 /*left=*/5, /*top=*/3, /*right=*/5, /*bottom=*/7};
41
K Mooneb9e0002019-08-06 19:25:3242DocumentLayout::Options::Options() = default;
K Moonbd80ce72019-07-26 19:27:5043
K Mooneb9e0002019-08-06 19:25:3244DocumentLayout::Options::Options(const Options& other) = default;
45DocumentLayout::Options& DocumentLayout::Options::operator=(
46 const Options& other) = default;
K Moonbd80ce72019-07-26 19:27:5047
K Mooneb9e0002019-08-06 19:25:3248DocumentLayout::Options::~Options() = default;
K Moonbd80ce72019-07-26 19:27:5049
K Moon23d56442019-10-03 05:06:2350pp::Var DocumentLayout::Options::ToVar() const {
51 pp::VarDictionary dictionary;
52 dictionary.Set(kDefaultPageOrientation,
53 static_cast<int32_t>(default_page_orientation_));
54 return dictionary;
55}
56
57void DocumentLayout::Options::FromVar(const pp::Var& var) {
58 pp::VarDictionary dictionary(var);
59
60 int32_t default_page_orientation =
61 dictionary.Get(kDefaultPageOrientation).AsInt();
62 DCHECK_GE(default_page_orientation,
63 static_cast<int32_t>(PageOrientation::kOriginal));
64 DCHECK_LE(default_page_orientation,
65 static_cast<int32_t>(PageOrientation::kLast));
66 default_page_orientation_ =
67 static_cast<PageOrientation>(default_page_orientation);
68}
69
K Mooneb9e0002019-08-06 19:25:3270void DocumentLayout::Options::RotatePagesClockwise() {
K Moon9a62bf42019-08-07 20:05:3671 default_page_orientation_ = RotateClockwise(default_page_orientation_);
K Moonbd80ce72019-07-26 19:27:5072}
73
K Mooneb9e0002019-08-06 19:25:3274void DocumentLayout::Options::RotatePagesCounterclockwise() {
K Moon9a62bf42019-08-07 20:05:3675 default_page_orientation_ = RotateCounterclockwise(default_page_orientation_);
K Moonbd80ce72019-07-26 19:27:5076}
77
K Mooneb9e0002019-08-06 19:25:3278DocumentLayout::DocumentLayout() = default;
79
80DocumentLayout::~DocumentLayout() = default;
81
K Moon6d326b92019-09-19 22:42:0782void DocumentLayout::SetOptions(const Options& options) {
83 // TODO(kmoon): This is pessimistic, but we still want to consider the layout
84 // dirty for orientation changes, even if the page rects don't change.
85 //
86 // We also probably don't want orientation changes to actually kick in until
87 // the next call to ComputeLayout(). (In practice, we'll call ComputeLayout()
88 // shortly after calling SetOptions().)
89 if (options_.default_page_orientation() !=
90 options.default_page_orientation()) {
91 dirty_ = true;
92 }
93 options_ = options;
94}
95
K Moonff7ec672019-08-14 19:19:5696void DocumentLayout::ComputeSingleViewLayout(
Jeremy Chinsen08beb482019-08-07 01:58:5497 const std::vector<pp::Size>& page_sizes) {
K Moon6d326b92019-09-19 22:42:0798 pp::Size document_size(GetWidestPageWidth(page_sizes), 0);
Jeremy Chinsen08beb482019-08-07 01:58:5499
K Moon6d326b92019-09-19 22:42:07100 if (page_layouts_.size() != page_sizes.size()) {
101 // TODO(kmoon): May want to do less work when shrinking a layout.
102 page_layouts_.resize(page_sizes.size());
103 dirty_ = true;
104 }
105
Jeremy Chinsen08beb482019-08-07 01:58:54106 for (size_t i = 0; i < page_sizes.size(); ++i) {
107 if (i != 0) {
108 // Add space for bottom separator.
K Moon6d326b92019-09-19 22:42:07109 document_size.Enlarge(0, kBottomSeparator);
Jeremy Chinsen08beb482019-08-07 01:58:54110 }
111
112 const pp::Size& page_size = page_sizes[i];
K Moon6d326b92019-09-19 22:42:07113 pp::Rect page_rect =
114 draw_utils::GetRectForSingleView(page_size, document_size);
115 CopyRectIfModified(page_rect, &page_layouts_[i].outer_rect);
116 CopyRectIfModified(InsetRect(page_rect, kSingleViewInsets),
117 &page_layouts_[i].inner_rect);
K Moone4bd7522019-08-23 00:12:56118
K Moon6d326b92019-09-19 22:42:07119 draw_utils::ExpandDocumentSize(page_size, &document_size);
120 }
121
122 if (size_ != document_size) {
123 size_ = document_size;
124 dirty_ = true;
Jeremy Chinsen08beb482019-08-07 01:58:54125 }
Jeremy Chinsen08beb482019-08-07 01:58:54126}
127
K Moonff7ec672019-08-14 19:19:56128void DocumentLayout::ComputeTwoUpViewLayout(
Jeremy Chinsen4a65aad2019-08-07 00:14:33129 const std::vector<pp::Size>& page_sizes) {
K Moon6d326b92019-09-19 22:42:07130 pp::Size document_size(GetWidestPageWidth(page_sizes), 0);
Jeremy Chinsend6fd27ce2019-08-06 00:40:17131
K Moon6d326b92019-09-19 22:42:07132 if (page_layouts_.size() != page_sizes.size()) {
133 // TODO(kmoon): May want to do less work when shrinking a layout.
134 page_layouts_.resize(page_sizes.size());
135 dirty_ = true;
136 }
137
Jeremy Chinsen4a65aad2019-08-07 00:14:33138 for (size_t i = 0; i < page_sizes.size(); ++i) {
Jeremy Chinsend6fd27ce2019-08-06 00:40:17139 draw_utils::PageInsetSizes page_insets =
140 draw_utils::GetPageInsetsForTwoUpView(
Jeremy Chinsen4a65aad2019-08-07 00:14:33141 i, page_sizes.size(), kSingleViewInsets, kHorizontalSeparator);
142 const pp::Size& page_size = page_sizes[i];
Jeremy Chinsend6fd27ce2019-08-06 00:40:17143
K Moone4bd7522019-08-23 00:12:56144 pp::Rect page_rect;
Jeremy Chinsend6fd27ce2019-08-06 00:40:17145 if (i % 2 == 0) {
K Moone4bd7522019-08-23 00:12:56146 page_rect = draw_utils::GetLeftRectForTwoUpView(
K Moon6d326b92019-09-19 22:42:07147 page_size, {document_size.width(), document_size.height()});
Jeremy Chinsend6fd27ce2019-08-06 00:40:17148 } else {
K Moone4bd7522019-08-23 00:12:56149 page_rect = draw_utils::GetRightRectForTwoUpView(
K Moon6d326b92019-09-19 22:42:07150 page_size, {document_size.width(), document_size.height()});
151 document_size.Enlarge(
152 0, std::max(page_size.height(), page_sizes[i - 1].height()));
Jeremy Chinsend6fd27ce2019-08-06 00:40:17153 }
K Moon6d326b92019-09-19 22:42:07154 CopyRectIfModified(page_rect, &page_layouts_[i].outer_rect);
155 CopyRectIfModified(InsetRect(page_rect, page_insets),
156 &page_layouts_[i].inner_rect);
Jeremy Chinsend6fd27ce2019-08-06 00:40:17157 }
158
Jeremy Chinsen4a65aad2019-08-07 00:14:33159 if (page_sizes.size() % 2 == 1) {
K Moon6d326b92019-09-19 22:42:07160 document_size.Enlarge(0, page_sizes.back().height());
Jeremy Chinsend6fd27ce2019-08-06 00:40:17161 }
162
K Moon6d326b92019-09-19 22:42:07163 document_size.set_width(2 * document_size.width());
164
165 if (size_ != document_size) {
166 size_ = document_size;
167 dirty_ = true;
168 }
169}
170
171void DocumentLayout::CopyRectIfModified(const pp::Rect& source_rect,
172 pp::Rect* destination_rect) {
173 if (*destination_rect != source_rect) {
174 *destination_rect = source_rect;
175 dirty_ = true;
176 }
Jeremy Chinsend6fd27ce2019-08-06 00:40:17177}
178
K Moonbd80ce72019-07-26 19:27:50179} // namespace chrome_pdf