printed_document.cc revision 3551c9c881056c480085172ff9840cab31610854
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/printed_document.h"
6
7#include <algorithm>
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/file_util.h"
13#include "base/files/file_path.h"
14#include "base/i18n/file_util_icu.h"
15#include "base/i18n/time_formatting.h"
16#include "base/lazy_instance.h"
17#include "base/message_loop/message_loop.h"
18#include "base/strings/string_util.h"
19#include "base/strings/stringprintf.h"
20#include "base/strings/utf_string_conversions.h"
21#include "printing/page_number.h"
22#include "printing/printed_page.h"
23#include "printing/printed_pages_source.h"
24#include "printing/units.h"
25#include "skia/ext/platform_device.h"
26#include "ui/base/text/text_elider.h"
27#include "ui/gfx/font.h"
28
29namespace {
30
31struct PrintDebugDumpPath {
32  PrintDebugDumpPath()
33    : enabled(false) {
34  }
35
36  bool enabled;
37  base::FilePath debug_dump_path;
38};
39
40base::LazyInstance<PrintDebugDumpPath> g_debug_dump_info =
41    LAZY_INSTANCE_INITIALIZER;
42
43}  // namespace
44
45namespace 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
66void PrintedDocument::SetPage(int page_number,
67                              Metafile* metafile,
68                              double shrink,
69                              const gfx::Size& paper_size,
70                              const gfx::Rect& page_rect) {
71  // Notice the page_number + 1, the reason is that this is the value that will
72  // be shown. Users dislike 0-based counting.
73  scoped_refptr<PrintedPage> page(
74      new PrintedPage(page_number + 1,
75                      metafile,
76                      paper_size,
77                      page_rect,
78                      shrink));
79  {
80    base::AutoLock lock(lock_);
81    mutable_.pages_[page_number] = page;
82
83#if defined(OS_POSIX) && !defined(OS_MACOSX)
84    if (page_number < mutable_.first_page)
85      mutable_.first_page = page_number;
86#endif
87  }
88  DebugDump(*page.get());
89}
90
91bool PrintedDocument::GetPage(int page_number,
92                              scoped_refptr<PrintedPage>* page) {
93  base::AutoLock lock(lock_);
94  PrintedPages::const_iterator itr = mutable_.pages_.find(page_number);
95  if (itr != mutable_.pages_.end()) {
96    if (itr->second.get()) {
97      *page = itr->second;
98      return true;
99    }
100  }
101  return false;
102}
103
104bool PrintedDocument::IsComplete() const {
105  base::AutoLock lock(lock_);
106  if (!mutable_.page_count_)
107    return false;
108  PageNumber page(immutable_.settings_, mutable_.page_count_);
109  if (page == PageNumber::npos())
110    return false;
111
112  for (; page != PageNumber::npos(); ++page) {
113#if defined(OS_WIN) || defined(OS_MACOSX)
114    const bool metafile_must_be_valid = true;
115#elif defined(OS_POSIX)
116    const bool metafile_must_be_valid = (page.ToInt() == mutable_.first_page);
117#endif
118    PrintedPages::const_iterator itr = mutable_.pages_.find(page.ToInt());
119    if (itr == mutable_.pages_.end() || !itr->second.get())
120      return false;
121    if (metafile_must_be_valid && !itr->second->metafile())
122      return false;
123  }
124  return true;
125}
126
127void PrintedDocument::DisconnectSource() {
128  base::AutoLock lock(lock_);
129  mutable_.source_ = NULL;
130}
131
132uint32 PrintedDocument::MemoryUsage() const {
133  std::vector< scoped_refptr<PrintedPage> > pages_copy;
134  {
135    base::AutoLock lock(lock_);
136    pages_copy.reserve(mutable_.pages_.size());
137    PrintedPages::const_iterator end = mutable_.pages_.end();
138    for (PrintedPages::const_iterator itr = mutable_.pages_.begin();
139         itr != end; ++itr) {
140      if (itr->second.get()) {
141        pages_copy.push_back(itr->second);
142      }
143    }
144  }
145  uint32 total = 0;
146  for (size_t i = 0; i < pages_copy.size(); ++i) {
147    total += pages_copy[i]->metafile()->GetDataSize();
148  }
149  return total;
150}
151
152void PrintedDocument::set_page_count(int max_page) {
153  base::AutoLock lock(lock_);
154  DCHECK_EQ(0, mutable_.page_count_);
155  mutable_.page_count_ = max_page;
156  if (immutable_.settings_.ranges.empty()) {
157    mutable_.expected_page_count_ = max_page;
158  } else {
159    // If there is a range, don't bother since expected_page_count_ is already
160    // initialized.
161    DCHECK_NE(mutable_.expected_page_count_, 0);
162  }
163}
164
165int PrintedDocument::page_count() const {
166  base::AutoLock lock(lock_);
167  return mutable_.page_count_;
168}
169
170int PrintedDocument::expected_page_count() const {
171  base::AutoLock lock(lock_);
172  return mutable_.expected_page_count_;
173}
174
175void PrintedDocument::DebugDump(const PrintedPage& page) {
176  if (!g_debug_dump_info.Get().enabled)
177    return;
178
179  string16 filename;
180  filename += name();
181  filename += ASCIIToUTF16("_");
182  filename += ASCIIToUTF16(base::StringPrintf("%02d", page.page_number()));
183#if defined(OS_WIN)
184  filename += ASCIIToUTF16("_.emf");
185  page.metafile()->SaveTo(
186      g_debug_dump_info.Get().debug_dump_path.Append(filename));
187#else  // OS_WIN
188  filename += ASCIIToUTF16("_.pdf");
189  page.metafile()->SaveTo(
190      g_debug_dump_info.Get().debug_dump_path.Append(UTF16ToUTF8(filename)));
191#endif  // OS_WIN
192}
193
194void PrintedDocument::set_debug_dump_path(
195    const base::FilePath& debug_dump_path) {
196  g_debug_dump_info.Get().enabled = !debug_dump_path.empty();
197  g_debug_dump_info.Get().debug_dump_path = debug_dump_path;
198}
199
200const base::FilePath& PrintedDocument::debug_dump_path() {
201  return g_debug_dump_info.Get().debug_dump_path;
202}
203
204PrintedDocument::Mutable::Mutable(PrintedPagesSource* source)
205    : source_(source),
206      expected_page_count_(0),
207      page_count_(0) {
208#if defined(OS_POSIX) && !defined(OS_MACOSX)
209  first_page = INT_MAX;
210#endif
211}
212
213PrintedDocument::Mutable::~Mutable() {
214}
215
216PrintedDocument::Immutable::Immutable(const PrintSettings& settings,
217                                      PrintedPagesSource* source,
218                                      int cookie)
219    : settings_(settings),
220      source_message_loop_(base::MessageLoop::current()),
221      name_(source->RenderSourceName()),
222      cookie_(cookie) {
223}
224
225PrintedDocument::Immutable::~Immutable() {
226}
227
228#if (defined(OS_POSIX) && defined(USE_AURA)) || defined(OS_ANDROID)
229// This function is not used on aura linux/chromeos or android.
230void PrintedDocument::RenderPrintedPage(const PrintedPage& page,
231                                        PrintingContext* context) const {
232}
233#endif
234
235}  // namespace printing
236