pdf_transform.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2015 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. #include "pdf/pdf_transform.h"
  5. #include <algorithm>
  6. #include <utility>
  7. #include "base/notreached.h"
  8. #include "ui/gfx/geometry/point_f.h"
  9. #include "ui/gfx/geometry/rect.h"
  10. #include "ui/gfx/geometry/size_f.h"
  11. namespace chrome_pdf {
  12. namespace {
  13. // When a PdfRectangle has top < bottom, or right < left, the values should be
  14. // swapped.
  15. void SwapPdfRectangleValuesIfNeeded(PdfRectangle* rect) {
  16. if (rect->top < rect->bottom)
  17. std::swap(rect->top, rect->bottom);
  18. if (rect->right < rect->left)
  19. std::swap(rect->right, rect->left);
  20. }
  21. } // namespace
  22. float CalculateScaleFactor(const gfx::Rect& content_rect,
  23. const gfx::SizeF& src_size,
  24. bool rotated) {
  25. if (src_size.IsEmpty())
  26. return 1.0f;
  27. float actual_source_page_width =
  28. rotated ? src_size.height() : src_size.width();
  29. float actual_source_page_height =
  30. rotated ? src_size.width() : src_size.height();
  31. float ratio_x = content_rect.width() / actual_source_page_width;
  32. float ratio_y = content_rect.height() / actual_source_page_height;
  33. return std::min(ratio_x, ratio_y);
  34. }
  35. void SetDefaultClipBox(bool rotated, PdfRectangle* clip_box) {
  36. constexpr int kDpi = 72;
  37. constexpr float kPaperWidth = 8.5 * kDpi;
  38. constexpr float kPaperHeight = 11 * kDpi;
  39. clip_box->left = 0;
  40. clip_box->bottom = 0;
  41. clip_box->right = rotated ? kPaperHeight : kPaperWidth;
  42. clip_box->top = rotated ? kPaperWidth : kPaperHeight;
  43. }
  44. void CalculateMediaBoxAndCropBox(bool rotated,
  45. bool has_media_box,
  46. bool has_crop_box,
  47. PdfRectangle* media_box,
  48. PdfRectangle* crop_box) {
  49. if (has_media_box)
  50. SwapPdfRectangleValuesIfNeeded(media_box);
  51. if (has_crop_box)
  52. SwapPdfRectangleValuesIfNeeded(crop_box);
  53. if (!has_media_box && !has_crop_box) {
  54. SetDefaultClipBox(rotated, crop_box);
  55. SetDefaultClipBox(rotated, media_box);
  56. } else if (has_crop_box && !has_media_box) {
  57. *media_box = *crop_box;
  58. } else if (has_media_box && !has_crop_box) {
  59. *crop_box = *media_box;
  60. }
  61. }
  62. PdfRectangle CalculateClipBoxBoundary(const PdfRectangle& media_box,
  63. const PdfRectangle& crop_box) {
  64. PdfRectangle clip_box;
  65. // Clip `media_box` to the size of `crop_box`, but ignore `crop_box` if it is
  66. // bigger than `media_box`.
  67. clip_box.left = std::max(crop_box.left, media_box.left);
  68. clip_box.bottom = std::max(crop_box.bottom, media_box.bottom);
  69. clip_box.right = std::min(crop_box.right, media_box.right);
  70. clip_box.top = std::min(crop_box.top, media_box.top);
  71. return clip_box;
  72. }
  73. void ScalePdfRectangle(float scale_factor, PdfRectangle* rect) {
  74. rect->left *= scale_factor;
  75. rect->bottom *= scale_factor;
  76. rect->right *= scale_factor;
  77. rect->top *= scale_factor;
  78. }
  79. gfx::PointF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect,
  80. const PdfRectangle& source_clip_box) {
  81. const float clip_box_width = source_clip_box.right - source_clip_box.left;
  82. const float clip_box_height = source_clip_box.top - source_clip_box.bottom;
  83. // Center the intended clip region to real clip region.
  84. return gfx::PointF((content_rect.width() - clip_box_width) / 2 +
  85. content_rect.x() - source_clip_box.left,
  86. (content_rect.height() - clip_box_height) / 2 +
  87. content_rect.y() - source_clip_box.bottom);
  88. }
  89. gfx::PointF CalculateNonScaledClipBoxOffset(
  90. int rotation,
  91. int page_width,
  92. int page_height,
  93. const PdfRectangle& source_clip_box) {
  94. // Align the intended clip region to left-top corner of real clip region.
  95. switch (rotation) {
  96. case 0:
  97. return gfx::PointF(-1 * source_clip_box.left,
  98. page_height - source_clip_box.top);
  99. case 1:
  100. return gfx::PointF(0, -1 * source_clip_box.bottom);
  101. case 2:
  102. return gfx::PointF(page_width - source_clip_box.right, 0);
  103. case 3:
  104. return gfx::PointF(page_height - source_clip_box.right,
  105. page_width - source_clip_box.top);
  106. default:
  107. NOTREACHED();
  108. return gfx::PointF();
  109. }
  110. }
  111. } // namespace chrome_pdf