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/base/text/text_elider.h"
     27 #include "ui/gfx/font.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   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 
    194 void 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 
    200 const base::FilePath& PrintedDocument::debug_dump_path() {
    201   return g_debug_dump_info.Get().debug_dump_path;
    202 }
    203 
    204 PrintedDocument::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 
    213 PrintedDocument::Mutable::~Mutable() {
    214 }
    215 
    216 PrintedDocument::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 
    225 PrintedDocument::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.
    230 void PrintedDocument::RenderPrintedPage(const PrintedPage& page,
    231                                         PrintingContext* context) const {
    232 }
    233 #endif
    234 
    235 }  // namespace printing
    236