Home | History | Annotate | Download | only in printing
      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
    238