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