Remove dead cairo code.
BUG= TEST=No visible changes. Review URL: http://codereview.chromium.org/7847002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100281 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -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)
|
||||
|
@ -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
|
@ -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_
|
@ -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
|
@ -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',
|
||||
|
@ -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
|
@ -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_
|
@ -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',
|
||||
|
Reference in New Issue
Block a user