blob: f1f61fdaccf85f39ca3a1f528ab4b8528aba1a2c [file] [log] [blame]
[email protected]5cc4c422011-02-19 00:09:221// Copyright (c) 2011 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>
dchenge48600452015-12-28 02:24:5010#include <utility>
[email protected]7d2d0d0e2010-03-06 22:16:1011#include <vector>
initial.commit09911bf2008-07-26 23:55:2912
[email protected]c95198b2014-06-12 16:56:5513#include "base/bind.h"
[email protected]57999812013-02-24 05:40:5214#include "base/files/file_path.h"
thestig22dfc4012014-09-05 08:29:4415#include "base/files/file_util.h"
[email protected]d0767cb542009-10-08 17:38:3016#include "base/i18n/file_util_icu.h"
[email protected]57999812013-02-24 05:40:5217#include "base/i18n/time_formatting.h"
[email protected]c95198b2014-06-12 16:56:5518#include "base/json/json_writer.h"
[email protected]625332e02010-12-14 07:48:4919#include "base/lazy_instance.h"
[email protected]c95198b2014-06-12 16:56:5520#include "base/memory/ref_counted_memory.h"
[email protected]c95198b2014-06-12 16:56:5521#include "base/numerics/safe_conversions.h"
[email protected]896d161f2013-06-11 22:52:2422#include "base/strings/string_util.h"
23#include "base/strings/stringprintf.h"
[email protected]906265872013-06-07 22:40:4524#include "base/strings/utf_string_conversions.h"
Gabriel Charette44db1422018-08-06 11:19:3325#include "base/task/post_task.h"
[email protected]c95198b2014-06-12 16:56:5526#include "base/time/time.h"
27#include "base/values.h"
rbpotter80cbe042017-12-08 07:00:5228#include "printing/metafile.h"
[email protected]8ff1d422009-07-07 21:31:3929#include "printing/page_number.h"
[email protected]c95198b2014-06-12 16:56:5530#include "printing/print_settings_conversion.h"
[email protected]4ae30d082009-02-20 17:55:5531#include "printing/units.h"
[email protected]08397d52011-02-05 01:53:3832#include "ui/gfx/font.h"
[email protected]dbb97ba2013-09-09 22:15:2533#include "ui/gfx/text_elider.h"
initial.commit09911bf2008-07-26 23:55:2934
rbpotter80cbe042017-12-08 07:00:5235#if defined(OS_WIN)
36#include "printing/printed_page_win.h"
37#endif
38
[email protected]c95198b2014-06-12 16:56:5539namespace printing {
40
[email protected]e1504d82009-07-03 15:27:1541namespace {
42
thestig6c884e642017-04-11 04:05:5143base::LazyInstance<base::FilePath>::Leaky g_debug_dump_info =
[email protected]6de0fd1d2011-11-15 13:31:4944 LAZY_INSTANCE_INITIALIZER;
[email protected]e1504d82009-07-03 15:27:1545
rbpotter80cbe042017-12-08 07:00:5246#if defined(OS_WIN)
[email protected]c95198b2014-06-12 16:56:5547void DebugDumpPageTask(const base::string16& doc_name,
48 const PrintedPage* page) {
Lei Zhangbdd63812017-12-12 06:29:5149 DCHECK(PrintedDocument::HasDebugDumpPath());
[email protected]c95198b2014-06-12 16:56:5550
Lei Zhang933d34b2017-11-13 20:59:2951 static constexpr base::FilePath::CharType kExtension[] =
Lei Zhang933d34b2017-11-13 20:59:2952 FILE_PATH_LITERAL(".emf");
Lei Zhang933d34b2017-11-13 20:59:2953
54 base::string16 name = doc_name;
55 name += base::ASCIIToUTF16(base::StringPrintf("_%04d", page->page_number()));
56 base::FilePath path = PrintedDocument::CreateDebugDumpPath(name, kExtension);
57 base::File file(path,
vitalybuka5d1290582014-09-12 09:19:5958 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
59 page->metafile()->SaveTo(&file);
[email protected]c95198b2014-06-12 16:56:5560}
rbpotter80cbe042017-12-08 07:00:5261#else
62void DebugDumpTask(const base::string16& doc_name,
63 const MetafilePlayer* metafile) {
Lei Zhangbdd63812017-12-12 06:29:5164 DCHECK(PrintedDocument::HasDebugDumpPath());
rbpotter80cbe042017-12-08 07:00:5265
66 static constexpr base::FilePath::CharType kExtension[] =
67 FILE_PATH_LITERAL(".pdf");
68
69 base::string16 name = doc_name;
70 base::FilePath path = PrintedDocument::CreateDebugDumpPath(name, kExtension);
71 base::File file(path,
72 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
73 metafile->SaveTo(&file);
74}
75#endif
[email protected]c95198b2014-06-12 16:56:5576
77void DebugDumpDataTask(const base::string16& doc_name,
78 const base::FilePath::StringType& extension,
79 const base::RefCountedMemory* data) {
80 base::FilePath path =
81 PrintedDocument::CreateDebugDumpPath(doc_name, extension);
82 if (path.empty())
83 return;
84 base::WriteFile(path,
85 reinterpret_cast<const char*>(data->front()),
86 base::checked_cast<int>(data->size()));
87}
88
89void DebugDumpSettings(const base::string16& doc_name,
Xiyuan Xia863ce9d2017-06-20 22:36:0090 const PrintSettings& settings) {
[email protected]c95198b2014-06-12 16:56:5591 base::DictionaryValue job_settings;
92 PrintSettingsToJobSettingsDebug(settings, &job_settings);
93 std::string settings_str;
94 base::JSONWriter::WriteWithOptions(
estade8d046462015-05-16 01:02:3495 job_settings, base::JSONWriter::OPTIONS_PRETTY_PRINT, &settings_str);
[email protected]c95198b2014-06-12 16:56:5596 scoped_refptr<base::RefCountedMemory> data =
97 base::RefCountedString::TakeString(&settings_str);
Xiyuan Xia863ce9d2017-06-20 22:36:0098 base::PostTaskWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:0099 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
Xiyuan Xia863ce9d2017-06-20 22:36:00100 base::BindOnce(&DebugDumpDataTask, doc_name, FILE_PATH_LITERAL(".json"),
101 base::RetainedRef(data)));
[email protected]c95198b2014-06-12 16:56:55102}
103
[email protected]e1504d82009-07-03 15:27:15104} // namespace
105
initial.commit09911bf2008-07-26 23:55:29106PrintedDocument::PrintedDocument(const PrintSettings& settings,
Vladislav Kuzkokovccceef02017-10-04 15:30:10107 const base::string16& name,
Xiyuan Xia863ce9d2017-06-20 22:36:00108 int cookie)
Vladislav Kuzkokovccceef02017-10-04 15:30:10109 : immutable_(settings, name, cookie) {
Lei Zhang99bb78d32018-05-04 18:38:37110 // If there is a range, set the number of page
111 for (const PageRange& range : settings.ranges())
112 mutable_.expected_page_count_ += range.to - range.from + 1;
[email protected]c95198b2014-06-12 16:56:55113
Lei Zhangbdd63812017-12-12 06:29:51114 if (HasDebugDumpPath())
Vladislav Kuzkokovccceef02017-10-04 15:30:10115 DebugDumpSettings(name, settings);
initial.commit09911bf2008-07-26 23:55:29116}
117
Chris Watkinsc360b972017-12-01 05:50:23118PrintedDocument::~PrintedDocument() = default;
initial.commit09911bf2008-07-26 23:55:29119
rbpotter80cbe042017-12-08 07:00:52120#if defined(OS_WIN)
rbpotterd20e4ef32018-03-09 20:50:39121void PrintedDocument::SetConvertingPdf() {
122 base::AutoLock lock(lock_);
123 mutable_.converting_pdf_ = true;
124}
125
[email protected]0e0fca32009-07-06 15:25:50126void PrintedDocument::SetPage(int page_number,
dchengc3df9ba2016-04-07 23:09:32127 std::unique_ptr<MetafilePlayer> metafile,
pkasting46a62912014-10-09 21:30:00128 float shrink,
rbpotter80cbe042017-12-08 07:00:52129 const gfx::Size& page_size,
130 const gfx::Rect& page_content_rect) {
initial.commit09911bf2008-07-26 23:55:29131 // Notice the page_number + 1, the reason is that this is the value that will
132 // be shown. Users dislike 0-based counting.
Lei Zhang764461802017-11-15 23:36:07133 auto page = base::MakeRefCounted<PrintedPage>(
rbpotter80cbe042017-12-08 07:00:52134 page_number + 1, std::move(metafile), page_size, page_content_rect);
[email protected]9de1347a2014-06-12 09:49:08135 page->set_shrink_factor(shrink);
initial.commit09911bf2008-07-26 23:55:29136 {
[email protected]20305ec2011-01-21 04:55:52137 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29138 mutable_.pages_[page_number] = page;
initial.commit09911bf2008-07-26 23:55:29139 }
[email protected]c95198b2014-06-12 16:56:55140
Lei Zhangbdd63812017-12-12 06:29:51141 if (HasDebugDumpPath()) {
Xiyuan Xia863ce9d2017-06-20 22:36:00142 base::PostTaskWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:00143 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
Xiyuan Xia863ce9d2017-06-20 22:36:00144 base::BindOnce(&DebugDumpPageTask, name(), base::RetainedRef(page)));
[email protected]c95198b2014-06-12 16:56:55145 }
initial.commit09911bf2008-07-26 23:55:29146}
147
[email protected]c95198b2014-06-12 16:56:55148scoped_refptr<PrintedPage> PrintedDocument::GetPage(int page_number) {
149 scoped_refptr<PrintedPage> page;
150 {
151 base::AutoLock lock(lock_);
Lei Zhang764461802017-11-15 23:36:07152 PrintedPages::const_iterator it = mutable_.pages_.find(page_number);
153 if (it != mutable_.pages_.end())
154 page = it->second;
initial.commit09911bf2008-07-26 23:55:29155 }
[email protected]c95198b2014-06-12 16:56:55156 return page;
initial.commit09911bf2008-07-26 23:55:29157}
158
rbpotter80cbe042017-12-08 07:00:52159#else
160void PrintedDocument::SetDocument(std::unique_ptr<MetafilePlayer> metafile,
161 const gfx::Size& page_size,
162 const gfx::Rect& page_content_rect) {
163 {
164 base::AutoLock lock(lock_);
165 mutable_.metafile_ = std::move(metafile);
166#if defined(OS_MACOSX)
167 mutable_.page_size_ = page_size;
168 mutable_.page_content_rect_ = page_content_rect;
169#endif
170 }
171
Lei Zhangbdd63812017-12-12 06:29:51172 if (HasDebugDumpPath()) {
rbpotter80cbe042017-12-08 07:00:52173 base::PostTaskWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:00174 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
rbpotter80cbe042017-12-08 07:00:52175 base::BindOnce(&DebugDumpTask, name(), mutable_.metafile_.get()));
176 }
177}
178
179const MetafilePlayer* PrintedDocument::GetMetafile() {
180 return mutable_.metafile_.get();
181}
182
183#endif
184
initial.commit09911bf2008-07-26 23:55:29185bool PrintedDocument::IsComplete() const {
[email protected]20305ec2011-01-21 04:55:52186 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29187 if (!mutable_.page_count_)
188 return false;
rbpotter80cbe042017-12-08 07:00:52189#if defined(OS_WIN)
rbpotterd20e4ef32018-03-09 20:50:39190 if (mutable_.converting_pdf_)
191 return true;
192
initial.commit09911bf2008-07-26 23:55:29193 PageNumber page(immutable_.settings_, mutable_.page_count_);
194 if (page == PageNumber::npos())
195 return false;
[email protected]5cc4c422011-02-19 00:09:22196
initial.commit09911bf2008-07-26 23:55:29197 for (; page != PageNumber::npos(); ++page) {
Lei Zhang764461802017-11-15 23:36:07198 PrintedPages::const_iterator it = mutable_.pages_.find(page.ToInt());
rbpotter80cbe042017-12-08 07:00:52199 if (it == mutable_.pages_.end() || !it->second.get() ||
200 !it->second->metafile()) {
[email protected]5cc4c422011-02-19 00:09:22201 return false;
rbpotter80cbe042017-12-08 07:00:52202 }
initial.commit09911bf2008-07-26 23:55:29203 }
204 return true;
rbpotter80cbe042017-12-08 07:00:52205#else
206 return !!mutable_.metafile_;
207#endif
initial.commit09911bf2008-07-26 23:55:29208}
209
initial.commit09911bf2008-07-26 23:55:29210void PrintedDocument::set_page_count(int max_page) {
[email protected]20305ec2011-01-21 04:55:52211 base::AutoLock lock(lock_);
[email protected]e1504d82009-07-03 15:27:15212 DCHECK_EQ(0, mutable_.page_count_);
213 mutable_.page_count_ = max_page;
[email protected]e5324b52013-10-29 03:16:37214 if (immutable_.settings_.ranges().empty()) {
[email protected]e1504d82009-07-03 15:27:15215 mutable_.expected_page_count_ = max_page;
216 } else {
217 // If there is a range, don't bother since expected_page_count_ is already
218 // initialized.
219 DCHECK_NE(mutable_.expected_page_count_, 0);
initial.commit09911bf2008-07-26 23:55:29220 }
initial.commit09911bf2008-07-26 23:55:29221}
222
223int PrintedDocument::page_count() const {
[email protected]20305ec2011-01-21 04:55:52224 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29225 return mutable_.page_count_;
226}
227
228int PrintedDocument::expected_page_count() const {
[email protected]20305ec2011-01-21 04:55:52229 base::AutoLock lock(lock_);
initial.commit09911bf2008-07-26 23:55:29230 return mutable_.expected_page_count_;
231}
232
Lei Zhangbdd63812017-12-12 06:29:51233// static
234void PrintedDocument::SetDebugDumpPath(const base::FilePath& debug_dump_path) {
235 DCHECK(!debug_dump_path.empty());
[email protected]c95198b2014-06-12 16:56:55236 g_debug_dump_info.Get() = debug_dump_path;
[email protected]e1504d82009-07-03 15:27:15237}
238
Lei Zhangbdd63812017-12-12 06:29:51239// static
240bool PrintedDocument::HasDebugDumpPath() {
241 return g_debug_dump_info.IsCreated();
242}
243
244// static
[email protected]c95198b2014-06-12 16:56:55245base::FilePath PrintedDocument::CreateDebugDumpPath(
246 const base::string16& document_name,
247 const base::FilePath::StringType& extension) {
Lei Zhangbdd63812017-12-12 06:29:51248 DCHECK(HasDebugDumpPath());
rbpotter80cbe042017-12-08 07:00:52249
[email protected]c95198b2014-06-12 16:56:55250 // Create a filename.
251 base::string16 filename;
252 base::Time now(base::Time::Now());
253 filename = base::TimeFormatShortDateAndTime(now);
254 filename += base::ASCIIToUTF16("_");
255 filename += document_name;
256 base::FilePath::StringType system_filename;
257#if defined(OS_WIN)
258 system_filename = filename;
259#else // OS_WIN
260 system_filename = base::UTF16ToUTF8(filename);
261#endif // OS_WIN
[email protected]6bc03de2014-08-07 23:59:15262 base::i18n::ReplaceIllegalCharactersInPath(&system_filename, '_');
Lei Zhangbdd63812017-12-12 06:29:51263 const auto& dump_path = g_debug_dump_info.Get();
264 DCHECK(!dump_path.empty());
265 return dump_path.Append(system_filename).AddExtension(extension);
[email protected]c95198b2014-06-12 16:56:55266}
267
268void PrintedDocument::DebugDumpData(
269 const base::RefCountedMemory* data,
270 const base::FilePath::StringType& extension) {
Lei Zhangbdd63812017-12-12 06:29:51271 DCHECK(HasDebugDumpPath());
tzikdf97f3d2017-06-28 08:11:51272 base::PostTaskWithTraits(FROM_HERE,
Gabriel Charetteb10aeeb2018-07-26 20:15:00273 {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
tzikdf97f3d2017-06-28 08:11:51274 base::BindOnce(&DebugDumpDataTask, name(), extension,
275 base::RetainedRef(data)));
[email protected]e1504d82009-07-03 15:27:15276}
277
rbpotter80cbe042017-12-08 07:00:52278#if defined(OS_WIN) || defined(OS_MACOSX)
279gfx::Rect PrintedDocument::GetCenteredPageContentRect(
280 const gfx::Size& paper_size,
281 const gfx::Size& page_size,
282 const gfx::Rect& page_content_rect) const {
283 gfx::Rect content_rect = page_content_rect;
284 if (paper_size.width() > page_size.width()) {
285 int diff = paper_size.width() - page_size.width();
286 content_rect.set_x(content_rect.x() + diff / 2);
287 }
288 if (paper_size.height() > page_size.height()) {
289 int diff = paper_size.height() - page_size.height();
290 content_rect.set_y(content_rect.y() + diff / 2);
291 }
292 return content_rect;
293}
294#endif
295
Chris Watkinsc360b972017-12-01 05:50:23296PrintedDocument::Mutable::Mutable() = default;
initial.commit09911bf2008-07-26 23:55:29297
Chris Watkinsc360b972017-12-01 05:50:23298PrintedDocument::Mutable::~Mutable() = default;
[email protected]20f0487a2010-09-30 20:06:30299
initial.commit09911bf2008-07-26 23:55:29300PrintedDocument::Immutable::Immutable(const PrintSettings& settings,
Vladislav Kuzkokovccceef02017-10-04 15:30:10301 const base::string16& name,
Xiyuan Xia863ce9d2017-06-20 22:36:00302 int cookie)
Vladislav Kuzkokovccceef02017-10-04 15:30:10303 : settings_(settings), name_(name), cookie_(cookie) {}
initial.commit09911bf2008-07-26 23:55:29304
Chris Watkinsc360b972017-12-01 05:50:23305PrintedDocument::Immutable::~Immutable() = default;
[email protected]20f0487a2010-09-30 20:06:30306
initial.commit09911bf2008-07-26 23:55:29307} // namespace printing