summaryrefslogtreecommitdiffstats
path: root/skia
diff options
context:
space:
mode:
authormmoss@chromium.org <mmoss@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-28 19:50:39 +0000
committermmoss@chromium.org <mmoss@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-28 19:50:39 +0000
commitb33892e62a94b183df6892cbe0edce7c523e4ba3 (patch)
tree1cc74750efc53a50aaa7b70c70d8ef1067098736 /skia
parent9132d2b58b32ec01d3859dc96c058124bd6c347d (diff)
downloadchromium_src-b33892e62a94b183df6892cbe0edce7c523e4ba3.zip
chromium_src-b33892e62a94b183df6892cbe0edce7c523e4ba3.tar.gz
chromium_src-b33892e62a94b183df6892cbe0edce7c523e4ba3.tar.bz2
Move cairo font handling from printing to skia to avoid circular dependency.
http://crbug.com/22792 Review URL: http://codereview.chromium.org/245027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27395 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia')
-rw-r--r--skia/ext/vector_platform_device_linux.cc149
-rw-r--r--skia/ext/vector_platform_device_linux.h5
2 files changed, 150 insertions, 4 deletions
diff --git a/skia/ext/vector_platform_device_linux.cc b/skia/ext/vector_platform_device_linux.cc
index f0afbef..31506b4 100644
--- a/skia/ext/vector_platform_device_linux.cc
+++ b/skia/ext/vector_platform_device_linux.cc
@@ -5,10 +5,67 @@
#include "skia/ext/vector_platform_device.h"
#include <cairo.h>
+#include <cairo-ft.h>
-#include "printing/pdf_ps_metafile_linux.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include <map>
+
+#include "third_party/skia/include/core/SkFontHost.h"
+#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
+#include "base/logging.h"
+#include "base/singleton.h"
+
+namespace {
+
+FT_Library g_ft_library = NULL; // handle to FreeType library.
+
+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;
+
+// NOTE: Only call this function when no further rendering will be performed,
+// and/or the metafile is closed.
+void CleanUpFonts() {
+ MapFontId2FontInfo* g_font_cache = Singleton<MapFontId2FontInfo>::get();
+ 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();
+}
+
+void CleanUpFreeType() {
+ if (g_ft_library) {
+ FT_Error ft_error = FT_Done_FreeType(g_ft_library);
+ g_ft_library = NULL;
+ DCHECK_EQ(ft_error, 0);
+ }
+}
+
+// Verify cairo surface after creation/modification.
+bool IsContextValid(cairo_t* context) {
+ return cairo_status(context) == CAIRO_STATUS_SUCCESS;
+}
+
+} // namespace
+
namespace skia {
VectorPlatformDevice* VectorPlatformDevice::create(PlatformSurface context,
@@ -40,6 +97,8 @@ VectorPlatformDevice::VectorPlatformDevice(PlatformSurface context,
VectorPlatformDevice::~VectorPlatformDevice() {
// Un-ref |context_| since we referenced it in the constructor.
cairo_destroy(context_);
+ CleanUpFonts();
+ CleanUpFreeType();
}
void VectorPlatformDevice::drawBitmap(const SkDraw& draw,
@@ -280,7 +339,7 @@ void VectorPlatformDevice::drawPosText(const SkDraw& draw,
}
} else { // kFill_Style.
// Selects correct font.
- if (!printing::PdfPsMetafile::SelectFontById(
+ if (!SelectFontById(
context_, paint.getTypeface()->uniqueID())) {
SkASSERT(false);
return;
@@ -509,5 +568,89 @@ void VectorPlatformDevice::LoadTransformToContext(const SkMatrix& matrix) {
cairo_set_matrix(context_, &m);
}
-} // namespace skia
+bool VectorPlatformDevice::SelectFontById(PlatformSurface context,
+ uint32_t font_id) {
+ DCHECK(IsContextValid(context));
+ DCHECK(SkFontHost::ValidFontID(font_id));
+
+ if (!g_ft_library) {
+ // Initializes FreeType library.
+ FT_Error ft_error = FT_Init_FreeType(&g_ft_library);
+ if (ft_error) {
+ DLOG(ERROR) << "Cannot initialize FreeType library for " \
+ << "VectorPlatformDevice.";
+ g_ft_library = NULL;
+ return false;
+ }
+ }
+
+ // Checks if we have a cache hit.
+ MapFontId2FontInfo* g_font_cache = Singleton<MapFontId2FontInfo>::get();
+ 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(
+ g_ft_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;
+}
+
+} // namespace skia
diff --git a/skia/ext/vector_platform_device_linux.h b/skia/ext/vector_platform_device_linux.h
index 67f1c48..8ec453b 100644
--- a/skia/ext/vector_platform_device_linux.h
+++ b/skia/ext/vector_platform_device_linux.h
@@ -89,6 +89,10 @@ class VectorPlatformDevice : public PlatformDevice {
// 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(PlatformSurface context, uint32_t font_id);
+
// Transformation assigned to the context.
SkMatrix transform_;
@@ -106,4 +110,3 @@ class VectorPlatformDevice : public PlatformDevice {
} // namespace skia
#endif // SKIA_EXT_VECTOR_PLATFORM_DEVICE_LINUX_H_
-