diff options
-rw-r--r-- | printing/metafile_impl.h | 2 | ||||
-rw-r--r-- | printing/pdf_metafile_cairo_linux.cc | 259 | ||||
-rw-r--r-- | printing/pdf_metafile_cairo_linux.h | 88 | ||||
-rw-r--r-- | printing/pdf_metafile_cairo_linux_unittest.cc | 85 | ||||
-rw-r--r-- | printing/printing.gyp | 3 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_cairo_linux.cc | 695 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_cairo_linux.h | 131 | ||||
-rw-r--r-- | skia/skia.gyp | 2 |
8 files changed, 0 insertions, 1265 deletions
diff --git a/printing/metafile_impl.h b/printing/metafile_impl.h index dd09e09..38c68a3 100644 --- a/printing/metafile_impl.h +++ b/printing/metafile_impl.h @@ -9,8 +9,6 @@ #include "printing/emf_win.h" #elif defined(OS_MACOSX) #include "printing/pdf_metafile_cg_mac.h" -#elif defined(OS_POSIX) -#include "printing/pdf_metafile_cairo_linux.h" #endif #if !defined(OS_MACOSX) || defined(USE_SKIA) diff --git a/printing/pdf_metafile_cairo_linux.cc b/printing/pdf_metafile_cairo_linux.cc deleted file mode 100644 index af2aa5c..0000000 --- a/printing/pdf_metafile_cairo_linux.cc +++ /dev/null @@ -1,259 +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_cairo_linux.h" - -#include <stdio.h> - -#include <cairo.h> -#include <cairo-pdf.h> - -#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<std::string*>(dst_buffer); - buffer->append(reinterpret_cast<const char*>(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<const char*>(src_buffer), - src_buffer_size); - current_data_ = &raw_data_; - return true; -} - -SkDevice* PdfMetafileCairo::StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Rect& content_area, - const float& scale_factor) { - if (!StartPage(page_size, content_area, scale_factor)) - return NULL; - - return skia::VectorPlatformDeviceCairo::CreateDevice( - context_, page_size.width(), page_size.height(), true); -} - -bool PdfMetafileCairo::StartPage(const gfx::Size& page_size, - const gfx::Rect& content_area, - 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_area.x(), - content_area.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<int>(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 deleted file mode 100644 index 28c0698..0000000 --- a/printing/pdf_metafile_cairo_linux.h +++ /dev/null @@ -1,88 +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_CAIRO_LINUX_H_ -#define PRINTING_PDF_METAFILE_CAIRO_LINUX_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "printing/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 PRINTING_EXPORT PdfMetafileCairo : public Metafile { - public: - PdfMetafileCairo(); - virtual ~PdfMetafileCairo(); - - // Metafile 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 SkDevice* StartPageForVectorCanvas( - const gfx::Size& page_size, const gfx::Rect& content_area, - const float& scale_factor); - - virtual bool StartPage(const gfx::Size& page_size, - const gfx::Rect& content_area, - 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) - - private: - // 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 deleted file mode 100644 index 0ea08f81..0000000 --- a/printing/pdf_metafile_cairo_linux_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_metafile_cairo_linux.h" - -#include <fcntl.h> -#include <string> -#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/rect.h" -#include "ui/gfx/size.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::Rect(4, 5, 64, 63), 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::Rect(4, 5, 64, 63), 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<char> 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<char> 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::Rect(4, 5, 64, 63), 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/printing.gyp b/printing/printing.gyp index 256108e..4d7aa20 100644 --- a/printing/printing.gyp +++ b/printing/printing.gyp @@ -50,8 +50,6 @@ 'page_setup.cc', 'page_setup.h', 'page_size_margins.h', - 'pdf_metafile_cairo_linux.cc', - 'pdf_metafile_cairo_linux.h', 'pdf_metafile_cg_mac.cc', 'pdf_metafile_cg_mac.h', 'pdf_metafile_skia.h', @@ -177,7 +175,6 @@ 'page_number_unittest.cc', 'page_range_unittest.cc', 'page_setup_unittest.cc', - 'pdf_metafile_cairo_linux_unittest.cc', 'pdf_metafile_cg_mac_unittest.cc', 'printed_page_unittest.cc', 'printing_context_win_unittest.cc', diff --git a/skia/ext/vector_platform_device_cairo_linux.cc b/skia/ext/vector_platform_device_cairo_linux.cc deleted file mode 100644 index 1d31cf6..0000000 --- a/skia/ext/vector_platform_device_cairo_linux.cc +++ /dev/null @@ -1,695 +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 "skia/ext/vector_platform_device_cairo_linux.h" - -#include <cairo.h> -#include <cairo-ft.h> - -#include <ft2build.h> -#include FT_FREETYPE_H - -#include <map> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "skia/ext/bitmap_platform_device.h" -#include "third_party/skia/include/core/SkFontHost.h" -#include "third_party/skia/include/core/SkStream.h" -#include "third_party/skia/include/core/SkTypeface.h" - -namespace { - -struct FontInfo { - SkStream* font_stream; - FT_Face ft_face; - cairo_font_face_t* cairo_face; - cairo_user_data_key_t data_key; -}; - -typedef std::map<uint32_t, FontInfo> MapFontId2FontInfo; -static base::LazyInstance<MapFontId2FontInfo> g_map_font_id_to_font_info( - base::LINKER_INITIALIZED); - -// Wrapper for FT_Library that handles initialization and cleanup, and allows -// us to use a singleton. -class FtLibrary { - public: - FtLibrary() : library_(NULL) { - FT_Error ft_error = FT_Init_FreeType(&library_); - if (ft_error) { - DLOG(ERROR) << "Cannot initialize FreeType library for " \ - << "VectorPlatformDeviceCairo."; - } - } - - ~FtLibrary() { - if (library_) { - FT_Error ft_error = FT_Done_FreeType(library_); - library_ = NULL; - DCHECK_EQ(ft_error, 0); - } - } - - FT_Library library() { return library_; } - - private: - FT_Library library_; -}; -static base::LazyInstance<FtLibrary> g_ft_library(base::LINKER_INITIALIZED); - -// Verify cairo surface after creation/modification. -bool IsContextValid(cairo_t* context) { - return cairo_status(context) == CAIRO_STATUS_SUCCESS; -} - -} // namespace - -namespace skia { - -// static -SkDevice* VectorPlatformDeviceCairo::CreateDevice(cairo_t* context, int width, - int height, bool isOpaque) { - // TODO(myhuang): Here we might also have similar issues as those on Windows - // (vector_canvas_win.cc, http://crbug.com/18382 & http://crbug.com/18383). - // Please note that is_opaque is true when we use this class for printing. - // Fallback to bitmap when context is NULL. - if (!isOpaque || NULL == context) { - return BitmapPlatformDevice::Create(width, height, isOpaque); - } - - SkASSERT(cairo_status(context) == CAIRO_STATUS_SUCCESS); - SkASSERT(width > 0); - SkASSERT(height > 0); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - - return new VectorPlatformDeviceCairo(context, bitmap); -} - -VectorPlatformDeviceCairo::VectorPlatformDeviceCairo(PlatformSurface context, - const SkBitmap& bitmap) - : SkDevice(bitmap), - context_(context) { - SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config); - - SetPlatformDevice(this, this); - - // Increase the reference count to keep the context alive. - cairo_reference(context_); - - transform_.reset(); -} - -VectorPlatformDeviceCairo::~VectorPlatformDeviceCairo() { - // Un-ref |context_| since we referenced it in the constructor. - cairo_destroy(context_); -} - -PlatformSurface VectorPlatformDeviceCairo::BeginPlatformPaint() { - return context_; -} - -void VectorPlatformDeviceCairo::DrawToNativeContext( - PlatformSurface surface, int x, int y, const PlatformRect* src_rect) { - // Should never be called on Linux. - SkASSERT(false); -} - -SkDevice* VectorPlatformDeviceCairo::onCreateCompatibleDevice( - SkBitmap::Config config, - int width, int height, - bool isOpaque, Usage) { - SkASSERT(config == SkBitmap::kARGB_8888_Config); - return CreateDevice(NULL, width, height, isOpaque); -} - -uint32_t VectorPlatformDeviceCairo::getDeviceCapabilities() { - return SkDevice::getDeviceCapabilities() | kVector_Capability; -} - -void VectorPlatformDeviceCairo::drawBitmap(const SkDraw& draw, - const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, - const SkMatrix& matrix, - const SkPaint& paint) { - SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config); - - // Load the temporary matrix. This is what will translate, rotate and resize - // the bitmap. - SkMatrix actual_transform(transform_); - actual_transform.preConcat(matrix); - LoadTransformToContext(actual_transform); - - InternalDrawBitmap(bitmap, 0, 0, paint); - - // Restore the original matrix. - LoadTransformToContext(transform_); -} - -void VectorPlatformDeviceCairo::drawDevice(const SkDraw& draw, - SkDevice* device, - int x, - int y, - const SkPaint& paint) { - SkASSERT(device); - - // TODO(myhuang): We may also have to consider http://b/1183870 . - drawSprite(draw, device->accessBitmap(false), x, y, paint); -} - -void VectorPlatformDeviceCairo::drawPaint(const SkDraw& draw, - const SkPaint& paint) { - // Bypass the current transformation matrix. - LoadIdentityTransformToContext(); - - // TODO(myhuang): Is there a better way to do this? - SkRect rect; - rect.fLeft = 0; - rect.fTop = 0; - rect.fRight = SkIntToScalar(width() + 1); - rect.fBottom = SkIntToScalar(height() + 1); - drawRect(draw, rect, paint); - - // Restore the original matrix. - LoadTransformToContext(transform_); -} - -void VectorPlatformDeviceCairo::drawPath(const SkDraw& draw, - const SkPath& path, - const SkPaint& paint, - const SkMatrix* prePathMatrix, - bool pathIsMutable) { - if (paint.getPathEffect()) { - // Apply the path effect forehand. - SkPath path_modified; - paint.getFillPath(path, &path_modified); - - // Removes the path effect from the temporary SkPaint object. - SkPaint paint_no_effet(paint); - SkSafeUnref(paint_no_effet.setPathEffect(NULL)); - - // Draw the calculated path. - drawPath(draw, path_modified, paint_no_effet); - return; - } - - // Setup paint color. - ApplyPaintColor(paint); - - SkPaint::Style style = paint.getStyle(); - // Setup fill style. - if (style & SkPaint::kFill_Style) { - ApplyFillStyle(path); - } - - // Setup stroke style. - if (style & SkPaint::kStroke_Style) { - ApplyStrokeStyle(paint); - } - - // Iterate path verbs. - // TODO(myhuang): Is there a better way to do this? - SkPoint current_points[4]; - SkPath::Iter iter(path, false); - for (SkPath::Verb verb = iter.next(current_points); - verb != SkPath::kDone_Verb; - verb = iter.next(current_points)) { - switch (verb) { - case SkPath::kMove_Verb: { // iter.next returns 1 point - cairo_move_to(context_, current_points[0].fX, current_points[0].fY); - } break; - - case SkPath::kLine_Verb: { // iter.next returns 2 points - cairo_line_to(context_, current_points[1].fX, current_points[1].fY); - } break; - - case SkPath::kQuad_Verb: { // iter.next returns 3 points - // Degree elevation (quadratic to cubic). - // c1 = (2 * p1 + p0) / 3 - // c2 = (2 * p1 + p2) / 3 - current_points[1].scale(2.); // p1 *= 2.0; - SkScalar c1_X = (current_points[1].fX + current_points[0].fX) / 3.; - SkScalar c1_Y = (current_points[1].fY + current_points[0].fY) / 3.; - SkScalar c2_X = (current_points[1].fX + current_points[2].fX) / 3.; - SkScalar c2_Y = (current_points[1].fY + current_points[2].fY) / 3.; - cairo_curve_to(context_, - c1_X, c1_Y, - c2_X, c2_Y, - current_points[2].fX, current_points[2].fY); - } break; - - case SkPath::kCubic_Verb: { // iter.next returns 4 points - cairo_curve_to(context_, - current_points[1].fX, current_points[1].fY, - current_points[2].fX, current_points[2].fY, - current_points[3].fX, current_points[3].fY); - } break; - - case SkPath::kClose_Verb: { // iter.next returns 1 point (the last pt). - cairo_close_path(context_); - } break; - - default: { - // Should not reach here! - SkASSERT(false); - } break; - } - } - - DoPaintStyle(paint); -} - -void VectorPlatformDeviceCairo::drawPoints(const SkDraw& draw, - SkCanvas::PointMode mode, - size_t count, - const SkPoint pts[], - const SkPaint& paint) { - SkASSERT(pts); - - if (!count) - return; - - // Setup paint color. - ApplyPaintColor(paint); - - // Setup stroke style. - ApplyStrokeStyle(paint); - - switch (mode) { - case SkCanvas::kPoints_PointMode: { - // There is a bug in Cairo that it won't draw anything when using some - // specific caps, e.g. SkPaint::kSquare_Cap. This is because Cairo does - // not have enough/ambiguous direction information. One possible work- - // around is to draw a really short line. - for (size_t i = 0; i < count; ++i) { - double x = pts[i].fX; - double y = pts[i].fY; - cairo_move_to(context_, x, y); - cairo_line_to(context_, x+.01, y); - } - } break; - - case SkCanvas::kLines_PointMode: { - if (count % 2) { - SkASSERT(false); - return; - } - - for (size_t i = 0; i < count >> 1; ++i) { - double x1 = pts[i << 1].fX; - double y1 = pts[i << 1].fY; - double x2 = pts[(i << 1) + 1].fX; - double y2 = pts[(i << 1) + 1].fY; - cairo_move_to(context_, x1, y1); - cairo_line_to(context_, x2, y2); - } - } break; - - case SkCanvas::kPolygon_PointMode: { - double x = pts[0].fX; - double y = pts[0].fY; - cairo_move_to(context_, x, y); - for (size_t i = 1; i < count; ++i) { - x = pts[i].fX; - y = pts[i].fY; - cairo_line_to(context_, x, y); - } - } break; - - default: - SkASSERT(false); - return; - } - cairo_stroke(context_); -} - -// TODO(myhuang): Embed fonts/texts into PDF surface. -// Please NOTE that len records text's length in byte, not uint16_t. -void VectorPlatformDeviceCairo::drawPosText(const SkDraw& draw, - const void* text, - size_t len, - const SkScalar pos[], - SkScalar constY, - int scalarsPerPos, - const SkPaint& paint) { - SkASSERT(text); - SkASSERT(pos); - SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); - // Each pos should contain either only x, or (x, y). - SkASSERT((scalarsPerPos == 1) || (scalarsPerPos == 2)); - - if (!len) - return; - - // Text color. - ApplyPaintColor(paint); - - const uint16_t* glyph_ids = static_cast<const uint16_t*>(text); - - // The style is either kFill_Style or kStroke_Style. - if (paint.getStyle() & SkPaint::kStroke_Style) { - ApplyStrokeStyle(paint); - - // Draw each glyph by its path. - for (size_t i = 0; i < len / sizeof(uint16_t); ++i) { - uint16_t glyph_id = glyph_ids[i]; - SkPath textPath; - paint.getTextPath(&glyph_id, - sizeof(uint16_t), - pos[i * scalarsPerPos], - (scalarsPerPos == 1) ? - constY : - pos[i * scalarsPerPos + 1], - &textPath); - drawPath(draw, textPath, paint); - } - } else { // kFill_Style. - // Selects correct font. - if (!SelectFontById(paint.getTypeface()->uniqueID())) { - SkASSERT(false); - return; - } - cairo_set_font_size(context_, paint.getTextSize()); - - // Draw glyphs. - for (size_t i = 0; i < len / sizeof(uint16_t); ++i) { - uint16_t glyph_id = glyph_ids[i]; - - cairo_glyph_t glyph; - glyph.index = glyph_id; - glyph.x = pos[i * scalarsPerPos]; - glyph.y = (scalarsPerPos == 1) ? constY : pos[i * scalarsPerPos + 1]; - - cairo_show_glyphs(context_, &glyph, 1); - } - } -} - -void VectorPlatformDeviceCairo::drawRect(const SkDraw& draw, - const SkRect& rect, - const SkPaint& paint) { - if (paint.getPathEffect()) { - // Draw a path instead. - SkPath path_orginal; - path_orginal.addRect(rect); - - // Apply the path effect to the rect. - SkPath path_modified; - paint.getFillPath(path_orginal, &path_modified); - - // Removes the path effect from the temporary SkPaint object. - SkPaint paint_no_effet(paint); - SkSafeUnref(paint_no_effet.setPathEffect(NULL)); - - // Draw the calculated path. - drawPath(draw, path_modified, paint_no_effet); - return; - } - - // Setup color. - ApplyPaintColor(paint); - - // Setup stroke style. - ApplyStrokeStyle(paint); - - // Draw rectangle. - cairo_rectangle(context_, - rect.fLeft, rect.fTop, - rect.fRight - rect.fLeft, rect.fBottom - rect.fTop); - - DoPaintStyle(paint); -} - -void VectorPlatformDeviceCairo::drawSprite(const SkDraw& draw, - const SkBitmap& bitmap, - int x, int y, - const SkPaint& paint) { - SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config); - - LoadIdentityTransformToContext(); - - InternalDrawBitmap(bitmap, x, y, paint); - - // Restore the original matrix. - LoadTransformToContext(transform_); -} - -void VectorPlatformDeviceCairo::drawText(const SkDraw& draw, - const void* text, - size_t byteLength, - SkScalar x, - SkScalar y, - const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - SkASSERT(false); -} - - -void VectorPlatformDeviceCairo::drawTextOnPath(const SkDraw& draw, - const void* text, - size_t len, - const SkPath& path, - const SkMatrix* matrix, - const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - SkASSERT(false); -} - -void VectorPlatformDeviceCairo::drawVertices(const SkDraw& draw, - SkCanvas::VertexMode vmode, - int vertexCount, - const SkPoint vertices[], - const SkPoint texs[], - const SkColor colors[], - SkXfermode* xmode, - const uint16_t indices[], - int indexCount, - const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - SkASSERT(false); -} - -void VectorPlatformDeviceCairo::setMatrixClip(const SkMatrix& transform, - const SkRegion& region, - const SkClipStack&) { - clip_region_ = region; - if (!clip_region_.isEmpty()) - LoadClipRegion(clip_region_); - - transform_ = transform; - LoadTransformToContext(transform_); -} - -void VectorPlatformDeviceCairo::ApplyPaintColor(const SkPaint& paint) { - SkColor color = paint.getColor(); - double a = static_cast<double>(SkColorGetA(color)) / 255.; - double r = static_cast<double>(SkColorGetR(color)) / 255.; - double g = static_cast<double>(SkColorGetG(color)) / 255.; - double b = static_cast<double>(SkColorGetB(color)) / 255.; - - cairo_set_source_rgba(context_, r, g, b, a); -} - -void VectorPlatformDeviceCairo::ApplyFillStyle(const SkPath& path) { - // Setup fill style. - // TODO(myhuang): Cairo does NOT support all skia fill rules!! - cairo_set_fill_rule(context_, - static_cast<cairo_fill_rule_t>(path.getFillType())); -} - -void VectorPlatformDeviceCairo::ApplyStrokeStyle(const SkPaint& paint) { - // Line width. - cairo_set_line_width(context_, paint.getStrokeWidth()); - - // Line join. - cairo_set_line_join(context_, - static_cast<cairo_line_join_t>(paint.getStrokeJoin())); - - // Line cap. - cairo_set_line_cap(context_, - static_cast<cairo_line_cap_t>(paint.getStrokeCap())); -} - -void VectorPlatformDeviceCairo::DoPaintStyle(const SkPaint& paint) { - SkPaint::Style style = paint.getStyle(); - - switch (style) { - case SkPaint::kFill_Style: { - cairo_fill(context_); - } break; - - case SkPaint::kStroke_Style: { - cairo_stroke(context_); - } break; - - case SkPaint::kStrokeAndFill_Style: { - cairo_fill_preserve(context_); - cairo_stroke(context_); - } break; - - default: - SkASSERT(false); - } -} - -void VectorPlatformDeviceCairo::InternalDrawBitmap(const SkBitmap& bitmap, - int x, int y, - const SkPaint& paint) { - SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config); - - unsigned char alpha = paint.getAlpha(); - - if (alpha == 0) - return; - - int src_size_x = bitmap.width(); - int src_size_y = bitmap.height(); - - if (!src_size_x || !src_size_y) - return; - - SkAutoLockPixels image_lock(bitmap); - - cairo_surface_t* bitmap_surface = - cairo_image_surface_create_for_data( - reinterpret_cast<unsigned char*>(bitmap.getPixels()), - CAIRO_FORMAT_ARGB32, src_size_x, src_size_y, bitmap.rowBytes()); - - cairo_set_source_surface(context_, bitmap_surface, x, y); - cairo_paint_with_alpha(context_, static_cast<double>(alpha) / 255.); - - cairo_surface_destroy(bitmap_surface); -} - -void VectorPlatformDeviceCairo::LoadClipRegion(const SkRegion& clip) { - cairo_reset_clip(context_); - - LoadIdentityTransformToContext(); - - // TODO(myhuang): Support non-rect clips. - SkIRect bounding = clip.getBounds(); - cairo_rectangle(context_, bounding.fLeft, bounding.fTop, - bounding.fRight - bounding.fLeft, - bounding.fBottom - bounding.fTop); - cairo_clip(context_); - - // Restore the original matrix. - LoadTransformToContext(transform_); -} - -void VectorPlatformDeviceCairo::LoadIdentityTransformToContext() { - SkMatrix identity; - identity.reset(); - LoadTransformToContext(identity); -} - -void VectorPlatformDeviceCairo::LoadTransformToContext(const SkMatrix& matrix) { - cairo_matrix_t m; - m.xx = matrix[SkMatrix::kMScaleX]; - m.xy = matrix[SkMatrix::kMSkewX]; - m.x0 = matrix[SkMatrix::kMTransX]; - m.yx = matrix[SkMatrix::kMSkewY]; - m.yy = matrix[SkMatrix::kMScaleY]; - m.y0 = matrix[SkMatrix::kMTransY]; - cairo_set_matrix(context_, &m); -} - -bool VectorPlatformDeviceCairo::SelectFontById(uint32_t font_id) { - DCHECK(IsContextValid(context_)); - DCHECK(SkFontHost::ValidFontID(font_id)); - - FtLibrary* ft_library = g_ft_library.Pointer(); - if (!ft_library->library()) - return false; - - // Checks if we have a cache hit. - MapFontId2FontInfo* g_font_cache = g_map_font_id_to_font_info.Pointer(); - DCHECK(g_font_cache); - - MapFontId2FontInfo::iterator it = g_font_cache->find(font_id); - if (it != g_font_cache->end()) { - cairo_set_font_face(context_, it->second.cairo_face); - if (IsContextValid(context_)) { - return true; - } else { - NOTREACHED() << "Cannot set font face in Cairo!"; - return false; - } - } - - // Cache missed. We need to load and create the font. - FontInfo new_font_info = {0}; - new_font_info.font_stream = SkFontHost::OpenStream(font_id); - DCHECK(new_font_info.font_stream); - size_t stream_size = new_font_info.font_stream->getLength(); - DCHECK(stream_size) << "The Font stream has nothing!"; - - FT_Error ft_error = FT_New_Memory_Face( - ft_library->library(), - static_cast<FT_Byte*>( - const_cast<void*>(new_font_info.font_stream->getMemoryBase())), - stream_size, - 0, - &new_font_info.ft_face); - - if (ft_error) { - new_font_info.font_stream->unref(); - DLOG(ERROR) << "Cannot create FT_Face!"; - SkASSERT(false); - return false; - } - - new_font_info.cairo_face = cairo_ft_font_face_create_for_ft_face( - new_font_info.ft_face, 0); - DCHECK(new_font_info.cairo_face) << "Cannot create font in Cairo!"; - - // Manage |new_font_info.ft_face|'s life by Cairo. - cairo_status_t status = cairo_font_face_set_user_data( - new_font_info.cairo_face, - &new_font_info.data_key, - new_font_info.ft_face, - reinterpret_cast<cairo_destroy_func_t>(FT_Done_Face)); - - if (status != CAIRO_STATUS_SUCCESS) { - DLOG(ERROR) << "Cannot set font's user data in Cairo!"; - cairo_font_face_destroy(new_font_info.cairo_face); - FT_Done_Face(new_font_info.ft_face); - new_font_info.font_stream->unref(); - SkASSERT(false); - return false; - } - - // Inserts |new_font_info| info |g_font_cache|. - (*g_font_cache)[font_id] = new_font_info; - - cairo_set_font_face(context_, new_font_info.cairo_face); - if (IsContextValid(context_)) { - return true; - } - - DLOG(ERROR) << "Connot set font face in Cairo!"; - return false; -} - -// static -void VectorPlatformDeviceCairo::ClearFontCache() { - MapFontId2FontInfo* g_font_cache = g_map_font_id_to_font_info.Pointer(); - DCHECK(g_font_cache); - - for (MapFontId2FontInfo::iterator it = g_font_cache->begin(); - it !=g_font_cache->end(); - ++it) { - DCHECK(it->second.cairo_face); - DCHECK(it->second.font_stream); - - cairo_font_face_destroy(it->second.cairo_face); - // |it->second.ft_face| is handled by Cairo. - it->second.font_stream->unref(); - } - g_font_cache->clear(); -} - -} // namespace skia diff --git a/skia/ext/vector_platform_device_cairo_linux.h b/skia/ext/vector_platform_device_cairo_linux.h deleted file mode 100644 index 36be0c76..0000000 --- a/skia/ext/vector_platform_device_cairo_linux.h +++ /dev/null @@ -1,131 +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 SKIA_EXT_VECTOR_PLATFORM_DEVICE_CAIRO_LINUX_H_ -#define SKIA_EXT_VECTOR_PLATFORM_DEVICE_CAIRO_LINUX_H_ -#pragma once - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "skia/ext/platform_device.h" -#include "third_party/skia/include/core/SkMatrix.h" -#include "third_party/skia/include/core/SkRegion.h" - -namespace skia { - -// This device is basically a wrapper that provides a surface for SkCanvas -// to draw into. It is basically an adaptor which converts skia APIs into -// cooresponding Cairo APIs and outputs to a Cairo surface. Please NOTE that -// since it is completely vectorial, the bitmap content in it is thus -// meaningless. -class SK_API VectorPlatformDeviceCairo : public PlatformDevice, - public SkDevice { - public: - virtual ~VectorPlatformDeviceCairo(); - - static SkDevice* CreateDevice(cairo_t* context, int width, int height, - bool isOpaque); - - // Clean up cached fonts. It is an error to call this while some - // VectorPlatformDeviceCairo callee is still using fonts created for it by - // this class. - static void ClearFontCache(); - - // Overridden from SkDevice - virtual uint32_t getDeviceCapabilities(); - virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) OVERRIDE; - virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, - size_t count, const SkPoint[], - const SkPaint& paint) OVERRIDE; - virtual void drawRect(const SkDraw& draw, const SkRect& r, - const SkPaint& paint) OVERRIDE; - virtual void drawPath(const SkDraw& draw, const SkPath& path, - const SkPaint& paint, - const SkMatrix* prePathMatrix = NULL, - bool pathIsMutable = false) OVERRIDE; - virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, - const SkMatrix& matrix, - const SkPaint& paint) OVERRIDE; - virtual void drawSprite(const SkDraw& draw, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint) OVERRIDE; - virtual void drawText(const SkDraw& draw, const void* text, size_t len, - SkScalar x, SkScalar y, const SkPaint& paint) OVERRIDE; - virtual void drawPosText(const SkDraw& draw, const void* text, size_t len, - const SkScalar pos[], SkScalar constY, - int scalarsPerPos, const SkPaint& paint) OVERRIDE; - virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len, - const SkPath& path, const SkMatrix* matrix, - const SkPaint& paint) OVERRIDE; - virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, - int vertexCount, - const SkPoint verts[], const SkPoint texs[], - const SkColor colors[], SkXfermode* xmode, - const uint16_t indices[], int indexCount, - const SkPaint& paint) OVERRIDE; - virtual void drawDevice(const SkDraw& draw, SkDevice*, int x, int y, - const SkPaint&) OVERRIDE; - - virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region, - const SkClipStack&) OVERRIDE; - - // Overridden from PlatformDevice - virtual PlatformSurface BeginPlatformPaint() OVERRIDE; - virtual void DrawToNativeContext(PlatformSurface surface, int x, int y, - const PlatformRect* src_rect) OVERRIDE; - - protected: - VectorPlatformDeviceCairo(PlatformSurface context, const SkBitmap& bitmap); - - virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config, int width, - int height, bool isOpaque, - Usage usage) OVERRIDE; - - private: - // Apply paint's color in the context. - void ApplyPaintColor(const SkPaint& paint); - - // Apply path's fill style in the context. - void ApplyFillStyle(const SkPath& path); - - // Apply paint's stroke style in the context. - void ApplyStrokeStyle(const SkPaint& paint); - - // Perform painting. - void DoPaintStyle(const SkPaint& paint); - - // Draws a bitmap in the the device, using the currently loaded matrix. - void InternalDrawBitmap(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint); - - // Set up the clipping region for the context. Please note that now we only - // use the bounding box of the region for clipping. - // TODO(myhuang): Support non-rectangular clipping. - void LoadClipRegion(const SkRegion& clip); - - // Use identity matrix to set up context's transformation. - void LoadIdentityTransformToContext(); - - // Use matrix to set up context's transformation. - void LoadTransformToContext(const SkMatrix& matrix); - - // Selects the font associated with |font_id| in |context|. - // Return true on success. - bool SelectFontById(uint32_t font_id); - - // Transformation assigned to the context. - SkMatrix transform_; - - // The current clipping region. - SkRegion clip_region_; - - // Device context. - PlatformSurface context_; - - DISALLOW_COPY_AND_ASSIGN(VectorPlatformDeviceCairo); -}; - -} // namespace skia - -#endif // SKIA_EXT_VECTOR_PLATFORM_DEVICE_CAIRO_LINUX_H_ diff --git a/skia/skia.gyp b/skia/skia.gyp index 4baef8b..106efa9 100644 --- a/skia/skia.gyp +++ b/skia/skia.gyp @@ -696,8 +696,6 @@ 'ext/skia_utils_win.h', 'ext/vector_canvas.cc', 'ext/vector_canvas.h', - 'ext/vector_platform_device_cairo_linux.cc', - 'ext/vector_platform_device_cairo_linux.h', 'ext/vector_platform_device_emf_win.cc', 'ext/vector_platform_device_emf_win.h', 'ext/vector_platform_device_skia.cc', |