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