gfx/skia/trunk/src/ports/SkFontHost_cairo.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     2 /*
     3  * Copyright 2012 Mozilla Foundation
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #include "cairo.h"
    10 #include "cairo-ft.h"
    12 #include "SkFontHost_FreeType_common.h"
    14 #include "SkAdvancedTypefaceMetrics.h"
    15 #include "SkFontHost.h"
    16 #include "SkPath.h"
    17 #include "SkScalerContext.h"
    18 #include "SkTypefaceCache.h"
    20 #include <ft2build.h>
    21 #include FT_FREETYPE_H
    23 #ifndef SK_FONTHOST_CAIRO_STANDALONE
    24 #define SK_FONTHOST_CAIRO_STANDALONE 1
    25 #endif
    27 static cairo_user_data_key_t kSkTypefaceKey;
    29 class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base {
    30 public:
    31     SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc);
    32     virtual ~SkScalerContext_CairoFT();
    34 protected:
    35     virtual unsigned generateGlyphCount() SK_OVERRIDE;
    36     virtual uint16_t generateCharToGlyph(SkUnichar uniChar) SK_OVERRIDE;
    37     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
    38     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
    39     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
    40     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
    41     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
    42                                      SkPaint::FontMetrics* my) SK_OVERRIDE;
    43     virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE;
    44 private:
    45     cairo_scaled_font_t* fScaledFont;
    46     uint32_t fLoadGlyphFlags;
    47 };
    49 class CairoLockedFTFace {
    50 public:
    51     CairoLockedFTFace(cairo_scaled_font_t* scaledFont)
    52         : fScaledFont(scaledFont)
    53         , fFace(cairo_ft_scaled_font_lock_face(scaledFont))
    54     {}
    56     ~CairoLockedFTFace()
    57     {
    58         cairo_ft_scaled_font_unlock_face(fScaledFont);
    59     }
    61     FT_Face getFace()
    62     {
    63         return fFace;
    64     }
    66 private:
    67     cairo_scaled_font_t* fScaledFont;
    68     FT_Face fFace;
    69 };
    71 class SkCairoFTTypeface : public SkTypeface {
    72 public:
    73     static SkTypeface* CreateTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth) {
    74         SkASSERT(fontFace != NULL);
    75         SkASSERT(cairo_font_face_get_type(fontFace) == CAIRO_FONT_TYPE_FT);
    77         SkFontID newId = SkTypefaceCache::NewFontID();
    79         return SkNEW_ARGS(SkCairoFTTypeface, (fontFace, style, newId, isFixedWidth));
    80     }
    82     cairo_font_face_t* getFontFace() {
    83         return fFontFace;
    84     }
    86     virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
    88     virtual SkAdvancedTypefaceMetrics*
    89         onGetAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::PerGlyphInfo,
    90                                      const uint32_t*, uint32_t) const SK_OVERRIDE
    91     {
    92         SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetAdvancedTypefaceMetrics unimplemented\n"));
    93         return NULL;
    94     }
    96     virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE
    97     {
    98         return SkNEW_ARGS(SkScalerContext_CairoFT, (const_cast<SkCairoFTTypeface*>(this), desc));
    99     }
   101     virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE
   102     {
   103         SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onFilterRec unimplemented\n"));
   104     }
   106     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
   107     {
   108         SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetFontDescriptor unimplemented\n"));
   109     }
   111     virtual int onCharsToGlyphs(void const*, SkTypeface::Encoding, uint16_t*, int) const SK_OVERRIDE
   112     {
   113         return 0;
   114     }
   116     virtual int onCountGlyphs() const SK_OVERRIDE
   117     {
   118         return 0;
   119     }
   121     virtual int onGetUPEM() const SK_OVERRIDE
   122     {
   123         return 0;
   124     }
   126     virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE
   127     {
   128         return NULL;
   129     }
   131     virtual int onGetTableTags(SkFontTableTag*) const SK_OVERRIDE
   132     {
   133         return 0;
   134     }
   136     virtual size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const SK_OVERRIDE
   137     {
   138         return 0;
   139     }
   141 private:
   143     SkCairoFTTypeface(cairo_font_face_t* fontFace, SkTypeface::Style style, SkFontID id, bool isFixedWidth)
   144         : SkTypeface(style, id, isFixedWidth)
   145         , fFontFace(fontFace)
   146     {
   147         cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, this, NULL);
   148         cairo_font_face_reference(fFontFace);
   149     }
   151     ~SkCairoFTTypeface()
   152     {
   153         cairo_font_face_set_user_data(fFontFace, &kSkTypefaceKey, NULL, NULL);
   154         cairo_font_face_destroy(fFontFace);
   155     }
   157     cairo_font_face_t* fFontFace;
   158 };
   160 SkTypeface* SkCreateTypefaceFromCairoFont(cairo_font_face_t* fontFace, SkTypeface::Style style, bool isFixedWidth)
   161 {
   162     SkTypeface* typeface = reinterpret_cast<SkTypeface*>(cairo_font_face_get_user_data(fontFace, &kSkTypefaceKey));
   164     if (typeface) {
   165         typeface->ref();
   166     } else {
   167         typeface = SkCairoFTTypeface::CreateTypeface(fontFace, style, isFixedWidth);
   168         SkTypefaceCache::Add(typeface, style);
   169     }
   171     return typeface;
   172 }
   174 #if defined(SK_FONTHOST_DOES_NOT_USE_FONTMGR) && SK_FONTHOST_CAIRO_STANDALONE
   175 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
   176                                      const char famillyName[],
   177                                      SkTypeface::Style style)
   178 {
   179     SkDEBUGFAIL("SkFontHost::FindTypeface unimplemented");
   180     return NULL;
   181 }
   183 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*)
   184 {
   185     SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented");
   186     return NULL;
   187 }
   189 SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*)
   190 {
   191     SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented");
   192     return NULL;
   193 }
   194 #endif
   196 ///////////////////////////////////////////////////////////////////////////////
   198 static bool isLCD(const SkScalerContext::Rec& rec) {
   199     switch (rec.fMaskFormat) {
   200         case SkMask::kLCD16_Format:
   201         case SkMask::kLCD32_Format:
   202             return true;
   203         default:
   204             return false;
   205     }
   206 }
   208 ///////////////////////////////////////////////////////////////////////////////
   209 SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc)
   210     : SkScalerContext_FreeType_Base(typeface, desc)
   211 {
   212     SkMatrix matrix;
   213     fRec.getSingleMatrix(&matrix);
   215     cairo_font_face_t* fontFace = static_cast<SkCairoFTTypeface*>(typeface)->getFontFace();
   217     cairo_matrix_t fontMatrix, ctMatrix;
   218     cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
   219     cairo_matrix_init_scale(&ctMatrix, 1.0, 1.0);
   221     // We need to ensure that the font options match for hinting, as generateMetrics()
   222     // uses the fScaledFont which uses these font options
   223     cairo_font_options_t *fontOptions = cairo_font_options_create();
   225     FT_Int32 loadFlags = FT_LOAD_DEFAULT;
   227     if (SkMask::kBW_Format == fRec.fMaskFormat) {
   228         // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
   229         loadFlags = FT_LOAD_TARGET_MONO;
   230         if (fRec.getHinting() == SkPaint::kNo_Hinting) {
   231             cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
   232             loadFlags = FT_LOAD_NO_HINTING;
   233         }
   234     } else {
   235         switch (fRec.getHinting()) {
   236         case SkPaint::kNo_Hinting:
   237             loadFlags = FT_LOAD_NO_HINTING;
   238             cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_NONE);
   239             break;
   240         case SkPaint::kSlight_Hinting:
   241             loadFlags = FT_LOAD_TARGET_LIGHT;  // This implies FORCE_AUTOHINT
   242             cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_SLIGHT);
   243             break;
   244         case SkPaint::kNormal_Hinting:
   245             cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_MEDIUM);
   246             if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
   247                 loadFlags = FT_LOAD_FORCE_AUTOHINT;
   248             }
   249             break;
   250         case SkPaint::kFull_Hinting:
   251             cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL);
   252             if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
   253                 loadFlags = FT_LOAD_FORCE_AUTOHINT;
   254             }
   255             if (isLCD(fRec)) {
   256                 if (SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag)) {
   257                     loadFlags = FT_LOAD_TARGET_LCD_V;
   258                 } else {
   259                     loadFlags = FT_LOAD_TARGET_LCD;
   260                 }
   261             }
   262             break;
   263         default:
   264             SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
   265             break;
   266         }
   267     }
   269     fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
   271     if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
   272         loadFlags |= FT_LOAD_NO_BITMAP;
   273     }
   275     // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
   276     // advances, as fontconfig and cairo do.
   277     // See http://code.google.com/p/skia/issues/detail?id=222.
   278     loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
   280     fLoadGlyphFlags = loadFlags;
   281 }
   283 SkScalerContext_CairoFT::~SkScalerContext_CairoFT()
   284 {
   285     cairo_scaled_font_destroy(fScaledFont);
   286 }
   288 unsigned SkScalerContext_CairoFT::generateGlyphCount()
   289 {
   290     CairoLockedFTFace faceLock(fScaledFont);
   291     return faceLock.getFace()->num_glyphs;
   292 }
   294 uint16_t SkScalerContext_CairoFT::generateCharToGlyph(SkUnichar uniChar)
   295 {
   296     CairoLockedFTFace faceLock(fScaledFont);
   297     return SkToU16(FT_Get_Char_Index(faceLock.getFace(), uniChar));
   298 }
   300 void SkScalerContext_CairoFT::generateAdvance(SkGlyph* glyph)
   301 {
   302     generateMetrics(glyph);
   303 }
   305 void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
   306 {
   307     SkASSERT(fScaledFont != NULL);
   308     cairo_text_extents_t extents;
   309     cairo_glyph_t cairoGlyph = { glyph->getGlyphID(fBaseGlyphCount), 0.0, 0.0 };
   310     cairo_scaled_font_glyph_extents(fScaledFont, &cairoGlyph, 1, &extents);
   312     glyph->fAdvanceX = SkDoubleToFixed(extents.x_advance);
   313     glyph->fAdvanceY = SkDoubleToFixed(extents.y_advance);
   314     glyph->fWidth = SkToU16(SkScalarCeilToInt(extents.width));
   315     glyph->fHeight = SkToU16(SkScalarCeilToInt(extents.height));
   316     glyph->fLeft = SkToS16(SkScalarCeilToInt(extents.x_bearing));
   317     glyph->fTop = SkToS16(SkScalarCeilToInt(extents.y_bearing));
   318     glyph->fLsbDelta = 0;
   319     glyph->fRsbDelta = 0;
   320 }
   322 void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph)
   323 {
   324     SkASSERT(fScaledFont != NULL);
   325     CairoLockedFTFace faceLock(fScaledFont);
   326     FT_Face face = faceLock.getFace();
   328     FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
   330     if (err != 0) {
   331         memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
   332         return;
   333     }
   335     generateGlyphImage(face, glyph);
   336 }
   338 void SkScalerContext_CairoFT::generatePath(const SkGlyph& glyph, SkPath* path)
   339 {
   340     SkASSERT(fScaledFont != NULL);
   341     CairoLockedFTFace faceLock(fScaledFont);
   342     FT_Face face = faceLock.getFace();
   344     SkASSERT(&glyph && path);
   346     uint32_t flags = fLoadGlyphFlags;
   347     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
   348     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
   350     FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(fBaseGlyphCount), flags);
   352     if (err != 0) {
   353         path->reset();
   354         return;
   355     }
   357     generateGlyphPath(face, path);
   358 }
   360 void SkScalerContext_CairoFT::generateFontMetrics(SkPaint::FontMetrics* mx,
   361                                                   SkPaint::FontMetrics* my)
   362 {
   363     SkDEBUGCODE(SkDebugf("SkScalerContext_CairoFT::generateFontMetrics unimplemented\n"));
   364 }
   366 SkUnichar SkScalerContext_CairoFT::generateGlyphToChar(uint16_t glyph)
   367 {
   368     SkASSERT(fScaledFont != NULL);
   369     CairoLockedFTFace faceLock(fScaledFont);
   370     FT_Face face = faceLock.getFace();
   372     FT_UInt glyphIndex;
   373     SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
   374     while (glyphIndex != 0) {
   375         if (glyphIndex == glyph) {
   376             return charCode;
   377         }
   378         charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
   379     }
   381     return 0;
   382 }
   384 ///////////////////////////////////////////////////////////////////////////////
   386 #include "SkFontMgr.h"
   388 SkFontMgr* SkFontMgr::Factory() {
   389     // todo
   390     return NULL;
   391 }

mercurial