SkFontHost_FreeType.cpp revision 62107f3888bc9011c404be4597b89e70c0987afe
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "SkAdvancedTypefaceMetrics.h"
10#include "SkBitmap.h"
11#include "SkCanvas.h"
12#include "SkColorPriv.h"
13#include "SkDescriptor.h"
14#include "SkFDot6.h"
15#include "SkFloatingPoint.h"
16#include "SkFontHost.h"
17#include "SkFontHost_FreeType_common.h"
18#include "SkGlyph.h"
19#include "SkMask.h"
20#include "SkMaskGamma.h"
21#include "SkMatrix22.h"
22#include "SkOTUtils.h"
23#include "SkOnce.h"
24#include "SkScalerContext.h"
25#include "SkStream.h"
26#include "SkString.h"
27#include "SkTemplates.h"
28#include "SkThread.h"
29
30#if defined(SK_CAN_USE_DLOPEN)
31#include <dlfcn.h>
32#endif
33#include <ft2build.h>
34#include FT_FREETYPE_H
35#include FT_OUTLINE_H
36#include FT_SIZES_H
37#include FT_TRUETYPE_TABLES_H
38#include FT_TYPE1_TABLES_H
39#include FT_BITMAP_H
40// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
41#include FT_SYNTHESIS_H
42#include FT_XFREE86_H
43#ifdef FT_LCD_FILTER_H
44#include FT_LCD_FILTER_H
45#endif
46
47// Defined in FreeType 2.3.8 and later.
48// This is a silly build time check, we would need a runtime check if we really cared.
49#ifdef   FT_ADVANCES_H
50#include FT_ADVANCES_H
51#endif
52
53#if 0
54// Also include the files by name for build tools which require this.
55#include <freetype/freetype.h>
56#include <freetype/ftoutln.h>
57#include <freetype/ftsizes.h>
58#include <freetype/tttables.h>
59#include <freetype/ftadvanc.h>
60#include <freetype/ftlcdfil.h>
61#include <freetype/ftbitmap.h>
62#include <freetype/ftsynth.h>
63#endif
64
65// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
66// were introduced in FreeType 2.5.0.
67// The following may be removed once FreeType 2.5.0 is required to build.
68#ifndef FT_LOAD_COLOR
69#    define FT_LOAD_COLOR ( 1L << 20 )
70#    define FT_PIXEL_MODE_BGRA 7
71#endif
72
73// FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR
74// were introduced in FreeType 2.5.1
75// The following may be removed once FreeType 2.5.1 is required to build.
76#ifndef FT_HAS_COLOR
77#    define FT_HAS_COLOR(face) false
78#endif
79
80//#define ENABLE_GLYPH_SPEW     // for tracing calls
81//#define DUMP_STRIKE_CREATION
82
83//#define SK_GAMMA_APPLY_TO_A8
84
85using namespace skia_advanced_typeface_metrics_utils;
86
87static bool isLCD(const SkScalerContext::Rec& rec) {
88    switch (rec.fMaskFormat) {
89        case SkMask::kLCD16_Format:
90        case SkMask::kLCD32_Format:
91            return true;
92        default:
93            return false;
94    }
95}
96
97//////////////////////////////////////////////////////////////////////////
98
99struct SkFaceRec;
100
101SK_DECLARE_STATIC_MUTEX(gFTMutex);
102static int          gFTCount;
103static FT_Library   gFTLibrary;
104static SkFaceRec*   gFaceRecHead;
105static bool         gLCDSupportValid;  // true iff |gLCDSupport| has been set.
106static bool         gLCDSupport;  // true iff LCD is supported by the runtime.
107static int          gLCDExtra;  // number of extra pixels for filtering.
108
109/////////////////////////////////////////////////////////////////////////
110
111// FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0.
112// The following platforms provide FreeType of at least 2.4.0.
113// Ubuntu >= 11.04 (previous deprecated April 2013)
114// Debian >= 6.0 (good)
115// OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2)
116// Fedora >= 14 (good)
117// Android >= Gingerbread (good)
118typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*);
119
120// Caller must lock gFTMutex before calling this function.
121static bool InitFreetype() {
122    FT_Error err = FT_Init_FreeType(&gFTLibrary);
123    if (err) {
124        return false;
125    }
126
127    // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs.
128#ifdef FT_LCD_FILTER_H
129    // Use default { 0x10, 0x40, 0x70, 0x40, 0x10 }, as it adds up to 0x110, simulating ink spread.
130    // SetLcdFilter must be called before SetLcdFilterWeights.
131    err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT);
132    if (0 == err) {
133        gLCDSupport = true;
134        gLCDExtra = 2; //Using a filter adds one full pixel to each side.
135
136#ifdef SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER
137        // This also adds to 0x110 simulating ink spread, but provides better results than default.
138        static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x56, 0x43, 0x1A, };
139
140#if defined(SK_FONTHOST_FREETYPE_RUNTIME_VERSION) && \
141            SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400
142        err = FT_Library_SetLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights);
143#elif defined(SK_CAN_USE_DLOPEN) && SK_CAN_USE_DLOPEN == 1
144        //The FreeType library is already loaded, so symbols are available in process.
145        void* self = dlopen(NULL, RTLD_LAZY);
146        if (NULL != self) {
147            FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights;
148            //The following cast is non-standard, but safe for POSIX.
149            *reinterpret_cast<void**>(&setLcdFilterWeights) = dlsym(self, "FT_Library_SetLcdFilterWeights");
150            dlclose(self);
151
152            if (NULL != setLcdFilterWeights) {
153                err = setLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights);
154            }
155        }
156#endif
157#endif
158    }
159#else
160    gLCDSupport = false;
161#endif
162    gLCDSupportValid = true;
163
164    return true;
165}
166
167// Called while holding gFTMutex.
168static void determine_lcd_support(bool* lcdSupported) {
169    if (!gLCDSupportValid) {
170        // This will determine LCD support as a side effect.
171        InitFreetype();
172        FT_Done_FreeType(gFTLibrary);
173    }
174    SkASSERT(gLCDSupportValid);
175    *lcdSupported = gLCDSupport;
176}
177
178// Lazy, once, wrapper to ask the FreeType Library if it can support LCD text
179static bool is_lcd_supported() {
180    static bool lcdSupported = false;
181    SkOnce(&gLCDSupportValid, &gFTMutex, determine_lcd_support, &lcdSupported);
182    return lcdSupported;
183}
184
185class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base {
186public:
187    SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc);
188    virtual ~SkScalerContext_FreeType();
189
190    bool success() const {
191        return fFaceRec != NULL &&
192               fFTSize != NULL &&
193               fFace != NULL;
194    }
195
196protected:
197    virtual unsigned generateGlyphCount() SK_OVERRIDE;
198    virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
199    virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
200    virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
201    virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
202    virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
203    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
204                                     SkPaint::FontMetrics* my) SK_OVERRIDE;
205    virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE;
206
207private:
208    SkFaceRec*  fFaceRec;
209    FT_Face     fFace;              // reference to shared face in gFaceRecHead
210    FT_Size     fFTSize;            // our own copy
211    FT_Int      fStrikeIndex;
212    SkFixed     fScaleX, fScaleY;
213    FT_Matrix   fMatrix22;
214    uint32_t    fLoadGlyphFlags;
215    bool        fDoLinearMetrics;
216    bool        fLCDIsVert;
217
218    // Need scalar versions for generateFontMetrics
219    SkVector    fScale;
220    SkMatrix    fMatrix22Scalar;
221
222    FT_Error setupSize();
223    void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox,
224                                bool snapToPixelBoundary = false);
225    bool getCBoxForLetter(char letter, FT_BBox* bbox);
226    // Caller must lock gFTMutex before calling this function.
227    void updateGlyphIfLCD(SkGlyph* glyph);
228    // Caller must lock gFTMutex before calling this function.
229    // update FreeType2 glyph slot with glyph emboldened
230    void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph);
231};
232
233///////////////////////////////////////////////////////////////////////////
234///////////////////////////////////////////////////////////////////////////
235
236struct SkFaceRec {
237    SkFaceRec*      fNext;
238    FT_Face         fFace;
239    FT_StreamRec    fFTStream;
240    SkStream*       fSkStream;
241    uint32_t        fRefCnt;
242    uint32_t        fFontID;
243
244    // assumes ownership of the stream, will call unref() when its done
245    SkFaceRec(SkStream* strm, uint32_t fontID);
246    ~SkFaceRec() {
247        fSkStream->unref();
248    }
249};
250
251extern "C" {
252    static unsigned long sk_stream_read(FT_Stream       stream,
253                                        unsigned long   offset,
254                                        unsigned char*  buffer,
255                                        unsigned long   count ) {
256        SkStream* str = (SkStream*)stream->descriptor.pointer;
257
258        if (count) {
259            if (!str->rewind()) {
260                return 0;
261            } else {
262                unsigned long ret;
263                if (offset) {
264                    ret = str->read(NULL, offset);
265                    if (ret != offset) {
266                        return 0;
267                    }
268                }
269                ret = str->read(buffer, count);
270                if (ret != count) {
271                    return 0;
272                }
273                count = ret;
274            }
275        }
276        return count;
277    }
278
279    static void sk_stream_close(FT_Stream) {}
280}
281
282SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID)
283        : fNext(NULL), fSkStream(strm), fRefCnt(1), fFontID(fontID) {
284//    SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm));
285
286    sk_bzero(&fFTStream, sizeof(fFTStream));
287    fFTStream.size = fSkStream->getLength();
288    fFTStream.descriptor.pointer = fSkStream;
289    fFTStream.read  = sk_stream_read;
290    fFTStream.close = sk_stream_close;
291}
292
293// Will return 0 on failure
294// Caller must lock gFTMutex before calling this function.
295static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
296    const SkFontID fontID = typeface->uniqueID();
297    SkFaceRec* rec = gFaceRecHead;
298    while (rec) {
299        if (rec->fFontID == fontID) {
300            SkASSERT(rec->fFace);
301            rec->fRefCnt += 1;
302            return rec;
303        }
304        rec = rec->fNext;
305    }
306
307    int face_index;
308    SkStream* strm = typeface->openStream(&face_index);
309    if (NULL == strm) {
310        return NULL;
311    }
312
313    // this passes ownership of strm to the rec
314    rec = SkNEW_ARGS(SkFaceRec, (strm, fontID));
315
316    FT_Open_Args    args;
317    memset(&args, 0, sizeof(args));
318    const void* memoryBase = strm->getMemoryBase();
319
320    if (NULL != memoryBase) {
321//printf("mmap(%s)\n", keyString.c_str());
322        args.flags = FT_OPEN_MEMORY;
323        args.memory_base = (const FT_Byte*)memoryBase;
324        args.memory_size = strm->getLength();
325    } else {
326//printf("fopen(%s)\n", keyString.c_str());
327        args.flags = FT_OPEN_STREAM;
328        args.stream = &rec->fFTStream;
329    }
330
331    FT_Error err = FT_Open_Face(gFTLibrary, &args, face_index, &rec->fFace);
332    if (err) {    // bad filename, try the default font
333        fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID);
334        SkDELETE(rec);
335        return NULL;
336    } else {
337        SkASSERT(rec->fFace);
338        //fprintf(stderr, "Opened font '%s'\n", filename.c_str());
339        rec->fNext = gFaceRecHead;
340        gFaceRecHead = rec;
341        return rec;
342    }
343}
344
345// Caller must lock gFTMutex before calling this function.
346static void unref_ft_face(FT_Face face) {
347    SkFaceRec*  rec = gFaceRecHead;
348    SkFaceRec*  prev = NULL;
349    while (rec) {
350        SkFaceRec* next = rec->fNext;
351        if (rec->fFace == face) {
352            if (--rec->fRefCnt == 0) {
353                if (prev) {
354                    prev->fNext = next;
355                } else {
356                    gFaceRecHead = next;
357                }
358                FT_Done_Face(face);
359                SkDELETE(rec);
360            }
361            return;
362        }
363        prev = rec;
364        rec = next;
365    }
366    SkDEBUGFAIL("shouldn't get here, face not in list");
367}
368
369class AutoFTAccess {
370public:
371    AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) {
372        gFTMutex.acquire();
373        if (1 == ++gFTCount) {
374            if (!InitFreetype()) {
375                sk_throw();
376            }
377        }
378        fRec = ref_ft_face(tf);
379        if (fRec) {
380            fFace = fRec->fFace;
381        }
382    }
383
384    ~AutoFTAccess() {
385        if (fFace) {
386            unref_ft_face(fFace);
387        }
388        if (0 == --gFTCount) {
389            FT_Done_FreeType(gFTLibrary);
390        }
391        gFTMutex.release();
392    }
393
394    SkFaceRec* rec() { return fRec; }
395    FT_Face face() { return fFace; }
396
397private:
398    SkFaceRec*  fRec;
399    FT_Face     fFace;
400};
401
402///////////////////////////////////////////////////////////////////////////
403
404// Work around for old versions of freetype.
405static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count,
406                           FT_Int32 loadFlags, FT_Fixed* advances) {
407#ifdef FT_ADVANCES_H
408    return FT_Get_Advances(face, start, count, loadFlags, advances);
409#else
410    if (!face || start >= face->num_glyphs ||
411            start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) {
412        return 6;  // "Invalid argument."
413    }
414    if (count == 0)
415        return 0;
416
417    for (int i = 0; i < count; i++) {
418        FT_Error err = FT_Load_Glyph(face, start + i, FT_LOAD_NO_SCALE);
419        if (err)
420            return err;
421        advances[i] = face->glyph->advance.x;
422    }
423
424    return 0;
425#endif
426}
427
428static bool canEmbed(FT_Face face) {
429#ifdef FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING
430    FT_UShort fsType = FT_Get_FSType_Flags(face);
431    return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
432                      FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0;
433#else
434    // No embedding is 0x2 and bitmap embedding only is 0x200.
435    TT_OS2* os2_table;
436    if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
437        return (os2_table->fsType & 0x202) == 0;
438    }
439    return false;  // We tried, fail safe.
440#endif
441}
442
443static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
444    const FT_UInt glyph_id = FT_Get_Char_Index(face, letter);
445    if (!glyph_id)
446        return false;
447    if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0)
448        return false;
449    FT_Outline_Get_CBox(&face->glyph->outline, bbox);
450    return true;
451}
452
453static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
454    FT_Fixed advance = 0;
455    if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
456        return false;
457    }
458    SkASSERT(data);
459    *data = advance;
460    return true;
461}
462
463static void populate_glyph_to_unicode(FT_Face& face,
464                                      SkTDArray<SkUnichar>* glyphToUnicode) {
465    // Check and see if we have Unicode cmaps.
466    for (int i = 0; i < face->num_charmaps; ++i) {
467        // CMaps known to support Unicode:
468        // Platform ID   Encoding ID   Name
469        // -----------   -----------   -----------------------------------
470        // 0             0,1           Apple Unicode
471        // 0             3             Apple Unicode 2.0 (preferred)
472        // 3             1             Microsoft Unicode UCS-2
473        // 3             10            Microsoft Unicode UCS-4 (preferred)
474        //
475        // See Apple TrueType Reference Manual
476        // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html
477        // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html#ID
478        // Microsoft OpenType Specification
479        // http://www.microsoft.com/typography/otspec/cmap.htm
480
481        FT_UShort platformId = face->charmaps[i]->platform_id;
482        FT_UShort encodingId = face->charmaps[i]->encoding_id;
483
484        if (platformId != 0 && platformId != 3) {
485            continue;
486        }
487        if (platformId == 3 && encodingId != 1 && encodingId != 10) {
488            continue;
489        }
490        bool preferredMap = ((platformId == 3 && encodingId == 10) ||
491                             (platformId == 0 && encodingId == 3));
492
493        FT_Set_Charmap(face, face->charmaps[i]);
494        if (glyphToUnicode->isEmpty()) {
495            glyphToUnicode->setCount(face->num_glyphs);
496            memset(glyphToUnicode->begin(), 0,
497                   sizeof(SkUnichar) * face->num_glyphs);
498        }
499
500        // Iterate through each cmap entry.
501        FT_UInt glyphIndex;
502        for (SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
503             glyphIndex != 0;
504             charCode = FT_Get_Next_Char(face, charCode, &glyphIndex)) {
505            if (charCode &&
506                    ((*glyphToUnicode)[glyphIndex] == 0 || preferredMap)) {
507                (*glyphToUnicode)[glyphIndex] = charCode;
508            }
509        }
510    }
511}
512
513SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
514        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
515        const uint32_t* glyphIDs,
516        uint32_t glyphIDsCount) const {
517#if defined(SK_BUILD_FOR_MAC)
518    return NULL;
519#else
520    AutoFTAccess fta(this);
521    FT_Face face = fta.face();
522    if (!face) {
523        return NULL;
524    }
525
526    SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
527    info->fFontName.set(FT_Get_Postscript_Name(face));
528    info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face);
529    info->fLastGlyphID = face->num_glyphs - 1;
530    info->fEmSize = 1000;
531
532    bool cid = false;
533    const char* fontType = FT_Get_X11_Font_Format(face);
534    if (strcmp(fontType, "Type 1") == 0) {
535        info->fType = SkAdvancedTypefaceMetrics::kType1_Font;
536    } else if (strcmp(fontType, "CID Type 1") == 0) {
537        info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font;
538        cid = true;
539    } else if (strcmp(fontType, "CFF") == 0) {
540        info->fType = SkAdvancedTypefaceMetrics::kCFF_Font;
541    } else if (strcmp(fontType, "TrueType") == 0) {
542        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
543        cid = true;
544        TT_Header* ttHeader;
545        if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face,
546                                                      ft_sfnt_head)) != NULL) {
547            info->fEmSize = ttHeader->Units_Per_EM;
548        }
549    } else {
550        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
551    }
552
553    info->fStyle = 0;
554    if (FT_IS_FIXED_WIDTH(face))
555        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
556    if (face->style_flags & FT_STYLE_FLAG_ITALIC)
557        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
558
559    PS_FontInfoRec ps_info;
560    TT_Postscript* tt_info;
561    if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
562        info->fItalicAngle = ps_info.italic_angle;
563    } else if ((tt_info =
564                (TT_Postscript*)FT_Get_Sfnt_Table(face,
565                                                  ft_sfnt_post)) != NULL) {
566        info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
567    } else {
568        info->fItalicAngle = 0;
569    }
570
571    info->fAscent = face->ascender;
572    info->fDescent = face->descender;
573
574    // Figure out a good guess for StemV - Min width of i, I, !, 1.
575    // This probably isn't very good with an italic font.
576    int16_t min_width = SHRT_MAX;
577    info->fStemV = 0;
578    char stem_chars[] = {'i', 'I', '!', '1'};
579    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
580        FT_BBox bbox;
581        if (GetLetterCBox(face, stem_chars[i], &bbox)) {
582            int16_t width = bbox.xMax - bbox.xMin;
583            if (width > 0 && width < min_width) {
584                min_width = width;
585                info->fStemV = min_width;
586            }
587        }
588    }
589
590    TT_PCLT* pclt_info;
591    TT_OS2* os2_table;
592    if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) {
593        info->fCapHeight = pclt_info->CapHeight;
594        uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
595        if (serif_style >= 2 && serif_style <= 6)
596            info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
597        else if (serif_style >= 9 && serif_style <= 12)
598            info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
599    } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) &&
600               // sCapHeight is available only when version 2 or later.
601               os2_table->version != 0xFFFF &&
602               os2_table->version >= 2) {
603        info->fCapHeight = os2_table->sCapHeight;
604    } else {
605        // Figure out a good guess for CapHeight: average the height of M and X.
606        FT_BBox m_bbox, x_bbox;
607        bool got_m, got_x;
608        got_m = GetLetterCBox(face, 'M', &m_bbox);
609        got_x = GetLetterCBox(face, 'X', &x_bbox);
610        if (got_m && got_x) {
611            info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax -
612                    x_bbox.yMin) / 2;
613        } else if (got_m && !got_x) {
614            info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
615        } else if (!got_m && got_x) {
616            info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
617        } else {
618            // Last resort, use the ascent.
619            info->fCapHeight = info->fAscent;
620        }
621    }
622
623    info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
624                                    face->bbox.xMax, face->bbox.yMin);
625
626    if (!canEmbed(face) || !FT_IS_SCALABLE(face) ||
627            info->fType == SkAdvancedTypefaceMetrics::kOther_Font) {
628        perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo;
629    }
630
631    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
632        if (FT_IS_FIXED_WIDTH(face)) {
633            appendRange(&info->fGlyphWidths, 0);
634            int16_t advance = face->max_advance_width;
635            info->fGlyphWidths->fAdvance.append(1, &advance);
636            finishRange(info->fGlyphWidths.get(), 0,
637                        SkAdvancedTypefaceMetrics::WidthRange::kDefault);
638        } else if (!cid) {
639            appendRange(&info->fGlyphWidths, 0);
640            // So as to not blow out the stack, get advances in batches.
641            for (int gID = 0; gID < face->num_glyphs; gID += 128) {
642                FT_Fixed advances[128];
643                int advanceCount = 128;
644                if (gID + advanceCount > face->num_glyphs)
645                    advanceCount = face->num_glyphs - gID;
646                getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE,
647                            advances);
648                for (int i = 0; i < advanceCount; i++) {
649                    int16_t advance = advances[i];
650                    info->fGlyphWidths->fAdvance.append(1, &advance);
651                }
652            }
653            finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
654                        SkAdvancedTypefaceMetrics::WidthRange::kRange);
655        } else {
656            info->fGlyphWidths.reset(
657                getAdvanceData(face,
658                               face->num_glyphs,
659                               glyphIDs,
660                               glyphIDsCount,
661                               &getWidthAdvance));
662        }
663    }
664
665    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo &&
666            FT_HAS_VERTICAL(face)) {
667        SkASSERT(false);  // Not implemented yet.
668    }
669
670    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo &&
671            info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
672        // Postscript fonts may contain more than 255 glyphs, so we end up
673        // using multiple font descriptions with a glyph ordering.  Record
674        // the name of each glyph.
675        info->fGlyphNames.reset(
676                new SkAutoTArray<SkString>(face->num_glyphs));
677        for (int gID = 0; gID < face->num_glyphs; gID++) {
678            char glyphName[128];  // PS limit for names is 127 bytes.
679            FT_Get_Glyph_Name(face, gID, glyphName, 128);
680            info->fGlyphNames->get()[gID].set(glyphName);
681        }
682    }
683
684    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo &&
685           info->fType != SkAdvancedTypefaceMetrics::kType1_Font &&
686           face->num_charmaps) {
687        populate_glyph_to_unicode(face, &(info->fGlyphToUnicode));
688    }
689
690    if (!canEmbed(face))
691        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
692
693    return info;
694#endif
695}
696
697///////////////////////////////////////////////////////////////////////////
698
699static bool bothZero(SkScalar a, SkScalar b) {
700    return 0 == a && 0 == b;
701}
702
703// returns false if there is any non-90-rotation or skew
704static bool isAxisAligned(const SkScalerContext::Rec& rec) {
705    return 0 == rec.fPreSkewX &&
706           (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
707            bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
708}
709
710SkScalerContext* SkTypeface_FreeType::onCreateScalerContext(
711                                               const SkDescriptor* desc) const {
712    SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType,
713                                        (const_cast<SkTypeface_FreeType*>(this),
714                                         desc));
715    if (!c->success()) {
716        SkDELETE(c);
717        c = NULL;
718    }
719    return c;
720}
721
722void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const {
723    //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119
724    //Cap the requested size as larger sizes give bogus values.
725    //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed.
726    if (rec->fTextSize > SkIntToScalar(1 << 14)) {
727        rec->fTextSize = SkIntToScalar(1 << 14);
728    }
729
730    if (!is_lcd_supported() && isLCD(*rec)) {
731        // If the runtime Freetype library doesn't support LCD mode, we disable
732        // it here.
733        rec->fMaskFormat = SkMask::kA8_Format;
734    }
735
736    SkPaint::Hinting h = rec->getHinting();
737    if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) {
738        // collapse full->normal hinting if we're not doing LCD
739        h = SkPaint::kNormal_Hinting;
740    }
741    if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag)) {
742        if (SkPaint::kNo_Hinting != h) {
743            h = SkPaint::kSlight_Hinting;
744        }
745    }
746
747    // rotated text looks bad with hinting, so we disable it as needed
748    if (!isAxisAligned(*rec)) {
749        h = SkPaint::kNo_Hinting;
750    }
751    rec->setHinting(h);
752
753#ifndef SK_GAMMA_APPLY_TO_A8
754    if (!isLCD(*rec)) {
755      rec->ignorePreBlend();
756    }
757#endif
758}
759
760int SkTypeface_FreeType::onGetUPEM() const {
761    AutoFTAccess fta(this);
762    FT_Face face = fta.face();
763    return face ? face->units_per_EM : 0;
764}
765
766bool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[],
767                                      int count, int32_t adjustments[]) const {
768    AutoFTAccess fta(this);
769    FT_Face face = fta.face();
770    if (!face || !FT_HAS_KERNING(face)) {
771        return false;
772    }
773
774    for (int i = 0; i < count - 1; ++i) {
775        FT_Vector delta;
776        FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1],
777                                      FT_KERNING_UNSCALED, &delta);
778        if (err) {
779            return false;
780        }
781        adjustments[i] = delta.x;
782    }
783    return true;
784}
785
786static FT_Int chooseBitmapStrike(FT_Face face, SkFixed scaleY) {
787    // early out if face is bad
788    if (face == NULL) {
789        SkDEBUGF(("chooseBitmapStrike aborted due to NULL face\n"));
790        return -1;
791    }
792    // determine target ppem
793    FT_Pos targetPPEM = SkFixedToFDot6(scaleY);
794    // find a bitmap strike equal to or just larger than the requested size
795    FT_Int chosenStrikeIndex = -1;
796    FT_Pos chosenPPEM = 0;
797    for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) {
798        FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem;
799        if (thisPPEM == targetPPEM) {
800            // exact match - our search stops here
801            chosenPPEM = thisPPEM;
802            chosenStrikeIndex = strikeIndex;
803            break;
804        } else if (chosenPPEM < targetPPEM) {
805            // attempt to increase chosenPPEM
806            if (thisPPEM > chosenPPEM) {
807                chosenPPEM = thisPPEM;
808                chosenStrikeIndex = strikeIndex;
809            }
810        } else {
811            // attempt to decrease chosenPPEM, but not below targetPPEM
812            if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) {
813                chosenPPEM = thisPPEM;
814                chosenStrikeIndex = strikeIndex;
815            }
816        }
817    }
818    if (chosenStrikeIndex != -1) {
819        // use the chosen strike
820        FT_Error err = FT_Select_Size(face, chosenStrikeIndex);
821        if (err != 0) {
822            SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_name,
823                      chosenStrikeIndex, err));
824            chosenStrikeIndex = -1;
825        }
826    }
827    return chosenStrikeIndex;
828}
829
830SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
831                                                   const SkDescriptor* desc)
832        : SkScalerContext_FreeType_Base(typeface, desc) {
833    SkAutoMutexAcquire  ac(gFTMutex);
834
835    if (gFTCount == 0) {
836        if (!InitFreetype()) {
837            sk_throw();
838        }
839    }
840    ++gFTCount;
841
842    // load the font file
843    fStrikeIndex = -1;
844    fFTSize = NULL;
845    fFace = NULL;
846    fFaceRec = ref_ft_face(typeface);
847    if (NULL == fFaceRec) {
848        return;
849    }
850    fFace = fFaceRec->fFace;
851
852    // A is the total matrix.
853    SkMatrix A;
854    fRec.getSingleMatrix(&A);
855
856    SkScalar sx = A.getScaleX();
857    SkScalar sy = A.getScaleY();
858    fMatrix22Scalar.reset();
859
860    // In GDI, the hinter is aware of the current transformation
861    // (the transform is in some sense applied before/with the hinting).
862    // The bytecode can then test if it is rotated or stretched and decide
863    // to apply instructions or not.
864    //
865    // FreeType, however, always does the transformation strictly after hinting.
866    // It just sets 'rotated' and 'stretched' to false and only applies the
867    // size before hinting.
868    //
869    // Also, FreeType respects the head::flags::IntegerScaling flag,
870    // (although this is patched out on most major distros)
871    // so it is critical to get the size correct on the request.
872    //
873    // This also gets us the actual closest size on bitmap fonts as well.
874    if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) {
875        // h is where A maps the horizontal baseline.
876        SkPoint h = SkPoint::Make(SK_Scalar1, 0);
877        A.mapPoints(&h, 1);
878
879        // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
880        SkMatrix G;
881        SkComputeGivensRotation(h, &G);
882
883        // GA is the matrix A with rotation removed.
884        SkMatrix GA(G);
885        GA.preConcat(A);
886
887        sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX));
888        sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
889
890        // sA is the total matrix A without the text scale.
891        SkMatrix sA(A);
892        sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size
893
894        fMatrix22Scalar.setScaleX(sA.getScaleX());
895        fMatrix22Scalar.setSkewX(-sA.getSkewX());
896        fMatrix22Scalar.setSkewY(-sA.getSkewY());
897        fMatrix22Scalar.setScaleY(sA.getScaleY());
898    }
899    fScale.set(sx, sy);
900    fScaleX = SkScalarToFixed(sx);
901    fScaleY = SkScalarToFixed(sy);
902    fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX());
903    fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX());
904    fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY());
905    fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
906
907    fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
908
909    // compute the flags we send to Load_Glyph
910    bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag);
911    {
912        FT_Int32 loadFlags = FT_LOAD_DEFAULT;
913
914        if (SkMask::kBW_Format == fRec.fMaskFormat) {
915            // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
916            loadFlags = FT_LOAD_TARGET_MONO;
917            if (fRec.getHinting() == SkPaint::kNo_Hinting) {
918                loadFlags = FT_LOAD_NO_HINTING;
919                linearMetrics = true;
920            }
921        } else {
922            switch (fRec.getHinting()) {
923            case SkPaint::kNo_Hinting:
924                loadFlags = FT_LOAD_NO_HINTING;
925                linearMetrics = true;
926                break;
927            case SkPaint::kSlight_Hinting:
928                loadFlags = FT_LOAD_TARGET_LIGHT;  // This implies FORCE_AUTOHINT
929                break;
930            case SkPaint::kNormal_Hinting:
931                if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
932                    loadFlags = FT_LOAD_FORCE_AUTOHINT;
933                }
934                break;
935            case SkPaint::kFull_Hinting:
936                if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
937                    loadFlags = FT_LOAD_FORCE_AUTOHINT;
938                    break;
939                }
940                loadFlags = FT_LOAD_TARGET_NORMAL;
941                if (isLCD(fRec)) {
942                    if (fLCDIsVert) {
943                        loadFlags = FT_LOAD_TARGET_LCD_V;
944                    } else {
945                        loadFlags = FT_LOAD_TARGET_LCD;
946                    }
947                }
948                break;
949            default:
950                SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
951                break;
952            }
953        }
954
955        if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
956            loadFlags |= FT_LOAD_NO_BITMAP;
957        }
958
959        // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
960        // advances, as fontconfig and cairo do.
961        // See http://code.google.com/p/skia/issues/detail?id=222.
962        loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
963
964        // Use vertical layout if requested.
965        if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
966            loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
967        }
968
969        loadFlags |= FT_LOAD_COLOR;
970
971        fLoadGlyphFlags = loadFlags;
972    }
973
974    FT_Error err = FT_New_Size(fFace, &fFTSize);
975    if (err != 0) {
976        SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_name));
977        fFace = NULL;
978        return;
979    }
980    err = FT_Activate_Size(fFTSize);
981    if (err != 0) {
982        SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, fScaleX, fScaleY,
983                  err));
984        fFTSize = NULL;
985        return;
986    }
987
988    if (FT_IS_SCALABLE(fFace)) {
989        err = FT_Set_Char_Size(fFace, SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY), 72, 72);
990        if (err != 0) {
991            SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n",
992                                    fFace, fScaleX, fScaleY,      err));
993            fFace = NULL;
994            return;
995        }
996        FT_Set_Transform(fFace, &fMatrix22, NULL);
997    } else if (FT_HAS_FIXED_SIZES(fFace)) {
998        fStrikeIndex = chooseBitmapStrike(fFace, fScaleY);
999        if (fStrikeIndex == -1) {
1000            SkDEBUGF(("no glyphs for font \"%s\" size %f?\n",
1001                            fFace->family_name,       SkFixedToScalar(fScaleY)));
1002        } else {
1003            // FreeType does no provide linear metrics for bitmap fonts.
1004            linearMetrics = false;
1005
1006            // FreeType documentation says:
1007            // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading.
1008            // Bitmap-only fonts ignore this flag.
1009            //
1010            // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag.
1011            // Force this flag off for bitmap only fonts.
1012            fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP;
1013        }
1014    } else {
1015        SkDEBUGF(("unknown kind of font \"%s\" size %f?\n",
1016                            fFace->family_name,       SkFixedToScalar(fScaleY)));
1017    }
1018
1019    fDoLinearMetrics = linearMetrics;
1020}
1021
1022SkScalerContext_FreeType::~SkScalerContext_FreeType() {
1023    SkAutoMutexAcquire  ac(gFTMutex);
1024
1025    if (fFTSize != NULL) {
1026        FT_Done_Size(fFTSize);
1027    }
1028
1029    if (fFace != NULL) {
1030        unref_ft_face(fFace);
1031    }
1032    if (--gFTCount == 0) {
1033        FT_Done_FreeType(gFTLibrary);
1034        SkDEBUGCODE(gFTLibrary = NULL;)
1035    }
1036}
1037
1038/*  We call this before each use of the fFace, since we may be sharing
1039    this face with other context (at different sizes).
1040*/
1041FT_Error SkScalerContext_FreeType::setupSize() {
1042    FT_Error err = FT_Activate_Size(fFTSize);
1043    if (err != 0) {
1044        SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
1045                  fFaceRec->fFontID, fScaleX, fScaleY, err));
1046        fFTSize = NULL;
1047        return err;
1048    }
1049
1050    // seems we need to reset this every time (not sure why, but without it
1051    // I get random italics from some other fFTSize)
1052    FT_Set_Transform(fFace, &fMatrix22, NULL);
1053    return 0;
1054}
1055
1056unsigned SkScalerContext_FreeType::generateGlyphCount() {
1057    return fFace->num_glyphs;
1058}
1059
1060uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) {
1061    return SkToU16(FT_Get_Char_Index( fFace, uni ));
1062}
1063
1064SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) {
1065    // iterate through each cmap entry, looking for matching glyph indices
1066    FT_UInt glyphIndex;
1067    SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex );
1068
1069    while (glyphIndex != 0) {
1070        if (glyphIndex == glyph) {
1071            return charCode;
1072        }
1073        charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex );
1074    }
1075
1076    return 0;
1077}
1078
1079void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
1080#ifdef FT_ADVANCES_H
1081   /* unhinted and light hinted text have linearly scaled advances
1082    * which are very cheap to compute with some font formats...
1083    */
1084    if (fDoLinearMetrics) {
1085        SkAutoMutexAcquire  ac(gFTMutex);
1086
1087        if (this->setupSize()) {
1088            glyph->zeroMetrics();
1089            return;
1090        }
1091
1092        FT_Error    error;
1093        FT_Fixed    advance;
1094
1095        error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount),
1096                                fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
1097                                &advance );
1098        if (0 == error) {
1099            glyph->fRsbDelta = 0;
1100            glyph->fLsbDelta = 0;
1101            glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, advance);
1102            glyph->fAdvanceY = - SkFixedMul(fMatrix22.yx, advance);
1103            return;
1104        }
1105    }
1106#endif /* FT_ADVANCES_H */
1107    /* otherwise, we need to load/hint the glyph, which is slower */
1108    this->generateMetrics(glyph);
1109    return;
1110}
1111
1112void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph,
1113                                                      FT_BBox* bbox,
1114                                                      bool snapToPixelBoundary) {
1115
1116    FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
1117
1118    if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
1119        int dx = SkFixedToFDot6(glyph->getSubXFixed());
1120        int dy = SkFixedToFDot6(glyph->getSubYFixed());
1121        // negate dy since freetype-y-goes-up and skia-y-goes-down
1122        bbox->xMin += dx;
1123        bbox->yMin -= dy;
1124        bbox->xMax += dx;
1125        bbox->yMax -= dy;
1126    }
1127
1128    // outset the box to integral boundaries
1129    if (snapToPixelBoundary) {
1130        bbox->xMin &= ~63;
1131        bbox->yMin &= ~63;
1132        bbox->xMax  = (bbox->xMax + 63) & ~63;
1133        bbox->yMax  = (bbox->yMax + 63) & ~63;
1134    }
1135
1136    // Must come after snapToPixelBoundary so that the width and height are
1137    // consistent. Otherwise asserts will fire later on when generating the
1138    // glyph image.
1139    if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1140        FT_Vector vector;
1141        vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1142        vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1143        FT_Vector_Transform(&vector, &fMatrix22);
1144        bbox->xMin += vector.x;
1145        bbox->xMax += vector.x;
1146        bbox->yMin += vector.y;
1147        bbox->yMax += vector.y;
1148    }
1149}
1150
1151bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
1152    const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter);
1153    if (!glyph_id)
1154        return false;
1155    if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0)
1156        return false;
1157    emboldenIfNeeded(fFace, fFace->glyph);
1158    FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
1159    return true;
1160}
1161
1162void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
1163    if (isLCD(fRec)) {
1164        if (fLCDIsVert) {
1165            glyph->fHeight += gLCDExtra;
1166            glyph->fTop -= gLCDExtra >> 1;
1167        } else {
1168            glyph->fWidth += gLCDExtra;
1169            glyph->fLeft -= gLCDExtra >> 1;
1170        }
1171    }
1172}
1173
1174inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) {
1175    glyph.fWidth *= scale;
1176    glyph.fHeight *= scale;
1177    glyph.fTop *= scale;
1178    glyph.fLeft *= scale;
1179
1180    SkFixed fixedScale = SkScalarToFixed(scale);
1181    glyph.fAdvanceX = SkFixedMul(glyph.fAdvanceX, fixedScale);
1182    glyph.fAdvanceY = SkFixedMul(glyph.fAdvanceY, fixedScale);
1183}
1184
1185void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
1186    SkAutoMutexAcquire  ac(gFTMutex);
1187
1188    glyph->fRsbDelta = 0;
1189    glyph->fLsbDelta = 0;
1190
1191    FT_Error    err;
1192
1193    if (this->setupSize()) {
1194        goto ERROR;
1195    }
1196
1197    err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
1198    if (err != 0) {
1199#if 0
1200        SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%x) returned 0x%x\n",
1201                    fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
1202#endif
1203    ERROR:
1204        glyph->zeroMetrics();
1205        return;
1206    }
1207    emboldenIfNeeded(fFace, fFace->glyph);
1208
1209    switch ( fFace->glyph->format ) {
1210      case FT_GLYPH_FORMAT_OUTLINE:
1211        if (0 == fFace->glyph->outline.n_contours) {
1212            glyph->fWidth = 0;
1213            glyph->fHeight = 0;
1214            glyph->fTop = 0;
1215            glyph->fLeft = 0;
1216        } else {
1217            FT_BBox bbox;
1218            getBBoxForCurrentGlyph(glyph, &bbox, true);
1219
1220            glyph->fWidth   = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
1221            glyph->fHeight  = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin));
1222            glyph->fTop     = -SkToS16(SkFDot6Floor(bbox.yMax));
1223            glyph->fLeft    = SkToS16(SkFDot6Floor(bbox.xMin));
1224
1225            updateGlyphIfLCD(glyph);
1226        }
1227        break;
1228
1229      case FT_GLYPH_FORMAT_BITMAP:
1230        if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1231            FT_Vector vector;
1232            vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1233            vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1234            FT_Vector_Transform(&vector, &fMatrix22);
1235            fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
1236            fFace->glyph->bitmap_top  += SkFDot6Floor(vector.y);
1237        }
1238
1239        if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
1240            glyph->fMaskFormat = SkMask::kARGB32_Format;
1241        }
1242
1243        glyph->fWidth   = SkToU16(fFace->glyph->bitmap.width);
1244        glyph->fHeight  = SkToU16(fFace->glyph->bitmap.rows);
1245        glyph->fTop     = -SkToS16(fFace->glyph->bitmap_top);
1246        glyph->fLeft    = SkToS16(fFace->glyph->bitmap_left);
1247        break;
1248
1249      default:
1250        SkDEBUGFAIL("unknown glyph format");
1251        goto ERROR;
1252    }
1253
1254    if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1255        if (fDoLinearMetrics) {
1256            glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
1257            glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
1258        } else {
1259            glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x);
1260            glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y);
1261        }
1262    } else {
1263        if (fDoLinearMetrics) {
1264            glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
1265            glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
1266        } else {
1267            glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
1268            glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
1269
1270            if (fRec.fFlags & kDevKernText_Flag) {
1271                glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
1272                glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
1273            }
1274        }
1275    }
1276
1277    if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && fScaleY && fFace->size->metrics.y_ppem) {
1278        // NOTE: both dimensions are scaled by y_ppem. this is WAI.
1279        scaleGlyphMetrics(*glyph, SkScalarDiv(SkFixedToScalar(fScaleY),
1280                                              SkIntToScalar(fFace->size->metrics.y_ppem)));
1281    }
1282
1283#ifdef ENABLE_GLYPH_SPEW
1284    SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
1285    SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth));
1286#endif
1287}
1288
1289
1290void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
1291    SkAutoMutexAcquire  ac(gFTMutex);
1292
1293    FT_Error    err;
1294
1295    if (this->setupSize()) {
1296        goto ERROR;
1297    }
1298
1299    err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
1300    if (err != 0) {
1301        SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
1302                    glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
1303    ERROR:
1304        memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
1305        return;
1306    }
1307
1308    emboldenIfNeeded(fFace, fFace->glyph);
1309    generateGlyphImage(fFace, glyph);
1310}
1311
1312
1313void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
1314                                            SkPath* path) {
1315    SkAutoMutexAcquire  ac(gFTMutex);
1316
1317    SkASSERT(&glyph && path);
1318
1319    if (this->setupSize()) {
1320        path->reset();
1321        return;
1322    }
1323
1324    uint32_t flags = fLoadGlyphFlags;
1325    flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1326    flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1327
1328    FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags);
1329
1330    if (err != 0) {
1331        SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
1332                    glyph.getGlyphID(fBaseGlyphCount), flags, err));
1333        path->reset();
1334        return;
1335    }
1336    emboldenIfNeeded(fFace, fFace->glyph);
1337
1338    generateGlyphPath(fFace, path);
1339
1340    // The path's origin from FreeType is always the horizontal layout origin.
1341    // Offset the path so that it is relative to the vertical origin if needed.
1342    if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
1343        FT_Vector vector;
1344        vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1345        vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1346        FT_Vector_Transform(&vector, &fMatrix22);
1347        path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y));
1348    }
1349}
1350
1351void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
1352                                                   SkPaint::FontMetrics* my) {
1353    if (NULL == mx && NULL == my) {
1354        return;
1355    }
1356
1357    SkAutoMutexAcquire  ac(gFTMutex);
1358
1359    if (this->setupSize()) {
1360        ERROR:
1361        if (mx) {
1362            sk_bzero(mx, sizeof(SkPaint::FontMetrics));
1363        }
1364        if (my) {
1365            sk_bzero(my, sizeof(SkPaint::FontMetrics));
1366        }
1367        return;
1368    }
1369
1370    FT_Face face = fFace;
1371    SkScalar scaleX = fScale.x();
1372    SkScalar scaleY = fScale.y();
1373    SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY;
1374    SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY;
1375
1376    // fetch units/EM from "head" table if needed (ie for bitmap fonts)
1377    SkScalar upem = SkIntToScalar(face->units_per_EM);
1378    if (!upem) {
1379        TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
1380        if (ttHeader) {
1381            upem = SkIntToScalar(ttHeader->Units_Per_EM);
1382        }
1383    }
1384
1385    // use the os/2 table as a source of reasonable defaults.
1386    SkScalar x_height = 0.0f;
1387    SkScalar avgCharWidth = 0.0f;
1388    SkScalar cap_height = 0.0f;
1389    TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1390    if (os2) {
1391        x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem;
1392        avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem;
1393        if (os2->version != 0xFFFF && os2->version >= 2) {
1394            cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem;
1395        }
1396    }
1397
1398    // pull from format-specific metrics as needed
1399    SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
1400    SkScalar underlineThickness, underlinePosition;
1401    if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
1402        ascent = -SkIntToScalar(face->ascender) / upem;
1403        descent = -SkIntToScalar(face->descender) / upem;
1404        leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem;
1405        xmin = SkIntToScalar(face->bbox.xMin) / upem;
1406        xmax = SkIntToScalar(face->bbox.xMax) / upem;
1407        ymin = -SkIntToScalar(face->bbox.yMin) / upem;
1408        ymax = -SkIntToScalar(face->bbox.yMax) / upem;
1409        underlineThickness = SkIntToScalar(face->underline_thickness) / upem;
1410#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX
1411        underlinePosition = -SkIntToScalar(face->underline_position) / upem;
1412#else
1413        underlinePosition = -SkIntToScalar(face->underline_position +
1414                                           face->underline_thickness / 2) / upem;
1415#endif
1416
1417        if(mx) {
1418            mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
1419            mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
1420        }
1421        if(my){
1422            my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
1423            my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
1424        }
1425        // we may be able to synthesize x_height and cap_height from outline
1426        if (!x_height) {
1427            FT_BBox bbox;
1428            if (getCBoxForLetter('x', &bbox)) {
1429                x_height = SkIntToScalar(bbox.yMax) / 64.0f;
1430            }
1431        }
1432        if (!cap_height) {
1433            FT_BBox bbox;
1434            if (getCBoxForLetter('H', &bbox)) {
1435                cap_height = SkIntToScalar(bbox.yMax) / 64.0f;
1436            }
1437        }
1438    } else if (fStrikeIndex != -1) { // bitmap strike metrics
1439        SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem);
1440        SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem);
1441        ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f);
1442        descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f);
1443        leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f))
1444                + ascent - descent;
1445        xmin = 0.0f;
1446        xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
1447        ymin = descent + leading;
1448        ymax = ascent - descent;
1449        underlineThickness = 0;
1450        underlinePosition = 0;
1451
1452        if(mx) {
1453            mx->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
1454            mx->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
1455        }
1456        if(my){
1457            my->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
1458            my->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
1459        }
1460    } else {
1461        goto ERROR;
1462    }
1463
1464    // synthesize elements that were not provided by the os/2 table or format-specific metrics
1465    if (!x_height) {
1466        x_height = -ascent;
1467    }
1468    if (!avgCharWidth) {
1469        avgCharWidth = xmax - xmin;
1470    }
1471    if (!cap_height) {
1472      cap_height = -ascent;
1473    }
1474
1475    // disallow negative linespacing
1476    if (leading < 0.0f) {
1477        leading = 0.0f;
1478    }
1479
1480    if (mx) {
1481        mx->fTop = ymax * mxy;
1482        mx->fAscent = ascent * mxy;
1483        mx->fDescent = descent * mxy;
1484        mx->fBottom = ymin * mxy;
1485        mx->fLeading = leading * mxy;
1486        mx->fAvgCharWidth = avgCharWidth * mxy;
1487        mx->fXMin = xmin;
1488        mx->fXMax = xmax;
1489        mx->fXHeight = x_height;
1490        mx->fCapHeight = cap_height;
1491#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX
1492        mx->fUnderlineThickness = underlineThickness;
1493        mx->fUnderlinePosition = underlinePosition;
1494#else
1495        mx->fUnderlineThickness = underlineThickness * mxy;
1496        mx->fUnderlinePosition = underlinePosition * mxy;
1497#endif
1498    }
1499    if (my) {
1500        my->fTop = ymax * myy;
1501        my->fAscent = ascent * myy;
1502        my->fDescent = descent * myy;
1503        my->fBottom = ymin * myy;
1504        my->fLeading = leading * myy;
1505        my->fAvgCharWidth = avgCharWidth * myy;
1506        my->fXMin = xmin;
1507        my->fXMax = xmax;
1508        my->fXHeight = x_height;
1509        my->fCapHeight = cap_height;
1510#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX
1511        my->fUnderlineThickness = underlineThickness;
1512        my->fUnderlinePosition = underlinePosition;
1513#else
1514        my->fUnderlineThickness = underlineThickness * myy;
1515        my->fUnderlinePosition = underlinePosition * myy;
1516#endif
1517    }
1518}
1519
1520///////////////////////////////////////////////////////////////////////////////
1521
1522// hand-tuned value to reduce outline embolden strength
1523#ifndef SK_OUTLINE_EMBOLDEN_DIVISOR
1524    #ifdef SK_BUILD_FOR_ANDROID
1525        #define SK_OUTLINE_EMBOLDEN_DIVISOR   34
1526    #else
1527        #define SK_OUTLINE_EMBOLDEN_DIVISOR   24
1528    #endif
1529#endif
1530
1531///////////////////////////////////////////////////////////////////////////////
1532
1533void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph)
1534{
1535    // check to see if the embolden bit is set
1536    if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) {
1537        return;
1538    }
1539
1540#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
1541    // Android doesn't want to embolden a font that is already bold.
1542    if ((fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
1543        return;
1544    }
1545#endif
1546
1547    switch (glyph->format) {
1548        case FT_GLYPH_FORMAT_OUTLINE:
1549            FT_Pos strength;
1550            strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale)
1551                       / SK_OUTLINE_EMBOLDEN_DIVISOR;
1552            FT_Outline_Embolden(&glyph->outline, strength);
1553            break;
1554        case FT_GLYPH_FORMAT_BITMAP:
1555            FT_GlyphSlot_Own_Bitmap(glyph);
1556            FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0);
1557            break;
1558        default:
1559            SkDEBUGFAIL("unknown glyph format");
1560    }
1561}
1562
1563///////////////////////////////////////////////////////////////////////////////
1564
1565#include "SkUtils.h"
1566
1567static SkUnichar next_utf8(const void** chars) {
1568    return SkUTF8_NextUnichar((const char**)chars);
1569}
1570
1571static SkUnichar next_utf16(const void** chars) {
1572    return SkUTF16_NextUnichar((const uint16_t**)chars);
1573}
1574
1575static SkUnichar next_utf32(const void** chars) {
1576    const SkUnichar** uniChars = (const SkUnichar**)chars;
1577    SkUnichar uni = **uniChars;
1578    *uniChars += 1;
1579    return uni;
1580}
1581
1582typedef SkUnichar (*EncodingProc)(const void**);
1583
1584static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
1585    static const EncodingProc gProcs[] = {
1586        next_utf8, next_utf16, next_utf32
1587    };
1588    SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
1589    return gProcs[enc];
1590}
1591
1592int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding,
1593                                      uint16_t glyphs[], int glyphCount) const {
1594    AutoFTAccess fta(this);
1595    FT_Face face = fta.face();
1596    if (!face) {
1597        if (glyphs) {
1598            sk_bzero(glyphs, glyphCount * sizeof(glyphs[0]));
1599        }
1600        return 0;
1601    }
1602
1603    EncodingProc next_uni_proc = find_encoding_proc(encoding);
1604
1605    if (NULL == glyphs) {
1606        for (int i = 0; i < glyphCount; ++i) {
1607            if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) {
1608                return i;
1609            }
1610        }
1611        return glyphCount;
1612    } else {
1613        int first = glyphCount;
1614        for (int i = 0; i < glyphCount; ++i) {
1615            unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars));
1616            glyphs[i] = SkToU16(id);
1617            if (0 == id && i < first) {
1618                first = i;
1619            }
1620        }
1621        return first;
1622    }
1623}
1624
1625int SkTypeface_FreeType::onCountGlyphs() const {
1626    // we cache this value, using -1 as a sentinel for "not computed"
1627    if (fGlyphCount < 0) {
1628        AutoFTAccess fta(this);
1629        FT_Face face = fta.face();
1630        // if the face failed, we still assign a non-negative value
1631        fGlyphCount = face ? face->num_glyphs : 0;
1632    }
1633    return fGlyphCount;
1634}
1635
1636SkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const {
1637    SkTypeface::LocalizedStrings* nameIter =
1638        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
1639    if (NULL == nameIter) {
1640        SkString familyName;
1641        this->getFamilyName(&familyName);
1642        SkString language("und"); //undetermined
1643        nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
1644    }
1645    return nameIter;
1646}
1647
1648int SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const {
1649    AutoFTAccess fta(this);
1650    FT_Face face = fta.face();
1651
1652    FT_ULong tableCount = 0;
1653    FT_Error error;
1654
1655    // When 'tag' is NULL, returns number of tables in 'length'.
1656    error = FT_Sfnt_Table_Info(face, 0, NULL, &tableCount);
1657    if (error) {
1658        return 0;
1659    }
1660
1661    if (tags) {
1662        for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) {
1663            FT_ULong tableTag;
1664            FT_ULong tablelength;
1665            error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength);
1666            if (error) {
1667                return 0;
1668            }
1669            tags[tableIndex] = static_cast<SkFontTableTag>(tableTag);
1670        }
1671    }
1672    return tableCount;
1673}
1674
1675size_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset,
1676                                           size_t length, void* data) const
1677{
1678    AutoFTAccess fta(this);
1679    FT_Face face = fta.face();
1680
1681    FT_ULong tableLength = 0;
1682    FT_Error error;
1683
1684    // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored.
1685    error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &tableLength);
1686    if (error) {
1687        return 0;
1688    }
1689
1690    if (offset > tableLength) {
1691        return 0;
1692    }
1693    FT_ULong size = SkTMin((FT_ULong)length, tableLength - (FT_ULong)offset);
1694    if (NULL != data) {
1695        error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size);
1696        if (error) {
1697            return 0;
1698        }
1699    }
1700
1701    return size;
1702}
1703
1704///////////////////////////////////////////////////////////////////////////////
1705///////////////////////////////////////////////////////////////////////////////
1706
1707/*  Export this so that other parts of our FonttHost port can make use of our
1708    ability to extract the name+style from a stream, using FreeType's api.
1709*/
1710bool find_name_and_attributes(SkStream* stream, SkString* name,
1711                              SkTypeface::Style* style, bool* isFixedPitch) {
1712    FT_Library  library;
1713    if (FT_Init_FreeType(&library)) {
1714        return false;
1715    }
1716
1717    FT_Open_Args    args;
1718    memset(&args, 0, sizeof(args));
1719
1720    const void* memoryBase = stream->getMemoryBase();
1721    FT_StreamRec    streamRec;
1722
1723    if (NULL != memoryBase) {
1724        args.flags = FT_OPEN_MEMORY;
1725        args.memory_base = (const FT_Byte*)memoryBase;
1726        args.memory_size = stream->getLength();
1727    } else {
1728        memset(&streamRec, 0, sizeof(streamRec));
1729        streamRec.size = stream->getLength();
1730        streamRec.descriptor.pointer = stream;
1731        streamRec.read  = sk_stream_read;
1732        streamRec.close = sk_stream_close;
1733
1734        args.flags = FT_OPEN_STREAM;
1735        args.stream = &streamRec;
1736    }
1737
1738    FT_Face face;
1739    if (FT_Open_Face(library, &args, 0, &face)) {
1740        FT_Done_FreeType(library);
1741        return false;
1742    }
1743
1744    int tempStyle = SkTypeface::kNormal;
1745    if (face->style_flags & FT_STYLE_FLAG_BOLD) {
1746        tempStyle |= SkTypeface::kBold;
1747    }
1748    if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
1749        tempStyle |= SkTypeface::kItalic;
1750    }
1751
1752    if (name) {
1753        name->set(face->family_name);
1754    }
1755    if (style) {
1756        *style = (SkTypeface::Style) tempStyle;
1757    }
1758    if (isFixedPitch) {
1759        *isFixedPitch = FT_IS_FIXED_WIDTH(face);
1760    }
1761
1762    FT_Done_Face(face);
1763    FT_Done_FreeType(library);
1764    return true;
1765}
1766