blob: 4bd6cadf65857644dfc2511ae09b593e6a4f5e4d [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#ifndef PDF_DOCUMENT_LAYOUT_H_
6#define PDF_DOCUMENT_LAYOUT_H_
7
K Moonff7ec672019-08-14 19:19:568#include <cstddef>
Jeremy Chinsend6fd27ce2019-08-06 00:40:179#include <vector>
10
Hans Wennborg29adea92020-06-22 16:13:5311#include "base/check_op.h"
Lei Zhang4906c102019-08-06 00:28:0312#include "pdf/draw_utils/coordinates.h"
K Moon9a62bf42019-08-07 20:05:3613#include "pdf/page_orientation.h"
Ankit Kumar 🌪️00798692020-08-26 22:57:1414#include "ui/gfx/geometry/rect.h"
Ankit Kumar 🌪️e35101152020-07-30 09:57:5915#include "ui/gfx/geometry/size.h"
K Moonbd80ce72019-07-26 19:27:5016
Gouarb Kunduc4338a62020-07-30 21:30:4817namespace base {
18class Value;
19}
20
K Moonbd80ce72019-07-26 19:27:5021namespace chrome_pdf {
22
23// Layout of pages within a PDF document. Pages are placed as rectangles
24// (possibly rotated) in a non-overlapping vertical sequence.
25//
26// All layout units are pixels.
K Mooneb9e0002019-08-06 19:25:3227//
Daniel Hosseiniane257d962021-04-23 21:18:3528// The `Options` class controls the behavior of the layout, such as the default
K Mooneb9e0002019-08-06 19:25:3229// orientation of pages.
K Moonbd80ce72019-07-26 19:27:5030class DocumentLayout final {
31 public:
Daniel Hosseinianbe882062021-04-22 01:22:3932 // TODO(crbug.com/1144505): Add `kTwoUpEven` page spread support.
33 enum class PageSpread {
34 kOneUp = 0, // One page per spread.
35 kTwoUpOdd = 1, // Two pages per spread, with odd pages first.
36 };
37
K Mooneb9e0002019-08-06 19:25:3238 // Options controlling layout behavior.
39 class Options final {
40 public:
41 Options();
42
43 Options(const Options& other);
44 Options& operator=(const Options& other);
45
46 ~Options();
47
Hui Yingst28f9f5c2020-01-16 19:52:5648 friend bool operator==(const Options& lhs, const Options& rhs) {
Daniel Hosseinianbe882062021-04-22 01:22:3949 return lhs.page_spread() == rhs.page_spread() &&
Hui Yingst28f9f5c2020-01-16 19:52:5650 lhs.default_page_orientation() == rhs.default_page_orientation();
51 }
52
53 friend bool operator!=(const Options& lhs, const Options& rhs) {
54 return !(lhs == rhs);
55 }
56
Gouarb Kunduc4338a62020-07-30 21:30:4857 // Serializes layout options to a base::Value.
58 base::Value ToValue() const;
K Moon23d56442019-10-03 05:06:2359
Gouarb Kundu18d80932020-09-23 04:29:1660 // Deserializes layout options from a base::Value.
61 void FromValue(const base::Value& value);
K Moon23d56442019-10-03 05:06:2362
K Moon9a62bf42019-08-07 20:05:3663 PageOrientation default_page_orientation() const {
64 return default_page_orientation_;
65 }
K Mooneb9e0002019-08-06 19:25:3266
67 // Rotates default page orientation 90 degrees clockwise.
68 void RotatePagesClockwise();
69
70 // Rotates default page orientation 90 degrees counterclockwise.
71 void RotatePagesCounterclockwise();
72
Daniel Hosseinianbe882062021-04-22 01:22:3973 PageSpread page_spread() const { return page_spread_; }
Hui Yingst28f9f5c2020-01-16 19:52:5674
75 // Changes two-up view status.
Daniel Hosseinianbe882062021-04-22 01:22:3976 void set_page_spread(PageSpread spread) { page_spread_ = spread; }
Hui Yingst28f9f5c2020-01-16 19:52:5677
K Mooneb9e0002019-08-06 19:25:3278 private:
K Moon9a62bf42019-08-07 20:05:3679 PageOrientation default_page_orientation_ = PageOrientation::kOriginal;
Daniel Hosseinianbe882062021-04-22 01:22:3980 PageSpread page_spread_ = PageSpread::kOneUp;
K Mooneb9e0002019-08-06 19:25:3281 };
82
Lei Zhang4906c102019-08-06 00:28:0383 static const draw_utils::PageInsetSizes kSingleViewInsets;
84 static constexpr int32_t kBottomSeparator = 4;
85 static constexpr int32_t kHorizontalSeparator = 1;
86
K Moonbd80ce72019-07-26 19:27:5087 DocumentLayout();
88
K Mooneb9e0002019-08-06 19:25:3289 DocumentLayout(const DocumentLayout& other) = delete;
90 DocumentLayout& operator=(const DocumentLayout& other) = delete;
K Moonbd80ce72019-07-26 19:27:5091
92 ~DocumentLayout();
93
K Mooneb9e0002019-08-06 19:25:3294 // Returns the layout options.
95 const Options& options() const { return options_; }
K Moonbd80ce72019-07-26 19:27:5096
K Moon6d326b92019-09-19 22:42:0797 // Sets the layout options. If certain options with immediate effect change
98 // (such as the default page orientation), the layout will be marked dirty.
99 //
100 // TODO(kmoon): We shouldn't have layout options that take effect immediately.
101 void SetOptions(const Options& options);
102
103 // Returns true if the layout has been modified since the last call to
104 // clear_dirty(). The initial state is false (clean), which assumes
105 // appropriate default behavior for an initially empty layout.
106 bool dirty() const { return dirty_; }
107
108 // Clears the dirty() state of the layout. This should be called after any
109 // layout changes have been applied.
110 void clear_dirty() { dirty_ = false; }
K Moonbd80ce72019-07-26 19:27:50111
112 // Returns the layout's total size.
Ankit Kumar 🌪️e35101152020-07-30 09:57:59113 const gfx::Size& size() const { return size_; }
K Moonbd80ce72019-07-26 19:27:50114
K Moone4bd7522019-08-23 00:12:56115 size_t page_count() const { return page_layouts_.size(); }
Jeremy Chinsen08beb482019-08-07 01:58:54116
K Moonff7ec672019-08-14 19:19:56117 // Gets the layout rectangle for a page. Only valid after computing a layout.
Ankit Kumar 🌪️00798692020-08-26 22:57:14118 const gfx::Rect& page_rect(size_t page_index) const {
K Moonff7ec672019-08-14 19:19:56119 DCHECK_LT(page_index, page_count());
K Moone4bd7522019-08-23 00:12:56120 return page_layouts_[page_index].outer_rect;
121 }
122
123 // Gets the layout rectangle for a page's bounds (which excludes additional
124 // regions like page shadows). Only valid after computing a layout.
Ankit Kumar 🌪️00798692020-08-26 22:57:14125 const gfx::Rect& page_bounds_rect(size_t page_index) const {
K Moone4bd7522019-08-23 00:12:56126 DCHECK_LT(page_index, page_count());
127 return page_layouts_[page_index].inner_rect;
K Moonff7ec672019-08-14 19:19:56128 }
129
Daniel Hosseiniane257d962021-04-23 21:18:35130 // Computes the layout for a given list of `page_sizes` based on `options_`.
Daniel Hosseinianbcbedda2021-04-23 19:09:51131 void ComputeLayout(const std::vector<gfx::Size>& page_sizes);
Jeremy Chinsend6fd27ce2019-08-06 00:40:17132
K Moonbd80ce72019-07-26 19:27:50133 private:
K Moone4bd7522019-08-23 00:12:56134 // Layout of a single page.
135 struct PageLayout {
136 // Bounding rectangle for the page with decorations.
Ankit Kumar 🌪️00798692020-08-26 22:57:14137 gfx::Rect outer_rect;
K Moone4bd7522019-08-23 00:12:56138
139 // Bounding rectangle for the page without decorations.
Ankit Kumar 🌪️00798692020-08-26 22:57:14140 gfx::Rect inner_rect;
K Moone4bd7522019-08-23 00:12:56141 };
142
Daniel Hosseinianbcbedda2021-04-23 19:09:51143 // Helpers for ComputeLayout() handling different page spreads.
144 void ComputeOneUpLayout(const std::vector<gfx::Size>& page_sizes);
145 void ComputeTwoUpOddLayout(const std::vector<gfx::Size>& page_sizes);
146
Daniel Hosseiniane257d962021-04-23 21:18:35147 // Copies `source_rect` to `destination_rect`, setting `dirty_` to true if
148 // `destination_rect` is modified as a result.
Ankit Kumar 🌪️00798692020-08-26 22:57:14149 void CopyRectIfModified(const gfx::Rect& source_rect,
150 gfx::Rect& destination_rect);
K Moon6d326b92019-09-19 22:42:07151
K Mooneb9e0002019-08-06 19:25:32152 Options options_;
K Moonbd80ce72019-07-26 19:27:50153
K Moon6d326b92019-09-19 22:42:07154 // Indicates if the layout has changed in an externally-observable way,
Daniel Hosseiniane257d962021-04-23 21:18:35155 // usually as a result of calling `ComputeLayout()` with different inputs.
K Moon6d326b92019-09-19 22:42:07156 //
157 // Some operations that may trigger layout changes:
158 // * Changing page sizes
159 // * Adding or removing pages
160 // * Changing page orientations
161 bool dirty_ = false;
162
K Moonbd80ce72019-07-26 19:27:50163 // Layout's total size.
Ankit Kumar 🌪️e35101152020-07-30 09:57:59164 gfx::Size size_;
K Moonff7ec672019-08-14 19:19:56165
K Moone4bd7522019-08-23 00:12:56166 std::vector<PageLayout> page_layouts_;
K Moonbd80ce72019-07-26 19:27:50167};
168
169} // namespace chrome_pdf
170
171#endif // PDF_DOCUMENT_LAYOUT_H_