initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 1 | // Copyright 2008, Google Inc. |
| 2 | // All rights reserved. |
| 3 | // |
| 4 | // Redistribution and use in source and binary forms, with or without |
| 5 | // modification, are permitted provided that the following conditions are |
| 6 | // met: |
| 7 | // |
| 8 | // * Redistributions of source code must retain the above copyright |
| 9 | // notice, this list of conditions and the following disclaimer. |
| 10 | // * Redistributions in binary form must reproduce the above |
| 11 | // copyright notice, this list of conditions and the following disclaimer |
| 12 | // in the documentation and/or other materials provided with the |
| 13 | // distribution. |
| 14 | // * Neither the name of Google Inc. nor the names of its |
| 15 | // contributors may be used to endorse or promote products derived from |
| 16 | // this software without specific prior written permission. |
| 17 | // |
| 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | |
| 30 | #include "chrome/browser/printing/print_settings.h" |
| 31 | |
[email protected] | d30e8e64 | 2008-08-06 12:05:24 | [diff] [blame^] | 32 | #include "base/atomic_sequence_num.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 33 | #include "base/logging.h" |
| 34 | #include "chrome/browser/printing/units.h" |
| 35 | #include "chrome/common/render_messages.h" |
| 36 | |
| 37 | namespace printing { |
| 38 | |
[email protected] | d30e8e64 | 2008-08-06 12:05:24 | [diff] [blame^] | 39 | // Global SequenceNumber used for generating unique cookie values. |
| 40 | static base::AtomicSequenceNumber cookie_seq; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 41 | |
| 42 | PrintSettings::PrintSettings() |
| 43 | : min_shrink(1.25), |
| 44 | max_shrink(2.0), |
| 45 | desired_dpi(72), |
| 46 | dpi_(0), |
| 47 | landscape_(false) { |
| 48 | } |
| 49 | |
| 50 | void PrintSettings::Clear() { |
| 51 | ranges.clear(); |
| 52 | min_shrink = 1.25; |
| 53 | max_shrink = 2.; |
| 54 | desired_dpi = 72; |
| 55 | printer_name_.clear(); |
| 56 | device_name_.clear(); |
| 57 | page_setup_cmm_.Clear(); |
| 58 | page_setup_pixels_.Clear(); |
| 59 | dpi_ = 0; |
| 60 | landscape_ = false; |
| 61 | } |
| 62 | |
| 63 | #ifdef WIN32 |
| 64 | void PrintSettings::Init(HDC hdc, |
| 65 | const DEVMODE& dev_mode, |
| 66 | const PageRanges& new_ranges, |
| 67 | const std::wstring& new_device_name) { |
| 68 | DCHECK(hdc); |
| 69 | printer_name_ = dev_mode.dmDeviceName; |
| 70 | device_name_ = new_device_name; |
| 71 | ranges = new_ranges; |
| 72 | landscape_ = dev_mode.dmOrientation == DMORIENT_LANDSCAPE; |
| 73 | |
| 74 | int old_dpi = dpi_; |
| 75 | dpi_ = GetDeviceCaps(hdc, LOGPIXELSX); |
| 76 | // No printer device is known to advertise different dpi in X and Y axis; even |
| 77 | // the fax device using the 200x100 dpi setting. It's ought to break so many |
| 78 | // applications that it's not even needed to care about. WebKit doesn't |
| 79 | // support different dpi settings in X and Y axis. |
| 80 | DCHECK_EQ(dpi_, GetDeviceCaps(hdc, LOGPIXELSY)); |
| 81 | |
| 82 | DCHECK_EQ(GetDeviceCaps(hdc, SCALINGFACTORX), 0); |
| 83 | DCHECK_EQ(GetDeviceCaps(hdc, SCALINGFACTORY), 0); |
| 84 | |
| 85 | // Initialize page_setup_pixels_. |
| 86 | gfx::Size physical_size_pixels(GetDeviceCaps(hdc, PHYSICALWIDTH), |
| 87 | GetDeviceCaps(hdc, PHYSICALHEIGHT)); |
| 88 | gfx::Rect printable_area_pixels(GetDeviceCaps(hdc, PHYSICALOFFSETX), |
| 89 | GetDeviceCaps(hdc, PHYSICALOFFSETY), |
| 90 | GetDeviceCaps(hdc, HORZRES), |
| 91 | GetDeviceCaps(hdc, VERTRES)); |
| 92 | // Hard-code text_height = 0.5cm = ~1/5 of inch |
| 93 | page_setup_pixels_.Init(physical_size_pixels, printable_area_pixels, |
| 94 | ConvertUnit(500, kHundrethsMMPerInch, dpi_)); |
| 95 | |
| 96 | // Initialize page_setup_cmm_. |
| 97 | // In theory, we should be using HORZSIZE and VERTSIZE but their value is |
| 98 | // so wrong it's useless. So read the values in dpi unit and convert them back |
| 99 | // in 0.01 mm. |
| 100 | gfx::Size physical_size_cmm( |
| 101 | ConvertUnit(physical_size_pixels.width(), dpi_, kHundrethsMMPerInch), |
| 102 | ConvertUnit(physical_size_pixels.height(), dpi_, kHundrethsMMPerInch)); |
| 103 | gfx::Rect printable_area_cmm( |
| 104 | ConvertUnit(printable_area_pixels.x(), dpi_, kHundrethsMMPerInch), |
| 105 | ConvertUnit(printable_area_pixels.y(), dpi_, kHundrethsMMPerInch), |
| 106 | ConvertUnit(printable_area_pixels.width(), dpi_, kHundrethsMMPerInch), |
| 107 | ConvertUnit(printable_area_pixels.bottom(), dpi_, kHundrethsMMPerInch)); |
| 108 | |
| 109 | static const int kRoundingTolerance = 5; |
| 110 | // Some printers may advertise a slightly larger printable area than the |
| 111 | // physical area. This is mostly due to integer calculation and rounding. |
| 112 | if (physical_size_cmm.height() > printable_area_cmm.bottom() && |
| 113 | physical_size_cmm.height() <= (printable_area_cmm.bottom() + |
| 114 | kRoundingTolerance)) { |
| 115 | physical_size_cmm.set_height(printable_area_cmm.bottom()); |
| 116 | } |
| 117 | if (physical_size_cmm.width() > printable_area_cmm.right() && |
| 118 | physical_size_cmm.width() <= (printable_area_cmm.right() + |
| 119 | kRoundingTolerance)) { |
| 120 | physical_size_cmm.set_width(printable_area_cmm.right()); |
| 121 | } |
| 122 | page_setup_cmm_.Init(physical_size_cmm, printable_area_cmm, 500); |
| 123 | } |
| 124 | #endif |
| 125 | |
| 126 | void PrintSettings::UpdateMarginsMetric(const PageMargins& new_margins) { |
| 127 | // Apply the new margins in 0.01 mm unit. |
| 128 | page_setup_cmm_.SetRequestedMargins(new_margins); |
| 129 | |
| 130 | // Converts the margins in dpi unit and apply those too. |
| 131 | PageMargins pixels_margins; |
| 132 | pixels_margins.header = ConvertUnit(new_margins.header, kHundrethsMMPerInch, |
| 133 | dpi_); |
| 134 | pixels_margins.footer = ConvertUnit(new_margins.footer, kHundrethsMMPerInch, |
| 135 | dpi_); |
| 136 | pixels_margins.left = ConvertUnit(new_margins.left, kHundrethsMMPerInch, |
| 137 | dpi_); |
| 138 | pixels_margins.top = ConvertUnit(new_margins.top, kHundrethsMMPerInch, dpi_); |
| 139 | pixels_margins.right = ConvertUnit(new_margins.right, kHundrethsMMPerInch, |
| 140 | dpi_); |
| 141 | pixels_margins.bottom = ConvertUnit(new_margins.bottom, kHundrethsMMPerInch, |
| 142 | dpi_); |
| 143 | page_setup_pixels_.SetRequestedMargins(pixels_margins); |
| 144 | } |
| 145 | |
| 146 | void PrintSettings::UpdateMarginsMilliInch(const PageMargins& new_margins) { |
| 147 | // Convert margins from thousandth inches to cmm (0.01mm). |
| 148 | PageMargins cmm_margins; |
| 149 | cmm_margins.header = |
| 150 | ConvertMilliInchToHundredThousanthMeter(new_margins.header); |
| 151 | cmm_margins.footer = |
| 152 | ConvertMilliInchToHundredThousanthMeter(new_margins.footer); |
| 153 | cmm_margins.left = ConvertMilliInchToHundredThousanthMeter(new_margins.left); |
| 154 | cmm_margins.top = ConvertMilliInchToHundredThousanthMeter(new_margins.top); |
| 155 | cmm_margins.right = |
| 156 | ConvertMilliInchToHundredThousanthMeter(new_margins.right); |
| 157 | cmm_margins.bottom = |
| 158 | ConvertMilliInchToHundredThousanthMeter(new_margins.bottom); |
| 159 | UpdateMarginsMetric(cmm_margins); |
| 160 | } |
| 161 | |
| 162 | void PrintSettings::RenderParams(ViewMsg_Print_Params* params) const { |
| 163 | DCHECK(params); |
| 164 | params->printable_size.SetSize(page_setup_pixels_.content_area().width(), |
| 165 | page_setup_pixels_.content_area().height()); |
| 166 | params->dpi = dpi_; |
| 167 | // Currently hardcoded at 1.25. See PrintSettings' constructor. |
| 168 | params->min_shrink = min_shrink; |
| 169 | // Currently hardcoded at 2.0. See PrintSettings' constructor. |
| 170 | params->max_shrink = max_shrink; |
| 171 | // Currently hardcoded at 72dpi. See PrintSettings' constructor. |
| 172 | params->desired_dpi = desired_dpi; |
| 173 | // Always use an invalid cookie. |
| 174 | params->document_cookie = 0; |
| 175 | } |
| 176 | |
| 177 | bool PrintSettings::Equals(const PrintSettings& rhs) const { |
| 178 | // Do not test the display device name (printer_name_) for equality since it |
| 179 | // may sometimes be chopped off at 30 chars. As long as device_name is the |
| 180 | // same, that's fine. |
| 181 | return ranges == rhs.ranges && |
| 182 | min_shrink == rhs.min_shrink && |
| 183 | max_shrink == rhs.max_shrink && |
| 184 | desired_dpi == rhs.desired_dpi && |
| 185 | overlays.Equals(rhs.overlays) && |
| 186 | device_name_ == rhs.device_name_ && |
| 187 | page_setup_pixels_.Equals(rhs.page_setup_pixels_) && |
| 188 | page_setup_cmm_.Equals(rhs.page_setup_cmm_) && |
| 189 | dpi_ == rhs.dpi_ && |
| 190 | landscape_ == rhs.landscape_; |
| 191 | } |
| 192 | |
| 193 | int PrintSettings::NewCookie() { |
[email protected] | d30e8e64 | 2008-08-06 12:05:24 | [diff] [blame^] | 194 | return cookie_seq.GetNext(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | } // namespace printing |