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