[email protected] | 68da8f78 | 2010-05-20 18:28:00 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
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 | |
[email protected] | 8ff1d42 | 2009-07-07 21:31:39 | [diff] [blame] | 5 | #include "printing/printed_document.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 6 | |
[email protected] | 7d2d0d0e | 2010-03-06 22:16:10 | [diff] [blame] | 7 | #include <algorithm> |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 8 | #include <set> |
[email protected] | 7d2d0d0e | 2010-03-06 22:16:10 | [diff] [blame] | 9 | #include <string> |
| 10 | #include <vector> |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 11 | |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 12 | #include "base/file_path.h" |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 13 | #include "base/file_util.h" |
[email protected] | d0767cb54 | 2009-10-08 17:38:30 | [diff] [blame] | 14 | #include "base/i18n/file_util_icu.h" |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 15 | #include "base/lazy_instance.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 16 | #include "base/message_loop.h" |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 17 | #include "base/string_util.h" |
[email protected] | 7d2d0d0e | 2010-03-06 22:16:10 | [diff] [blame] | 18 | #include "base/utf_string_conversions.h" |
[email protected] | fb895c6 | 2009-10-09 18:20:30 | [diff] [blame] | 19 | #include "base/i18n/time_formatting.h" |
[email protected] | d07b6b5 | 2010-03-23 04:05:01 | [diff] [blame] | 20 | #include "gfx/font.h" |
[email protected] | 8ff1d42 | 2009-07-07 21:31:39 | [diff] [blame] | 21 | #include "printing/page_number.h" |
| 22 | #include "printing/page_overlays.h" |
| 23 | #include "printing/printed_pages_source.h" |
| 24 | #include "printing/printed_page.h" |
[email protected] | 4ae30d08 | 2009-02-20 17:55:55 | [diff] [blame] | 25 | #include "printing/units.h" |
[email protected] | c399a8a | 2008-11-22 19:38:00 | [diff] [blame] | 26 | #include "skia/ext/platform_device.h" |
[email protected] | 9dd7e3d7 | 2011-01-20 18:27:06 | [diff] [blame] | 27 | #include "ui/base/text/text_elider.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 28 | |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | struct PrintDebugDumpPath { |
| 32 | PrintDebugDumpPath() |
| 33 | : enabled(false) { |
| 34 | } |
| 35 | |
| 36 | bool enabled; |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 37 | FilePath debug_dump_path; |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 38 | }; |
| 39 | |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 40 | static base::LazyInstance<PrintDebugDumpPath> g_debug_dump_info( |
| 41 | base::LINKER_INITIALIZED); |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 42 | |
| 43 | } // namespace |
| 44 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 45 | namespace printing { |
| 46 | |
| 47 | PrintedDocument::PrintedDocument(const PrintSettings& settings, |
| 48 | PrintedPagesSource* source, |
| 49 | int cookie) |
| 50 | : mutable_(source), |
| 51 | immutable_(settings, source, cookie) { |
| 52 | |
| 53 | // Records the expected page count if a range is setup. |
| 54 | if (!settings.ranges.empty()) { |
| 55 | // If there is a range, set the number of page |
| 56 | for (unsigned i = 0; i < settings.ranges.size(); ++i) { |
| 57 | const PageRange& range = settings.ranges[i]; |
| 58 | mutable_.expected_page_count_ += range.to - range.from + 1; |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | PrintedDocument::~PrintedDocument() { |
| 64 | } |
| 65 | |
[email protected] | 0e0fca3 | 2009-07-06 15:25:50 | [diff] [blame] | 66 | void PrintedDocument::SetPage(int page_number, |
| 67 | NativeMetafile* metafile, |
[email protected] | 40c7cfe | 2010-07-01 07:04:05 | [diff] [blame] | 68 | double shrink, |
| 69 | const gfx::Size& paper_size, |
[email protected] | 3c5fb6b | 2010-07-02 05:32:38 | [diff] [blame] | 70 | const gfx::Rect& page_rect, |
| 71 | bool has_visible_overlays) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 72 | // Notice the page_number + 1, the reason is that this is the value that will |
| 73 | // be shown. Users dislike 0-based counting. |
| 74 | scoped_refptr<PrintedPage> page( |
| 75 | new PrintedPage(page_number + 1, |
[email protected] | 40c7cfe | 2010-07-01 07:04:05 | [diff] [blame] | 76 | metafile, |
| 77 | paper_size, |
[email protected] | 3c5fb6b | 2010-07-02 05:32:38 | [diff] [blame] | 78 | page_rect, |
| 79 | has_visible_overlays)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 80 | { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 81 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 82 | mutable_.pages_[page_number] = page; |
| 83 | if (mutable_.shrink_factor == 0) { |
| 84 | mutable_.shrink_factor = shrink; |
| 85 | } else { |
| 86 | DCHECK_EQ(mutable_.shrink_factor, shrink); |
| 87 | } |
| 88 | } |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 89 | DebugDump(*page); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | bool PrintedDocument::GetPage(int page_number, |
| 93 | scoped_refptr<PrintedPage>* page) { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 94 | base::AutoLock lock(lock_); |
[email protected] | 8227045 | 2009-06-19 15:58:01 | [diff] [blame] | 95 | PrintedPages::const_iterator itr = mutable_.pages_.find(page_number); |
| 96 | if (itr != mutable_.pages_.end()) { |
| 97 | if (itr->second.get()) { |
| 98 | *page = itr->second; |
| 99 | return true; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 100 | } |
| 101 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 102 | return false; |
| 103 | } |
| 104 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 105 | bool PrintedDocument::IsComplete() const { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 106 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 107 | if (!mutable_.page_count_) |
| 108 | return false; |
| 109 | PageNumber page(immutable_.settings_, mutable_.page_count_); |
| 110 | if (page == PageNumber::npos()) |
| 111 | return false; |
| 112 | for (; page != PageNumber::npos(); ++page) { |
| 113 | PrintedPages::const_iterator itr = mutable_.pages_.find(page.ToInt()); |
| 114 | if (itr == mutable_.pages_.end() || !itr->second.get() || |
[email protected] | 0e0fca3 | 2009-07-06 15:25:50 | [diff] [blame] | 115 | !itr->second->native_metafile()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 116 | return false; |
| 117 | } |
| 118 | return true; |
| 119 | } |
| 120 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 121 | void PrintedDocument::DisconnectSource() { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 122 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 123 | mutable_.source_ = NULL; |
| 124 | } |
| 125 | |
[email protected] | b5ab398 | 2010-02-16 23:58:27 | [diff] [blame] | 126 | uint32 PrintedDocument::MemoryUsage() const { |
[email protected] | 60741b4 | 2009-09-14 13:57:10 | [diff] [blame] | 127 | std::vector< scoped_refptr<PrintedPage> > pages_copy; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 128 | { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 129 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 130 | pages_copy.reserve(mutable_.pages_.size()); |
| 131 | PrintedPages::const_iterator end = mutable_.pages_.end(); |
| 132 | for (PrintedPages::const_iterator itr = mutable_.pages_.begin(); |
| 133 | itr != end; ++itr) { |
| 134 | if (itr->second.get()) { |
| 135 | pages_copy.push_back(itr->second); |
| 136 | } |
| 137 | } |
| 138 | } |
[email protected] | b5ab398 | 2010-02-16 23:58:27 | [diff] [blame] | 139 | uint32 total = 0; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 140 | for (size_t i = 0; i < pages_copy.size(); ++i) { |
[email protected] | 0e0fca3 | 2009-07-06 15:25:50 | [diff] [blame] | 141 | total += pages_copy[i]->native_metafile()->GetDataSize(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 142 | } |
| 143 | return total; |
| 144 | } |
| 145 | |
| 146 | void PrintedDocument::set_page_count(int max_page) { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 147 | base::AutoLock lock(lock_); |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 148 | DCHECK_EQ(0, mutable_.page_count_); |
| 149 | mutable_.page_count_ = max_page; |
| 150 | if (immutable_.settings_.ranges.empty()) { |
| 151 | mutable_.expected_page_count_ = max_page; |
| 152 | } else { |
| 153 | // If there is a range, don't bother since expected_page_count_ is already |
| 154 | // initialized. |
| 155 | DCHECK_NE(mutable_.expected_page_count_, 0); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 156 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | int PrintedDocument::page_count() const { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 160 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 161 | return mutable_.page_count_; |
| 162 | } |
| 163 | |
| 164 | int PrintedDocument::expected_page_count() const { |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame^] | 165 | base::AutoLock lock(lock_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 166 | return mutable_.expected_page_count_; |
| 167 | } |
| 168 | |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 169 | void PrintedDocument::PrintHeaderFooter(gfx::NativeDrawingContext context, |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 170 | const PrintedPage& page, |
| 171 | PageOverlays::HorizontalPosition x, |
| 172 | PageOverlays::VerticalPosition y, |
[email protected] | 7322c440 | 2009-05-15 02:16:10 | [diff] [blame] | 173 | const gfx::Font& font) const { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 174 | const PrintSettings& settings = immutable_.settings_; |
[email protected] | 3c5fb6b | 2010-07-02 05:32:38 | [diff] [blame] | 175 | if (!settings.use_overlays || !page.has_visible_overlays()) { |
[email protected] | 38bba4f | 2010-03-12 05:29:07 | [diff] [blame] | 176 | return; |
| 177 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 178 | const std::wstring& line = settings.overlays.GetOverlay(x, y); |
| 179 | if (line.empty()) { |
| 180 | return; |
| 181 | } |
| 182 | std::wstring output(PageOverlays::ReplaceVariables(line, *this, page)); |
| 183 | if (output.empty()) { |
[email protected] | be3b19a | 2009-07-13 14:58:18 | [diff] [blame] | 184 | // May happen if document name or url is empty. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 185 | return; |
| 186 | } |
[email protected] | 13658c4 | 2011-01-04 20:46:14 | [diff] [blame] | 187 | const gfx::Size string_size(font.GetStringWidth(WideToUTF16Hack(output)), |
| 188 | font.GetHeight()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 189 | gfx::Rect bounding; |
| 190 | bounding.set_height(string_size.height()); |
[email protected] | 6ab86ac | 2010-05-29 07:18:29 | [diff] [blame] | 191 | const gfx::Rect& overlay_area( |
| 192 | settings.page_setup_device_units().overlay_area()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 193 | // Hard code .25 cm interstice between overlays. Make sure that some space is |
| 194 | // kept between each headers. |
[email protected] | 6ab86ac | 2010-05-29 07:18:29 | [diff] [blame] | 195 | const int interstice = ConvertUnit(250, kHundrethsMMPerInch, |
| 196 | settings.device_units_per_inch()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 197 | const int max_width = overlay_area.width() / 3 - interstice; |
| 198 | const int actual_width = std::min(string_size.width(), max_width); |
| 199 | switch (x) { |
| 200 | case PageOverlays::LEFT: |
| 201 | bounding.set_x(overlay_area.x()); |
| 202 | bounding.set_width(max_width); |
| 203 | break; |
| 204 | case PageOverlays::CENTER: |
| 205 | bounding.set_x(overlay_area.x() + |
| 206 | (overlay_area.width() - actual_width) / 2); |
| 207 | bounding.set_width(actual_width); |
| 208 | break; |
| 209 | case PageOverlays::RIGHT: |
| 210 | bounding.set_x(overlay_area.right() - actual_width); |
| 211 | bounding.set_width(actual_width); |
| 212 | break; |
| 213 | } |
| 214 | |
| 215 | DCHECK_LE(bounding.right(), overlay_area.right()); |
| 216 | |
| 217 | switch (y) { |
| 218 | case PageOverlays::BOTTOM: |
| 219 | bounding.set_y(overlay_area.bottom() - string_size.height()); |
| 220 | break; |
| 221 | case PageOverlays::TOP: |
| 222 | bounding.set_y(overlay_area.y()); |
| 223 | break; |
| 224 | } |
| 225 | |
[email protected] | 4345680 | 2008-11-04 16:09:52 | [diff] [blame] | 226 | if (string_size.width() > bounding.width()) { |
| 227 | if (line == PageOverlays::kUrl) { |
[email protected] | 9dd7e3d7 | 2011-01-20 18:27:06 | [diff] [blame] | 228 | output = UTF16ToWideHack(ui::ElideUrl(url(), font, bounding.width(), |
| 229 | std::wstring())); |
[email protected] | 4345680 | 2008-11-04 16:09:52 | [diff] [blame] | 230 | } else { |
[email protected] | 9dd7e3d7 | 2011-01-20 18:27:06 | [diff] [blame] | 231 | output = UTF16ToWideHack(ui::ElideText(WideToUTF16Hack(output), |
[email protected] | d6b671d | 2010-10-21 22:02:55 | [diff] [blame] | 232 | font, bounding.width(), false)); |
[email protected] | 4345680 | 2008-11-04 16:09:52 | [diff] [blame] | 233 | } |
| 234 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 235 | |
[email protected] | e059878 | 2010-10-07 22:01:52 | [diff] [blame] | 236 | DrawHeaderFooter(context, output, bounding); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 237 | } |
| 238 | |
[email protected] | be3b19a | 2009-07-13 14:58:18 | [diff] [blame] | 239 | void PrintedDocument::DebugDump(const PrintedPage& page) { |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 240 | if (!g_debug_dump_info.Get().enabled) |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 241 | return; |
| 242 | |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 243 | string16 filename; |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 244 | filename += date(); |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 245 | filename += ASCIIToUTF16("_"); |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 246 | filename += time(); |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 247 | filename += ASCIIToUTF16("_"); |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 248 | filename += name(); |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 249 | filename += ASCIIToUTF16("_"); |
| 250 | filename += ASCIIToUTF16(StringPrintf("%02d", page.page_number())); |
| 251 | filename += ASCIIToUTF16("_.emf"); |
[email protected] | de294335 | 2009-10-22 23:06:12 | [diff] [blame] | 252 | #if defined(OS_WIN) |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 253 | page.native_metafile()->SaveTo( |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 254 | g_debug_dump_info.Get().debug_dump_path.Append(filename).ToWStringHack()); |
[email protected] | 60741b4 | 2009-09-14 13:57:10 | [diff] [blame] | 255 | #else // OS_WIN |
| 256 | NOTIMPLEMENTED(); |
| 257 | #endif // OS_WIN |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 258 | } |
| 259 | |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 260 | void PrintedDocument::set_debug_dump_path(const FilePath& debug_dump_path) { |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 261 | g_debug_dump_info.Get().enabled = !debug_dump_path.empty(); |
| 262 | g_debug_dump_info.Get().debug_dump_path = debug_dump_path; |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 263 | } |
| 264 | |
[email protected] | d9d4299 | 2010-09-13 19:39:19 | [diff] [blame] | 265 | const FilePath& PrintedDocument::debug_dump_path() { |
[email protected] | 625332e0 | 2010-12-14 07:48:49 | [diff] [blame] | 266 | return g_debug_dump_info.Get().debug_dump_path; |
[email protected] | e1504d8 | 2009-07-03 15:27:15 | [diff] [blame] | 267 | } |
| 268 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 269 | PrintedDocument::Mutable::Mutable(PrintedPagesSource* source) |
| 270 | : source_(source), |
| 271 | expected_page_count_(0), |
| 272 | page_count_(0), |
| 273 | shrink_factor(0) { |
| 274 | } |
| 275 | |
[email protected] | 20f0487a | 2010-09-30 20:06:30 | [diff] [blame] | 276 | PrintedDocument::Mutable::~Mutable() { |
| 277 | } |
| 278 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 279 | PrintedDocument::Immutable::Immutable(const PrintSettings& settings, |
| 280 | PrintedPagesSource* source, |
| 281 | int cookie) |
| 282 | : settings_(settings), |
| 283 | source_message_loop_(MessageLoop::current()), |
| 284 | name_(source->RenderSourceName()), |
| 285 | url_(source->RenderSourceUrl()), |
| 286 | cookie_(cookie) { |
[email protected] | e059878 | 2010-10-07 22:01:52 | [diff] [blame] | 287 | SetDocumentDate(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 288 | } |
| 289 | |
[email protected] | 20f0487a | 2010-09-30 20:06:30 | [diff] [blame] | 290 | PrintedDocument::Immutable::~Immutable() { |
| 291 | } |
| 292 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 293 | } // namespace printing |