| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "pdf/pdf_transform.h" |
| |
| #include <algorithm> |
| |
| #include "base/notreached.h" |
| #include "pdf/pdf_rect.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size_f.h" |
| #include "ui/gfx/geometry/vector2d_f.h" |
| |
| namespace chrome_pdf { |
| |
| namespace { |
| |
| // Return the default size letter size (8.5" X 11") clip box. This just follows |
| // the PDFium way of handling these corner cases. PDFium always considers |
| // US-Letter as the default page size. |
| PdfRect GetDefaultClipBox(bool rotated) { |
| constexpr int kDpi = 72; |
| constexpr float kPaperWidth = 8.5 * kDpi; |
| constexpr float kPaperHeight = 11 * kDpi; |
| return PdfRect(/*left=*/0, /*bottom=*/0, |
| /*right=*/rotated ? kPaperHeight : kPaperWidth, |
| /*top=*/rotated ? kPaperWidth : kPaperHeight); |
| } |
| |
| } // namespace |
| |
| float CalculateScaleFactor(const gfx::Rect& content_rect, |
| const gfx::SizeF& src_size, |
| bool rotated) { |
| if (src_size.IsEmpty()) |
| return 1.0f; |
| |
| float actual_source_page_width = |
| rotated ? src_size.height() : src_size.width(); |
| float actual_source_page_height = |
| rotated ? src_size.width() : src_size.height(); |
| float ratio_x = content_rect.width() / actual_source_page_width; |
| float ratio_y = content_rect.height() / actual_source_page_height; |
| return std::min(ratio_x, ratio_y); |
| } |
| |
| void CalculateMediaBoxAndCropBox(bool rotated, |
| bool has_media_box, |
| bool has_crop_box, |
| PdfRect* media_box, |
| PdfRect* crop_box) { |
| if (has_media_box) |
| media_box->Normalize(); |
| if (has_crop_box) |
| crop_box->Normalize(); |
| |
| if (!has_media_box && !has_crop_box) { |
| *crop_box = GetDefaultClipBox(rotated); |
| *media_box = *crop_box; |
| } else if (has_crop_box && !has_media_box) { |
| *media_box = *crop_box; |
| } else if (has_media_box && !has_crop_box) { |
| *crop_box = *media_box; |
| } |
| } |
| |
| PdfRect CalculateClipBoxBoundary(const PdfRect& media_box, |
| const PdfRect& crop_box) { |
| // Clip `media_box` to the size of `crop_box`, but ignore `crop_box` if it is |
| // bigger than `media_box`. |
| PdfRect clip_box = crop_box; |
| clip_box.Intersect(media_box); |
| return clip_box; |
| } |
| |
| gfx::Vector2dF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect, |
| const PdfRect& source_clip_box) { |
| // Center the intended clip region to real clip region. |
| return gfx::Vector2dF((content_rect.width() - source_clip_box.width()) / 2 + |
| content_rect.x() - source_clip_box.left(), |
| (content_rect.height() - source_clip_box.height()) / 2 + |
| content_rect.y() - source_clip_box.bottom()); |
| } |
| |
| gfx::Vector2dF CalculateNonScaledClipBoxOffset(int rotation, |
| int page_width, |
| int page_height, |
| const PdfRect& source_clip_box) { |
| // Align the intended clip region to left-top corner of real clip region. |
| switch (rotation) { |
| case 0: |
| return gfx::Vector2dF(-1 * source_clip_box.left(), |
| page_height - source_clip_box.top()); |
| case 1: |
| return gfx::Vector2dF(0, -1 * source_clip_box.bottom()); |
| case 2: |
| return gfx::Vector2dF(page_width - source_clip_box.right(), 0); |
| case 3: |
| return gfx::Vector2dF(page_height - source_clip_box.right(), |
| page_width - source_clip_box.top()); |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| } // namespace chrome_pdf |