1From: George Wright <george@mozilla.com> 2Date: Wed, 1 Aug 2012 16:43:15 -0400 3Subject: Bug 736276 - Add a new SkFontHost that takes a cairo_scaled_font_t r=karl 4 5 6diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in 7index 5ebbd2e..7c8cdbf 100644 8--- a/gfx/skia/Makefile.in 9+++ b/gfx/skia/Makefile.in 10@@ -60,15 +60,15 @@ VPATH += \ 11 $(NULL) 12 13 ifeq (android,$(MOZ_WIDGET_TOOLKIT)) 14-OS_CXXFLAGS += $(CAIRO_FT_CFLAGS) 15+OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(CAIRO_FT_CFLAGS) 16 endif 17 18 ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT)) 19-OS_CXXFLAGS += $(MOZ_PANGO_CFLAGS) 20+OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PANGO_CFLAGS) $(CAIRO_FT_CFLAGS) 21 endif 22 23 ifeq (qt,$(MOZ_WIDGET_TOOLKIT)) 24-OS_CXXFLAGS += $(MOZ_PANGO_CFLAGS) 25+OS_CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PANGO_CFLAGS) $(CAIRO_FT_CFLAGS) 26 ifeq (Linux,$(OS_TARGET)) 27 DEFINES += -DSK_USE_POSIX_THREADS=1 28 endif 29diff --git a/gfx/skia/include/ports/SkTypeface_cairo.h b/gfx/skia/include/ports/SkTypeface_cairo.h 30new file mode 100644 31index 0000000..7e44f04 32--- /dev/null 33+++ b/gfx/skia/include/ports/SkTypeface_cairo.h 34@@ -0,0 +1,11 @@ 35+#ifndef SkTypeface_cairo_DEFINED 36+#define SkTypeface_cairo_DEFINED 37+ 38+#include <cairo.h> 39+ 40+#include "SkTypeface.h" 41+ 42+SK_API extern SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth); 43+ 44+#endif 45+ 46diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build 47index 9ceba59..66efd52 100644 48--- a/gfx/skia/moz.build 49+++ b/gfx/skia/moz.build 50@@ -171,10 +171,12 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 51 'SkTime_win.cpp', 52 ] 53 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2': 54+ EXPORTS.skia += [ 55+ 'include/ports/SkTypeface_cairo.h', 56+ ] 57 CPP_SOURCES += [ 58- 'SkFontHost_FreeType.cpp', 59+ 'SkFontHost_cairo.cpp', 60 'SkFontHost_FreeType_common.cpp', 61- 'SkFontHost_linux.cpp', 62 'SkThread_pthread.cpp', 63 'SkThreadUtils_pthread.cpp', 64 'SkThreadUtils_pthread_linux.cpp', 65@@ -183,14 +185,15 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2': 66 ] 67 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': 68 CPP_SOURCES += [ 69- 'SkFontHost_FreeType.cpp', 70+ 'SkFontHost_cairo.cpp', 71 'SkFontHost_FreeType_common.cpp', 72 'SkOSFile.cpp', 73 ] 74 if CONFIG['OS_TARGET'] == 'Linux': 75+ EXPORTS.skia += [ 76+ 'include/ports/SkTypeface_cairo.h', 77+ ] 78 CPP_SOURCES += [ 79- 'SkFontHost_linux.cpp', 80- 'SkFontHost_tables.cpp', 81 'SkThread_pthread.cpp', 82 'SkThreadUtils_pthread.cpp', 83 'SkThreadUtils_pthread_linux.cpp', 84@@ -204,11 +207,13 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 85 # Separate 'if' from above, since the else below applies to all != 'android' 86 # toolkits. 87 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': 88+ EXPORTS.skia += [ 89+ 'include/ports/SkTypeface_cairo.h', 90+ ] 91 CPP_SOURCES += [ 92 'ashmem.cpp', 93 'SkDebug_android.cpp', 94- 'SkFontHost_android_old.cpp', 95- 'SkFontHost_FreeType.cpp', 96+ 'SkFontHost_cairo.cpp', 97 'SkFontHost_FreeType_common.cpp', 98 'SkImageRef_ashmem.cpp', 99 'SkTime_Unix.cpp', 100diff --git a/gfx/skia/src/ports/SkFontHost_cairo.cpp b/gfx/skia/src/ports/SkFontHost_cairo.cpp 101new file mode 100644 102index 0000000..bb5b778 103--- /dev/null 104+++ b/gfx/skia/src/ports/SkFontHost_cairo.cpp 105@@ -0,0 +1,364 @@ 106+ 107+/* 108+ * Copyright 2012 Mozilla Foundation 109+ * 110+ * Use of this source code is governed by a BSD-style license that can be 111+ * found in the LICENSE file. 112+ */ 113+ 114+#include "cairo.h" 115+#include "cairo-ft.h" 116+ 117+#include "SkFontHost_FreeType_common.h" 118+ 119+#include "SkAdvancedTypefaceMetrics.h" 120+#include "SkFontHost.h" 121+#include "SkPath.h" 122+#include "SkScalerContext.h" 123+#include "SkTypefaceCache.h" 124+ 125+#include <ft2build.h> 126+#include FT_FREETYPE_H 127+ 128+static cairo_user_data_key_t kSkTypefaceKey; 129+ 130+class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base { 131+public: 132+ SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc); 133+ virtual ~SkScalerContext_CairoFT(); 134+ 135+protected: 136+ virtual unsigned generateGlyphCount() SK_OVERRIDE; 137+ virtual uint16_t generateCharToGlyph(SkUnichar uniChar) SK_OVERRIDE; 138+ virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 139+ virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 140+ virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 141+ virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 142+ virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 143+ SkPaint::FontMetrics* my) SK_OVERRIDE; 144+ virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; 145+private: 146+ cairo_scaled_font_t* fScaledFont; 147+ uint32_t fLoadGlyphFlags; 148+}; 149+ 150+class CairoLockedFTFace { 151+public: 152+ CairoLockedFTFace(cairo_scaled_font_t* scaledFont) 153+ : fScaledFont(scaledFont) 154+ , fFace(cairo_ft_scaled_font_lock_face(scaledFont)) 155+ {} 156+ 157+ ~CairoLockedFTFace() 158+ { 159+ cairo_ft_scaled_font_unlock_face(fScaledFont); 160+ } 161+ 162+ FT_Face getFace() 163+ { 164+ return fFace; 165+ } 166+ 167+private: 168+ cairo_scaled_font_t* fScaledFont; 169+ FT_Face fFace; 170+}; 171+ 172+class SkCairoFTTypeface : public SkTypeface { 173+public: 174+ static SkTypeface* CreateTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth) { 175+ SkASSERT(fontFace != NULL); 176+ SkASSERT(cairo_font_face_get_type(fontFace) == CAIRO_FONT_TYPE_FT); 177+ 178+ SkFontID newId = SkTypefaceCache::NewFontID(); 179+ 180+ return SkNEW_ARGS(SkCairoFTTypeface, (fontFace, style, newId, isFixedWidth)); 181+ } 182+ 183+ cairo_font_face_t* getFontFace() { 184+ return fFontFace; 185+ } 186+ 187+ virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } 188+ 189+ virtual SkAdvancedTypefaceMetrics* 190+ onGetAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::PerGlyphInfo, 191+ const uint32_t*, uint32_t) const SK_OVERRIDE 192+ { 193+ SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetAdvancedTypefaceMetrics unimplemented\n")); 194+ return NULL; 195+ } 196+ 197+ virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE 198+ { 199+ return SkNEW_ARGS(SkScalerContext_CairoFT, (const_cast<SkCairoFTTypeface*>(this), desc)); 200+ } 201+ 202+ virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE 203+ { 204+ SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onFilterRec unimplemented\n")); 205+ } 206+ 207+ virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE 208+ { 209+ SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetFontDescriptor unimplemented\n")); 210+ } 211+ 212+ 213+private: 214+ 215+ SkCairoFTTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, SkFontID id, bool isFixedWidth) 216+ : SkTypeface(style, id, isFixedWidth) 217+ , fFontFace(fontFace) 218+ { 219+ cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, this, NULL); 220+ cairo_font_face_reference(fFontFace); 221+ } 222+ 223+ ~SkCairoFTTypeface() 224+ { 225+ cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, NULL, NULL); 226+ cairo_font_face_destroy(fFontFace); 227+ } 228+ 229+ cairo_font_face_t* fFontFace; 230+}; 231+ 232+SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth) 233+{ 234+ SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey)); 235+ 236+ if (typeface) { 237+ typeface->ref(); 238+ } else { 239+ typeface = SkCairoFTTypeface::CreateTypeface(fontFace, style, isFixedWidth); 240+ SkTypefaceCache::Add(typeface, style); 241+ } 242+ 243+ return typeface; 244+} 245+ 246+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 247+ const char famillyName[], 248+ SkTypeface::Style style) 249+{ 250+ SkDEBUGFAIL("SkFontHost::FindTypeface unimplemented"); 251+ return NULL; 252+} 253+ 254+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*) 255+{ 256+ SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented"); 257+ return NULL; 258+} 259+ 260+SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) 261+{ 262+ SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented"); 263+ return NULL; 264+} 265+ 266+/////////////////////////////////////////////////////////////////////////////// 267+ 268+static bool isLCD(const SkScalerContext::Rec& rec) { 269+ switch (rec.fMaskFormat) { 270+ case SkMask::kLCD16_Format: 271+ case SkMask::kLCD32_Format: 272+ return true; 273+ default: 274+ return false; 275+ } 276+} 277+ 278+/////////////////////////////////////////////////////////////////////////////// 279+SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc) 280+ : SkScalerContext_FreeType_Base(typeface, desc) 281+{ 282+ SkMatrix matrix; 283+ fRec.getSingleMatrix(&matrix); 284+ 285+ cairo_font_face_t* fontFace = static_cast<SkCairoFTTypeface*>(typeface)->getFontFace(); 286+ 287+ cairo_matrix_t fontMatrix, ctMatrix; 288+ cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0); 289+ cairo_matrix_init_scale(&ctMatrix, 1.0, 1.0); 290+ 291+ // We need to ensure that the font options match for hinting, as generateMetrics() 292+ // uses the fScaledFont which uses these font options 293+ cairo_font_options_t *fontOptions = cairo_font_options_create(); 294+ 295+ FT_Int32 loadFlags = FT_LOAD_DEFAULT; 296+ 297+ if (SkMask::kBW_Format == fRec.fMaskFormat) { 298+ // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 299+ loadFlags = FT_LOAD_TARGET_MONO; 300+ if (fRec.getHinting() == SkPaint::kNo_Hinting) { 301+ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE); 302+ loadFlags = FT_LOAD_NO_HINTING; 303+ } 304+ } else { 305+ switch (fRec.getHinting()) { 306+ case SkPaint::kNo_Hinting: 307+ loadFlags = FT_LOAD_NO_HINTING; 308+ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE); 309+ break; 310+ case SkPaint::kSlight_Hinting: 311+ loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 312+ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_SLIGHT); 313+ break; 314+ case SkPaint::kNormal_Hinting: 315+ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_MEDIUM); 316+ if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) { 317+ loadFlags = FT_LOAD_FORCE_AUTOHINT; 318+ } 319+ break; 320+ case SkPaint::kFull_Hinting: 321+ cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL); 322+ if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) { 323+ loadFlags = FT_LOAD_FORCE_AUTOHINT; 324+ } 325+ if (isLCD(fRec)) { 326+ if (SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag)) { 327+ loadFlags = FT_LOAD_TARGET_LCD_V; 328+ } else { 329+ loadFlags = FT_LOAD_TARGET_LCD; 330+ } 331+ } 332+ break; 333+ default: 334+ SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 335+ break; 336+ } 337+ } 338+ 339+ fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions); 340+ 341+ if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 342+ loadFlags |= FT_LOAD_NO_BITMAP; 343+ } 344+ 345+ // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 346+ // advances, as fontconfig and cairo do. 347+ // See http://code.google.com/p/skia/issues/detail?id=222. 348+ loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 349+ 350+ fLoadGlyphFlags = loadFlags; 351+} 352+ 353+SkScalerContext_CairoFT::~SkScalerContext_CairoFT() 354+{ 355+ cairo_scaled_font_destroy(fScaledFont); 356+} 357+ 358+unsigned SkScalerContext_CairoFT::generateGlyphCount() 359+{ 360+ CairoLockedFTFace faceLock(fScaledFont); 361+ return faceLock.getFace()->num_glyphs; 362+} 363+ 364+uint16_t SkScalerContext_CairoFT::generateCharToGlyph(SkUnichar uniChar) 365+{ 366+ CairoLockedFTFace faceLock(fScaledFont); 367+ return SkToU16(FT_Get_Char_Index(faceLock.getFace(), uniChar)); 368+} 369+ 370+void SkScalerContext_CairoFT::generateAdvance(SkGlyph* glyph) 371+{ 372+ generateMetrics(glyph); 373+} 374+ 375+void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph) 376+{ 377+ SkASSERT(fScaledFont != NULL); 378+ cairo_text_extents_t extents; 379+ cairo_glyph_t cairoGlyph = { glyph->getGlyphID(fBaseGlyphCount), 0.0, 0.0 }; 380+ cairo_scaled_font_glyph_extents(fScaledFont, &cairoGlyph, 1, &extents); 381+ 382+ glyph->fAdvanceX = SkDoubleToFixed(extents.x_advance); 383+ glyph->fAdvanceY = SkDoubleToFixed(extents.y_advance); 384+ glyph->fWidth = SkToU16(SkScalarCeil(extents.width)); 385+ glyph->fHeight = SkToU16(SkScalarCeil(extents.height)); 386+ glyph->fLeft = SkToS16(SkScalarCeil(extents.x_bearing)); 387+ glyph->fTop = SkToS16(SkScalarCeil(extents.y_bearing)); 388+ glyph->fLsbDelta = 0; 389+ glyph->fRsbDelta = 0; 390+} 391+ 392+void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph) 393+{ 394+ SkASSERT(fScaledFont != NULL); 395+ CairoLockedFTFace faceLock(fScaledFont); 396+ FT_Face face = faceLock.getFace(); 397+ 398+ FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags); 399+ 400+ if (err != 0) { 401+ memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 402+ return; 403+ } 404+ 405+ generateGlyphImage(face, glyph); 406+} 407+ 408+void SkScalerContext_CairoFT::generatePath(const SkGlyph& glyph, SkPath* path) 409+{ 410+ SkASSERT(fScaledFont != NULL); 411+ CairoLockedFTFace faceLock(fScaledFont); 412+ FT_Face face = faceLock.getFace(); 413+ 414+ SkASSERT(&glyph && path); 415+ 416+ uint32_t flags = fLoadGlyphFlags; 417+ flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 418+ flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 419+ 420+ FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), flags); 421+ 422+ if (err != 0) { 423+ path->reset(); 424+ return; 425+ } 426+ 427+ generateGlyphPath(face, path); 428+} 429+ 430+void SkScalerContext_CairoFT::generateFontMetrics(SkPaint::FontMetrics* mx, 431+ SkPaint::FontMetrics* my) 432+{ 433+ SkDEBUGCODE(SkDebugf("SkScalerContext_CairoFT::generateFontMetrics unimplemented\n")); 434+} 435+ 436+SkUnichar SkScalerContext_CairoFT::generateGlyphToChar(uint16_t glyph) 437+{ 438+ SkASSERT(fScaledFont != NULL); 439+ CairoLockedFTFace faceLock(fScaledFont); 440+ FT_Face face = faceLock.getFace(); 441+ 442+ FT_UInt glyphIndex; 443+ SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 444+ while (glyphIndex != 0) { 445+ if (glyphIndex == glyph) { 446+ return charCode; 447+ } 448+ charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); 449+ } 450+ 451+ return 0; 452+} 453+ 454+#ifdef SK_BUILD_FOR_ANDROID 455+SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, 456+ SkFontID origFontID) { 457+ return NULL; 458+} 459+#endif 460+ 461+/////////////////////////////////////////////////////////////////////////////// 462+ 463+#include "SkFontMgr.h" 464+ 465+SkFontMgr* SkFontMgr::Factory() { 466+ // todo 467+ return NULL; 468+} 469+ 470-- 4711.7.11.7 472 473