From 9b61753963f16cc6cf48f388a2c24e064add4cbb Mon Sep 17 00:00:00 2001 From: "vandebo@chromium.org" Date: Mon, 4 Apr 2011 23:15:06 +0000 Subject: Rename some printing classes and minor cleanups. Rename: PdfPsMetafile -> PdfMetafileCairo PdfMetafile -> PdfMetafileCg (Mac) VectorPlatformDevice -> VectorPlatformDeviceEmf/Cairo (Windows/Linux varients) This is in preparation for VectorPlatformDeviceSkia. BUG=NONE TEST=NONE Review URL: http://codereview.chromium.org/6783036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80390 0039d316-1c4b-4281-b951-d872f2087c98 --- printing/emf_win.cc | 8 +- printing/native_metafile_factory.cc | 8 +- printing/pdf_metafile_cairo_linux.cc | 259 +++++++++++++++++++++++++ printing/pdf_metafile_cairo_linux.h | 92 +++++++++ printing/pdf_metafile_cairo_linux_unittest.cc | 85 +++++++++ printing/pdf_metafile_cg_mac.cc | 257 +++++++++++++++++++++++++ printing/pdf_metafile_cg_mac.h | 94 ++++++++++ printing/pdf_metafile_cg_mac_unittest.cc | 67 +++++++ printing/pdf_metafile_mac.cc | 254 ------------------------- printing/pdf_metafile_mac.h | 94 ---------- printing/pdf_metafile_mac_unittest.cc | 67 ------- printing/pdf_ps_metafile_cairo.cc | 261 -------------------------- printing/pdf_ps_metafile_cairo.h | 92 --------- printing/pdf_ps_metafile_cairo_unittest.cc | 85 --------- printing/print_settings_initializer_gtk.cc | 1 - printing/printing.gyp | 12 +- 16 files changed, 868 insertions(+), 868 deletions(-) create mode 100644 printing/pdf_metafile_cairo_linux.cc create mode 100644 printing/pdf_metafile_cairo_linux.h create mode 100644 printing/pdf_metafile_cairo_linux_unittest.cc create mode 100644 printing/pdf_metafile_cg_mac.cc create mode 100644 printing/pdf_metafile_cg_mac.h create mode 100644 printing/pdf_metafile_cg_mac_unittest.cc delete mode 100644 printing/pdf_metafile_mac.cc delete mode 100644 printing/pdf_metafile_mac.h delete mode 100644 printing/pdf_metafile_mac_unittest.cc delete mode 100644 printing/pdf_ps_metafile_cairo.cc delete mode 100644 printing/pdf_ps_metafile_cairo.h delete mode 100644 printing/pdf_ps_metafile_cairo_unittest.cc (limited to 'printing') diff --git a/printing/emf_win.cc b/printing/emf_win.cc index 849e125..1b5601a 100644 --- a/printing/emf_win.cc +++ b/printing/emf_win.cc @@ -9,7 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/time.h" -#include "skia/ext/vector_platform_device_win.h" +#include "skia/ext/vector_platform_device_emf_win.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/png_codec.h" @@ -409,9 +409,9 @@ skia::PlatformDevice* Emf::StartPageForVectorCanvas( if (!StartPage(page_size, content_origin, scale_factor)) return NULL; - return skia::VectorPlatformDeviceFactory::CreateDevice(page_size.width(), - page_size.height(), - true, hdc_); + return skia::VectorPlatformDeviceEmfFactory::CreateDevice(page_size.width(), + page_size.height(), + true, hdc_); } bool Emf::StartPage(const gfx::Size& /*page_size*/, diff --git a/printing/native_metafile_factory.cc b/printing/native_metafile_factory.cc index 3b77ae0..5db823e 100644 --- a/printing/native_metafile_factory.cc +++ b/printing/native_metafile_factory.cc @@ -9,9 +9,9 @@ #if defined(OS_WIN) #include "printing/emf_win.h" #elif defined(OS_MACOSX) -#include "printing/pdf_metafile_mac.h" +#include "printing/pdf_metafile_cg_mac.h" #elif defined(OS_POSIX) -#include "printing/pdf_ps_metafile_cairo.h" +#include "printing/pdf_metafile_cairo_linux.h" #endif namespace printing { @@ -38,9 +38,9 @@ NativeMetafile* NativeMetafileFactory::CreateNewMetafile(){ #if defined(OS_WIN) return new printing::Emf; #elif defined(OS_MACOSX) - return new printing::PdfMetafile; + return new printing::PdfMetafileCg; #elif defined(OS_POSIX) - return new printing::PdfPsMetafile; + return new printing::PdfMetafileCairo; #endif } diff --git a/printing/pdf_metafile_cairo_linux.cc b/printing/pdf_metafile_cairo_linux.cc new file mode 100644 index 0000000..5780574 --- /dev/null +++ b/printing/pdf_metafile_cairo_linux.cc @@ -0,0 +1,259 @@ +// 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. + +#include "printing/pdf_metafile_cairo_linux.h" + +#include + +#include +#include + +#include "base/eintr_wrapper.h" +#include "base/file_descriptor_posix.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "printing/units.h" +#include "skia/ext/vector_platform_device_cairo_linux.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/size.h" + +namespace { + +// Tests if |surface| is valid. +bool IsSurfaceValid(cairo_surface_t* surface) { + return cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS; +} + +// Tests if |context| is valid. +bool IsContextValid(cairo_t* context) { + return cairo_status(context) == CAIRO_STATUS_SUCCESS; +} + +// Destroys and resets |surface|. +void CleanUpSurface(cairo_surface_t** surface) { + if (*surface) { + cairo_surface_destroy(*surface); + *surface = NULL; + } +} + +// Destroys and resets |context|. +void CleanUpContext(cairo_t** context) { + if (*context) { + cairo_destroy(*context); + *context = NULL; + } +} + +// Callback function for Cairo to write PDF stream. +// |dst_buffer| is actually a pointer of type `std::string*`. +cairo_status_t WriteCairoStream(void* dst_buffer, + const unsigned char* src_data, + unsigned int src_data_length) { + DCHECK(dst_buffer); + DCHECK(src_data); + DCHECK_GT(src_data_length, 0u); + + std::string* buffer = reinterpret_cast(dst_buffer); + buffer->append(reinterpret_cast(src_data), src_data_length); + + return CAIRO_STATUS_SUCCESS; +} + +} // namespace + +namespace printing { + +PdfMetafileCairo::PdfMetafileCairo() + : surface_(NULL), + context_(NULL), + current_data_(NULL) { +} + +PdfMetafileCairo::~PdfMetafileCairo() { + // Releases all resources if we forgot to do so. + CleanUpAll(); +} + +bool PdfMetafileCairo::Init() { + // We need to check |current_data_| to ensure Init/InitFromData has not been + // called before. + DCHECK(!current_data_); + + current_data_ = &cairo_data_; + // Creates an 1 by 1 Cairo surface for the entire PDF file. + // The size for each page will be overwritten later in StartPage(). + surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, + current_data_, 1, 1); + + // Cairo always returns a valid pointer. + // Hence, we have to check if it points to a "nil" object. + if (!IsSurfaceValid(surface_)) { + DLOG(ERROR) << "Cannot create Cairo surface for PdfMetafileCairo!"; + CleanUpSurface(&surface_); + return false; + } + + // Creates a context. + context_ = cairo_create(surface_); + if (!IsContextValid(context_)) { + DLOG(ERROR) << "Cannot create Cairo context for PdfMetafileCairo!"; + CleanUpContext(&context_); + CleanUpSurface(&surface_); + return false; + } + + return true; +} + +bool PdfMetafileCairo::InitFromData(const void* src_buffer, + uint32 src_buffer_size) { + if (src_buffer == NULL || src_buffer_size == 0) + return false; + + raw_data_ = std::string(reinterpret_cast(src_buffer), + src_buffer_size); + current_data_ = &raw_data_; + return true; +} + +skia::PlatformDevice* PdfMetafileCairo::StartPageForVectorCanvas( + const gfx::Size& page_size, const gfx::Point& content_origin, + const float& scale_factor) { + if (!StartPage(page_size, content_origin, scale_factor)) + return NULL; + + return skia::VectorPlatformDeviceCairoFactory::CreateDevice( + context_, page_size.width(), page_size.height(), true); +} + +bool PdfMetafileCairo::StartPage(const gfx::Size& page_size, + const gfx::Point& content_origin, + const float& scale_factor) { + DCHECK(IsSurfaceValid(surface_)); + DCHECK(IsContextValid(context_)); + // Passing this check implies page_surface_ is NULL, and current_page_ is + // empty. + DCHECK_GT(page_size.width(), 0); + DCHECK_GT(page_size.height(), 0); + // |scale_factor| is not supported yet. + DCHECK_EQ(scale_factor, 1); + + // Don't let WebKit draw over the margins. + cairo_surface_set_device_offset(surface_, + content_origin.x(), + content_origin.y()); + + cairo_pdf_surface_set_size(surface_, page_size.width(), page_size.height()); + return context_ != NULL; +} + +bool PdfMetafileCairo::FinishPage() { + DCHECK(IsSurfaceValid(surface_)); + DCHECK(IsContextValid(context_)); + + // Flushes all rendering for current page. + cairo_surface_flush(surface_); + cairo_show_page(context_); + return true; +} + +bool PdfMetafileCairo::FinishDocument() { + DCHECK(IsSurfaceValid(surface_)); + DCHECK(IsContextValid(context_)); + + cairo_surface_finish(surface_); + + DCHECK(!cairo_data_.empty()); // Make sure we did get something. + + CleanUpContext(&context_); + CleanUpSurface(&surface_); + return true; +} + +uint32 PdfMetafileCairo::GetDataSize() 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(!current_data_->empty()); + + return current_data_->size(); +} + +bool PdfMetafileCairo::GetData(void* dst_buffer, uint32 dst_buffer_size) const { + DCHECK(dst_buffer); + DCHECK_GT(dst_buffer_size, 0u); + memcpy(dst_buffer, current_data_->data(), dst_buffer_size); + + return true; +} + +cairo_t* PdfMetafileCairo::context() const { + return context_; +} + +bool PdfMetafileCairo::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(!current_data_->empty()); + + bool success = true; + if (file_util::WriteFile(file_path, current_data_->data(), GetDataSize()) + != static_cast(GetDataSize())) { + DLOG(ERROR) << "Failed to save file " << file_path.value().c_str(); + success = false; + } + return success; +} + +gfx::Rect PdfMetafileCairo::GetPageBounds(unsigned int page_number) const { + NOTIMPLEMENTED(); + return gfx::Rect(); +} + +unsigned int PdfMetafileCairo::GetPageCount() const { + NOTIMPLEMENTED(); + return 1; +} + +#if defined(OS_CHROMEOS) +bool PdfMetafileCairo::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_); + DCHECK(!current_data_->empty()); + + if (fd.fd < 0) { + DLOG(ERROR) << "Invalid file descriptor!"; + return false; + } + + bool success = true; + if (file_util::WriteFileDescriptor(fd.fd, current_data_->data(), + GetDataSize()) < 0) { + DLOG(ERROR) << "Failed to save file with fd " << fd.fd; + success = false; + } + + if (fd.auto_close) { + if (HANDLE_EINTR(close(fd.fd)) < 0) { + DPLOG(WARNING) << "close"; + success = false; + } + } + + return success; +} +#endif // if defined(OS_CHROMEOS) + +void PdfMetafileCairo::CleanUpAll() { + CleanUpContext(&context_); + CleanUpSurface(&surface_); + cairo_data_.clear(); + raw_data_.clear(); + skia::VectorPlatformDeviceCairo::ClearFontCache(); +} + +} // namespace printing diff --git a/printing/pdf_metafile_cairo_linux.h b/printing/pdf_metafile_cairo_linux.h new file mode 100644 index 0000000..f3a80aa --- /dev/null +++ b/printing/pdf_metafile_cairo_linux.h @@ -0,0 +1,92 @@ +// 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_PDF_METAFILE_CAIRO_LINUX_H_ +#define PRINTING_PDF_METAFILE_CAIRO_LINUX_H_ + +#include + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "printing/native_metafile.h" + +namespace gfx { +class Point; +class Rect; +class Size; +} + +typedef struct _cairo_surface cairo_surface_t; + +namespace printing { + +// This class uses Cairo graphics library to generate PDF stream and stores +// rendering results in a string buffer. +class PdfMetafileCairo : public NativeMetafile { + public: + virtual ~PdfMetafileCairo(); + + // NativeMetafile methods. + virtual bool Init(); + + // Calling InitFromData() sets the data for this metafile and masks data + // induced by previous calls to Init() or InitFromData(), even if drawing + // continues on the surface returned by a previous call to Init(). + virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size); + + virtual skia::PlatformDevice* StartPageForVectorCanvas( + const gfx::Size& page_size, const gfx::Point& content_origin, + const float& scale_factor); + virtual bool StartPage(const gfx::Size& page_size, + const gfx::Point& content_origin, + const float& scale_factor); + virtual bool FinishPage(); + virtual bool FinishDocument(); + + virtual uint32 GetDataSize() const; + virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) 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; + +#if defined(OS_CHROMEOS) + virtual bool SaveToFD(const base::FileDescriptor& fd) const; +#endif // if defined(OS_CHROMEOS) + + protected: + PdfMetafileCairo(); + + private: + friend class NativeMetafileFactory; + FRIEND_TEST_ALL_PREFIXES(PdfMetafileCairoTest, Pdf); + + // Cleans up all resources. + void CleanUpAll(); + + // Cairo surface and context for entire PDF file. + cairo_surface_t* surface_; + cairo_t* context_; + + // Buffer stores PDF contents for entire PDF file. + std::string cairo_data_; + // Buffer stores PDF contents. It can only be populated from InitFromData(). + // Any calls to StartPage(), FinishPage(), FinishDocument() do not affect + // this buffer. + // Note: Such calls will result in DCHECK errors if Init() has not been called + // first. + std::string raw_data_; + // Points to the appropriate buffer depending on the way the object was + // initialized (Init() vs InitFromData()). + std::string* current_data_; + + DISALLOW_COPY_AND_ASSIGN(PdfMetafileCairo); +}; + +} // namespace printing + +#endif // PRINTING_PDF_METAFILE_CAIRO_LINUX_H_ diff --git a/printing/pdf_metafile_cairo_linux_unittest.cc b/printing/pdf_metafile_cairo_linux_unittest.cc new file mode 100644 index 0000000..c644a3d --- /dev/null +++ b/printing/pdf_metafile_cairo_linux_unittest.cc @@ -0,0 +1,85 @@ +// 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. + +#include "printing/pdf_metafile_cairo_linux.h" + +#include +#include +#include + +#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" +#include "ui/gfx/point.h" + +typedef struct _cairo cairo_t; + +namespace { + +class PdfMetafileCairoTest : public testing::Test {}; + +} // namespace + +namespace printing { + +TEST_F(PdfMetafileCairoTest, Pdf) { + // Tests in-renderer constructor. + printing::PdfMetafileCairo pdf; + EXPECT_TRUE(pdf.Init()); + + // Renders page 1. + EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); + // In theory, we should use Cairo to draw something on |context|. + EXPECT_TRUE(pdf.FinishPage()); + + // Renders page 2. + EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); + // In theory, we should use Cairo to draw something on |context|. + EXPECT_TRUE(pdf.FinishPage()); + + // Closes the file. + pdf.FinishDocument(); + + // Checks data size. + uint32 size = pdf.GetDataSize(); + EXPECT_GT(size, 0u); + + // Gets resulting data. + std::vector buffer(size, 0x00); + pdf.GetData(&buffer.front(), size); + + // Tests another constructor. + printing::PdfMetafileCairo pdf2; + EXPECT_TRUE(pdf2.InitFromData(&buffer.front(), size)); + + // Tries to get the first 4 characters from pdf2. + std::vector buffer2(4, 0x00); + pdf2.GetData(&buffer2.front(), 4); + + // Tests if the header begins with "%PDF". + std::string header(&buffer2.front(), 4); + EXPECT_EQ(header.find("%PDF", 0), 0u); + + // Tests if we can save data. + EXPECT_TRUE(pdf.SaveTo(FilePath("/dev/null"))); + + // Test overriding the metafile with raw data. + printing::PdfMetafileCairo pdf3; + EXPECT_TRUE(pdf3.Init()); + EXPECT_TRUE(pdf3.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); + std::string test_raw_data = "Dummy PDF"; + EXPECT_TRUE(pdf3.InitFromData(test_raw_data.c_str(), test_raw_data.size())); + EXPECT_TRUE(pdf3.FinishPage()); + pdf3.FinishDocument(); + size = pdf3.GetDataSize(); + EXPECT_EQ(test_raw_data.size(), size); + std::string output; + pdf3.GetData(WriteInto(&output, size + 1), size); + EXPECT_EQ(test_raw_data, output); +} + +} // namespace printing diff --git a/printing/pdf_metafile_cg_mac.cc b/printing/pdf_metafile_cg_mac.cc new file mode 100644 index 0000000..f1b387a --- /dev/null +++ b/printing/pdf_metafile_cg_mac.cc @@ -0,0 +1,257 @@ +// 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. + +#include "printing/pdf_metafile_cg_mac.h" + +#include "base/file_path.h" +#include "base/logging.h" +#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; + +namespace printing { + +PdfMetafileCg::PdfMetafileCg() + : page_is_open_(false) { +} + +PdfMetafileCg::~PdfMetafileCg() {} + +bool PdfMetafileCg::Init() { + // Ensure that Init hasn't already been called. + DCHECK(!context_.get()); + DCHECK(!pdf_data_.get()); + + pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0)); + if (!pdf_data_.get()) { + LOG(ERROR) << "Failed to create pdf data for metafile"; + return false; + } + ScopedCFTypeRef pdf_consumer( + CGDataConsumerCreateWithCFData(pdf_data_)); + if (!pdf_consumer.get()) { + LOG(ERROR) << "Failed to create data consumer for metafile"; + pdf_data_.reset(NULL); + return false; + } + context_.reset(CGPDFContextCreate(pdf_consumer, NULL, NULL)); + if (!context_.get()) { + LOG(ERROR) << "Failed to create pdf context for metafile"; + pdf_data_.reset(NULL); + } + + return true; +} + +bool PdfMetafileCg::InitFromData(const void* src_buffer, + uint32 src_buffer_size) { + DCHECK(!context_.get()); + DCHECK(!pdf_data_.get()); + + if (!src_buffer || src_buffer_size == 0) { + return false; + } + + pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size)); + CFDataAppendBytes(pdf_data_, static_cast(src_buffer), + src_buffer_size); + + return true; +} + +skia::PlatformDevice* PdfMetafileCg::StartPageForVectorCanvas( + const gfx::Size& page_size, const gfx::Point& content_origin, + const float& scale_factor) { + NOTIMPLEMENTED(); + return NULL; +} + +bool PdfMetafileCg::StartPage(const gfx::Size& page_size, + const gfx::Point& content_origin, + const float& scale_factor) { + DCHECK(context_.get()); + DCHECK(!page_is_open_); + + double height = page_size.height(); + double width = page_size.width(); + + CGRect bounds = CGRectMake(0, 0, width, height); + CGContextBeginPage(context_, &bounds); + page_is_open_ = true; + CGContextSaveGState(context_); + + // Flip the context. + CGContextTranslateCTM(context_, 0, height); + CGContextScaleCTM(context_, scale_factor, -scale_factor); + + // Move the context to origin. + CGContextTranslateCTM(context_, content_origin.x(), content_origin.y()); + + return context_.get() != NULL; +} + +bool PdfMetafileCg::FinishPage() { + DCHECK(context_.get()); + DCHECK(page_is_open_); + + CGContextRestoreGState(context_); + CGContextEndPage(context_); + page_is_open_ = false; + return true; +} + +bool PdfMetafileCg::FinishDocument() { + DCHECK(context_.get()); + DCHECK(!page_is_open_); + +#ifndef NDEBUG + // Check that the context will be torn down properly; if it's not, pdf_data_ + // will be incomplete and generate invalid PDF files/documents. + if (context_.get()) { + CFIndex extra_retain_count = CFGetRetainCount(context_.get()) - 1; + if (extra_retain_count > 0) { + LOG(ERROR) << "Metafile context has " << extra_retain_count + << " extra retain(s) on Close"; + } + } +#endif + CGPDFContextClose(context_.get()); + context_.reset(NULL); + return true; +} + +bool PdfMetafileCg::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 { + CGPDFDocumentRef pdf_doc = GetPDFDocument(); + if (!pdf_doc) { + LOG(ERROR) << "Unable to create PDF document from data"; + return false; + } + CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); + CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox); + float scaling_factor = 1.0; + // See if we need to scale the output. + bool scaling_needed = + (shrink_to_fit && ((source_rect.size.width > rect.size.width) || + (source_rect.size.height > rect.size.height))) || + (stretch_to_fit && (source_rect.size.width < rect.size.width) && + (source_rect.size.height < rect.size.height)); + if (scaling_needed) { + float x_scaling_factor = rect.size.width / source_rect.size.width; + float y_scaling_factor = rect.size.height / source_rect.size.height; + if (x_scaling_factor > y_scaling_factor) { + scaling_factor = y_scaling_factor; + } else { + scaling_factor = x_scaling_factor; + } + } + // Some PDFs have a non-zero origin. Need to take that into account. + float x_offset = rect.origin.x - (source_rect.origin.x * scaling_factor); + float y_offset = rect.origin.y - (source_rect.origin.y * scaling_factor); + + if (center_vertically) { + x_offset += (rect.size.width - + (source_rect.size.width * scaling_factor))/2; + } + if (center_horizontally) { + y_offset += (rect.size.height - + (source_rect.size.height * scaling_factor))/2; + } else { + // Since 0 y begins at the bottom, we need to adjust so the output appears + // nearer the top if we are not centering horizontally. + y_offset += rect.size.height - (source_rect.size.height * scaling_factor); + } + CGContextSaveGState(context); + CGContextTranslateCTM(context, x_offset, y_offset); + CGContextScaleCTM(context, scaling_factor, scaling_factor); + CGContextDrawPDFPage(context, pdf_page); + CGContextRestoreGState(context); + return true; +} + +unsigned int PdfMetafileCg::GetPageCount() const { + CGPDFDocumentRef pdf_doc = GetPDFDocument(); + return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; +} + +gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const { + CGPDFDocumentRef pdf_doc = GetPDFDocument(); + if (!pdf_doc) { + LOG(ERROR) << "Unable to create PDF document from data"; + return gfx::Rect(); + } + if (page_number > GetPageCount()) { + LOG(ERROR) << "Invalid page number: " << page_number; + return gfx::Rect(); + } + CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); + CGRect page_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox); + return gfx::Rect(page_rect); +} + +uint32 PdfMetafileCg::GetDataSize() const { + // PDF data is only valid/complete once the context is released. + DCHECK(!context_); + + if (!pdf_data_) + return 0; + return static_cast(CFDataGetLength(pdf_data_)); +} + +bool PdfMetafileCg::GetData(void* dst_buffer, uint32 dst_buffer_size) const { + // PDF data is only valid/complete once the context is released. + DCHECK(!context_); + DCHECK(pdf_data_); + DCHECK(dst_buffer); + DCHECK_GT(dst_buffer_size, 0U); + + uint32 data_size = GetDataSize(); + if (dst_buffer_size > data_size) { + return false; + } + + CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size), + static_cast(dst_buffer)); + return true; +} + +bool PdfMetafileCg::SaveTo(const FilePath& file_path) const { + DCHECK(pdf_data_.get()); + DCHECK(!context_.get()); + + std::string path_string = file_path.value(); + ScopedCFTypeRef path_url(CFURLCreateFromFileSystemRepresentation( + kCFAllocatorDefault, reinterpret_cast(path_string.c_str()), + path_string.length(), false)); + SInt32 error_code; + CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code); + return error_code == 0; +} + +CGContextRef PdfMetafileCg::context() const { + return context_.get(); +} + +CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const { + // Make sure that we have data, and that it's not being modified any more. + DCHECK(pdf_data_.get()); + DCHECK(!context_.get()); + + if (!pdf_doc_.get()) { + ScopedCFTypeRef pdf_data_provider( + CGDataProviderCreateWithCFData(pdf_data_)); + pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); + } + return pdf_doc_.get(); +} + +} // namespace printing diff --git a/printing/pdf_metafile_cg_mac.h b/printing/pdf_metafile_cg_mac.h new file mode 100644 index 0000000..0183246 --- /dev/null +++ b/printing/pdf_metafile_cg_mac.h @@ -0,0 +1,94 @@ +// 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_PDF_METAFILE_CG_MAC_H_ +#define PRINTING_PDF_METAFILE_CG_MAC_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "base/mac/scoped_cftyperef.h" +#include "printing/native_metafile.h" + +class FilePath; + +namespace gfx { +class Rect; +class Size; +class Point; +} + +namespace printing { + +// This class creates a graphics context that renders into a PDF data stream. +class PdfMetafileCg : public NativeMetafile { + public: + + virtual ~PdfMetafileCg(); + + // NativeMetafile methods. + virtual bool Init(); + virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size); + + // Not implemented on mac. + virtual skia::PlatformDevice* StartPageForVectorCanvas( + const gfx::Size& page_size, const gfx::Point& content_origin, + const float& scale_factor); + virtual bool StartPage(const gfx::Size& page_size, + const gfx::Point& content_origin, + const float& scale_factor); + virtual bool FinishPage(); + virtual bool FinishDocument(); + + virtual uint32 GetDataSize() const; + virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const; + + // 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: + PdfMetafileCg(); + + private: + friend class NativeMetafileFactory; + FRIEND_TEST_ALL_PREFIXES(PdfMetafileCgTest, Pdf); + + // Returns a CGPDFDocumentRef version of pdf_data_. + CGPDFDocumentRef GetPDFDocument() const; + + // Context for rendering to the pdf. + base::mac::ScopedCFTypeRef context_; + + // PDF backing store. + base::mac::ScopedCFTypeRef pdf_data_; + + // Lazily-created CGPDFDocument representation of pdf_data_. + mutable base::mac::ScopedCFTypeRef pdf_doc_; + + // Whether or not a page is currently open. + bool page_is_open_; + + DISALLOW_COPY_AND_ASSIGN(PdfMetafileCg); +}; + +} // namespace printing + +#endif // PRINTING_PDF_METAFILE_CG_MAC_H_ diff --git a/printing/pdf_metafile_cg_mac_unittest.cc b/printing/pdf_metafile_cg_mac_unittest.cc new file mode 100644 index 0000000..5324514 --- /dev/null +++ b/printing/pdf_metafile_cg_mac_unittest.cc @@ -0,0 +1,67 @@ +// 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. + +#include "printing/pdf_metafile_cg_mac.h" + +#import + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/rect.h" + +namespace printing { + +TEST(PdfMetafileCgTest, Pdf) { + // Test in-renderer constructor. + printing::PdfMetafileCg pdf; + 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); + gfx::Size size_1(540, 720); + pdf.StartPage(size_1, origin_1, 1.25); + pdf.FinishPage(); + + // Render page 2 at origin (10.0, 10.0). + gfx::Point origin_2(10.0f, 10.0f); + gfx::Size size_2(720, 540); + pdf.StartPage(size_2, origin_2, 2.0); + pdf.FinishPage(); + + pdf.FinishDocument(); + + // Check data size. + uint32 size = pdf.GetDataSize(); + EXPECT_GT(size, 0U); + + // Get resulting data. + std::vector buffer(size, 0); + pdf.GetData(&buffer.front(), size); + + // Test browser-side constructor. + printing::PdfMetafileCg pdf2; + EXPECT_TRUE(pdf2.InitFromData(&buffer.front(), size)); + + // Get the first 4 characters from pdf2. + std::vector buffer2(4, 0); + pdf2.GetData(&buffer2.front(), 4); + + // Test that the header begins with "%PDF". + std::string header(&buffer2.front(), 4); + EXPECT_EQ(0U, header.find("%PDF", 0)); + + // Test that the PDF is correctly reconstructed. + EXPECT_EQ(2U, pdf2.GetPageCount()); + gfx::Size page_size = pdf2.GetPageBounds(1).size(); + EXPECT_EQ(540, page_size.width()); + EXPECT_EQ(720, page_size.height()); + page_size = pdf2.GetPageBounds(2).size(); + EXPECT_EQ(720, page_size.width()); + EXPECT_EQ(540, page_size.height()); +} + +} // namespace printing diff --git a/printing/pdf_metafile_mac.cc b/printing/pdf_metafile_mac.cc deleted file mode 100644 index 913f6aa..0000000 --- a/printing/pdf_metafile_mac.cc +++ /dev/null @@ -1,254 +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. - -#include "printing/pdf_metafile_mac.h" - -#include "base/file_path.h" -#include "base/logging.h" -#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; - -namespace printing { - -PdfMetafile::PdfMetafile() - : page_is_open_(false) { -} - -PdfMetafile::~PdfMetafile() {} - -bool PdfMetafile::Init() { - // Ensure that Init hasn't already been called. - DCHECK(!context_.get()); - DCHECK(!pdf_data_.get()); - - pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0)); - if (!pdf_data_.get()) { - LOG(ERROR) << "Failed to create pdf data for metafile"; - return false; - } - ScopedCFTypeRef pdf_consumer( - CGDataConsumerCreateWithCFData(pdf_data_)); - if (!pdf_consumer.get()) { - LOG(ERROR) << "Failed to create data consumer for metafile"; - pdf_data_.reset(NULL); - return false; - } - context_.reset(CGPDFContextCreate(pdf_consumer, NULL, NULL)); - if (!context_.get()) { - LOG(ERROR) << "Failed to create pdf context for metafile"; - pdf_data_.reset(NULL); - } - - return true; -} - -bool PdfMetafile::InitFromData(const void* src_buffer, uint32 src_buffer_size) { - DCHECK(!context_.get()); - DCHECK(!pdf_data_.get()); - - if (!src_buffer || src_buffer_size == 0) { - return false; - } - - pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size)); - CFDataAppendBytes(pdf_data_, static_cast(src_buffer), - src_buffer_size); - - return true; -} - -skia::PlatformDevice* PdfMetafile::StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Point& content_origin, - const float& scale_factor) { - NOTIMPLEMENTED(); - return NULL; -} - -bool PdfMetafile::StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor) { - DCHECK(context_.get()); - DCHECK(!page_is_open_); - - double height = page_size.height(); - double width = page_size.width(); - - CGRect bounds = CGRectMake(0, 0, width, height); - CGContextBeginPage(context_, &bounds); - page_is_open_ = true; - CGContextSaveGState(context_); - - // Flip the context. - CGContextTranslateCTM(context_, 0, height); - CGContextScaleCTM(context_, scale_factor, -scale_factor); - - // Move the context to origin. - CGContextTranslateCTM(context_, content_origin.x(), content_origin.y()); - - return context_.get() != NULL; -} - -bool PdfMetafile::FinishPage() { - DCHECK(context_.get()); - DCHECK(page_is_open_); - - CGContextRestoreGState(context_); - CGContextEndPage(context_); - page_is_open_ = false; - return true; -} - -bool PdfMetafile::FinishDocument() { - DCHECK(context_.get()); - DCHECK(!page_is_open_); - -#ifndef NDEBUG - // Check that the context will be torn down properly; if it's not, pdf_data_ - // will be incomplete and generate invalid PDF files/documents. - if (context_.get()) { - CFIndex extra_retain_count = CFGetRetainCount(context_.get()) - 1; - if (extra_retain_count > 0) { - LOG(ERROR) << "Metafile context has " << extra_retain_count - << " extra retain(s) on Close"; - } - } -#endif - CGPDFContextClose(context_.get()); - context_.reset(NULL); - return true; -} - -bool PdfMetafile::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 { - CGPDFDocumentRef pdf_doc = GetPDFDocument(); - if (!pdf_doc) { - LOG(ERROR) << "Unable to create PDF document from data"; - return false; - } - CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); - CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox); - float scaling_factor = 1.0; - // See if we need to scale the output. - bool scaling_needed = - (shrink_to_fit && ((source_rect.size.width > rect.size.width) || - (source_rect.size.height > rect.size.height))) || - (stretch_to_fit && (source_rect.size.width < rect.size.width) && - (source_rect.size.height < rect.size.height)); - if (scaling_needed) { - float x_scaling_factor = rect.size.width / source_rect.size.width; - float y_scaling_factor = rect.size.height / source_rect.size.height; - if (x_scaling_factor > y_scaling_factor) { - scaling_factor = y_scaling_factor; - } else { - scaling_factor = x_scaling_factor; - } - } - // Some PDFs have a non-zero origin. Need to take that into account. - float x_offset = rect.origin.x - (source_rect.origin.x * scaling_factor); - float y_offset = rect.origin.y - (source_rect.origin.y * scaling_factor); - - if (center_vertically) { - x_offset += (rect.size.width - - (source_rect.size.width * scaling_factor))/2; - } - if (center_horizontally) { - y_offset += (rect.size.height - - (source_rect.size.height * scaling_factor))/2; - } else { - // Since 0 y begins at the bottom, we need to adjust so the output appears - // nearer the top if we are not centering horizontally. - y_offset += rect.size.height - (source_rect.size.height * scaling_factor); - } - CGContextSaveGState(context); - CGContextTranslateCTM(context, x_offset, y_offset); - CGContextScaleCTM(context, scaling_factor, scaling_factor); - CGContextDrawPDFPage(context, pdf_page); - CGContextRestoreGState(context); - return true; -} - -unsigned int PdfMetafile::GetPageCount() const { - CGPDFDocumentRef pdf_doc = GetPDFDocument(); - return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; -} - -gfx::Rect PdfMetafile::GetPageBounds(unsigned int page_number) const { - CGPDFDocumentRef pdf_doc = GetPDFDocument(); - if (!pdf_doc) { - LOG(ERROR) << "Unable to create PDF document from data"; - return gfx::Rect(); - } - if (page_number > GetPageCount()) { - LOG(ERROR) << "Invalid page number: " << page_number; - return gfx::Rect(); - } - CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); - CGRect page_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox); - return gfx::Rect(page_rect); -} - -uint32 PdfMetafile::GetDataSize() const { - // PDF data is only valid/complete once the context is released. - DCHECK(!context_); - - if (!pdf_data_) - return 0; - return static_cast(CFDataGetLength(pdf_data_)); -} - -bool PdfMetafile::GetData(void* dst_buffer, uint32 dst_buffer_size) const { - // PDF data is only valid/complete once the context is released. - DCHECK(!context_); - DCHECK(pdf_data_); - DCHECK(dst_buffer); - DCHECK_GT(dst_buffer_size, 0U); - - uint32 data_size = GetDataSize(); - if (dst_buffer_size > data_size) { - return false; - } - - CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size), - static_cast(dst_buffer)); - return true; -} - -bool PdfMetafile::SaveTo(const FilePath& file_path) const { - DCHECK(pdf_data_.get()); - DCHECK(!context_.get()); - - std::string path_string = file_path.value(); - ScopedCFTypeRef path_url(CFURLCreateFromFileSystemRepresentation( - kCFAllocatorDefault, reinterpret_cast(path_string.c_str()), - path_string.length(), false)); - SInt32 error_code; - CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code); - 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()); - DCHECK(!context_.get()); - - if (!pdf_doc_.get()) { - ScopedCFTypeRef pdf_data_provider( - CGDataProviderCreateWithCFData(pdf_data_)); - pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); - } - return pdf_doc_.get(); -} - -} // namespace printing diff --git a/printing/pdf_metafile_mac.h b/printing/pdf_metafile_mac.h deleted file mode 100644 index 496b275..0000000 --- a/printing/pdf_metafile_mac.h +++ /dev/null @@ -1,94 +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_PDF_METAFILE_MAC_H_ -#define PRINTING_PDF_METAFILE_MAC_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "printing/native_metafile.h" - -class FilePath; - -namespace gfx { -class Rect; -class Size; -class Point; -} - -namespace printing { - -// This class creates a graphics context that renders into a PDF data stream. -class PdfMetafile : public NativeMetafile { - public: - - virtual ~PdfMetafile(); - - // NativeMetafile methods. - virtual bool Init(); - virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size); - - // Not implemented on mac. - virtual skia::PlatformDevice* StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Point& content_origin, - const float& scale_factor); - virtual bool StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor); - virtual bool FinishPage(); - virtual bool FinishDocument(); - - virtual uint32 GetDataSize() const; - virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) const; - - // 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: - PdfMetafile(); - - private: - friend class NativeMetafileFactory; - FRIEND_TEST_ALL_PREFIXES(PdfMetafileTest, Pdf); - - // Returns a CGPDFDocumentRef version of pdf_data_. - CGPDFDocumentRef GetPDFDocument() const; - - // Context for rendering to the pdf. - base::mac::ScopedCFTypeRef context_; - - // PDF backing store. - base::mac::ScopedCFTypeRef pdf_data_; - - // Lazily-created CGPDFDocument representation of pdf_data_. - mutable base::mac::ScopedCFTypeRef pdf_doc_; - - // Whether or not a page is currently open. - bool page_is_open_; - - DISALLOW_COPY_AND_ASSIGN(PdfMetafile); -}; - -} // namespace printing - -#endif // PRINTING_PDF_METAFILE_MAC_H_ diff --git a/printing/pdf_metafile_mac_unittest.cc b/printing/pdf_metafile_mac_unittest.cc deleted file mode 100644 index b237978..0000000 --- a/printing/pdf_metafile_mac_unittest.cc +++ /dev/null @@ -1,67 +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. - -#include "printing/pdf_metafile_mac.h" - -#import - -#include -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/rect.h" - -namespace printing { - -TEST(PdfMetafileTest, Pdf) { - // Test in-renderer constructor. - printing::PdfMetafile pdf; - 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); - gfx::Size size_1(540, 720); - pdf.StartPage(size_1, origin_1, 1.25); - pdf.FinishPage(); - - // Render page 2 at origin (10.0, 10.0). - gfx::Point origin_2(10.0f, 10.0f); - gfx::Size size_2(720, 540); - pdf.StartPage(size_2, origin_2, 2.0); - pdf.FinishPage(); - - pdf.FinishDocument(); - - // Check data size. - uint32 size = pdf.GetDataSize(); - EXPECT_GT(size, 0U); - - // Get resulting data. - std::vector buffer(size, 0); - pdf.GetData(&buffer.front(), size); - - // Test browser-side constructor. - printing::PdfMetafile pdf2; - EXPECT_TRUE(pdf2.InitFromData(&buffer.front(), size)); - - // Get the first 4 characters from pdf2. - std::vector buffer2(4, 0); - pdf2.GetData(&buffer2.front(), 4); - - // Test that the header begins with "%PDF". - std::string header(&buffer2.front(), 4); - EXPECT_EQ(0U, header.find("%PDF", 0)); - - // Test that the PDF is correctly reconstructed. - EXPECT_EQ(2U, pdf2.GetPageCount()); - gfx::Size page_size = pdf2.GetPageBounds(1).size(); - EXPECT_EQ(540, page_size.width()); - EXPECT_EQ(720, page_size.height()); - page_size = pdf2.GetPageBounds(2).size(); - EXPECT_EQ(720, page_size.width()); - EXPECT_EQ(540, page_size.height()); -} - -} // namespace printing diff --git a/printing/pdf_ps_metafile_cairo.cc b/printing/pdf_ps_metafile_cairo.cc deleted file mode 100644 index a10b125..0000000 --- a/printing/pdf_ps_metafile_cairo.cc +++ /dev/null @@ -1,261 +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. - -#include "printing/pdf_ps_metafile_cairo.h" - -#include - -#include -#include - -#include "base/eintr_wrapper.h" -#include "base/file_descriptor_posix.h" -#include "base/file_util.h" -#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 { - -// Tests if |surface| is valid. -bool IsSurfaceValid(cairo_surface_t* surface) { - return cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS; -} - -// Tests if |context| is valid. -bool IsContextValid(cairo_t* context) { - return cairo_status(context) == CAIRO_STATUS_SUCCESS; -} - -// Destroys and resets |surface|. -void CleanUpSurface(cairo_surface_t** surface) { - if (*surface) { - cairo_surface_destroy(*surface); - *surface = NULL; - } -} - -// Destroys and resets |context|. -void CleanUpContext(cairo_t** context) { - if (*context) { - cairo_destroy(*context); - *context = NULL; - } -} - -// Callback function for Cairo to write PDF stream. -// |dst_buffer| is actually a pointer of type `std::string*`. -cairo_status_t WriteCairoStream(void* dst_buffer, - const unsigned char* src_data, - unsigned int src_data_length) { - DCHECK(dst_buffer); - DCHECK(src_data); - DCHECK_GT(src_data_length, 0u); - - std::string* buffer = reinterpret_cast(dst_buffer); - buffer->append(reinterpret_cast(src_data), src_data_length); - - return CAIRO_STATUS_SUCCESS; -} - -} // namespace - -namespace printing { - -PdfPsMetafile::PdfPsMetafile() - : surface_(NULL), - context_(NULL), - current_data_(NULL) { -} - -PdfPsMetafile::~PdfPsMetafile() { - // Releases all resources if we forgot to do so. - CleanUpAll(); -} - -bool PdfPsMetafile::Init() { - // We need to check |current_data_| to ensure Init/InitFromData has not been - // called before. - DCHECK(!current_data_); - - current_data_ = &cairo_data_; - // Creates an 1 by 1 Cairo surface for the entire PDF file. - // The size for each page will be overwritten later in StartPage(). - surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, - current_data_, 1, 1); - - // Cairo always returns a valid pointer. - // Hence, we have to check if it points to a "nil" object. - if (!IsSurfaceValid(surface_)) { - DLOG(ERROR) << "Cannot create Cairo surface for PdfPsMetafile!"; - CleanUpSurface(&surface_); - return false; - } - - // Creates a context. - context_ = cairo_create(surface_); - if (!IsContextValid(context_)) { - DLOG(ERROR) << "Cannot create Cairo context for PdfPsMetafile!"; - CleanUpContext(&context_); - CleanUpSurface(&surface_); - return false; - } - - return true; -} - -bool PdfPsMetafile::InitFromData(const void* src_buffer, - uint32 src_buffer_size) { - if (src_buffer == NULL || src_buffer_size == 0) - return false; - - raw_data_ = std::string(reinterpret_cast(src_buffer), - src_buffer_size); - current_data_ = &raw_data_; - return true; -} - -skia::PlatformDevice* PdfPsMetafile::StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Point& content_origin, - const float& scale_factor) { - if (!StartPage(page_size, content_origin, scale_factor)) - return NULL; - - return skia::VectorPlatformDeviceFactory::CreateDevice(context_, - page_size.width(), - page_size.height(), - true); -} - -bool PdfPsMetafile::StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor) { - DCHECK(IsSurfaceValid(surface_)); - DCHECK(IsContextValid(context_)); - // Passing this check implies page_surface_ is NULL, and current_page_ is - // empty. - DCHECK_GT(page_size.width(), 0); - DCHECK_GT(page_size.height(), 0); - // |scale_factor| is not supported yet. - DCHECK_EQ(scale_factor, 1); - - // Don't let WebKit draw over the margins. - cairo_surface_set_device_offset(surface_, - content_origin.x(), - content_origin.y()); - - cairo_pdf_surface_set_size(surface_, page_size.width(), page_size.height()); - return context_ != NULL; -} - -bool PdfPsMetafile::FinishPage() { - DCHECK(IsSurfaceValid(surface_)); - DCHECK(IsContextValid(context_)); - - // Flushes all rendering for current page. - cairo_surface_flush(surface_); - cairo_show_page(context_); - return true; -} - -bool PdfPsMetafile::FinishDocument() { - DCHECK(IsSurfaceValid(surface_)); - DCHECK(IsContextValid(context_)); - - cairo_surface_finish(surface_); - - DCHECK(!cairo_data_.empty()); // Make sure we did get something. - - CleanUpContext(&context_); - CleanUpSurface(&surface_); - return true; -} - -uint32 PdfPsMetafile::GetDataSize() 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(!current_data_->empty()); - - return current_data_->size(); -} - -bool PdfPsMetafile::GetData(void* dst_buffer, uint32 dst_buffer_size) const { - DCHECK(dst_buffer); - DCHECK_GT(dst_buffer_size, 0u); - memcpy(dst_buffer, current_data_->data(), dst_buffer_size); - - return true; -} - -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(!current_data_->empty()); - - bool success = true; - if (file_util::WriteFile(file_path, current_data_->data(), GetDataSize()) - != static_cast(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_); - DCHECK(!current_data_->empty()); - - if (fd.fd < 0) { - DLOG(ERROR) << "Invalid file descriptor!"; - return false; - } - - bool success = true; - if (file_util::WriteFileDescriptor(fd.fd, current_data_->data(), - GetDataSize()) < 0) { - DLOG(ERROR) << "Failed to save file with fd " << fd.fd; - success = false; - } - - if (fd.auto_close) { - if (HANDLE_EINTR(close(fd.fd)) < 0) { - DPLOG(WARNING) << "close"; - success = false; - } - } - - return success; -} -#endif // if defined(OS_CHROMEOS) - -void PdfPsMetafile::CleanUpAll() { - CleanUpContext(&context_); - CleanUpSurface(&surface_); - cairo_data_.clear(); - raw_data_.clear(); - skia::VectorPlatformDevice::ClearFontCache(); -} - -} // namespace printing diff --git a/printing/pdf_ps_metafile_cairo.h b/printing/pdf_ps_metafile_cairo.h deleted file mode 100644 index 6d5cf5c..0000000 --- a/printing/pdf_ps_metafile_cairo.h +++ /dev/null @@ -1,92 +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_PDF_PS_METAFILE_CAIRO_H_ -#define PRINTING_PDF_PS_METAFILE_CAIRO_H_ - -#include - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "printing/native_metafile.h" - -namespace gfx { -class Point; -class Rect; -class Size; -} - -typedef struct _cairo_surface cairo_surface_t; - -namespace printing { - -// 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(); - - // NativeMetafile methods. - virtual bool Init(); - - // Calling InitFromData() sets the data for this metafile and masks data - // induced by previous calls to Init() or InitFromData(), even if drawing - // continues on the surface returned by a previous call to Init(). - virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size); - - virtual skia::PlatformDevice* StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Point& content_origin, - const float& scale_factor); - virtual bool StartPage(const gfx::Size& page_size, - const gfx::Point& content_origin, - const float& scale_factor); - virtual bool FinishPage(); - virtual bool FinishDocument(); - - virtual uint32 GetDataSize() const; - virtual bool GetData(void* dst_buffer, uint32 dst_buffer_size) 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; - -#if defined(OS_CHROMEOS) - virtual bool SaveToFD(const base::FileDescriptor& fd) const; -#endif // if defined(OS_CHROMEOS) - - protected: - PdfPsMetafile(); - - private: - friend class NativeMetafileFactory; - FRIEND_TEST_ALL_PREFIXES(PdfPsTest, Pdf); - - // Cleans up all resources. - void CleanUpAll(); - - // Cairo surface and context for entire PDF file. - cairo_surface_t* surface_; - cairo_t* context_; - - // Buffer stores PDF contents for entire PDF file. - std::string cairo_data_; - // Buffer stores PDF contents. It can only be populated from InitFromData(). - // Any calls to StartPage(), FinishPage(), FinishDocument() do not affect - // this buffer. - // Note: Such calls will result in DCHECK errors if Init() has not been called - // first. - std::string raw_data_; - // Points to the appropriate buffer depending on the way the object was - // initialized (Init() vs InitFromData()). - std::string* current_data_; - - DISALLOW_COPY_AND_ASSIGN(PdfPsMetafile); -}; - -} // namespace printing - -#endif // PRINTING_PDF_PS_METAFILE_CAIRO_H_ diff --git a/printing/pdf_ps_metafile_cairo_unittest.cc b/printing/pdf_ps_metafile_cairo_unittest.cc deleted file mode 100644 index 5b2bf2a..0000000 --- a/printing/pdf_ps_metafile_cairo_unittest.cc +++ /dev/null @@ -1,85 +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. - -#include "printing/pdf_ps_metafile_cairo.h" - -#include -#include -#include - -#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" -#include "ui/gfx/point.h" - -typedef struct _cairo cairo_t; - -namespace { - -class PdfPsTest : public testing::Test {}; - -} // namespace - -namespace printing { - -TEST_F(PdfPsTest, Pdf) { - // Tests in-renderer constructor. - printing::PdfPsMetafile pdf; - EXPECT_TRUE(pdf.Init()); - - // Renders page 1. - EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); - // In theory, we should use Cairo to draw something on |context|. - EXPECT_TRUE(pdf.FinishPage()); - - // Renders page 2. - EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); - // In theory, we should use Cairo to draw something on |context|. - EXPECT_TRUE(pdf.FinishPage()); - - // Closes the file. - pdf.FinishDocument(); - - // Checks data size. - uint32 size = pdf.GetDataSize(); - EXPECT_GT(size, 0u); - - // Gets resulting data. - std::vector buffer(size, 0x00); - pdf.GetData(&buffer.front(), size); - - // Tests another constructor. - printing::PdfPsMetafile pdf2; - EXPECT_TRUE(pdf2.InitFromData(&buffer.front(), size)); - - // Tries to get the first 4 characters from pdf2. - std::vector buffer2(4, 0x00); - pdf2.GetData(&buffer2.front(), 4); - - // Tests if the header begins with "%PDF". - std::string header(&buffer2.front(), 4); - EXPECT_EQ(header.find("%PDF", 0), 0u); - - // Tests if we can save data. - EXPECT_TRUE(pdf.SaveTo(FilePath("/dev/null"))); - - // Test overriding the metafile with raw data. - printing::PdfPsMetafile pdf3; - EXPECT_TRUE(pdf3.Init()); - EXPECT_TRUE(pdf3.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1)); - std::string test_raw_data = "Dummy PDF"; - EXPECT_TRUE(pdf3.InitFromData(test_raw_data.c_str(), test_raw_data.size())); - EXPECT_TRUE(pdf3.FinishPage()); - pdf3.FinishDocument(); - size = pdf3.GetDataSize(); - EXPECT_EQ(test_raw_data.size(), size); - std::string output; - pdf3.GetData(WriteInto(&output, size + 1), size); - EXPECT_EQ(test_raw_data, output); -} - -} // namespace printing diff --git a/printing/print_settings_initializer_gtk.cc b/printing/print_settings_initializer_gtk.cc index 833db52..a42561ba 100644 --- a/printing/print_settings_initializer_gtk.cc +++ b/printing/print_settings_initializer_gtk.cc @@ -9,7 +9,6 @@ #include "base/string_piece.h" #include "base/utf_string_conversions.h" -#include "printing/pdf_ps_metafile_cairo.h" #include "printing/print_settings.h" #include "printing/units.h" diff --git a/printing/printing.gyp b/printing/printing.gyp index 94c90a6..ae61a41 100644 --- a/printing/printing.gyp +++ b/printing/printing.gyp @@ -47,10 +47,10 @@ 'page_range.h', 'page_setup.cc', 'page_setup.h', - 'pdf_metafile_mac.cc', - 'pdf_metafile_mac.h', - 'pdf_ps_metafile_cairo.cc', - 'pdf_ps_metafile_cairo.h', + 'pdf_metafile_cairo_linux.cc', + 'pdf_metafile_cairo_linux.h', + 'pdf_metafile_cg_mac.cc', + 'pdf_metafile_cg_mac.h', 'printed_document_cairo.cc', 'printed_document.cc', 'printed_document.h', @@ -165,8 +165,8 @@ 'page_overlays_unittest.cc', 'page_range_unittest.cc', 'page_setup_unittest.cc', - 'pdf_metafile_mac_unittest.cc', - 'pdf_ps_metafile_cairo_unittest.cc', + 'pdf_metafile_cairo_linux_unittest.cc', + 'pdf_metafile_cg_mac_unittest.cc', 'printed_page_unittest.cc', 'printing_context_win_unittest.cc', 'run_all_unittests.cc', -- cgit v1.1