123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "pdf/document_layout.h"
- #include <algorithm>
- #include "base/check_op.h"
- #include "base/values.h"
- #include "ui/gfx/geometry/point.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size.h"
- namespace chrome_pdf {
- namespace {
- constexpr char kDirection[] = "direction";
- constexpr char kDefaultPageOrientation[] = "defaultPageOrientation";
- constexpr char kTwoUpViewEnabled[] = "twoUpViewEnabled";
- int GetWidestPageWidth(const std::vector<gfx::Size>& page_sizes) {
- int widest_page_width = 0;
- for (const auto& page_size : page_sizes) {
- widest_page_width = std::max(widest_page_width, page_size.width());
- }
- return widest_page_width;
- }
- gfx::Rect InsetRect(const gfx::Rect& rect,
- const draw_utils::PageInsetSizes& inset_sizes) {
- gfx::Rect inset_rect(rect);
- inset_rect.Inset(gfx::Insets::TLBR(inset_sizes.top, inset_sizes.left,
- inset_sizes.bottom, inset_sizes.right));
- return inset_rect;
- }
- } // namespace
- const draw_utils::PageInsetSizes DocumentLayout::kSingleViewInsets{
- /*left=*/5, /*top=*/3, /*right=*/5, /*bottom=*/7};
- DocumentLayout::Options::Options() = default;
- DocumentLayout::Options::Options(const Options& other) = default;
- DocumentLayout::Options& DocumentLayout::Options::operator=(
- const Options& other) = default;
- DocumentLayout::Options::~Options() = default;
- base::Value::Dict DocumentLayout::Options::ToValue() const {
- base::Value::Dict dictionary;
- dictionary.Set(kDirection, direction_);
- dictionary.Set(kDefaultPageOrientation,
- static_cast<int>(default_page_orientation_));
- dictionary.Set(kTwoUpViewEnabled, page_spread_ == PageSpread::kTwoUpOdd);
- return dictionary;
- }
- void DocumentLayout::Options::FromValue(const base::Value::Dict& value) {
- int32_t direction = value.FindInt(kDirection).value();
- DCHECK_GE(direction, base::i18n::UNKNOWN_DIRECTION);
- DCHECK_LE(direction, base::i18n::TEXT_DIRECTION_MAX);
- direction_ = static_cast<base::i18n::TextDirection>(direction);
- int32_t default_page_orientation =
- value.FindInt(kDefaultPageOrientation).value();
- DCHECK_GE(default_page_orientation,
- static_cast<int32_t>(PageOrientation::kOriginal));
- DCHECK_LE(default_page_orientation,
- static_cast<int32_t>(PageOrientation::kLast));
- default_page_orientation_ =
- static_cast<PageOrientation>(default_page_orientation);
- page_spread_ = value.FindBool(kTwoUpViewEnabled).value()
- ? PageSpread::kTwoUpOdd
- : PageSpread::kOneUp;
- }
- void DocumentLayout::Options::RotatePagesClockwise() {
- default_page_orientation_ = RotateClockwise(default_page_orientation_);
- }
- void DocumentLayout::Options::RotatePagesCounterclockwise() {
- default_page_orientation_ = RotateCounterclockwise(default_page_orientation_);
- }
- DocumentLayout::DocumentLayout() = default;
- DocumentLayout::~DocumentLayout() = default;
- void DocumentLayout::SetOptions(const Options& options) {
- // To be conservative, we want to consider the layout dirty for any layout
- // option changes, even if the page rects don't necessarily change when
- // layout options change.
- //
- // We also probably don't want layout changes to actually kick in until
- // the next call to ComputeLayout(). (In practice, we'll call ComputeLayout()
- // shortly after calling SetOptions().)
- if (options_ != options) {
- dirty_ = true;
- }
- options_ = options;
- }
- void DocumentLayout::ComputeLayout(const std::vector<gfx::Size>& page_sizes) {
- switch (options_.page_spread()) {
- case PageSpread::kOneUp:
- return ComputeOneUpLayout(page_sizes);
- case PageSpread::kTwoUpOdd:
- return ComputeTwoUpOddLayout(page_sizes);
- }
- }
- void DocumentLayout::ComputeOneUpLayout(
- const std::vector<gfx::Size>& page_sizes) {
- gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);
- if (page_layouts_.size() != page_sizes.size()) {
- // TODO(kmoon): May want to do less work when shrinking a layout.
- page_layouts_.resize(page_sizes.size());
- dirty_ = true;
- }
- for (size_t i = 0; i < page_sizes.size(); ++i) {
- if (i != 0) {
- // Add space for bottom separator.
- document_size.Enlarge(0, kBottomSeparator);
- }
- const gfx::Size& page_size = page_sizes[i];
- gfx::Rect page_rect =
- draw_utils::GetRectForSingleView(page_size, document_size);
- CopyRectIfModified(page_rect, page_layouts_[i].outer_rect);
- CopyRectIfModified(InsetRect(page_rect, kSingleViewInsets),
- page_layouts_[i].inner_rect);
- draw_utils::ExpandDocumentSize(page_size, &document_size);
- }
- if (size_ != document_size) {
- size_ = document_size;
- dirty_ = true;
- }
- }
- void DocumentLayout::ComputeTwoUpOddLayout(
- const std::vector<gfx::Size>& page_sizes) {
- gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);
- if (page_layouts_.size() != page_sizes.size()) {
- // TODO(kmoon): May want to do less work when shrinking a layout.
- page_layouts_.resize(page_sizes.size());
- dirty_ = true;
- }
- for (size_t i = 0; i < page_sizes.size(); ++i) {
- draw_utils::PageInsetSizes page_insets =
- draw_utils::GetPageInsetsForTwoUpView(
- i, page_sizes.size(), kSingleViewInsets, kHorizontalSeparator);
- const gfx::Size& page_size = page_sizes[i];
- gfx::Rect page_rect;
- if (i % 2 == 0) {
- page_rect = draw_utils::GetLeftRectForTwoUpView(
- page_size, {document_size.width(), document_size.height()});
- } else {
- page_rect = draw_utils::GetRightRectForTwoUpView(
- page_size, {document_size.width(), document_size.height()});
- document_size.Enlarge(
- 0, std::max(page_size.height(), page_sizes[i - 1].height()));
- }
- CopyRectIfModified(page_rect, page_layouts_[i].outer_rect);
- CopyRectIfModified(InsetRect(page_rect, page_insets),
- page_layouts_[i].inner_rect);
- }
- if (page_sizes.size() % 2 == 1) {
- document_size.Enlarge(0, page_sizes.back().height());
- }
- document_size.set_width(2 * document_size.width());
- if (size_ != document_size) {
- size_ = document_size;
- dirty_ = true;
- }
- }
- void DocumentLayout::CopyRectIfModified(const gfx::Rect& source_rect,
- gfx::Rect& destination_rect) {
- if (destination_rect != source_rect) {
- destination_rect = source_rect;
- dirty_ = true;
- }
- }
- } // namespace chrome_pdf
|