blob: 0360b5b777cf14d7e17a86871b8cbc3f61e55b62 [file] [log] [blame]
[email protected]68da8f782010-05-20 18:28:001// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]8ff1d422009-07-07 21:31:395#include "printing/printed_document.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]7d2d0d0e2010-03-06 22:16:107#include <algorithm>
initial.commit09911bf2008-07-26 23:55:298#include <set>
[email protected]7d2d0d0e2010-03-06 22:16:109#include <string>
10#include <vector>
initial.commit09911bf2008-07-26 23:55:2911
[email protected]d9d42992010-09-13 19:39:1912#include "base/file_path.h"
[email protected]e1504d82009-07-03 15:27:1513#include "base/file_util.h"
[email protected]d0767cb542009-10-08 17:38:3014#include "base/i18n/file_util_icu.h"
[email protected]625332e02010-12-14 07:48:4915#include "base/lazy_instance.h"
initial.commit09911bf2008-07-26 23:55:2916#include "base/message_loop.h"
[email protected]e1504d82009-07-03 15:27:1517#include "base/string_util.h"
[email protected]7d2d0d0e2010-03-06 22:16:1018#include "base/utf_string_conversions.h"
[email protected]fb895c62009-10-09 18:20:3019#include "base/i18n/time_formatting.h"
[email protected]d07b6b52010-03-23 04:05:0120#include "gfx/font.h"
[email protected]8ff1d422009-07-07 21:31:3921#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]4ae30d082009-02-20 17:55:5525#include "printing/units.h"
[email protected]c399a8a2008-11-22 19:38:0026#include "skia/ext/platform_device.h"
[email protected]9dd7e3d72011-01-20 18:27:0627#include "ui/base/text/text_elider.h"
initial.commit09911bf2008-07-26 23:55:2928
[email protected]e1504d82009-07-03 15:27:1529namespace {
30
31struct PrintDebugDumpPath {
32 PrintDebugDumpPath()
33 : enabled(false) {
34 }
35
36 bool enabled;
[email protected]d9d42992010-09-13 19:39:1937 FilePath debug_dump_path;
[email protected]e1504d82009-07-03 15:27:1538};
39
[email protected]625332e02010-12-14 07:48:4940static base::LazyInstance<PrintDebugDumpPath> g_debug_dump_info(
41 base::LINKER_INITIALIZED);
[email protected]e1504d82009-07-03 15:27:1542
43} // namespace
44
initial.commit09911bf2008-07-26 23:55:2945namespace printing {
46
47PrintedDocument::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
63PrintedDocument::~PrintedDocument() {
64}
65
[email protected]0e0fca32009-07-06 15:25:5066void PrintedDocument::SetPage(int page_number,
67 NativeMetafile* metafile,
[email protected]40c7cfe2010-07-01 07:04:0568 double shrink,
69 const gfx::Size& paper_size,
[email protected]3c5fb6b2010-07-02 05:32:3870 const gfx::Rect& page_rect,
71 bool has_visible_overlays) {
initial.commit09911bf2008-07-26 23:55:2972 // 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]40c7cfe2010-07-01 07:04:0576 metafile,
77 paper_size,
[email protected]3c5fb6b2010-07-02 05:32:3878 page_rect,
79 has_visible_overlays));
initial.commit09911bf2008-07-26 23:55:2980 {
[email protected]20305ec2011-01-21 04:55:5281 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:2982 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]e1504d82009-07-03 15:27:1589 DebugDump(*page);
initial.commit09911bf2008-07-26 23:55:2990}
91
92bool PrintedDocument::GetPage(int page_number,
93 scoped_refptr<PrintedPage>* page) {
[email protected]20305ec2011-01-21 04:55:5294 base::AutoLock lock(lock_);
[email protected]82270452009-06-19 15:58:0195 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.commit09911bf2008-07-26 23:55:29100 }
101 }
initial.commit09911bf2008-07-26 23:55:29102 return false;
103}
104
initial.commit09911bf2008-07-26 23:55:29105bool PrintedDocument::IsComplete() const {
[email protected]20305ec2011-01-21 04:55:52106 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29107 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]0e0fca32009-07-06 15:25:50115 !itr->second->native_metafile())
initial.commit09911bf2008-07-26 23:55:29116 return false;
117 }
118 return true;
119}
120
initial.commit09911bf2008-07-26 23:55:29121void PrintedDocument::DisconnectSource() {
[email protected]20305ec2011-01-21 04:55:52122 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29123 mutable_.source_ = NULL;
124}
125
[email protected]b5ab3982010-02-16 23:58:27126uint32 PrintedDocument::MemoryUsage() const {
[email protected]60741b42009-09-14 13:57:10127 std::vector< scoped_refptr<PrintedPage> > pages_copy;
initial.commit09911bf2008-07-26 23:55:29128 {
[email protected]20305ec2011-01-21 04:55:52129 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29130 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]b5ab3982010-02-16 23:58:27139 uint32 total = 0;
initial.commit09911bf2008-07-26 23:55:29140 for (size_t i = 0; i < pages_copy.size(); ++i) {
[email protected]0e0fca32009-07-06 15:25:50141 total += pages_copy[i]->native_metafile()->GetDataSize();
initial.commit09911bf2008-07-26 23:55:29142 }
143 return total;
144}
145
146void PrintedDocument::set_page_count(int max_page) {
[email protected]20305ec2011-01-21 04:55:52147 base::AutoLock lock(lock_);
[email protected]e1504d82009-07-03 15:27:15148 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.commit09911bf2008-07-26 23:55:29156 }
initial.commit09911bf2008-07-26 23:55:29157}
158
159int PrintedDocument::page_count() const {
[email protected]20305ec2011-01-21 04:55:52160 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29161 return mutable_.page_count_;
162}
163
164int PrintedDocument::expected_page_count() const {
[email protected]20305ec2011-01-21 04:55:52165 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29166 return mutable_.expected_page_count_;
167}
168
[email protected]b75dca82009-10-13 18:46:21169void PrintedDocument::PrintHeaderFooter(gfx::NativeDrawingContext context,
initial.commit09911bf2008-07-26 23:55:29170 const PrintedPage& page,
171 PageOverlays::HorizontalPosition x,
172 PageOverlays::VerticalPosition y,
[email protected]7322c4402009-05-15 02:16:10173 const gfx::Font& font) const {
initial.commit09911bf2008-07-26 23:55:29174 const PrintSettings& settings = immutable_.settings_;
[email protected]3c5fb6b2010-07-02 05:32:38175 if (!settings.use_overlays || !page.has_visible_overlays()) {
[email protected]38bba4f2010-03-12 05:29:07176 return;
177 }
initial.commit09911bf2008-07-26 23:55:29178 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]be3b19a2009-07-13 14:58:18184 // May happen if document name or url is empty.
initial.commit09911bf2008-07-26 23:55:29185 return;
186 }
[email protected]13658c42011-01-04 20:46:14187 const gfx::Size string_size(font.GetStringWidth(WideToUTF16Hack(output)),
188 font.GetHeight());
initial.commit09911bf2008-07-26 23:55:29189 gfx::Rect bounding;
190 bounding.set_height(string_size.height());
[email protected]6ab86ac2010-05-29 07:18:29191 const gfx::Rect& overlay_area(
192 settings.page_setup_device_units().overlay_area());
initial.commit09911bf2008-07-26 23:55:29193 // Hard code .25 cm interstice between overlays. Make sure that some space is
194 // kept between each headers.
[email protected]6ab86ac2010-05-29 07:18:29195 const int interstice = ConvertUnit(250, kHundrethsMMPerInch,
196 settings.device_units_per_inch());
initial.commit09911bf2008-07-26 23:55:29197 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]43456802008-11-04 16:09:52226 if (string_size.width() > bounding.width()) {
227 if (line == PageOverlays::kUrl) {
[email protected]9dd7e3d72011-01-20 18:27:06228 output = UTF16ToWideHack(ui::ElideUrl(url(), font, bounding.width(),
229 std::wstring()));
[email protected]43456802008-11-04 16:09:52230 } else {
[email protected]9dd7e3d72011-01-20 18:27:06231 output = UTF16ToWideHack(ui::ElideText(WideToUTF16Hack(output),
[email protected]d6b671d2010-10-21 22:02:55232 font, bounding.width(), false));
[email protected]43456802008-11-04 16:09:52233 }
234 }
initial.commit09911bf2008-07-26 23:55:29235
[email protected]e0598782010-10-07 22:01:52236 DrawHeaderFooter(context, output, bounding);
initial.commit09911bf2008-07-26 23:55:29237}
238
[email protected]be3b19a2009-07-13 14:58:18239void PrintedDocument::DebugDump(const PrintedPage& page) {
[email protected]625332e02010-12-14 07:48:49240 if (!g_debug_dump_info.Get().enabled)
[email protected]e1504d82009-07-03 15:27:15241 return;
242
[email protected]d9d42992010-09-13 19:39:19243 string16 filename;
[email protected]e1504d82009-07-03 15:27:15244 filename += date();
[email protected]d9d42992010-09-13 19:39:19245 filename += ASCIIToUTF16("_");
[email protected]e1504d82009-07-03 15:27:15246 filename += time();
[email protected]d9d42992010-09-13 19:39:19247 filename += ASCIIToUTF16("_");
[email protected]e1504d82009-07-03 15:27:15248 filename += name();
[email protected]d9d42992010-09-13 19:39:19249 filename += ASCIIToUTF16("_");
250 filename += ASCIIToUTF16(StringPrintf("%02d", page.page_number()));
251 filename += ASCIIToUTF16("_.emf");
[email protected]de2943352009-10-22 23:06:12252#if defined(OS_WIN)
[email protected]d9d42992010-09-13 19:39:19253 page.native_metafile()->SaveTo(
[email protected]625332e02010-12-14 07:48:49254 g_debug_dump_info.Get().debug_dump_path.Append(filename).ToWStringHack());
[email protected]60741b42009-09-14 13:57:10255#else // OS_WIN
256 NOTIMPLEMENTED();
257#endif // OS_WIN
[email protected]e1504d82009-07-03 15:27:15258}
259
[email protected]d9d42992010-09-13 19:39:19260void PrintedDocument::set_debug_dump_path(const FilePath& debug_dump_path) {
[email protected]625332e02010-12-14 07:48:49261 g_debug_dump_info.Get().enabled = !debug_dump_path.empty();
262 g_debug_dump_info.Get().debug_dump_path = debug_dump_path;
[email protected]e1504d82009-07-03 15:27:15263}
264
[email protected]d9d42992010-09-13 19:39:19265const FilePath& PrintedDocument::debug_dump_path() {
[email protected]625332e02010-12-14 07:48:49266 return g_debug_dump_info.Get().debug_dump_path;
[email protected]e1504d82009-07-03 15:27:15267}
268
initial.commit09911bf2008-07-26 23:55:29269PrintedDocument::Mutable::Mutable(PrintedPagesSource* source)
270 : source_(source),
271 expected_page_count_(0),
272 page_count_(0),
273 shrink_factor(0) {
274}
275
[email protected]20f0487a2010-09-30 20:06:30276PrintedDocument::Mutable::~Mutable() {
277}
278
initial.commit09911bf2008-07-26 23:55:29279PrintedDocument::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]e0598782010-10-07 22:01:52287 SetDocumentDate();
initial.commit09911bf2008-07-26 23:55:29288}
289
[email protected]20f0487a2010-09-30 20:06:30290PrintedDocument::Immutable::~Immutable() {
291}
292
initial.commit09911bf2008-07-26 23:55:29293} // namespace printing