Avi Drissman | db497b3 | 2022-09-15 19:47:28 | [diff] [blame] | 1 | // Copyright 2011 The Chromium Authors |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
sverrir@google.com | 8ff1d42 | 2009-07-07 21:31:39 | [diff] [blame] | 5 | #include "printing/page_setup.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 6 | |
thestig@chromium.org | c48bee2 | 2011-03-29 02:36:26 | [diff] [blame] | 7 | #include <algorithm> |
Peter Kasting | 70a70cc | 2023-05-12 17:53:17 | [diff] [blame] | 8 | #include <tuple> |
thestig@chromium.org | c48bee2 | 2011-03-29 02:36:26 | [diff] [blame] | 9 | |
Hans Wennborg | e0d04ff2 | 2020-04-24 20:17:55 | [diff] [blame] | 10 | #include "base/check_op.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 11 | |
| 12 | namespace printing { |
| 13 | |
Lei Zhang | 3d64dc6 | 2018-09-28 17:08:36 | [diff] [blame] | 14 | namespace { |
| 15 | |
Daniel Hosseinian | 3553e27 | 2021-04-24 00:51:18 | [diff] [blame] | 16 | // Checks whether `printable_area` can be used to form a valid symmetrical |
Lei Zhang | 3d64dc6 | 2018-09-28 17:08:36 | [diff] [blame] | 17 | // printable area, so that margin_left equals margin_right, and margin_top |
| 18 | // equals margin_bottom. For example if |
| 19 | // printable_area.x() * 2 >= page_size.width(), then the |
| 20 | // content_width = page_size.width() - 2 * printable_area.x() would be zero or |
| 21 | // negative, which is invalid. |
Daniel Hosseinian | 3553e27 | 2021-04-24 00:51:18 | [diff] [blame] | 22 | // `page_size` is the physical page size that includes margins. |
Lei Zhang | 3d64dc6 | 2018-09-28 17:08:36 | [diff] [blame] | 23 | bool IsValidPrintableArea(const gfx::Size& page_size, |
| 24 | const gfx::Rect& printable_area) { |
| 25 | return !printable_area.IsEmpty() && printable_area.x() >= 0 && |
| 26 | printable_area.y() >= 0 && |
| 27 | printable_area.right() <= page_size.width() && |
| 28 | printable_area.bottom() <= page_size.height() && |
| 29 | printable_area.x() * 2 < page_size.width() && |
| 30 | printable_area.y() * 2 < page_size.height() && |
| 31 | printable_area.right() * 2 > page_size.width() && |
| 32 | printable_area.bottom() * 2 > page_size.height(); |
| 33 | } |
| 34 | |
| 35 | } // namespace |
| 36 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 37 | PageMargins::PageMargins() |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 38 | : header(0), footer(0), left(0), right(0), top(0), bottom(0) {} |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 39 | |
Alan Screen | c568a1ad | 2021-07-30 16:00:56 | [diff] [blame] | 40 | PageMargins::PageMargins(int header, |
| 41 | int footer, |
| 42 | int left, |
| 43 | int right, |
| 44 | int top, |
| 45 | int bottom) |
| 46 | : header(header), |
| 47 | footer(footer), |
| 48 | left(left), |
| 49 | right(right), |
| 50 | top(top), |
| 51 | bottom(bottom) {} |
| 52 | |
Peter Kasting | 70a70cc | 2023-05-12 17:53:17 | [diff] [blame] | 53 | bool PageMargins::operator==(const PageMargins& other) const { |
| 54 | return std::tie(header, footer, left, right, top, bottom) == |
| 55 | std::tie(other.header, other.footer, other.left, other.right, |
| 56 | other.top, other.bottom); |
| 57 | } |
Alan Screen | b411fe6 | 2023-02-16 18:53:20 | [diff] [blame] | 58 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 59 | void PageMargins::Clear() { |
| 60 | header = 0; |
| 61 | footer = 0; |
| 62 | left = 0; |
| 63 | right = 0; |
| 64 | top = 0; |
| 65 | bottom = 0; |
| 66 | } |
| 67 | |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 68 | PageSetup::PageSetup() { |
| 69 | Clear(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 70 | } |
| 71 | |
Alan Screen | 535f4d9 | 2021-07-30 21:23:59 | [diff] [blame] | 72 | PageSetup::PageSetup(const gfx::Size& physical_size, |
| 73 | const gfx::Rect& printable_area, |
| 74 | const PageMargins& requested_margins, |
| 75 | bool forced_margins, |
| 76 | int text_height) |
| 77 | : requested_margins_(requested_margins), forced_margins_(forced_margins) { |
| 78 | Init(physical_size, printable_area, text_height); |
| 79 | } |
| 80 | |
vmpstr | 04b8358f | 2016-02-26 01:38:29 | [diff] [blame] | 81 | PageSetup::PageSetup(const PageSetup& other) = default; |
| 82 | |
Chris Watkins | c360b97 | 2017-12-01 05:50:23 | [diff] [blame] | 83 | PageSetup::~PageSetup() = default; |
erg@google.com | d2f05d0 | 2011-01-27 18:51:01 | [diff] [blame] | 84 | |
Peter Kasting | 70a70cc | 2023-05-12 17:53:17 | [diff] [blame] | 85 | bool PageSetup::operator==(const PageSetup& other) const { |
| 86 | return std::tie(physical_size_, printable_area_, overlay_area_, content_area_, |
| 87 | effective_margins_, requested_margins_, forced_margins_, |
| 88 | text_height_) == |
| 89 | std::tie(other.physical_size_, other.printable_area_, |
| 90 | other.overlay_area_, other.content_area_, |
| 91 | other.effective_margins_, other.requested_margins_, |
| 92 | other.forced_margins_, other.text_height_); |
| 93 | } |
Alan Screen | b411fe6 | 2023-02-16 18:53:20 | [diff] [blame] | 94 | |
Lei Zhang | 3d64dc6 | 2018-09-28 17:08:36 | [diff] [blame] | 95 | // static |
| 96 | gfx::Rect PageSetup::GetSymmetricalPrintableArea( |
| 97 | const gfx::Size& page_size, |
| 98 | const gfx::Rect& printable_area) { |
| 99 | if (!IsValidPrintableArea(page_size, printable_area)) |
| 100 | return gfx::Rect(); |
| 101 | |
| 102 | int left_right_margin = |
| 103 | std::max(printable_area.x(), page_size.width() - printable_area.right()); |
| 104 | int top_bottom_margin = std::max( |
| 105 | printable_area.y(), page_size.height() - printable_area.bottom()); |
| 106 | int width = page_size.width() - 2 * left_right_margin; |
| 107 | int height = page_size.height() - 2 * top_bottom_margin; |
| 108 | |
| 109 | gfx::Rect symmetrical_printable_area = gfx::Rect(page_size); |
| 110 | symmetrical_printable_area.ClampToCenteredSize(gfx::Size(width, height)); |
| 111 | |
| 112 | return symmetrical_printable_area; |
| 113 | } |
| 114 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 115 | void PageSetup::Clear() { |
| 116 | physical_size_.SetSize(0, 0); |
| 117 | printable_area_.SetRect(0, 0, 0, 0); |
| 118 | overlay_area_.SetRect(0, 0, 0, 0); |
| 119 | content_area_.SetRect(0, 0, 0, 0); |
| 120 | effective_margins_.Clear(); |
| 121 | text_height_ = 0; |
kmadhusu@chromium.org | b89615d | 2011-11-04 00:29:21 | [diff] [blame] | 122 | forced_margins_ = false; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 123 | } |
| 124 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 125 | void PageSetup::Init(const gfx::Size& physical_size, |
| 126 | const gfx::Rect& printable_area, |
| 127 | int text_height) { |
| 128 | DCHECK_LE(printable_area.right(), physical_size.width()); |
maruel@google.com | 8ecd00f | 2008-08-14 21:16:24 | [diff] [blame] | 129 | // I've seen this assert triggers on Canon GP160PF PCL 5e and HP LaserJet 5. |
| 130 | // Since we don't know the dpi here, just disable the check. |
| 131 | // DCHECK_LE(printable_area.bottom(), physical_size.height()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 132 | DCHECK_GE(printable_area.x(), 0); |
| 133 | DCHECK_GE(printable_area.y(), 0); |
| 134 | DCHECK_GE(text_height, 0); |
| 135 | physical_size_ = physical_size; |
| 136 | printable_area_ = printable_area; |
| 137 | text_height_ = text_height; |
| 138 | |
kmadhusu@chromium.org | b89615d | 2011-11-04 00:29:21 | [diff] [blame] | 139 | SetRequestedMarginsAndCalculateSizes(requested_margins_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | void PageSetup::SetRequestedMargins(const PageMargins& requested_margins) { |
kmadhusu@chromium.org | b89615d | 2011-11-04 00:29:21 | [diff] [blame] | 143 | forced_margins_ = false; |
| 144 | SetRequestedMarginsAndCalculateSizes(requested_margins); |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | void PageSetup::ForceRequestedMargins(const PageMargins& requested_margins) { |
kmadhusu@chromium.org | b89615d | 2011-11-04 00:29:21 | [diff] [blame] | 148 | forced_margins_ = true; |
| 149 | SetRequestedMarginsAndCalculateSizes(requested_margins); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 150 | } |
| 151 | |
thestig@chromium.org | c48bee2 | 2011-03-29 02:36:26 | [diff] [blame] | 152 | void PageSetup::FlipOrientation() { |
| 153 | if (physical_size_.width() && physical_size_.height()) { |
| 154 | gfx::Size new_size(physical_size_.height(), physical_size_.width()); |
| 155 | int new_y = physical_size_.width() - |
| 156 | (printable_area_.width() + printable_area_.x()); |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 157 | gfx::Rect new_printable_area(printable_area_.y(), new_y, |
thestig@chromium.org | c48bee2 | 2011-03-29 02:36:26 | [diff] [blame] | 158 | printable_area_.height(), |
| 159 | printable_area_.width()); |
| 160 | Init(new_size, new_printable_area, text_height_); |
| 161 | } |
| 162 | } |
| 163 | |
kmadhusu@chromium.org | b89615d | 2011-11-04 00:29:21 | [diff] [blame] | 164 | void PageSetup::SetRequestedMarginsAndCalculateSizes( |
| 165 | const PageMargins& requested_margins) { |
| 166 | requested_margins_ = requested_margins; |
| 167 | if (physical_size_.width() && physical_size_.height()) { |
| 168 | if (forced_margins_) |
| 169 | CalculateSizesWithinRect(gfx::Rect(physical_size_), 0); |
| 170 | else |
| 171 | CalculateSizesWithinRect(printable_area_, text_height_); |
| 172 | } |
| 173 | } |
| 174 | |
vandebo@chromium.org | d69d322d | 2011-10-18 00:15:21 | [diff] [blame] | 175 | void PageSetup::CalculateSizesWithinRect(const gfx::Rect& bounds, |
| 176 | int text_height) { |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 177 | // Calculate the effective margins. The tricky part. |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 178 | effective_margins_.header = std::max(requested_margins_.header, bounds.y()); |
| 179 | effective_margins_.footer = std::max( |
| 180 | requested_margins_.footer, physical_size_.height() - bounds.bottom()); |
| 181 | effective_margins_.left = std::max(requested_margins_.left, bounds.x()); |
Peter Kasting | 14eab5c | 2019-09-12 18:18:27 | [diff] [blame] | 182 | effective_margins_.top = std::max({requested_margins_.top, bounds.y(), |
| 183 | effective_margins_.header + text_height}); |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 184 | effective_margins_.right = std::max(requested_margins_.right, |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 185 | physical_size_.width() - bounds.right()); |
Peter Kasting | 14eab5c | 2019-09-12 18:18:27 | [diff] [blame] | 186 | effective_margins_.bottom = std::max( |
| 187 | {requested_margins_.bottom, physical_size_.height() - bounds.bottom(), |
| 188 | effective_margins_.footer + text_height}); |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 189 | |
| 190 | // Calculate the overlay area. If the margins are excessive, the overlay_area |
| 191 | // size will be (0, 0). |
| 192 | overlay_area_.set_x(effective_margins_.left); |
| 193 | overlay_area_.set_y(effective_margins_.header); |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 194 | overlay_area_.set_width(std::max( |
| 195 | 0, |
| 196 | physical_size_.width() - effective_margins_.right - overlay_area_.x())); |
| 197 | overlay_area_.set_height(std::max( |
| 198 | 0, |
| 199 | physical_size_.height() - effective_margins_.footer - overlay_area_.y())); |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 200 | |
| 201 | // Calculate the content area. If the margins are excessive, the content_area |
| 202 | // size will be (0, 0). |
| 203 | content_area_.set_x(effective_margins_.left); |
| 204 | content_area_.set_y(effective_margins_.top); |
Lei Zhang | 01a1d3c | 2019-05-21 04:59:10 | [diff] [blame] | 205 | content_area_.set_width(std::max( |
| 206 | 0, |
| 207 | physical_size_.width() - effective_margins_.right - content_area_.x())); |
| 208 | content_area_.set_height(std::max( |
| 209 | 0, |
| 210 | physical_size_.height() - effective_margins_.bottom - content_area_.y())); |
vandebo@chromium.org | 1c23b4e | 2011-10-15 22:30:48 | [diff] [blame] | 211 | } |
| 212 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 213 | } // namespace printing |