| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef PRINTING_EMF_WIN_H_ | 
 | #define PRINTING_EMF_WIN_H_ | 
 |  | 
 | #include <windows.h> | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "base/basictypes.h" | 
 | #include "base/compiler_specific.h" | 
 | #include "base/gtest_prod_util.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 | #include "printing/metafile.h" | 
 |  | 
 | namespace base { | 
 | class FilePath; | 
 | } | 
 |  | 
 | namespace gfx { | 
 | class Rect; | 
 | class Size; | 
 | } | 
 |  | 
 | namespace printing { | 
 |  | 
 | // http://msdn2.microsoft.com/en-us/library/ms535522.aspx | 
 | // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 | 
 | // MB, it can fail to print and not send an error message. | 
 | const size_t kMetafileMaxSize = 350*1024*1024; | 
 |  | 
 | // Simple wrapper class that manage an EMF data stream and its virtual HDC. | 
 | class PRINTING_EXPORT Emf : public Metafile { | 
 |  public: | 
 |   class Record; | 
 |   class Enumerator; | 
 |   struct EnumerationContext; | 
 |  | 
 |   // Generates a virtual HDC that will record every GDI commands and compile | 
 |   // it in a EMF data stream. | 
 |   Emf(); | 
 |   virtual ~Emf(); | 
 |  | 
 |   // Closes metafile. | 
 |   void Close(); | 
 |  | 
 |   // Generates a new metafile that will record every GDI command, and will | 
 |   // be saved to |metafile_path|. | 
 |   bool InitToFile(const base::FilePath& metafile_path); | 
 |  | 
 |   // Initializes the Emf with the data in |metafile_path|. | 
 |   bool InitFromFile(const base::FilePath& metafile_path); | 
 |  | 
 |   // Metafile methods. | 
 |   virtual bool Init() override; | 
 |   virtual bool InitFromData(const void* src_buffer, | 
 |                             uint32 src_buffer_size) override; | 
 |  | 
 |   // Inserts a custom GDICOMMENT records indicating StartPage/EndPage calls | 
 |   // (since StartPage and EndPage do not work in a metafile DC). Only valid | 
 |   // when hdc_ is non-NULL. |page_size|, |content_area|, and |scale_factor| are | 
 |   // ignored. | 
 |   virtual bool StartPage(const gfx::Size& page_size, | 
 |                          const gfx::Rect& content_area, | 
 |                          const float& scale_factor) override; | 
 |   virtual bool FinishPage() override; | 
 |   virtual bool FinishDocument() override; | 
 |  | 
 |   virtual uint32 GetDataSize() const override; | 
 |   virtual bool GetData(void* buffer, uint32 size) const override; | 
 |  | 
 |   // Should be passed to Playback to keep the exact same size. | 
 |   virtual gfx::Rect GetPageBounds(unsigned int page_number) const override; | 
 |  | 
 |   virtual unsigned int GetPageCount() const override { return 1; } | 
 |  | 
 |   virtual HDC context() const override { | 
 |     return hdc_; | 
 |   } | 
 |  | 
 |   virtual bool Playback(HDC hdc, const RECT* rect) const override; | 
 |   virtual bool SafePlayback(HDC hdc) const override; | 
 |  | 
 |   HENHMETAFILE emf() const { return emf_; } | 
 |  | 
 |   // Returns true if metafile contains alpha blend. | 
 |   bool IsAlphaBlendUsed() const; | 
 |  | 
 |   // Returns new metafile with only bitmap created by playback of the current | 
 |   // metafile. Returns NULL if fails. | 
 |   scoped_ptr<Emf> RasterizeMetafile(int raster_area_in_pixels) const; | 
 |  | 
 |   // Returns new metafile where AlphaBlend replaced by bitmaps. Returns NULL | 
 |   // if fails. | 
 |   scoped_ptr<Emf> RasterizeAlphaBlend() const; | 
 |  | 
 |  private: | 
 |   FRIEND_TEST_ALL_PREFIXES(EmfTest, DC); | 
 |   FRIEND_TEST_ALL_PREFIXES(EmfPrintingTest, PageBreak); | 
 |   FRIEND_TEST_ALL_PREFIXES(EmfTest, FileBackedEmf); | 
 |  | 
 |   // Playbacks safely one EMF record. | 
 |   static int CALLBACK SafePlaybackProc(HDC hdc, | 
 |                                        HANDLETABLE* handle_table, | 
 |                                        const ENHMETARECORD* record, | 
 |                                        int objects_count, | 
 |                                        LPARAM param); | 
 |  | 
 |   // Compiled EMF data handle. | 
 |   HENHMETAFILE emf_; | 
 |  | 
 |   // Valid when generating EMF data through a virtual HDC. | 
 |   HDC hdc_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(Emf); | 
 | }; | 
 |  | 
 | struct Emf::EnumerationContext { | 
 |   EnumerationContext(); | 
 |  | 
 |   HANDLETABLE* handle_table; | 
 |   int objects_count; | 
 |   HDC hdc; | 
 |   const XFORM* base_matrix; | 
 |   int dc_on_page_start; | 
 | }; | 
 |  | 
 | // One EMF record. It keeps pointers to the EMF buffer held by Emf::emf_. | 
 | // The entries become invalid once Emf::CloseEmf() is called. | 
 | class PRINTING_EXPORT Emf::Record { | 
 |  public: | 
 |   // Plays the record. | 
 |   bool Play(EnumerationContext* context) const; | 
 |  | 
 |   // Plays the record working around quirks with SetLayout, | 
 |   // SetWorldTransform and ModifyWorldTransform. See implementation for details. | 
 |   bool SafePlayback(EnumerationContext* context) const; | 
 |  | 
 |   // Access the underlying EMF record. | 
 |   const ENHMETARECORD* record() const { return record_; } | 
 |  | 
 |  protected: | 
 |   explicit Record(const ENHMETARECORD* record); | 
 |  | 
 |  private: | 
 |   friend class Emf; | 
 |   friend class Enumerator; | 
 |   const ENHMETARECORD* record_; | 
 | }; | 
 |  | 
 | // Retrieves individual records out of a Emf buffer. The main use is to skip | 
 | // over records that are unsupported on a specific printer or to play back | 
 | // only a part of an EMF buffer. | 
 | class PRINTING_EXPORT Emf::Enumerator { | 
 |  public: | 
 |   // Iterator type used for iterating the records. | 
 |   typedef std::vector<Record>::const_iterator const_iterator; | 
 |  | 
 |   // Enumerates the records at construction time. |hdc| and |rect| are | 
 |   // both optional at the same time or must both be valid. | 
 |   // Warning: |emf| must be kept valid for the time this object is alive. | 
 |   Enumerator(const Emf& emf, HDC hdc, const RECT* rect); | 
 |  | 
 |   // Retrieves the first Record. | 
 |   const_iterator begin() const; | 
 |  | 
 |   // Retrieves the end of the array. | 
 |   const_iterator end() const; | 
 |  | 
 |  private: | 
 |   FRIEND_TEST_ALL_PREFIXES(EmfPrintingTest, Enumerate); | 
 |  | 
 |   // Processes one EMF record and saves it in the items_ array. | 
 |   static int CALLBACK EnhMetaFileProc(HDC hdc, | 
 |                                       HANDLETABLE* handle_table, | 
 |                                       const ENHMETARECORD* record, | 
 |                                       int objects_count, | 
 |                                       LPARAM param); | 
 |  | 
 |   // The collection of every EMF records in the currently loaded EMF buffer. | 
 |   // Initialized by Enumerate(). It keeps pointers to the EMF buffer held by | 
 |   // Emf::emf_. The entries become invalid once Emf::CloseEmf() is called. | 
 |   std::vector<Record> items_; | 
 |  | 
 |   EnumerationContext context_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(Enumerator); | 
 | }; | 
 |  | 
 | }  // namespace printing | 
 |  | 
 | #endif  // PRINTING_EMF_WIN_H_ |