blob: 0acb36c44bc0119b69ad3121adf85b1db6802799 [file] [log] [blame]
// Copyright 2015 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/pdf_transform.h"
#include <algorithm>
#include <utility>
#include "base/logging.h"
#include "ui/gfx/geometry/rect.h"
namespace chrome_pdf {
namespace {
// When a PdfRectangle has top < bottom, or right < left, the values should be
// swapped.
void SwapPdfRectangleValuesIfNeeded(PdfRectangle* rect) {
if (rect->top < rect->bottom)
std::swap(rect->top, rect->bottom);
if (rect->right < rect->left)
std::swap(rect->right, rect->left);
}
} // namespace
double CalculateScaleFactor(const gfx::Rect& content_rect,
double src_width,
double src_height,
bool rotated) {
if (src_width == 0 || src_height == 0)
return 1.0;
double actual_source_page_width = rotated ? src_height : src_width;
double actual_source_page_height = rotated ? src_width : src_height;
double ratio_x =
static_cast<double>(content_rect.width()) / actual_source_page_width;
double ratio_y =
static_cast<double>(content_rect.height()) / actual_source_page_height;
return std::min(ratio_x, ratio_y);
}
void SetDefaultClipBox(bool rotated, PdfRectangle* clip_box) {
constexpr int kDpi = 72;
constexpr float kPaperWidth = 8.5 * kDpi;
constexpr float kPaperHeight = 11 * kDpi;
clip_box->left = 0;
clip_box->bottom = 0;
clip_box->right = rotated ? kPaperHeight : kPaperWidth;
clip_box->top = rotated ? kPaperWidth : kPaperHeight;
}
void CalculateMediaBoxAndCropBox(bool rotated,
bool has_media_box,
bool has_crop_box,
PdfRectangle* media_box,
PdfRectangle* crop_box) {
if (has_media_box)
SwapPdfRectangleValuesIfNeeded(media_box);
if (has_crop_box)
SwapPdfRectangleValuesIfNeeded(crop_box);
if (!has_media_box && !has_crop_box) {
SetDefaultClipBox(rotated, crop_box);
SetDefaultClipBox(rotated, media_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;
}
}
PdfRectangle CalculateClipBoxBoundary(const PdfRectangle& media_box,
const PdfRectangle& crop_box) {
PdfRectangle clip_box;
// Clip |media_box| to the size of |crop_box|, but ignore |crop_box| if it is
// bigger than |media_box|.
clip_box.left = std::max(crop_box.left, media_box.left);
clip_box.bottom = std::max(crop_box.bottom, media_box.bottom);
clip_box.right = std::min(crop_box.right, media_box.right);
clip_box.top = std::min(crop_box.top, media_box.top);
return clip_box;
}
void ScalePdfRectangle(double scale_factor, PdfRectangle* rect) {
rect->left *= scale_factor;
rect->bottom *= scale_factor;
rect->right *= scale_factor;
rect->top *= scale_factor;
}
void CalculateScaledClipBoxOffset(const gfx::Rect& content_rect,
const PdfRectangle& source_clip_box,
double* offset_x,
double* offset_y) {
const float clip_box_width = source_clip_box.right - source_clip_box.left;
const float clip_box_height = source_clip_box.top - source_clip_box.bottom;
// Center the intended clip region to real clip region.
*offset_x = (content_rect.width() - clip_box_width) / 2 + content_rect.x() -
source_clip_box.left;
*offset_y = (content_rect.height() - clip_box_height) / 2 + content_rect.y() -
source_clip_box.bottom;
}
void CalculateNonScaledClipBoxOffset(const gfx::Rect& content_rect,
int rotation,
int page_width,
int page_height,
const PdfRectangle& source_clip_box,
double* offset_x,
double* offset_y) {
// Align the intended clip region to left-top corner of real clip region.
switch (rotation) {
case 0:
*offset_x = -1 * source_clip_box.left;
*offset_y = page_height - source_clip_box.top;
break;
case 1:
*offset_x = 0;
*offset_y = -1 * source_clip_box.bottom;
break;
case 2:
*offset_x = page_width - source_clip_box.right;
*offset_y = 0;
break;
case 3:
*offset_x = page_height - source_clip_box.right;
*offset_y = page_width - source_clip_box.top;
break;
default:
NOTREACHED();
break;
}
}
} // namespace chrome_pdf