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