Home | History | Annotate | Download | only in printing
      1 // Copyright (c) 2012 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 #ifndef PRINTING_EMF_WIN_H_
      6 #define PRINTING_EMF_WIN_H_
      7 
      8 #include <windows.h>
      9 
     10 #include <vector>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/gtest_prod_util.h"
     15 #include "printing/metafile.h"
     16 
     17 namespace base {
     18 class FilePath;
     19 }
     20 
     21 namespace gfx {
     22 class Rect;
     23 class Size;
     24 }
     25 
     26 namespace printing {
     27 
     28 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
     29 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
     30 // MB, it can fail to print and not send an error message.
     31 const size_t kMetafileMaxSize = 350*1024*1024;
     32 
     33 // Simple wrapper class that manage an EMF data stream and its virtual HDC.
     34 class PRINTING_EXPORT Emf : public Metafile {
     35  public:
     36   class Record;
     37   class Enumerator;
     38   struct EnumerationContext;
     39 
     40   // Generates a virtual HDC that will record every GDI commands and compile
     41   // it in a EMF data stream.
     42   Emf();
     43   virtual ~Emf();
     44 
     45   // Generates a new metafile that will record every GDI command, and will
     46   // be saved to |metafile_path|.
     47   virtual bool InitToFile(const base::FilePath& metafile_path);
     48 
     49   // Initializes the Emf with the data in |metafile_path|.
     50   virtual bool InitFromFile(const base::FilePath& metafile_path);
     51 
     52   // Metafile methods.
     53   virtual bool Init() OVERRIDE;
     54   virtual bool InitFromData(const void* src_buffer,
     55                             uint32 src_buffer_size) OVERRIDE;
     56 
     57   virtual SkBaseDevice* StartPageForVectorCanvas(
     58       const gfx::Size& page_size, const gfx::Rect& content_area,
     59       const float& scale_factor) OVERRIDE;
     60   // Inserts a custom GDICOMMENT records indicating StartPage/EndPage calls
     61   // (since StartPage and EndPage do not work in a metafile DC). Only valid
     62   // when hdc_ is non-NULL. |page_size|, |content_area|, and |scale_factor| are
     63   // ignored.
     64   virtual bool StartPage(const gfx::Size& page_size,
     65                          const gfx::Rect& content_area,
     66                          const float& scale_factor) OVERRIDE;
     67   virtual bool FinishPage() OVERRIDE;
     68   virtual bool FinishDocument() OVERRIDE;
     69 
     70   virtual uint32 GetDataSize() const OVERRIDE;
     71   virtual bool GetData(void* buffer, uint32 size) const OVERRIDE;
     72 
     73   // Saves the EMF data to a file as-is. It is recommended to use the .emf file
     74   // extension but it is not enforced. This function synchronously writes to the
     75   // file. For testing only.
     76   virtual bool SaveTo(const base::FilePath& file_path) const OVERRIDE;
     77 
     78   // Should be passed to Playback to keep the exact same size.
     79   virtual gfx::Rect GetPageBounds(unsigned int page_number) const OVERRIDE;
     80 
     81   virtual unsigned int GetPageCount() const OVERRIDE {
     82     return page_count_;
     83   }
     84 
     85   virtual HDC context() const OVERRIDE {
     86     return hdc_;
     87   }
     88 
     89   virtual bool Playback(HDC hdc, const RECT* rect) const OVERRIDE;
     90   virtual bool SafePlayback(HDC hdc) const OVERRIDE;
     91 
     92   virtual HENHMETAFILE emf() const OVERRIDE {
     93     return emf_;
     94   }
     95 
     96   // Returns true if metafile contains alpha blend.
     97   bool IsAlphaBlendUsed() const;
     98 
     99   // Returns new metafile with only bitmap created by playback of the current
    100   // metafile. Returns NULL if fails.
    101   Emf* RasterizeMetafile(int raster_area_in_pixels) const;
    102 
    103   // Returns new metafile where AlphaBlend replaced by bitmaps. Returns NULL
    104   // if fails.
    105   Emf* RasterizeAlphaBlend() const;
    106 
    107  private:
    108   FRIEND_TEST_ALL_PREFIXES(EmfTest, DC);
    109   FRIEND_TEST_ALL_PREFIXES(EmfPrintingTest, PageBreak);
    110   FRIEND_TEST_ALL_PREFIXES(EmfTest, FileBackedEmf);
    111 
    112   // Retrieves the underlying data stream. It is a helper function.
    113   bool GetDataAsVector(std::vector<uint8>* buffer) const;
    114 
    115   // Playbacks safely one EMF record.
    116   static int CALLBACK SafePlaybackProc(HDC hdc,
    117                                        HANDLETABLE* handle_table,
    118                                        const ENHMETARECORD* record,
    119                                        int objects_count,
    120                                        LPARAM param);
    121 
    122   // Compiled EMF data handle.
    123   HENHMETAFILE emf_;
    124 
    125   // Valid when generating EMF data through a virtual HDC.
    126   HDC hdc_;
    127 
    128   int page_count_;
    129 
    130   DISALLOW_COPY_AND_ASSIGN(Emf);
    131 };
    132 
    133 struct Emf::EnumerationContext {
    134   EnumerationContext();
    135 
    136   HANDLETABLE* handle_table;
    137   int objects_count;
    138   HDC hdc;
    139   const XFORM* base_matrix;
    140   int dc_on_page_start;
    141 };
    142 
    143 // One EMF record. It keeps pointers to the EMF buffer held by Emf::emf_.
    144 // The entries become invalid once Emf::CloseEmf() is called.
    145 class PRINTING_EXPORT Emf::Record {
    146  public:
    147   // Plays the record.
    148   bool Play(EnumerationContext* context) const;
    149 
    150   // Plays the record working around quirks with SetLayout,
    151   // SetWorldTransform and ModifyWorldTransform. See implementation for details.
    152   bool SafePlayback(EnumerationContext* context) const;
    153 
    154   // Access the underlying EMF record.
    155   const ENHMETARECORD* record() const { return record_; }
    156 
    157  protected:
    158   explicit Record(const ENHMETARECORD* record);
    159 
    160  private:
    161   friend class Emf;
    162   friend class Enumerator;
    163   const ENHMETARECORD* record_;
    164 };
    165 
    166 // Retrieves individual records out of a Emf buffer. The main use is to skip
    167 // over records that are unsupported on a specific printer or to play back
    168 // only a part of an EMF buffer.
    169 class PRINTING_EXPORT Emf::Enumerator {
    170  public:
    171   // Iterator type used for iterating the records.
    172   typedef std::vector<Record>::const_iterator const_iterator;
    173 
    174   // Enumerates the records at construction time. |hdc| and |rect| are
    175   // both optional at the same time or must both be valid.
    176   // Warning: |emf| must be kept valid for the time this object is alive.
    177   Enumerator(const Emf& emf, HDC hdc, const RECT* rect);
    178 
    179   // Retrieves the first Record.
    180   const_iterator begin() const;
    181 
    182   // Retrieves the end of the array.
    183   const_iterator end() const;
    184 
    185  private:
    186   FRIEND_TEST_ALL_PREFIXES(EmfPrintingTest, Enumerate);
    187 
    188   // Processes one EMF record and saves it in the items_ array.
    189   static int CALLBACK EnhMetaFileProc(HDC hdc,
    190                                       HANDLETABLE* handle_table,
    191                                       const ENHMETARECORD* record,
    192                                       int objects_count,
    193                                       LPARAM param);
    194 
    195   // The collection of every EMF records in the currently loaded EMF buffer.
    196   // Initialized by Enumerate(). It keeps pointers to the EMF buffer held by
    197   // Emf::emf_. The entries become invalid once Emf::CloseEmf() is called.
    198   std::vector<Record> items_;
    199 
    200   EnumerationContext context_;
    201 
    202   DISALLOW_COPY_AND_ASSIGN(Enumerator);
    203 };
    204 
    205 }  // namespace printing
    206 
    207 #endif  // PRINTING_EMF_WIN_H_
    208