Home | History | Annotate | Download | only in printing
      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 
     11 namespace printing {
     12 
     13 PageMargins::PageMargins()
     14     : header(0),
     15       footer(0),
     16       left(0),
     17       right(0),
     18       top(0),
     19       bottom(0) {
     20 }
     21 
     22 void PageMargins::Clear() {
     23   header = 0;
     24   footer = 0;
     25   left = 0;
     26   right = 0;
     27   top = 0;
     28   bottom = 0;
     29 }
     30 
     31 bool 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 
     40 PageSetup::PageSetup() {
     41   Clear();
     42 }
     43 
     44 PageSetup::~PageSetup() {}
     45 
     46 void 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 
     56 bool 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 
     66 void 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 
     83 void PageSetup::SetRequestedMargins(const PageMargins& requested_margins) {
     84   forced_margins_ = false;
     85   SetRequestedMarginsAndCalculateSizes(requested_margins);
     86 }
     87 
     88 void PageSetup::ForceRequestedMargins(const PageMargins& requested_margins) {
     89   forced_margins_ = true;
     90   SetRequestedMarginsAndCalculateSizes(requested_margins);
     91 }
     92 
     93 void 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 
    106 void 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 
    117 void 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