blob: 3161cee1c28a53888f6dd1a434dfcd1a23f2c8be [file] [log] [blame]
// 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/draw_utils/coordinates.h"
#include <math.h>
#include <algorithm>
#include "base/check_op.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
namespace chrome_pdf {
namespace draw_utils {
IndexedPage::IndexedPage(int index, const gfx::Rect& rect)
: index(index), rect(rect) {}
IndexedPage::IndexedPage(const IndexedPage& other) = default;
IndexedPage& IndexedPage::operator=(const IndexedPage& other) = default;
IndexedPage::~IndexedPage() = default;
void AdjustBottomGapForRightSidePage(int page_x, gfx::Rect* bottom_gap) {
bottom_gap->set_x(page_x);
bottom_gap->set_width(bottom_gap->width() / 2);
}
void CenterRectHorizontally(int doc_width, gfx::Rect* rect) {
DCHECK_GE(doc_width, rect->width());
rect->set_x((doc_width - rect->width()) / 2);
}
void ExpandDocumentSize(const gfx::Size& rect_size, gfx::Size* doc_size) {
int width_diff = std::max(0, rect_size.width() - doc_size->width());
doc_size->Enlarge(width_diff, rect_size.height());
}
gfx::Rect GetBottomGapBetweenRects(int page_rect_bottom,
const gfx::Rect& bottom_rect) {
if (page_rect_bottom >= bottom_rect.bottom())
return gfx::Rect(0, 0, 0, 0);
return gfx::Rect(bottom_rect.x(), page_rect_bottom, bottom_rect.width(),
bottom_rect.bottom() - page_rect_bottom);
}
int GetMostVisiblePage(const std::vector<IndexedPage>& visible_pages,
const gfx::Rect& visible_screen) {
if (visible_pages.empty())
return -1;
int most_visible_page_index = visible_pages.front().index;
float most_visible_page_area = 0;
for (const auto& visible_page : visible_pages) {
float page_area = gfx::SizeF(visible_page.rect.size()).GetArea();
// TODO(thestig): Check whether we can remove this check.
if (page_area <= 0)
continue;
gfx::Rect screen_intersect =
gfx::IntersectRects(visible_screen, visible_page.rect);
float intersect_area =
gfx::SizeF(screen_intersect.size()).GetArea() / page_area;
if (intersect_area > most_visible_page_area) {
most_visible_page_index = visible_page.index;
most_visible_page_area = intersect_area;
}
}
return most_visible_page_index;
}
PageInsetSizes GetPageInsetsForTwoUpView(
size_t page_index,
size_t num_of_pages,
const PageInsetSizes& single_view_insets,
int horizontal_separator) {
DCHECK_LT(page_index, num_of_pages);
// Don't change `two_up_insets` if the page is on the left side and is the
// last page. In this case, the shadows on both sides should be the same size.
PageInsetSizes two_up_insets = single_view_insets;
if (page_index % 2 == 1)
two_up_insets.left = horizontal_separator;
else if (page_index != num_of_pages - 1)
two_up_insets.right = horizontal_separator;
return two_up_insets;
}
gfx::Rect GetRectForSingleView(const gfx::Size& rect_size,
const gfx::Size& document_size) {
gfx::Rect page_rect({0, document_size.height()}, rect_size);
CenterRectHorizontally(document_size.width(), &page_rect);
return page_rect;
}
gfx::Rect GetScreenRect(const gfx::Rect& rect,
const gfx::Point& position,
double zoom) {
DCHECK_GT(zoom, 0);
int x = static_cast<int>(rect.x() * zoom - position.x());
int y = static_cast<int>(rect.y() * zoom - position.y());
int right = static_cast<int>(ceil(rect.right() * zoom - position.x()));
int bottom = static_cast<int>(ceil(rect.bottom() * zoom - position.y()));
return gfx::Rect(x, y, right - x, bottom - y);
}
gfx::Rect GetSurroundingRect(int page_y,
int page_height,
const PageInsetSizes& inset_sizes,
int doc_width,
int bottom_separator) {
return gfx::Rect(
0, page_y - inset_sizes.top, doc_width,
page_height + inset_sizes.top + inset_sizes.bottom + bottom_separator);
}
gfx::Rect GetLeftFillRect(const gfx::Rect& page_rect,
const PageInsetSizes& inset_sizes,
int bottom_separator) {
DCHECK_GE(page_rect.x(), inset_sizes.left);
return gfx::Rect(0, page_rect.y() - inset_sizes.top,
page_rect.x() - inset_sizes.left,
page_rect.height() + inset_sizes.top + inset_sizes.bottom +
bottom_separator);
}
gfx::Rect GetRightFillRect(const gfx::Rect& page_rect,
const PageInsetSizes& inset_sizes,
int doc_width,
int bottom_separator) {
int right_gap_x = page_rect.right() + inset_sizes.right;
DCHECK_GE(doc_width, right_gap_x);
return gfx::Rect(right_gap_x, page_rect.y() - inset_sizes.top,
doc_width - right_gap_x,
page_rect.height() + inset_sizes.top + inset_sizes.bottom +
bottom_separator);
}
gfx::Rect GetBottomFillRect(const gfx::Rect& page_rect,
const PageInsetSizes& inset_sizes,
int bottom_separator) {
return gfx::Rect(page_rect.x() - inset_sizes.left,
page_rect.bottom() + inset_sizes.bottom,
page_rect.width() + inset_sizes.left + inset_sizes.right,
bottom_separator);
}
gfx::Rect GetLeftRectForTwoUpView(const gfx::Size& rect_size,
const gfx::Point& position) {
DCHECK_LE(rect_size.width(), position.x());
return gfx::Rect(position.x() - rect_size.width(), position.y(),
rect_size.width(), rect_size.height());
}
gfx::Rect GetRightRectForTwoUpView(const gfx::Size& rect_size,
const gfx::Point& position) {
return gfx::Rect(position, rect_size);
}
} // namespace draw_utils
} // namespace chrome_pdf