diff options
author | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 01:39:42 +0000 |
---|---|---|
committer | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-16 01:39:42 +0000 |
commit | 8f17cd3e165a4d0cc9a03c029ee5f4d39c5e77e7 (patch) | |
tree | fba63800e4b02432be8c45673e32f234d69cce9e /printing | |
parent | 0da15e586f92f3488658034bfef5ecbf42656791 (diff) | |
download | chromium_src-8f17cd3e165a4d0cc9a03c029ee5f4d39c5e77e7.zip chromium_src-8f17cd3e165a4d0cc9a03c029ee5f4d39c5e77e7.tar.gz chromium_src-8f17cd3e165a4d0cc9a03c029ee5f4d39c5e77e7.tar.bz2 |
Unifying NativeMetafile class interface (as much as possible) for Linux, Mac, Win
BUG=NONE
TEST=NONE
Review URL: http://codereview.chromium.org/6611032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78320 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing')
-rw-r--r-- | printing/emf_win.cc | 16 | ||||
-rw-r--r-- | printing/emf_win.h | 88 | ||||
-rw-r--r-- | printing/emf_win_unittest.cc | 18 | ||||
-rw-r--r-- | printing/image_win.cc | 2 | ||||
-rw-r--r-- | printing/native_metafile.h | 176 | ||||
-rw-r--r-- | printing/native_metafile_linux.h | 81 | ||||
-rw-r--r-- | printing/native_metafile_mac.h | 90 | ||||
-rw-r--r-- | printing/native_metafile_win.h | 103 | ||||
-rw-r--r-- | printing/pdf_metafile_mac.cc | 19 | ||||
-rw-r--r-- | printing/pdf_metafile_mac.h | 80 | ||||
-rw-r--r-- | printing/pdf_metafile_mac_unittest.cc | 3 | ||||
-rw-r--r-- | printing/pdf_ps_metafile_cairo.cc | 58 | ||||
-rw-r--r-- | printing/pdf_ps_metafile_cairo.h | 68 | ||||
-rw-r--r-- | printing/pdf_ps_metafile_cairo_unittest.cc | 17 | ||||
-rw-r--r-- | printing/printed_document.cc | 8 | ||||
-rw-r--r-- | printing/printing.gyp | 3 |
16 files changed, 330 insertions, 500 deletions
diff --git a/printing/emf_win.cc b/printing/emf_win.cc index f2b22fa..1d1dd53 100644 --- a/printing/emf_win.cc +++ b/printing/emf_win.cc @@ -85,7 +85,7 @@ bool Emf::CreateFromFile(const FilePath& metafile_path) { } -bool Emf::CloseDc() { +bool Emf::Close() { DCHECK(!emf_ && hdc_); emf_ = CloseEnhMetaFile(hdc_); DCHECK(emf_); @@ -106,7 +106,7 @@ bool Emf::Playback(HDC hdc, const RECT* rect) const { RECT bounds; if (!rect) { // Get the natural bounds of the EMF buffer. - bounds = GetBounds().ToRECT(); + bounds = GetPageBounds(1).ToRECT(); rect = &bounds; } return PlayEnhMetaFile(hdc, emf_, rect) != 0; @@ -123,11 +123,12 @@ bool Emf::SafePlayback(HDC context) const { emf_, &Emf::SafePlaybackProc, reinterpret_cast<void*>(&base_matrix), - &GetBounds().ToRECT()) != 0; + &GetPageBounds(1).ToRECT()) != 0; } -gfx::Rect Emf::GetBounds() const { +gfx::Rect Emf::GetPageBounds(unsigned int page_number) const { DCHECK(emf_ && !hdc_); + DCHECK_EQ(1U, page_number); ENHMETAHEADER header; if (GetEnhMetaFileHeader(emf_, sizeof(header), &header) != sizeof(header)) { NOTREACHED(); @@ -173,8 +174,8 @@ bool Emf::GetData(std::vector<uint8>* buffer) const { return true; } -bool Emf::SaveTo(const std::wstring& filename) const { - HANDLE file = CreateFile(filename.c_str(), GENERIC_WRITE, +bool Emf::SaveTo(const FilePath& file_path) const { + HANDLE file = CreateFile(file_path.value().c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); if (file == INVALID_HANDLE_VALUE) @@ -418,7 +419,7 @@ bool Emf::StartPage() { reinterpret_cast<const BYTE *>(&record)); } -bool Emf::EndPage() { +bool Emf::FinishPage() { DCHECK(hdc_); if (!hdc_) return false; @@ -427,7 +428,6 @@ bool Emf::EndPage() { reinterpret_cast<const BYTE *>(&record)); } - Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) { context_.handle_table = NULL; context_.objects_count = 0; diff --git a/printing/emf_win.h b/printing/emf_win.h index ba139d8..e054db3 100644 --- a/printing/emf_win.h +++ b/printing/emf_win.h @@ -10,7 +10,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" -#include "printing/native_metafile_win.h" +#include "printing/native_metafile.h" class FilePath; @@ -29,83 +29,51 @@ class Emf : public NativeMetafile { virtual ~Emf(); - // Initializes the Emf with the data in |src_buffer|. Returns true on success. + // NativeMetafile methods. + virtual bool Init() { return true; } virtual bool Init(const void* src_buffer, uint32 src_buffer_size); - // Generates a virtual HDC that will record every GDI commands and compile it - // in a EMF data stream. - // hdc is used to setup the default DPI and color settings. hdc is optional. - // rect specifies the dimensions (in .01-millimeter units) of the EMF. rect is - // optional. - virtual bool CreateDc(HDC sibling, const RECT* rect); + virtual bool StartPage(); + virtual bool FinishPage(); + virtual bool Close(); - // Similar to the above method but the metafile is backed by a file. - virtual bool CreateFileBackedDc(HDC sibling, - const RECT* rect, - const FilePath& path); + virtual uint32 GetDataSize() const; + virtual bool GetData(void* buffer, uint32 size) const; - // Load an EMF file. - virtual bool CreateFromFile(const FilePath& metafile_path); + // Saves the EMF data to a file as-is. It is recommended to use the .emf file + // extension but it is not enforced. This function synchronously writes to the + // file. For testing only. + virtual bool SaveTo(const FilePath& file_path) const; + + // Should be passed to Playback to keep the exact same size. + virtual gfx::Rect GetPageBounds(unsigned int page_number) const; + + virtual unsigned int GetPageCount() const { + // TODO(dpapad): count the number of times StartPage() is called + return 1; + } - // TODO(maruel): CreateFromFile(). If ever used. Maybe users would like to - // have the ability to save web pages to an EMF file? Afterward, it is easy to - // convert to PDF or PS. + virtual HDC context() const { + return hdc_; + } - // Closes the HDC created by CreateDc() and generates the compiled EMF - // data. - virtual bool CloseDc(); + virtual bool CreateDc(HDC sibling, const RECT* rect); + virtual bool CreateFileBackedDc(HDC sibling, + const RECT* rect, + const FilePath& path); + virtual bool CreateFromFile(const FilePath& file_path); - // Closes the EMF data handle when it is not needed anymore. virtual void CloseEmf(); - // "Plays" the EMF buffer in a HDC. It is the same effect as calling the - // original GDI function that were called when recording the EMF. |rect| is in - // "logical units" and is optional. If |rect| is NULL, the natural EMF bounds - // are used. - // Note: Windows has been known to have stack buffer overflow in its GDI - // functions, whether used directly or indirectly through precompiled EMF - // data. We have to accept the risk here. Since it is used only for printing, - // it requires user intervention. virtual bool Playback(HDC hdc, const RECT* rect) const; - - // The slow version of Playback(). It enumerates all the records and play them - // back in the HDC. The trick is that it skip over the records known to have - // issue with some printers. See Emf::Record::SafePlayback implementation for - // details. virtual bool SafePlayback(HDC hdc) const; - // Retrieves the bounds of the painted area by this EMF buffer. This value - // should be passed to Playback to keep the exact same size. - virtual gfx::Rect GetBounds() const; - - // Retrieves the EMF stream size. - virtual uint32 GetDataSize() const; - - // Retrieves the EMF stream. - virtual bool GetData(void* buffer, uint32 size) const; - - // Retrieves the EMF stream. It is an helper function. virtual bool GetData(std::vector<uint8>* buffer) const; virtual HENHMETAFILE emf() const { return emf_; } - virtual HDC hdc() const { - return hdc_; - } - - // 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. - virtual bool StartPage(); - virtual bool EndPage(); - - // Saves the EMF data to a file as-is. It is recommended to use the .emf file - // extension but it is not enforced. This function synchronously writes to the - // file. For testing only. - virtual bool SaveTo(const std::wstring& filename) const; - protected: Emf(); diff --git a/printing/emf_win_unittest.cc b/printing/emf_win_unittest.cc index 9d3aa00..9ae9323 100644 --- a/printing/emf_win_unittest.cc +++ b/printing/emf_win_unittest.cc @@ -48,9 +48,9 @@ TEST(EmfTest, DC) { HDC hdc = CreateCompatibleDC(NULL); EXPECT_TRUE(hdc != NULL); EXPECT_TRUE(emf.CreateDc(hdc, &rect)); - EXPECT_TRUE(emf.hdc() != NULL); + EXPECT_TRUE(emf.context() != NULL); // In theory, you'd use the HDC with GDI functions here. - EXPECT_TRUE(emf.CloseDc()); + EXPECT_TRUE(emf.Close()); uint32 size = emf.GetDataSize(); EXPECT_EQ(size, EMF_HEADER_SIZE); std::vector<BYTE> data; @@ -104,7 +104,7 @@ TEST_F(EmfPrintingTest, Enumerate) { context->NewPage(); // Process one at a time. printing::Emf::Enumerator emf_enum(emf, context->context(), - &emf.GetBounds().ToRECT()); + &emf.GetPageBounds(1).ToRECT()); for (printing::Emf::Enumerator::const_iterator itr = emf_enum.begin(); itr != emf_enum.end(); ++itr) { @@ -128,15 +128,15 @@ TEST_F(EmfPrintingTest, PageBreak) { return; printing::Emf emf; EXPECT_TRUE(emf.CreateDc(dc.Get(), NULL)); - EXPECT_TRUE(emf.hdc() != NULL); + EXPECT_TRUE(emf.context() != NULL); int pages = 3; while (pages) { EXPECT_TRUE(emf.StartPage()); - ::Rectangle(emf.hdc(), 10, 10, 190, 190); - EXPECT_TRUE(emf.EndPage()); + ::Rectangle(emf.context(), 10, 10, 190, 190); + EXPECT_TRUE(emf.FinishPage()); --pages; } - EXPECT_TRUE(emf.CloseDc()); + EXPECT_TRUE(emf.Close()); uint32 size = emf.GetDataSize(); std::vector<BYTE> data; EXPECT_TRUE(emf.GetData(&data)); @@ -172,9 +172,9 @@ TEST(EmfTest, FileBackedDC) { EXPECT_TRUE(file_util::CreateTemporaryFileInDir(scratch_metafile_dir.path(), &metafile_path)); EXPECT_TRUE(emf.CreateFileBackedDc(hdc, &rect, metafile_path)); - EXPECT_TRUE(emf.hdc() != NULL); + EXPECT_TRUE(emf.context() != NULL); // In theory, you'd use the HDC with GDI functions here. - EXPECT_TRUE(emf.CloseDc()); + EXPECT_TRUE(emf.Close()); uint32 size = emf.GetDataSize(); EXPECT_EQ(size, EMF_HEADER_SIZE); diff --git a/printing/image_win.cc b/printing/image_win.cc index c4bc1a7..be089dc 100644 --- a/printing/image_win.cc +++ b/printing/image_win.cc @@ -45,7 +45,7 @@ class DisableFontSmoothing { namespace printing { bool Image::LoadMetafile(const NativeMetafile& metafile) { - gfx::Rect rect(metafile.GetBounds()); + gfx::Rect rect(metafile.GetPageBounds(1)); DisableFontSmoothing disable_in_this_scope; // Create a temporary HDC and bitmap to retrieve the rendered data. diff --git a/printing/native_metafile.h b/printing/native_metafile.h index 7e1d25b..65f9f4c 100644 --- a/printing/native_metafile.h +++ b/printing/native_metafile.h @@ -7,13 +7,183 @@ #include "base/basictypes.h" #include "build/build_config.h" +#include "ui/gfx/native_widget_types.h" #if defined(OS_WIN) -#include "printing/native_metafile_win.h" +#include <windows.h> +#include <vector> #elif defined(OS_MACOSX) -#include "printing/native_metafile_mac.h" +#include <ApplicationServices/ApplicationServices.h> +#include <CoreFoundation/CoreFoundation.h> +#include "base/mac/scoped_cftyperef.h" +#endif + +class FilePath; + +namespace gfx { +class Rect; +class Size; +class Point; +} + +#if defined(OS_CHROMEOS) +namespace base { +class FileDescriptor; +} +#endif + +namespace printing { + +// This class creates a graphics context that renders into a data stream +// (usually PDF or EMF). +class NativeMetafile { + public: + virtual ~NativeMetafile() {} + + // Initializes a fresh new metafile for rendering. Returns false on failure. + // Note: It should only be called from within the renderer process to allocate + // rendering resources. + virtual bool Init() = 0; + + // Initializes the metafile with the data in |src_buffer|. Returns true + // on success. + // Note: It should only be called from within the browser process. + virtual bool Init(const void* src_buffer, uint32 src_buffer_size) = 0; + +#if defined(OS_WIN) + // 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. + virtual bool StartPage() = 0; +#elif defined(OS_MACOSX) + // Prepares a new pdf page at specified |content_origin| with the given + // |page_size| and a |scale_factor| to use for the drawing. + virtual gfx::NativeDrawingContext StartPage(const gfx::Size& page_size, + const gfx::Point& content_origin, + const float& scale_factor) = 0; +#elif defined(OS_POSIX) + // Prepares a new cairo surface/context for rendering a new page. + // The unit is in point (=1/72 in). + // Returns NULL when failed. + virtual gfx::NativeDrawingContext StartPage(const gfx::Size& page_size, + double margin_top_in_points, + double margin_left_in_points) = 0; +#endif + + + // Closes the current page and destroys the context used in rendering that + // page. The results of current page will be appended into the underlying + // data stream. Returns true on success. + virtual bool FinishPage() = 0; + + // Closes the metafile. No further rendering is allowed (the current page + // is implicitly closed). + virtual bool Close() = 0; + + // Returns the size of the underlying data stream. Only valid after Close() + // has been called. + virtual uint32 GetDataSize() const = 0; + + // Copies the first |dst_buffer_size| bytes of the underlying data stream into + // |dst_buffer|. This function should ONLY be called after Close() is invoked. + // Returns true if the copy succeeds. + virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const = 0; + + // Saves the underlying data to the given file. This function should ONLY be + // called after the metafile is closed. Returns true if writing succeeded. + virtual bool SaveTo(const FilePath& file_path) const = 0; + + // Returns the bounds of the given page. Pages use a 1-based index. + virtual gfx::Rect GetPageBounds(unsigned int page_number) const = 0; + virtual unsigned int GetPageCount() const = 0; + + // Get the context for rendering to the PDF. + virtual gfx::NativeDrawingContext context() const = 0; + +#if defined(OS_WIN) + // Generates a virtual HDC that will record every GDI commands and compile it + // in a EMF data stream. + // hdc is used to setup the default DPI and color settings. hdc is optional. + // rect specifies the dimensions (in .01-millimeter units) of the EMF. rect is + // optional. + virtual bool CreateDc(gfx::NativeDrawingContext sibling, + const RECT* rect) = 0; + + // Similar to the above method but the metafile is backed by a file. + virtual bool CreateFileBackedDc(gfx::NativeDrawingContext sibling, + const RECT* rect, + const FilePath& path) = 0; + + // TODO(maruel): CreateFromFile(). If ever used. Maybe users would like to + // have the ability to save web pages to an EMF file? Afterward, it is easy to + // convert to PDF or PS. + // Load a metafile fromdisk. + virtual bool CreateFromFile(const FilePath& metafile_path) = 0; + + // Closes the HDC created by CreateDc() and generates the compiled EMF + // data. + virtual void CloseEmf() = 0; + + // "Plays" the EMF buffer in a HDC. It is the same effect as calling the + // original GDI function that were called when recording the EMF. |rect| is in + // "logical units" and is optional. If |rect| is NULL, the natural EMF bounds + // are used. + // Note: Windows has been known to have stack buffer overflow in its GDI + // functions, whether used directly or indirectly through precompiled EMF + // data. We have to accept the risk here. Since it is used only for printing, + // it requires user intervention. + virtual bool Playback(gfx::NativeDrawingContext hdc, + const RECT* rect) const = 0; + + // The slow version of Playback(). It enumerates all the records and play them + // back in the HDC. The trick is that it skip over the records known to have + // issue with some printers. See Emf::Record::SafePlayback implementation for + // details. + virtual bool SafePlayback(gfx::NativeDrawingContext hdc) const = 0; + + // Retrieves the underlying data stream. It is a helper function. + virtual bool GetData(std::vector<uint8>* buffer) const = 0; + + virtual HENHMETAFILE emf() const = 0; +#elif defined(OS_MACOSX) + // Renders the given page into |rect| in the given context. + // Pages use a 1-based index. The rendering uses the following arguments + // to determine scaling and translation factors. + // |shrink_to_fit| specifies whether the output should be shrunk to fit the + // supplied |rect| if the page size is larger than |rect| in any dimension. + // If this is false, parts of the PDF page that lie outside the bounds will be + // clipped. + // |stretch_to_fit| specifies whether the output should be stretched to fit + // the supplied bounds if the page size is smaller than |rect| in all + // dimensions. + // |center_horizontally| specifies whether the final image (after any scaling + // is done) should be centered horizontally within the given |rect|. + // |center_vertically| specifies whether the final image (after any scaling + // is done) should be centered vertically within the given |rect|. + // Note that all scaling preserves the original aspect ratio of the page. + virtual bool RenderPage(unsigned int page_number, + gfx::NativeDrawingContext context, + const CGRect rect, + bool shrink_to_fit, + bool stretch_to_fit, + bool center_horizontally, + bool center_vertically) const = 0; #elif defined(OS_POSIX) -#include "printing/native_metafile_linux.h" + // Sets raw PDF data for the document. This is used when a cairo drawing + // surface has already been created. This method will cause all subsequent + // drawing on the surface to be discarded (in Close()). If Init() has not yet + // been called this method simply calls the second version of Init. + virtual bool SetRawData(const void* src_buffer, uint32 src_buffer_size) = 0; +#if defined(OS_CHROMEOS) + // Saves the underlying data to the file associated with fd. This function + // should ONLY be called after the metafile is closed. + // Returns true if writing succeeded. + virtual bool SaveToFD(const base::FileDescriptor& fd) const = 0; +#endif // if defined(OS_CHROMEOS) + #endif +}; + +} // namespace printing #endif // PRINTING_NATIVE_METAFILE_H_ diff --git a/printing/native_metafile_linux.h b/printing/native_metafile_linux.h deleted file mode 100644 index 9fe622b..0000000 --- a/printing/native_metafile_linux.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_METAFILE_LINUX_H_ -#define PRINTING_NATIVE_METAFILE_LINUX_H_ - -#include "base/basictypes.h" - -typedef struct _cairo_surface cairo_surface_t; -typedef struct _cairo cairo_t; - -namespace base { -struct FileDescriptor; -} - -class FilePath; - -namespace printing { - -// This class is used to generate a PDF stream and to store rendering results -// in a string buffer. -class NativeMetafile { - public: - virtual ~NativeMetafile() {} - - // Initializes to a fresh new metafile. Returns true on success. - // Note: It should only be called from the renderer process to allocate - // rendering resources. - virtual bool Init() = 0; - - // Initializes a copy of metafile from PDF stream data. - // Returns true on success. - // |src_buffer| should point to the shared memory which stores PDF - // contents generated in the renderer. - // Note: It should only be called from the browser process to initialize - // |data_|. - virtual bool Init(const void* src_buffer, uint32 src_buffer_size) = 0; - - // Sets raw PDF data for the document. This is used when a cairo drawing - // surface has already been created. This method will cause all subsequent - // drawing on the surface to be discarded (in Close()). If Init() has not yet - // been called this method simply calls the second version of Init. - virtual bool SetRawData(const void* src_buffer, uint32 src_buffer_size) = 0; - - // Prepares a new cairo surface/context for rendering a new page. - // The unit is in point (=1/72 in). - // Returns NULL when failed. - virtual cairo_t* StartPage(double width_in_points, - double height_in_points, - double margin_top_in_points, - double margin_right_in_points, - double margin_bottom_in_points, - double margin_left_in_points) = 0; - - // Destroys the surface and the context used in rendering current page. - // The results of current page will be appended into buffer |data_|. - // Returns true on success. - virtual bool FinishPage() = 0; - - // Closes resulting PDF file. No further rendering is allowed. - virtual void Close() = 0; - - // Returns size of PDF contents stored in buffer |data_|. - // This function should ONLY be called after PDF file is closed. - virtual uint32 GetDataSize() const = 0; - - // Copies PDF contents stored in buffer |data_| into |dst_buffer|. - // This function should ONLY be called after PDF file is closed. - // Returns true only when success. - virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const = 0; - - // Saves PDF contents stored in buffer |data_| into the file - // associated with |fd|. - // This function should ONLY be called after PDF file is closed. - virtual bool SaveTo(const base::FileDescriptor& fd) const = 0; -}; - -} // namespace printing - -#endif // PRINTING_NATIVE_METAFILE_LINUX_H_ diff --git a/printing/native_metafile_mac.h b/printing/native_metafile_mac.h deleted file mode 100644 index 940da50..0000000 --- a/printing/native_metafile_mac.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_METAFILE_MAC_H_ -#define PRINTING_NATIVE_METAFILE_MAC_H_ - -#include <ApplicationServices/ApplicationServices.h> -#include <CoreFoundation/CoreFoundation.h> - -#include "base/basictypes.h" -#include "base/mac/scoped_cftyperef.h" - -namespace gfx { -class Rect; -class Size; -class Point; -} -class FilePath; - -namespace printing { - -// This class creates a graphics context that renders into a PDF data stream. -class NativeMetafile { - public: - - virtual ~NativeMetafile() {} - - // Initializes a new metafile, and returns a drawing context for rendering - // into the PDF. Returns NULL on failure. - // Note: The returned context *must not be retained* past Close(). If it is, - // the data returned from GetData will not be valid PDF data. - virtual CGContextRef Init() = 0; - - // Initializes a copy of metafile from PDF data. Returns true on success. - virtual bool Init(const void* src_buffer, uint32 src_buffer_size) = 0; - - // Prepares a new pdf page at specified |content_origin| with the given - // |page_size| and a |scale_factor| to use for the drawing. - virtual CGContextRef StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor) = 0; - - // Closes the current page. - virtual void FinishPage() = 0; - - // Closes the PDF file; no further rendering is allowed. - virtual void Close() = 0; - - // Renders the given page into |rect| in the given context. - // Pages use a 1-based index. The rendering uses the following arguments - // to determine scaling and translation factors. - // |shrink_to_fit| specifies whether the output should be shrunk to fit the - // supplied |rect| if the page size is larger than |rect| in any dimension. - // If this is false, parts of the PDF page that lie outside the bounds will be - // clipped. - // |stretch_to_fit| specifies whether the output should be stretched to fit - // the supplied bounds if the page size is smaller than |rect| in all - // dimensions. - // |center_horizontally| specifies whether the final image (after any scaling - // is done) should be centered horizontally within the given |rect|. - // |center_vertically| specifies whether the final image (after any scaling - // is done) should be centered vertically within the given |rect|. - // Note that all scaling preserves the original aspect ratio of the page. - virtual bool RenderPage(unsigned int page_number, CGContextRef context, - const CGRect rect, bool shrink_to_fit, bool stretch_to_fit, - bool center_horizontally, bool center_vertically) const = 0; - virtual unsigned int GetPageCount() const = 0; - - // Returns the bounds of the given page. - // Pages use a 1-based index. - virtual gfx::Rect GetPageBounds(unsigned int page_number) const = 0; - - // Returns the size of the underlying PDF data. Only valid after Close() has - // been called. - virtual uint32 GetDataSize() const = 0; - - // Copies the first |dst_buffer_size| bytes of the PDF data into |dst_buffer|. - // Only valid after Close() has been called. - // Returns true if the copy succeeds. - virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const = 0; - - // Saves the raw PDF data to the given file. For testing only. - // Returns true if writing succeeded. - virtual bool SaveTo(const FilePath& file_path) const = 0; -}; - -} // namespace printing - -#endif // PRINTING_NATIVE_METAFILE_MAC_H_ diff --git a/printing/native_metafile_win.h b/printing/native_metafile_win.h deleted file mode 100644 index fa00121..0000000 --- a/printing/native_metafile_win.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_METAFILE_WIN_H_ -#define PRINTING_NATIVE_METAFILE_WIN_H_ - -#include <windows.h> -#include <vector> - -#include "base/basictypes.h" - -class FilePath; - -namespace gfx { -class Rect; -} - -namespace printing { - -// Simple wrapper class that manages a data stream and its virtual HDC. -class NativeMetafile { - public: - virtual ~NativeMetafile() {} - - // Initializes the data stream with the data in |src_buffer|. Returns - // true on success. - virtual bool Init(const void* src_buffer, uint32 src_buffer_size) = 0; - - // Generates a virtual HDC that will record every GDI commands and compile it - // in a EMF data stream. - // hdc is used to setup the default DPI and color settings. hdc is optional. - // rect specifies the dimensions (in .01-millimeter units) of the EMF. rect is - // optional. - virtual bool CreateDc(HDC sibling, const RECT* rect) = 0; - - // Similar to the above method but the metafile is backed by a file. - virtual bool CreateFileBackedDc(HDC sibling, - const RECT* rect, - const FilePath& path) = 0; - - // Load a data stream from file. - virtual bool CreateFromFile(const FilePath& metafile_path) = 0; - - // TODO(maruel): CreateFromFile(). If ever used. Maybe users would like to - // have the ability to save web pages to an EMF file? Afterward, it is easy to - // convert to PDF. - - // Closes the HDC created by CreateDc() and generates the compiled EMF - // data. - virtual bool CloseDc() = 0; - - // Closes the EMF data handle when it is not needed anymore. - virtual void CloseEmf() = 0; - - // "Plays" the EMF buffer in a HDC. It is the same effect as calling the - // original GDI function that were called when recording the EMF. |rect| is in - // "logical units" and is optional. If |rect| is NULL, the natural EMF bounds - // are used. - // Note: Windows has been known to have stack buffer overflow in its GDI - // functions, whether used directly or indirectly through precompiled EMF - // data. We have to accept the risk here. Since it is used only for printing, - // it requires user intervention. - virtual bool Playback(HDC hdc, const RECT* rect) const = 0; - - // The slow version of Playback(). It enumerates all the records and play them - // back in the HDC. The trick is that it skip over the records known to have - // issue with some printers. See Emf::Record::SafePlayback implementation for - // details. - virtual bool SafePlayback(HDC hdc) const = 0; - - // Retrieves the bounds of the painted area by this EMF buffer. This value - // should be passed to Playback to keep the exact same size. - virtual gfx::Rect GetBounds() const = 0; - - // Retrieves the data stream size. - virtual uint32 GetDataSize() const = 0; - - // Retrieves the data stream. - virtual bool GetData(void* buffer, uint32 size) const = 0; - - // Retrieves the data stream. It is an helper function. - virtual bool GetData(std::vector<uint8>* buffer) const = 0; - - virtual HENHMETAFILE emf() const = 0; - - virtual HDC hdc() const = 0; - - // 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. - virtual bool StartPage() = 0; - virtual bool EndPage() = 0; - - // Saves the EMF data to a file as-is. It is recommended to use the .emf file - // extension but it is not enforced. This function synchronously writes to the - // file. For testing only. - virtual bool SaveTo(const std::wstring& filename) const = 0; -}; - -} // namespace printing - -#endif // PRINTING_NATIVE_METAFILE_WIN_H_ diff --git a/printing/pdf_metafile_mac.cc b/printing/pdf_metafile_mac.cc index ffd80e8..36f4947 100644 --- a/printing/pdf_metafile_mac.cc +++ b/printing/pdf_metafile_mac.cc @@ -9,6 +9,7 @@ #include "base/mac/scoped_cftyperef.h" #include "base/sys_string_conversions.h" #include "ui/gfx/rect.h" +#include "ui/gfx/size.h" using base::mac::ScopedCFTypeRef; @@ -20,7 +21,7 @@ PdfMetafile::PdfMetafile() PdfMetafile::~PdfMetafile() {} -CGContextRef PdfMetafile::Init() { +bool PdfMetafile::Init() { // Ensure that Init hasn't already been called. DCHECK(!context_.get()); DCHECK(!pdf_data_.get()); @@ -28,14 +29,14 @@ CGContextRef PdfMetafile::Init() { pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0)); if (!pdf_data_.get()) { LOG(ERROR) << "Failed to create pdf data for metafile"; - return NULL; + return false; } ScopedCFTypeRef<CGDataConsumerRef> pdf_consumer( CGDataConsumerCreateWithCFData(pdf_data_)); if (!pdf_consumer.get()) { LOG(ERROR) << "Failed to create data consumer for metafile"; pdf_data_.reset(NULL); - return NULL; + return false; } context_.reset(CGPDFContextCreate(pdf_consumer, NULL, NULL)); if (!context_.get()) { @@ -43,7 +44,7 @@ CGContextRef PdfMetafile::Init() { pdf_data_.reset(NULL); } - return context_.get(); + return true; } bool PdfMetafile::Init(const void* src_buffer, uint32 src_buffer_size) { @@ -84,16 +85,17 @@ CGContextRef PdfMetafile::StartPage(const gfx::Size& page_size, return context_.get(); } -void PdfMetafile::FinishPage() { +bool PdfMetafile::FinishPage() { DCHECK(context_.get()); DCHECK(page_is_open_); CGContextRestoreGState(context_); CGContextEndPage(context_); page_is_open_ = false; + return true; } -void PdfMetafile::Close() { +bool PdfMetafile::Close() { DCHECK(context_.get()); DCHECK(!page_is_open_); @@ -110,6 +112,7 @@ void PdfMetafile::Close() { #endif CGPDFContextClose(context_.get()); context_.reset(NULL); + return true; } bool PdfMetafile::RenderPage(unsigned int page_number, CGContextRef context, @@ -223,6 +226,10 @@ bool PdfMetafile::SaveTo(const FilePath& file_path) const { return error_code == 0; } +CGContextRef PdfMetafile::context() const { + return context_.get(); +} + CGPDFDocumentRef PdfMetafile::GetPDFDocument() const { // Make sure that we have data, and that it's not being modified any more. DCHECK(pdf_data_.get()); diff --git a/printing/pdf_metafile_mac.h b/printing/pdf_metafile_mac.h index c5669a8..b1d3944 100644 --- a/printing/pdf_metafile_mac.h +++ b/printing/pdf_metafile_mac.h @@ -11,14 +11,15 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/mac/scoped_cftyperef.h" -#include "printing/native_metafile_mac.h" +#include "printing/native_metafile.h" + +class FilePath; namespace gfx { class Rect; class Size; class Point; } -class FilePath; namespace printing { @@ -28,69 +29,38 @@ class PdfMetafile : public NativeMetafile { virtual ~PdfMetafile(); - // Initializes a new metafile, and returns a drawing context for rendering - // into the PDF. Returns NULL on failure. - // Note: The returned context *must not be retained* past Close(). If it is, - // the data returned from GetData will not be valid PDF data. - virtual CGContextRef Init(); - - // Initializes a copy of metafile from PDF data. Returns true on success. + // NativeMetafile methods. + virtual bool Init(); virtual bool Init(const void* src_buffer, uint32 src_buffer_size); - // Prepares a new pdf page at specified |content_origin| with the given - // |page_size| and a |scale_factor| to use for the drawing. virtual CGContextRef StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor); - - // Closes the current page. - virtual void FinishPage(); - - // Closes the PDF file; no further rendering is allowed. - virtual void Close(); - - // Renders the given page into |rect| in the given context. - // Pages use a 1-based index. The rendering uses the following arguments - // to determine scaling and translation factors. - // |shrink_to_fit| specifies whether the output should be shrunk to fit the - // supplied |rect| if the page size is larger than |rect| in any dimension. - // If this is false, parts of the PDF page that lie outside the bounds will be - // clipped. - // |stretch_to_fit| specifies whether the output should be stretched to fit - // the supplied bounds if the page size is smaller than |rect| in all - // dimensions. - // |center_horizontally| specifies whether the final image (after any scaling - // is done) should be centered horizontally within the given |rect|. - // |center_vertically| specifies whether the final image (after any scaling - // is done) should be centered vertically within the given |rect|. - // Note that all scaling preserves the original aspect ratio of the page. - virtual bool RenderPage(unsigned int page_number, CGContextRef context, - const CGRect rect, bool shrink_to_fit, bool stretch_to_fit, - bool center_horizontally, bool center_vertically) const; - virtual unsigned int GetPageCount() const; - - // Returns the bounds of the given page. - // Pages use a 1-based index. - virtual gfx::Rect GetPageBounds(unsigned int page_number) const; + const gfx::Point& content_origin, + const float& scale_factor); + virtual bool FinishPage(); + virtual bool Close(); - // Returns the size of the underlying PDF data. Only valid after Close() has - // been called. virtual uint32 GetDataSize() const; - - // Copies the first |dst_buffer_size| bytes of the PDF data into |dst_buffer|. - // Only valid after Close() has been called. - // Returns true if the copy succeeds. virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const; - // Saves the raw PDF data to the given file. For testing only. - // Returns true if writing succeeded. + // For testing purposes only. virtual bool SaveTo(const FilePath& file_path) const; + virtual gfx::Rect GetPageBounds(unsigned int page_number) const; + virtual unsigned int GetPageCount() const; + + // Note: The returned context *must not be retained* past Close(). If it is, + // the data returned from GetData will not be valid PDF data. + virtual CGContextRef context() const; + + virtual bool RenderPage(unsigned int page_number, + CGContextRef context, + const CGRect rect, + bool shrink_to_fit, + bool stretch_to_fit, + bool center_horizontally, + bool center_vertically) const; + protected: - // To create PDF data, callers should call Init() to set up the rendering - // context. - // To create a metafile from existing data, callers should call - // Init(const void*, uint32). PdfMetafile(); private: diff --git a/printing/pdf_metafile_mac_unittest.cc b/printing/pdf_metafile_mac_unittest.cc index 8b52b06..b45370d 100644 --- a/printing/pdf_metafile_mac_unittest.cc +++ b/printing/pdf_metafile_mac_unittest.cc @@ -17,7 +17,8 @@ namespace printing { TEST(PdfMetafileTest, Pdf) { // Test in-renderer constructor. printing::PdfMetafile pdf; - EXPECT_TRUE(pdf.Init() != NULL); + EXPECT_TRUE(pdf.Init()); + EXPECT_TRUE(pdf.context() != NULL); // Render page 1 at origin (10.0, 10.0). gfx::Point origin_1(10.0f, 10.0f); diff --git a/printing/pdf_ps_metafile_cairo.cc b/printing/pdf_ps_metafile_cairo.cc index bf0b0e2..faab29f4 100644 --- a/printing/pdf_ps_metafile_cairo.cc +++ b/printing/pdf_ps_metafile_cairo.cc @@ -15,6 +15,8 @@ #include "base/logging.h" #include "printing/units.h" #include "skia/ext/vector_platform_device_linux.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/size.h" namespace { @@ -108,7 +110,6 @@ bool PdfPsMetafile::Init() { } cairo_set_user_data(context_, &kPdfMetafileKey, this, DestroyContextData); - return true; } @@ -123,7 +124,6 @@ bool PdfPsMetafile::Init(const void* src_buffer, uint32 src_buffer_size) { data_ = std::string(reinterpret_cast<const char*>(src_buffer), src_buffer_size); - return true; } @@ -144,32 +144,22 @@ bool PdfPsMetafile::SetRawData(const void* src_buffer, return true; } -cairo_t* PdfPsMetafile::StartPage(double width_in_points, - double height_in_points, +cairo_t* PdfPsMetafile::StartPage(const gfx::Size& page_size, double margin_top_in_points, - double margin_right_in_points, - double margin_bottom_in_points, double margin_left_in_points) { DCHECK(IsSurfaceValid(surface_)); DCHECK(IsContextValid(context_)); // Passing this check implies page_surface_ is NULL, and current_page_ is // empty. - DCHECK_GT(width_in_points, 0.); - DCHECK_GT(height_in_points, 0.); - - // We build in extra room for the margins. The Cairo PDF backend will scale - // the output to fit a page. - double width = - width_in_points + margin_left_in_points + margin_right_in_points; - double height = - height_in_points + margin_top_in_points + margin_bottom_in_points; + DCHECK_GT(page_size.width(), 0); + DCHECK_GT(page_size.height(), 0); // Don't let WebKit draw over the margins. cairo_surface_set_device_offset(surface_, margin_left_in_points, margin_top_in_points); - cairo_pdf_surface_set_size(surface_, width, height); + cairo_pdf_surface_set_size(surface_, page_size.width(), page_size.height()); return context_; } @@ -183,7 +173,7 @@ bool PdfPsMetafile::FinishPage() { return true; } -void PdfPsMetafile::Close() { +bool PdfPsMetafile::Close() { DCHECK(IsSurfaceValid(surface_)); DCHECK(IsContextValid(context_)); @@ -198,6 +188,7 @@ void PdfPsMetafile::Close() { CleanUpContext(&context_); CleanUpSurface(&surface_); + return true; } uint32 PdfPsMetafile::GetDataSize() const { @@ -217,7 +208,37 @@ bool PdfPsMetafile::GetData(void* dst_buffer, uint32 dst_buffer_size) const { return true; } -bool PdfPsMetafile::SaveTo(const base::FileDescriptor& fd) const { +cairo_t* PdfPsMetafile::context() const { + return context_; +} + +bool PdfPsMetafile::SaveTo(const FilePath& file_path) const { + // We need to check at least these two members to ensure that either Init() + // has been called to initialize |data_|, or metafile has been closed. + DCHECK(!context_); + DCHECK(!data_.empty()); + + bool success = true; + if (file_util::WriteFile(file_path, data_.data(), GetDataSize()) + != static_cast<int>(GetDataSize())) { + DLOG(ERROR) << "Failed to save file " << file_path.value().c_str(); + success = false; + } + return success; +} + +gfx::Rect PdfPsMetafile::GetPageBounds(unsigned int page_number) const { + NOTIMPLEMENTED(); + return gfx::Rect(); +} + +unsigned int PdfPsMetafile::GetPageCount() const { + NOTIMPLEMENTED(); + return 1; +} + +#if defined(OS_CHROMEOS) +bool PdfPsMetafile::SaveToFD(const base::FileDescriptor& fd) const { // We need to check at least these two members to ensure that either Init() // has been called to initialize |data_|, or metafile has been closed. DCHECK(!context_); @@ -244,6 +265,7 @@ bool PdfPsMetafile::SaveTo(const base::FileDescriptor& fd) const { return success; } +#endif // if defined(OS_CHROMEOS) PdfPsMetafile* PdfPsMetafile::FromCairoContext(cairo_t* context) { return reinterpret_cast<PdfPsMetafile*>( diff --git a/printing/pdf_ps_metafile_cairo.h b/printing/pdf_ps_metafile_cairo.h index 0b7514a..6cfe5ff 100644 --- a/printing/pdf_ps_metafile_cairo.h +++ b/printing/pdf_ps_metafile_cairo.h @@ -9,73 +9,43 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" -#include "printing/native_metafile_linux.h" +#include "printing/native_metafile.h" typedef struct _cairo_surface cairo_surface_t; -typedef struct _cairo cairo_t; - -namespace base { -struct FileDescriptor; -} - -class FilePath; namespace printing { -// This class uses Cairo graphics library to generate PostScript/PDF stream -// and stores rendering results in a string buffer. -class PdfPsMetafile : public NativeMetafile { +// This class uses Cairo graphics library to generate PDF stream and stores +// rendering results in a string buffer. +class PdfPsMetafile : public NativeMetafile { public: virtual ~PdfPsMetafile(); - // Initializes to a fresh new metafile. Returns true on success. - // Note: Only call in the renderer to allocate rendering resources. + // NativeMetafile methods. virtual bool Init(); - - // Initializes a copy of metafile from PDF stream data. - // Returns true on success. - // |src_buffer| should point to the shared memory which stores PDF - // contents generated in the renderer. - // Note: Only call in the browser to initialize |data_|. virtual bool Init(const void* src_buffer, uint32 src_buffer_size); - // Sets raw PDF data for the document. This is used when a cairo drawing - // surface has already been created. This method will cause all subsequent - // drawing on the surface to be discarded (in Close()). If Init() has not yet - // been called this method simply calls the second version of Init. - virtual bool SetRawData(const void* src_buffer, uint32 src_buffer_size); - - // Prepares a new cairo surface/context for rendering a new page. - // The unit is in point (=1/72 in). - // Returns NULL when failed. - virtual cairo_t* StartPage(double width_in_points, - double height_in_points, + virtual cairo_t* StartPage(const gfx::Size& page_size, double margin_top_in_points, - double margin_right_in_points, - double margin_bottom_in_points, double margin_left_in_points); - - // Destroys the surface and the context used in rendering current page. - // The results of current page will be appended into buffer |data_|. - // Returns true on success. virtual bool FinishPage(); + virtual bool Close(); - // Closes resulting PDF file. No further rendering is allowed. - virtual void Close(); - - // Returns size of PDF contents stored in buffer |data_|. - // This function should ONLY be called after PDF file is closed. virtual uint32 GetDataSize() const; - - // Copies PDF contents stored in buffer |data_| into |dst_buffer|. - // This function should ONLY be called after PDF file is closed. - // Returns true only when success. virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const; - // Saves PDF contents stored in buffer |data_| into the file - // associated with |fd|. - // This function should ONLY be called after PDF file is closed. - virtual bool SaveTo(const base::FileDescriptor& fd) const; + virtual bool SaveTo(const FilePath& file_path) const; + + virtual gfx::Rect GetPageBounds(unsigned int page_number) const; + virtual unsigned int GetPageCount() const; + + virtual cairo_t* context() const; + + virtual bool SetRawData(const void* src_buffer, uint32 src_buffer_size); + +#if defined(OS_CHROMEOS) + virtual bool SaveToFD(const base::FileDescriptor& fd) const; +#endif // if defined(OS_CHROMEOS) // Returns the PdfPsMetafile object that owns the given context. Returns NULL // if the context was not created by a PdfPsMetafile object. diff --git a/printing/pdf_ps_metafile_cairo_unittest.cc b/printing/pdf_ps_metafile_cairo_unittest.cc index a3442c8..048c98c 100644 --- a/printing/pdf_ps_metafile_cairo_unittest.cc +++ b/printing/pdf_ps_metafile_cairo_unittest.cc @@ -9,20 +9,17 @@ #include <vector> #include "base/file_descriptor_posix.h" +#include "base/file_path.h" #include "base/file_util.h" #include "base/string_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/size.h" typedef struct _cairo cairo_t; namespace { -class PdfPsTest : public testing::Test { - protected: - base::FileDescriptor DevNullFD() { - return base::FileDescriptor(open("/dev/null", O_WRONLY), true); - } -}; +class PdfPsTest : public testing::Test {}; } // namespace @@ -34,14 +31,14 @@ TEST_F(PdfPsTest, Pdf) { EXPECT_TRUE(pdf.Init()); // Renders page 1. - cairo_t* context = pdf.StartPage(72, 72, 1, 2, 3, 4); + cairo_t* context = pdf.StartPage(gfx::Size(72 + 2 + 4, 72 + 1 + 3), 1, 4); EXPECT_TRUE(context != NULL); EXPECT_EQ(printing::PdfPsMetafile::FromCairoContext(context), &pdf); // In theory, we should use Cairo to draw something on |context|. EXPECT_TRUE(pdf.FinishPage()); // Renders page 2. - context = pdf.StartPage(64, 64, 1, 2, 3, 4); + context = pdf.StartPage(gfx::Size(64 + 2 + 4, 64 + 1 + 3), 1, 4); EXPECT_TRUE(context != NULL); // In theory, we should use Cairo to draw something on |context|. EXPECT_TRUE(pdf.FinishPage()); @@ -70,12 +67,12 @@ TEST_F(PdfPsTest, Pdf) { EXPECT_EQ(header.find("%PDF", 0), 0u); // Tests if we can save data. - EXPECT_TRUE(pdf.SaveTo(DevNullFD())); + EXPECT_TRUE(pdf.SaveTo(FilePath("/dev/null"))); // Test overriding the metafile with raw data. printing::PdfPsMetafile pdf3; EXPECT_TRUE(pdf3.Init()); - context = pdf3.StartPage(72, 72, 1, 2, 3, 4); + context = pdf3.StartPage(gfx::Size(72 + 2 + 4, 72 + 1 + 3), 1, 4); EXPECT_TRUE(context != NULL); std::string test_raw_data = "Dummy PDF"; EXPECT_TRUE(pdf3.SetRawData(test_raw_data.c_str(), test_raw_data.size())); diff --git a/printing/printed_document.cc b/printing/printed_document.cc index 45603b5..07eeec6d 100644 --- a/printing/printed_document.cc +++ b/printing/printed_document.cc @@ -261,12 +261,14 @@ void PrintedDocument::DebugDump(const PrintedPage& page) { filename += name(); filename += ASCIIToUTF16("_"); filename += ASCIIToUTF16(StringPrintf("%02d", page.page_number())); - filename += ASCIIToUTF16("_.emf"); #if defined(OS_WIN) + filename += ASCIIToUTF16("_.emf"); page.native_metafile()->SaveTo( - g_debug_dump_info.Get().debug_dump_path.Append(filename).value()); + g_debug_dump_info.Get().debug_dump_path.Append(filename)); #else // OS_WIN - NOTIMPLEMENTED(); // TODO: convert SaveTo to accept a FilePath + filename += ASCIIToUTF16("_.pdf"); + page.native_metafile()->SaveTo( + g_debug_dump_info.Get().debug_dump_path.Append(UTF16ToUTF8(filename))); #endif // OS_WIN } diff --git a/printing/printing.gyp b/printing/printing.gyp index 9201e69..049e752 100644 --- a/printing/printing.gyp +++ b/printing/printing.gyp @@ -38,9 +38,6 @@ 'image.h', 'native_metafile_factory.cc', 'native_metafile_factory.h', - 'native_metafile_linux.h', - 'native_metafile_mac.h', - 'native_metafile_win.h', 'native_metafile.h', 'page_number.cc', 'page_number.h', |