- add sources.
[platform/framework/web/crosswalk.git] / src / printing / printed_document.cc
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/gfx/font.h"
27 #include "ui/gfx/text_elider.h"
28
29 namespace {
30
31 struct PrintDebugDumpPath {
32   PrintDebugDumpPath()
33     : enabled(false) {
34   }
35
36   bool enabled;
37   base::FilePath debug_dump_path;
38 };
39
40 base::LazyInstance<PrintDebugDumpPath> g_debug_dump_info =
41     LAZY_INSTANCE_INITIALIZER;
42
43 }  // namespace
44
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
66 void 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
91 bool 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
104 bool 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
127 void PrintedDocument::DisconnectSource() {
128   base::AutoLock lock(lock_);
129   mutable_.source_ = NULL;
130 }
131
132 uint32 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
152 void 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
165 int PrintedDocument::page_count() const {
166   base::AutoLock lock(lock_);
167   return mutable_.page_count_;
168 }
169
170 int PrintedDocument::expected_page_count() const {
171   base::AutoLock lock(lock_);
172   return mutable_.expected_page_count_;
173 }
174
175 void PrintedDocument::DebugDump(const PrintedPage& page) {
176   if (!g_debug_dump_info.Get().enabled)
177     return;
178
179   base::string16 filename;
180   filename += name();
181   filename += base::ASCIIToUTF16("_");
182   filename += base::ASCIIToUTF16(
183       base::StringPrintf("%02d", page.page_number()));
184 #if defined(OS_WIN)
185   filename += base::ASCIIToUTF16("_.emf");
186   page.metafile()->SaveTo(
187       g_debug_dump_info.Get().debug_dump_path.Append(filename));
188 #else  // OS_WIN
189   filename += base::ASCIIToUTF16("_.pdf");
190   page.metafile()->SaveTo(
191       g_debug_dump_info.Get().debug_dump_path.Append(
192           base::UTF16ToUTF8(filename)));
193 #endif  // OS_WIN
194 }
195
196 void PrintedDocument::set_debug_dump_path(
197     const base::FilePath& debug_dump_path) {
198   g_debug_dump_info.Get().enabled = !debug_dump_path.empty();
199   g_debug_dump_info.Get().debug_dump_path = debug_dump_path;
200 }
201
202 const base::FilePath& PrintedDocument::debug_dump_path() {
203   return g_debug_dump_info.Get().debug_dump_path;
204 }
205
206 PrintedDocument::Mutable::Mutable(PrintedPagesSource* source)
207     : source_(source),
208       expected_page_count_(0),
209       page_count_(0) {
210 #if defined(OS_POSIX) && !defined(OS_MACOSX)
211   first_page = INT_MAX;
212 #endif
213 }
214
215 PrintedDocument::Mutable::~Mutable() {
216 }
217
218 PrintedDocument::Immutable::Immutable(const PrintSettings& settings,
219                                       PrintedPagesSource* source,
220                                       int cookie)
221     : settings_(settings),
222       source_message_loop_(base::MessageLoop::current()),
223       name_(source->RenderSourceName()),
224       cookie_(cookie) {
225 }
226
227 PrintedDocument::Immutable::~Immutable() {
228 }
229
230 #if (defined(OS_POSIX) && defined(USE_AURA)) || defined(OS_ANDROID)
231 // This function is not used on aura linux/chromeos or android.
232 void PrintedDocument::RenderPrintedPage(const PrintedPage& page,
233                                         PrintingContext* context) const {
234 }
235 #endif
236
237 }  // namespace printing