1// Copyright (c) 2011 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
5#include "printing/page_setup.h"
6
7#include <algorithm>
8
9#include "base/logging.h"
10
11namespace printing {
12
13PageMargins::PageMargins()
14    : header(0),
15      footer(0),
16      left(0),
17      right(0),
18      top(0),
19      bottom(0) {
20}
21
22void PageMargins::Clear() {
23  header = 0;
24  footer = 0;
25  left = 0;
26  right = 0;
27  top = 0;
28  bottom = 0;
29}
30
31bool PageMargins::Equals(const PageMargins& rhs) const {
32  return header == rhs.header &&
33      footer == rhs.footer &&
34      left == rhs.left &&
35      top == rhs.top &&
36      right == rhs.right &&
37      bottom == rhs.bottom;
38}
39
40PageSetup::PageSetup() {
41  Clear();
42}
43
44PageSetup::~PageSetup() {}
45
46void PageSetup::Clear() {
47  physical_size_.SetSize(0, 0);
48  printable_area_.SetRect(0, 0, 0, 0);
49  overlay_area_.SetRect(0, 0, 0, 0);
50  content_area_.SetRect(0, 0, 0, 0);
51  effective_margins_.Clear();
52  text_height_ = 0;
53  forced_margins_ = false;
54}
55
56bool PageSetup::Equals(const PageSetup& rhs) const {
57  return physical_size_ == rhs.physical_size_ &&
58      printable_area_ == rhs.printable_area_ &&
59      overlay_area_ == rhs.overlay_area_ &&
60      content_area_ == rhs.content_area_ &&
61      effective_margins_.Equals(rhs.effective_margins_) &&
62      requested_margins_.Equals(rhs.requested_margins_) &&
63      text_height_ == rhs.text_height_;
64}
65
66void PageSetup::Init(const gfx::Size& physical_size,
67                     const gfx::Rect& printable_area,
68                     int text_height) {
69  DCHECK_LE(printable_area.right(), physical_size.width());
70  // I've seen this assert triggers on Canon GP160PF PCL 5e and HP LaserJet 5.
71  // Since we don't know the dpi here, just disable the check.
72  // DCHECK_LE(printable_area.bottom(), physical_size.height());
73  DCHECK_GE(printable_area.x(), 0);
74  DCHECK_GE(printable_area.y(), 0);
75  DCHECK_GE(text_height, 0);
76  physical_size_ = physical_size;
77  printable_area_ = printable_area;
78  text_height_ = text_height;
79
80  SetRequestedMarginsAndCalculateSizes(requested_margins_);
81}
82
83void PageSetup::SetRequestedMargins(const PageMargins& requested_margins) {
84  forced_margins_ = false;
85  SetRequestedMarginsAndCalculateSizes(requested_margins);
86}
87
88void PageSetup::ForceRequestedMargins(const PageMargins& requested_margins) {
89  forced_margins_ = true;
90  SetRequestedMarginsAndCalculateSizes(requested_margins);
91}
92
93void PageSetup::FlipOrientation() {
94  if (physical_size_.width() && physical_size_.height()) {
95    gfx::Size new_size(physical_size_.height(), physical_size_.width());
96    int new_y = physical_size_.width() -
97                (printable_area_.width() + printable_area_.x());
98    gfx::Rect new_printable_area(printable_area_.y(),
99                                 new_y,
100                                 printable_area_.height(),
101                                 printable_area_.width());
102    Init(new_size, new_printable_area, text_height_);
103  }
104}
105
106void PageSetup::SetRequestedMarginsAndCalculateSizes(
107    const PageMargins& requested_margins) {
108  requested_margins_ = requested_margins;
109  if (physical_size_.width() && physical_size_.height()) {
110    if (forced_margins_)
111      CalculateSizesWithinRect(gfx::Rect(physical_size_), 0);
112    else
113      CalculateSizesWithinRect(printable_area_, text_height_);
114  }
115}
116
117void PageSetup::CalculateSizesWithinRect(const gfx::Rect& bounds,
118                                         int text_height) {
119  // Calculate the effective margins. The tricky part.
120  effective_margins_.header = std::max(requested_margins_.header,
121                                       bounds.y());
122  effective_margins_.footer = std::max(requested_margins_.footer,
123                                       physical_size_.height() -
124                                           bounds.bottom());
125  effective_margins_.left = std::max(requested_margins_.left,
126                                     bounds.x());
127  effective_margins_.top = std::max(std::max(requested_margins_.top,
128                                             bounds.y()),
129                                    effective_margins_.header + text_height);
130  effective_margins_.right = std::max(requested_margins_.right,
131                                      physical_size_.width() -
132                                          bounds.right());
133  effective_margins_.bottom =
134      std::max(std::max(requested_margins_.bottom,
135                        physical_size_.height() - bounds.bottom()),
136               effective_margins_.footer + text_height);
137
138  // Calculate the overlay area. If the margins are excessive, the overlay_area
139  // size will be (0, 0).
140  overlay_area_.set_x(effective_margins_.left);
141  overlay_area_.set_y(effective_margins_.header);
142  overlay_area_.set_width(std::max(0,
143                                   physical_size_.width() -
144                                       effective_margins_.right -
145                                       overlay_area_.x()));
146  overlay_area_.set_height(std::max(0,
147                                    physical_size_.height() -
148                                        effective_margins_.footer -
149                                        overlay_area_.y()));
150
151  // Calculate the content area. If the margins are excessive, the content_area
152  // size will be (0, 0).
153  content_area_.set_x(effective_margins_.left);
154  content_area_.set_y(effective_margins_.top);
155  content_area_.set_width(std::max(0,
156                                   physical_size_.width() -
157                                       effective_margins_.right -
158                                       content_area_.x()));
159  content_area_.set_height(std::max(0,
160                                    physical_size_.height() -
161                                        effective_margins_.bottom -
162                                        content_area_.y()));
163}
164
165}  // namespace printing
166