• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetPageCount()81   virtual unsigned int GetPageCount() const OVERRIDE {
82     return page_count_;
83   }
84 
context()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 
emf()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.
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