SkFontHost_FreeType.cpp revision 618ef5ee3bc1fae284c766597fd518faabf7373d
1/* libs/graphics/ports/SkFontHost_FreeType.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkBitmap.h"
19#include "SkCanvas.h"
20#include "SkColorPriv.h"
21#include "SkDescriptor.h"
22#include "SkFDot6.h"
23#include "SkFontHost.h"
24#include "SkMask.h"
25#include "SkPDFTypefaceInfo.h"
26#include "SkScalerContext.h"
27#include "SkStream.h"
28#include "SkString.h"
29#include "SkTemplates.h"
30#include "SkThread.h"
31
32#include <ft2build.h>
33#include FT_FREETYPE_H
34#include FT_OUTLINE_H
35#include FT_SIZES_H
36#include FT_TRUETYPE_TABLES_H
37#include FT_TYPE1_TABLES_H
38#include FT_BITMAP_H
39// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
40#include FT_SYNTHESIS_H
41#include FT_XFREE86_H
42
43#if defined(SK_SUPPORT_LCDTEXT)
44#include FT_LCD_FILTER_H
45#endif
46
47#ifdef   FT_ADVANCES_H
48#include FT_ADVANCES_H
49#endif
50
51#if 0
52// Also include the files by name for build tools which require this.
53#include <freetype/freetype.h>
54#include <freetype/ftoutln.h>
55#include <freetype/ftsizes.h>
56#include <freetype/tttables.h>
57#include <freetype/ftadvanc.h>
58#include <freetype/ftlcdfil.h>
59#include <freetype/ftbitmap.h>
60#include <freetype/ftsynth.h>
61#endif
62
63//#define ENABLE_GLYPH_SPEW     // for tracing calls
64//#define DUMP_STRIKE_CREATION
65
66#ifdef SK_DEBUG
67    #define SkASSERT_CONTINUE(pred)                                                         \
68        do {                                                                                \
69            if (!(pred))                                                                    \
70                SkDebugf("file %s:%d: assert failed '" #pred "'\n", __FILE__, __LINE__);    \
71        } while (false)
72#else
73    #define SkASSERT_CONTINUE(pred)
74#endif
75
76//////////////////////////////////////////////////////////////////////////
77
78struct SkFaceRec;
79
80static SkMutex      gFTMutex;
81static int          gFTCount;
82static FT_Library   gFTLibrary;
83static SkFaceRec*   gFaceRecHead;
84static bool         gLCDSupportValid;  // true iff |gLCDSupport| has been set.
85static bool         gLCDSupport;  // true iff LCD is supported by the runtime.
86
87/////////////////////////////////////////////////////////////////////////
88
89// See http://freetype.sourceforge.net/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden
90// This value was chosen by eyeballing the result in Firefox and trying to match it.
91static const FT_Pos kBitmapEmboldenStrength = 1 << 6;
92
93static bool
94InitFreetype() {
95    FT_Error err = FT_Init_FreeType(&gFTLibrary);
96    if (err)
97        return false;
98
99#if defined(SK_SUPPORT_LCDTEXT)
100    // Setup LCD filtering. This reduces colour fringes for LCD rendered
101    // glyphs.
102    err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT);
103    gLCDSupport = err == 0;
104#endif
105    gLCDSupportValid = true;
106
107    return true;
108}
109
110class SkScalerContext_FreeType : public SkScalerContext {
111public:
112    SkScalerContext_FreeType(const SkDescriptor* desc);
113    virtual ~SkScalerContext_FreeType();
114
115    bool success() const {
116        return fFaceRec != NULL &&
117               fFTSize != NULL &&
118               fFace != NULL;
119    }
120
121protected:
122    virtual unsigned generateGlyphCount() const;
123    virtual uint16_t generateCharToGlyph(SkUnichar uni);
124    virtual void generateAdvance(SkGlyph* glyph);
125    virtual void generateMetrics(SkGlyph* glyph);
126    virtual void generateImage(const SkGlyph& glyph);
127    virtual void generatePath(const SkGlyph& glyph, SkPath* path);
128    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
129                                     SkPaint::FontMetrics* my);
130    virtual SkUnichar generateGlyphToChar(uint16_t glyph);
131
132private:
133    SkFaceRec*  fFaceRec;
134    FT_Face     fFace;              // reference to shared face in gFaceRecHead
135    FT_Size     fFTSize;            // our own copy
136    SkFixed     fScaleX, fScaleY;
137    FT_Matrix   fMatrix22;
138    uint32_t    fLoadGlyphFlags;
139
140    FT_Error setupSize();
141    void emboldenOutline(FT_Outline* outline);
142};
143
144///////////////////////////////////////////////////////////////////////////
145///////////////////////////////////////////////////////////////////////////
146
147#include "SkStream.h"
148
149struct SkFaceRec {
150    SkFaceRec*      fNext;
151    FT_Face         fFace;
152    FT_StreamRec    fFTStream;
153    SkStream*       fSkStream;
154    uint32_t        fRefCnt;
155    uint32_t        fFontID;
156
157    // assumes ownership of the stream, will call unref() when its done
158    SkFaceRec(SkStream* strm, uint32_t fontID);
159    ~SkFaceRec() {
160        fSkStream->unref();
161    }
162};
163
164extern "C" {
165    static unsigned long sk_stream_read(FT_Stream       stream,
166                                        unsigned long   offset,
167                                        unsigned char*  buffer,
168                                        unsigned long   count ) {
169        SkStream* str = (SkStream*)stream->descriptor.pointer;
170
171        if (count) {
172            if (!str->rewind()) {
173                return 0;
174            } else {
175                unsigned long ret;
176                if (offset) {
177                    ret = str->read(NULL, offset);
178                    if (ret != offset) {
179                        return 0;
180                    }
181                }
182                ret = str->read(buffer, count);
183                if (ret != count) {
184                    return 0;
185                }
186                count = ret;
187            }
188        }
189        return count;
190    }
191
192    static void sk_stream_close( FT_Stream stream) {}
193}
194
195SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID)
196        : fSkStream(strm), fFontID(fontID) {
197//    SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm));
198
199    sk_bzero(&fFTStream, sizeof(fFTStream));
200    fFTStream.size = fSkStream->getLength();
201    fFTStream.descriptor.pointer = fSkStream;
202    fFTStream.read  = sk_stream_read;
203    fFTStream.close = sk_stream_close;
204}
205
206// Will return 0 on failure
207static SkFaceRec* ref_ft_face(uint32_t fontID) {
208    SkFaceRec* rec = gFaceRecHead;
209    while (rec) {
210        if (rec->fFontID == fontID) {
211            SkASSERT(rec->fFace);
212            rec->fRefCnt += 1;
213            return rec;
214        }
215        rec = rec->fNext;
216    }
217
218    SkStream* strm = SkFontHost::OpenStream(fontID);
219    if (NULL == strm) {
220        SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID));
221        return 0;
222    }
223
224    // this passes ownership of strm to the rec
225    rec = SkNEW_ARGS(SkFaceRec, (strm, fontID));
226
227    FT_Open_Args    args;
228    memset(&args, 0, sizeof(args));
229    const void* memoryBase = strm->getMemoryBase();
230
231    if (NULL != memoryBase) {
232//printf("mmap(%s)\n", keyString.c_str());
233        args.flags = FT_OPEN_MEMORY;
234        args.memory_base = (const FT_Byte*)memoryBase;
235        args.memory_size = strm->getLength();
236    } else {
237//printf("fopen(%s)\n", keyString.c_str());
238        args.flags = FT_OPEN_STREAM;
239        args.stream = &rec->fFTStream;
240    }
241
242    int face_index;
243    int length = SkFontHost::GetFileName(fontID, NULL, 0, &face_index);
244    FT_Error err = FT_Open_Face(gFTLibrary, &args, length ? face_index : 0,
245                                &rec->fFace);
246
247    if (err) {    // bad filename, try the default font
248        fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID);
249        SkDELETE(rec);
250        return 0;
251    } else {
252        SkASSERT(rec->fFace);
253        //fprintf(stderr, "Opened font '%s'\n", filename.c_str());
254        rec->fNext = gFaceRecHead;
255        gFaceRecHead = rec;
256        rec->fRefCnt = 1;
257        return rec;
258    }
259}
260
261static void unref_ft_face(FT_Face face) {
262    SkFaceRec*  rec = gFaceRecHead;
263    SkFaceRec*  prev = NULL;
264    while (rec) {
265        SkFaceRec* next = rec->fNext;
266        if (rec->fFace == face) {
267            if (--rec->fRefCnt == 0) {
268                if (prev) {
269                    prev->fNext = next;
270                } else {
271                    gFaceRecHead = next;
272                }
273                FT_Done_Face(face);
274                SkDELETE(rec);
275            }
276            return;
277        }
278        prev = rec;
279        rec = next;
280    }
281    SkASSERT("shouldn't get here, face not in list");
282}
283
284///////////////////////////////////////////////////////////////////////////
285
286#ifdef SK_SUPPORT_PDF
287static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
288    const FT_UInt glyph_id = FT_Get_Char_Index(face, letter);
289    if (!glyph_id)
290        return false;
291    FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE);
292    FT_Outline_Get_CBox(&face->glyph->outline, bbox);
293    return true;
294}
295
296int getWidthAdvance(FT_Face face, int gId, int scaleDivisor) {
297    FT_Fixed unscaledAdvance = 0;
298    SkAssertResult(FT_Get_Advance(face, gId, FT_LOAD_NO_SCALE,
299                   &unscaledAdvance) == 0);
300    return unscaledAdvance * 1000 / scaleDivisor;
301}
302
303template <typename Data>
304void resetRange(SkPDFTypefaceInfo::AdvanceMetric<Data>* range, int startId) {
305    range->fStartId = startId;
306    range->fAdvance.setCount(0);
307}
308
309template <typename Data>
310SkPDFTypefaceInfo::AdvanceMetric<Data>* appendRange(
311        SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> >* nextSlot,
312        int startId) {
313    nextSlot->reset(new SkPDFTypefaceInfo::AdvanceMetric<Data>);
314    resetRange(nextSlot->get(), startId);
315    return nextSlot->get();
316}
317
318template <typename Data>
319void finishRange(
320        SkPDFTypefaceInfo::AdvanceMetric<Data>* range,
321        int endId,
322        typename SkPDFTypefaceInfo::AdvanceMetric<Data>::MetricType type) {
323    range->fEndId = endId;
324    range->fType = type;
325    int newLength;
326    if (type == SkPDFTypefaceInfo::AdvanceMetric<Data>::kRange)
327        newLength = endId - range->fStartId + 1;
328    else
329        newLength = 1;
330    SkASSERT(range->fAdvance.count() >= newLength);
331    range->fAdvance.setCount(newLength);
332}
333
334template <typename Data>
335SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData(
336        FT_Face face,
337        int scaleDivisor,
338        Data (*getAdvance)(FT_Face face, int gId, int scaleDivisor)) {
339    // Assuming that an ASCII representation of a width or a glyph id is,
340    // on average, 3 characters long gives the following cut offs for
341    // using different range types:
342    // When currently in a range
343    //  - Removing 4 0's is a win
344    //  - Removing 5 repeats is a win
345    // When not currently in a range
346    //  - Removing 1 0 is a win
347    //  - Removing 3 repeats is a win
348
349    SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> > result;
350    SkPDFTypefaceInfo::AdvanceMetric<Data>* curRange;
351    curRange = appendRange(&result, 0);
352    int lastAdvance = INT_MIN;
353    int repeats = 0;
354    for (FT_UInt gId = 0; gId < face->num_glyphs; gId++) {
355        int advance = getAdvance(face, gId, scaleDivisor);
356        if (advance == lastAdvance) {
357            repeats++;
358        } else if (curRange->fAdvance.count() == repeats + 1) {
359            if (lastAdvance == 0 && repeats >= 0) {
360                resetRange(curRange, gId);
361            } else if (repeats >= 2) {
362                finishRange(curRange, gId - 1,
363                            SkPDFTypefaceInfo::WidthRange::kRun);
364                curRange = appendRange(&curRange->fNext, gId);
365            }
366            repeats = 0;
367        } else {
368            if (lastAdvance == 0 && repeats >= 3) {
369                finishRange(curRange, gId - repeats - 2,
370                            SkPDFTypefaceInfo::WidthRange::kRange);
371                curRange = appendRange(&curRange->fNext, gId);
372            } else if (repeats >= 4) {
373                finishRange(curRange, gId - repeats - 2,
374                            SkPDFTypefaceInfo::WidthRange::kRange);
375                curRange = appendRange(&curRange->fNext, gId - repeats - 1);
376                curRange->fAdvance.append(1, &lastAdvance);
377                finishRange(curRange, gId - 1,
378                            SkPDFTypefaceInfo::WidthRange::kRun);
379                curRange = appendRange(&curRange->fNext, gId);
380            }
381            repeats = 0;
382        }
383        curRange->fAdvance.append(1, &advance);
384        lastAdvance = advance;
385    }
386    finishRange(curRange, face->num_glyphs - 1,
387                SkPDFTypefaceInfo::WidthRange::kRange);
388    return result.release();
389}
390
391// static
392SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
393    SkAutoMutexAcquire ac(gFTMutex);
394    FT_Library libInit = NULL;
395    if (gFTCount == 0) {
396        if (!InitFreetype())
397            sk_throw();
398        libInit = gFTLibrary;
399    }
400    SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit);
401    SkFaceRec* rec = ref_ft_face(fontID);
402    if (NULL == rec)
403        return NULL;
404    FT_Face face = rec->fFace;
405
406    SkPDFTypefaceInfo* info = new SkPDFTypefaceInfo;
407    info->fMultiMaster = false;
408    bool cid = false;
409    int scaleDivisor = 1000;
410    const char* fontType = FT_Get_X11_Font_Format(face);
411    if (FT_Get_FSType_Flags(face) & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
412                                     FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) {
413        info->fType = SkPDFTypefaceInfo::kNotEmbeddable_Font;
414    } else if (FT_HAS_MULTIPLE_MASTERS(face)) {
415        // PDF requires that embedded MM fonts be reduced to a simple font.
416        info->fType = SkPDFTypefaceInfo::kOther_Font;
417    } else if (strcmp(fontType, "Type 1") == 0) {
418        info->fType = SkPDFTypefaceInfo::kType1_Font;
419    } else if (strcmp(fontType, "CID Type 1") == 0) {
420        info->fType = SkPDFTypefaceInfo::kType1CID_Font;
421        cid = true;
422    } else if (strcmp(fontType, "CFF") == 0) {
423        info->fType = SkPDFTypefaceInfo::kCFF_Font;
424    } else if (strcmp(fontType, "TrueType") == 0) {
425        info->fType = SkPDFTypefaceInfo::kTrueType_Font;
426        cid = true;
427        TT_Header* ttHeader;
428        if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face,
429                                                      ft_sfnt_head)) != NULL) {
430            scaleDivisor = ttHeader->Units_Per_EM;
431        }
432    }
433    info->fFontName.set(FT_Get_Postscript_Name(face));
434    SkASSERT(FT_IS_CID_KEYED(face) ==
435             (info->fType == SkPDFTypefaceInfo::kType1CID_Font));
436
437    if (info->fType == SkPDFTypefaceInfo::kOther_Font ||
438            info->fType == SkPDFTypefaceInfo::kNotEmbeddable_Font ||
439            !FT_IS_SCALABLE(face)) {
440        unref_ft_face(face);
441        return info;
442    }
443
444    info->fLastGlyphID = face->num_glyphs - 1;
445
446    SkASSERT(!FT_HAS_VERTICAL(face));
447
448    if (FT_IS_FIXED_WIDTH(face)) {
449        appendRange(&info->fGlyphWidths, 0);
450        int advance = face->max_advance_width * 1000 / scaleDivisor;
451        info->fGlyphWidths->fAdvance.append(1, &advance);
452        finishRange(info->fGlyphWidths.get(), 0,
453                    SkPDFTypefaceInfo::WidthRange::kDefault);
454    } else if(!cid) {
455        appendRange(&info->fGlyphWidths, 0);
456        // So as to not blow out the stack, get advances in batches.
457        for (int gIDStart = 0; gIDStart < face->num_glyphs; gIDStart += 128) {
458            FT_Fixed advances[128];
459            int advanceCount = 128;
460            if (gIDStart + advanceCount > face->num_glyphs)
461                advanceCount = face->num_glyphs - gIDStart + 1;
462            FT_Get_Advances(face, gIDStart, advanceCount, FT_LOAD_NO_SCALE,
463                            advances);
464            for (int i = 0; i < advanceCount; i++) {
465                int advance = advances[gIDStart + i];
466                info->fGlyphWidths->fAdvance.append(1, &advance);
467            }
468        }
469        finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
470                    SkPDFTypefaceInfo::WidthRange::kRange);
471    } else {
472        // For CID keyed fonts, an identity pdf-cmap is used, so we iterate and
473        // report on glyph ids, not character ids (tt-cmap indices).
474        info->fGlyphWidths.reset(getAdvanceData(face, scaleDivisor,
475                                                &getWidthAdvance));
476    }
477
478    if (info->fType == SkPDFTypefaceInfo::kType1_Font) {
479        // Postscript fonts may contain more than 255 glyphs, so we end up
480        // using multiple font descriptions with a glyph ordering.  Record
481        // the name of each glyph.
482        info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs));
483        for (FT_UInt gID = 0; gID < face->num_glyphs; gID++) {
484            char glyphName[128];  // Postscript limit for names is 127 bytes.
485            FT_Get_Glyph_Name(face, gID, glyphName, 128);
486            info->fGlyphNames->get()[gID].set(glyphName);
487        }
488    }
489
490    info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin * 1000 / scaleDivisor,
491                                    face->bbox.yMax * 1000 / scaleDivisor,
492                                    face->bbox.xMax * 1000 / scaleDivisor,
493                                    face->bbox.yMin * 1000 / scaleDivisor);
494    info->fStyle = 0;
495    if (FT_IS_FIXED_WIDTH(face))
496        info->fStyle |= SkPDFTypefaceInfo::kFixedPitch_Style;
497    if (face->style_flags & FT_STYLE_FLAG_ITALIC)
498        info->fStyle |= SkPDFTypefaceInfo::kItalic_Style;
499    // We should set either Symbolic or Nonsymbolic; Nonsymbolic if the font's
500    // character set is a subset of 'Adobe standard Latin.'
501    info->fStyle |= SkPDFTypefaceInfo::kSymbolic_Style;
502
503    TT_PCLT* pclt_info;
504    TT_OS2* os2_table;
505    if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) {
506        info->fCapHeight = pclt_info->CapHeight;
507        uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
508        if (serif_style >= 2 && serif_style <= 6)
509            info->fStyle |= SkPDFTypefaceInfo::kSerif_Style;
510        else if (serif_style >= 9 && serif_style <= 12)
511            info->fStyle |= SkPDFTypefaceInfo::kScript_Style;
512    } else if ((os2_table =
513                (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
514        info->fCapHeight = os2_table->sCapHeight;
515    } else {
516        // Figure out a good guess for CapHeight: average the height of M and X.
517        FT_BBox m_bbox, x_bbox;
518        bool got_m, got_x;
519        got_m = GetLetterCBox(face, 'M', &m_bbox);
520        got_x = GetLetterCBox(face, 'X', &x_bbox);
521        if (got_m && got_x) {
522            info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax -
523                    x_bbox.yMin) / 2;
524        } else if (got_m && !got_x) {
525            info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
526        } else if (!got_m && got_x) {
527            info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
528        }
529    }
530    info->fCapHeight = info->fCapHeight * 1000 / scaleDivisor;
531
532    // Figure out a good guess for StemV - Min width of i, I, !, 1.
533    // This probably isn't very good with an italic font.
534    int min_width = INT_MAX;
535    char stem_chars[] = {'i', 'I', '!', '1'};
536    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
537        FT_BBox bbox;
538        if (GetLetterCBox(face, stem_chars[i], &bbox)) {
539            int width = bbox.xMax - bbox.xMin;
540            if (width > 0 && width < min_width) {
541                min_width = width;
542                info->fStemV = min_width * 1000 / scaleDivisor;
543            }
544        }
545    }
546
547    PS_FontInfoRec ps_info;
548    TT_Postscript* tt_info;
549    if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
550        info->fItalicAngle = ps_info.italic_angle;
551    } else if ((tt_info =
552                (TT_Postscript*)FT_Get_Sfnt_Table(face,
553                                                  ft_sfnt_post)) != NULL) {
554        info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
555    } else {
556        info->fItalicAngle = 0;
557    }
558
559    info->fAscent = face->ascender * 1000 / scaleDivisor;
560    info->fDescent = face->descender * 1000 / scaleDivisor;
561
562    unref_ft_face(face);
563    return info;
564}
565#else
566SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
567    SkDebugf("--- GetPDFTypefaceInfo unimplemented\n");
568    return NULL;
569}
570#endif
571
572///////////////////////////////////////////////////////////////////////////
573
574void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
575    if (!gLCDSupportValid) {
576        InitFreetype();
577        FT_Done_FreeType(gFTLibrary);
578    }
579
580    if (!gLCDSupport && rec->isLCD()) {
581        // If the runtime Freetype library doesn't support LCD mode, we disable
582        // it here.
583        rec->fMaskFormat = SkMask::kA8_Format;
584    }
585
586    SkPaint::Hinting h = rec->getHinting();
587    if (SkPaint::kFull_Hinting == h && !rec->isLCD()) {
588        // collapse full->normal hinting if we're not doing LCD
589        h = SkPaint::kNormal_Hinting;
590    } else if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag) &&
591               SkPaint::kNo_Hinting != h) {
592        // to do subpixel, we must have at most slight hinting
593        h = SkPaint::kSlight_Hinting;
594    }
595    rec->setHinting(h);
596}
597
598SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
599        : SkScalerContext(desc) {
600    SkAutoMutexAcquire  ac(gFTMutex);
601
602    if (gFTCount == 0) {
603        if (!InitFreetype()) {
604            sk_throw();
605        }
606    }
607    ++gFTCount;
608
609    // load the font file
610    fFTSize = NULL;
611    fFace = NULL;
612    fFaceRec = ref_ft_face(fRec.fFontID);
613    if (NULL == fFaceRec) {
614        return;
615    }
616    fFace = fFaceRec->fFace;
617
618    // compute our factors from the record
619
620    SkMatrix    m;
621
622    fRec.getSingleMatrix(&m);
623
624#ifdef DUMP_STRIKE_CREATION
625    SkString     keyString;
626    SkFontHost::GetDescriptorKeyString(desc, &keyString);
627    printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
628           SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
629           SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
630           SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
631           fRec.getHinting(), fRec.fMaskFormat, keyString.c_str());
632#endif
633
634    //  now compute our scale factors
635    SkScalar    sx = m.getScaleX();
636    SkScalar    sy = m.getScaleY();
637
638    if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
639        // sort of give up on hinting
640        sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
641        sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
642        sx = sy = SkScalarAve(sx, sy);
643
644        SkScalar inv = SkScalarInvert(sx);
645
646        // flip the skew elements to go from our Y-down system to FreeType's
647        fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
648        fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
649        fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
650        fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
651    } else {
652        fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
653        fMatrix22.xy = fMatrix22.yx = 0;
654    }
655
656    fScaleX = SkScalarToFixed(sx);
657    fScaleY = SkScalarToFixed(sy);
658
659    // compute the flags we send to Load_Glyph
660    {
661        FT_Int32 loadFlags = FT_LOAD_DEFAULT;
662
663        if (SkMask::kBW_Format == fRec.fMaskFormat) {
664            // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
665            loadFlags = FT_LOAD_TARGET_MONO;
666            if (fRec.getHinting() == SkPaint::kNo_Hinting)
667                loadFlags = FT_LOAD_NO_HINTING;
668        } else {
669            switch (fRec.getHinting()) {
670            case SkPaint::kNo_Hinting:
671                loadFlags = FT_LOAD_NO_HINTING;
672                break;
673            case SkPaint::kSlight_Hinting:
674                loadFlags = FT_LOAD_TARGET_LIGHT;  // This implies FORCE_AUTOHINT
675                break;
676            case SkPaint::kNormal_Hinting:
677                if (fRec.fFlags & SkScalerContext::kAutohinting_Flag)
678                    loadFlags = FT_LOAD_FORCE_AUTOHINT;
679                else
680                    loadFlags = FT_LOAD_NO_AUTOHINT;
681                break;
682            case SkPaint::kFull_Hinting:
683                if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) {
684                    loadFlags = FT_LOAD_FORCE_AUTOHINT;
685                    break;
686                }
687                loadFlags = FT_LOAD_TARGET_NORMAL;
688                if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat)
689                    loadFlags = FT_LOAD_TARGET_LCD;
690                else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat)
691                    loadFlags = FT_LOAD_TARGET_LCD_V;
692                break;
693            default:
694                SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
695                break;
696            }
697        }
698
699        if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0)
700            loadFlags |= FT_LOAD_NO_BITMAP;
701
702        fLoadGlyphFlags = loadFlags;
703    }
704
705    // now create the FT_Size
706
707    {
708        FT_Error    err;
709
710        err = FT_New_Size(fFace, &fFTSize);
711        if (err != 0) {
712            SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n",
713                        fFaceRec->fFontID, fScaleX, fScaleY, err));
714            fFace = NULL;
715            return;
716        }
717
718        err = FT_Activate_Size(fFTSize);
719        if (err != 0) {
720            SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
721                        fFaceRec->fFontID, fScaleX, fScaleY, err));
722            fFTSize = NULL;
723        }
724
725        err = FT_Set_Char_Size( fFace,
726                                SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY),
727                                72, 72);
728        if (err != 0) {
729            SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
730                        fFaceRec->fFontID, fScaleX, fScaleY, err));
731            fFace = NULL;
732            return;
733        }
734
735        FT_Set_Transform( fFace, &fMatrix22, NULL);
736    }
737}
738
739SkScalerContext_FreeType::~SkScalerContext_FreeType() {
740    if (fFTSize != NULL) {
741        FT_Done_Size(fFTSize);
742    }
743
744    SkAutoMutexAcquire  ac(gFTMutex);
745
746    if (fFace != NULL) {
747        unref_ft_face(fFace);
748    }
749    if (--gFTCount == 0) {
750//        SkDEBUGF(("FT_Done_FreeType\n"));
751        FT_Done_FreeType(gFTLibrary);
752        SkDEBUGCODE(gFTLibrary = NULL;)
753    }
754}
755
756/*  We call this before each use of the fFace, since we may be sharing
757    this face with other context (at different sizes).
758*/
759FT_Error SkScalerContext_FreeType::setupSize() {
760    /*  In the off-chance that a font has been removed, we want to error out
761        right away, so call resolve just to be sure.
762
763        TODO: perhaps we can skip this, by walking the global font cache and
764        killing all of the contexts when we know that a given fontID is going
765        away...
766     */
767    if (!SkFontHost::ValidFontID(fRec.fFontID)) {
768        return (FT_Error)-1;
769    }
770
771    FT_Error    err = FT_Activate_Size(fFTSize);
772
773    if (err != 0) {
774        SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
775                    fFaceRec->fFontID, fScaleX, fScaleY, err));
776        fFTSize = NULL;
777    } else {
778        // seems we need to reset this every time (not sure why, but without it
779        // I get random italics from some other fFTSize)
780        FT_Set_Transform( fFace, &fMatrix22, NULL);
781    }
782    return err;
783}
784
785void SkScalerContext_FreeType::emboldenOutline(FT_Outline* outline) {
786    FT_Pos strength;
787    strength = FT_MulFix(fFace->units_per_EM, fFace->size->metrics.y_scale)
788               / 24;
789    FT_Outline_Embolden(outline, strength);
790}
791
792unsigned SkScalerContext_FreeType::generateGlyphCount() const {
793    return fFace->num_glyphs;
794}
795
796uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) {
797    return SkToU16(FT_Get_Char_Index( fFace, uni ));
798}
799
800SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) {
801    // iterate through each cmap entry, looking for matching glyph indices
802    FT_UInt glyphIndex;
803    SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex );
804
805    while (glyphIndex != 0) {
806        if (glyphIndex == glyph) {
807            return charCode;
808        }
809        charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex );
810    }
811
812    return 0;
813}
814
815static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
816    switch (format) {
817        case SkMask::kHorizontalLCD_Format:
818        case SkMask::kVerticalLCD_Format:
819            SkASSERT(!"An LCD format should never be passed here");
820            return FT_PIXEL_MODE_GRAY;
821        case SkMask::kBW_Format:
822            return FT_PIXEL_MODE_MONO;
823        case SkMask::kA8_Format:
824        default:
825            return FT_PIXEL_MODE_GRAY;
826    }
827}
828
829void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
830#ifdef FT_ADVANCES_H
831   /* unhinted and light hinted text have linearly scaled advances
832    * which are very cheap to compute with some font formats...
833    */
834    {
835        SkAutoMutexAcquire  ac(gFTMutex);
836
837        if (this->setupSize()) {
838            glyph->zeroMetrics();
839            return;
840        }
841
842        FT_Error    error;
843        FT_Fixed    advance;
844
845        error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount),
846                                fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
847                                &advance );
848        if (0 == error) {
849            glyph->fRsbDelta = 0;
850            glyph->fLsbDelta = 0;
851            glyph->fAdvanceX = advance;  // advance *2/3; //DEBUG
852            glyph->fAdvanceY = 0;
853            return;
854        }
855    }
856#endif /* FT_ADVANCES_H */
857    /* otherwise, we need to load/hint the glyph, which is slower */
858    this->generateMetrics(glyph);
859    return;
860}
861
862void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
863    SkAutoMutexAcquire  ac(gFTMutex);
864
865    glyph->fRsbDelta = 0;
866    glyph->fLsbDelta = 0;
867
868    FT_Error    err;
869
870    if (this->setupSize()) {
871        goto ERROR;
872    }
873
874    err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
875    if (err != 0) {
876        SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
877                    fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
878    ERROR:
879        glyph->zeroMetrics();
880        return;
881    }
882
883    switch ( fFace->glyph->format ) {
884      case FT_GLYPH_FORMAT_OUTLINE:
885        FT_BBox bbox;
886
887        if (fRec.fFlags & kEmbolden_Flag) {
888            emboldenOutline(&fFace->glyph->outline);
889        }
890        FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
891
892        if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
893            int dx = glyph->getSubXFixed() >> 10;
894            int dy = glyph->getSubYFixed() >> 10;
895            // negate dy since freetype-y-goes-up and skia-y-goes-down
896            bbox.xMin += dx;
897            bbox.yMin -= dy;
898            bbox.xMax += dx;
899            bbox.yMax -= dy;
900        }
901
902        bbox.xMin &= ~63;
903        bbox.yMin &= ~63;
904        bbox.xMax  = (bbox.xMax + 63) & ~63;
905        bbox.yMax  = (bbox.yMax + 63) & ~63;
906
907        glyph->fWidth   = SkToU16((bbox.xMax - bbox.xMin) >> 6);
908        glyph->fHeight  = SkToU16((bbox.yMax - bbox.yMin) >> 6);
909        glyph->fTop     = -SkToS16(bbox.yMax >> 6);
910        glyph->fLeft    = SkToS16(bbox.xMin >> 6);
911        break;
912
913      case FT_GLYPH_FORMAT_BITMAP:
914        if (fRec.fFlags & kEmbolden_Flag) {
915            FT_GlyphSlot_Own_Bitmap(fFace->glyph);
916            FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
917        }
918        glyph->fWidth   = SkToU16(fFace->glyph->bitmap.width);
919        glyph->fHeight  = SkToU16(fFace->glyph->bitmap.rows);
920        glyph->fTop     = -SkToS16(fFace->glyph->bitmap_top);
921        glyph->fLeft    = SkToS16(fFace->glyph->bitmap_left);
922        break;
923
924      default:
925        SkASSERT(!"unknown glyph format");
926        goto ERROR;
927    }
928
929    if ((fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) == 0) {
930        glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
931        glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
932        if (fRec.fFlags & kDevKernText_Flag) {
933            glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
934            glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
935        }
936    } else {
937        glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
938        glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
939    }
940
941#ifdef ENABLE_GLYPH_SPEW
942    SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
943    SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth));
944#endif
945}
946
947#if defined(SK_SUPPORT_LCDTEXT)
948namespace skia_freetype_support {
949// extern functions from SkFontHost_FreeType_Subpixel
950extern void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source);
951extern void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& source);
952}
953
954using namespace skia_freetype_support;
955#endif
956
957void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
958    SkAutoMutexAcquire  ac(gFTMutex);
959
960    FT_Error    err;
961
962    if (this->setupSize()) {
963        goto ERROR;
964    }
965
966    err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
967    if (err != 0) {
968        SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
969                    glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
970    ERROR:
971        memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
972        return;
973    }
974
975    const bool lcdRenderMode = fRec.fMaskFormat == SkMask::kHorizontalLCD_Format ||
976                               fRec.fMaskFormat == SkMask::kVerticalLCD_Format;
977
978    switch ( fFace->glyph->format ) {
979        case FT_GLYPH_FORMAT_OUTLINE: {
980            FT_Outline* outline = &fFace->glyph->outline;
981            FT_BBox     bbox;
982            FT_Bitmap   target;
983
984            if (fRec.fFlags & kEmbolden_Flag) {
985                emboldenOutline(outline);
986            }
987
988            int dx = 0, dy = 0;
989            if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
990                dx = glyph.getSubXFixed() >> 10;
991                dy = glyph.getSubYFixed() >> 10;
992                // negate dy since freetype-y-goes-up and skia-y-goes-down
993                dy = -dy;
994            }
995            FT_Outline_Get_CBox(outline, &bbox);
996            /*
997                what we really want to do for subpixel is
998                    offset(dx, dy)
999                    compute_bounds
1000                    offset(bbox & !63)
1001                but that is two calls to offset, so we do the following, which
1002                achieves the same thing with only one offset call.
1003            */
1004            FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
1005                                          dy - ((bbox.yMin + dy) & ~63));
1006
1007#if defined(SK_SUPPORT_LCDTEXT)
1008            if (lcdRenderMode) {
1009                // FT_Outline_Get_Bitmap cannot render LCD glyphs. In this case
1010                // we have to call FT_Render_Glyph and memcpy the image out.
1011                const bool isVertical = fRec.fMaskFormat == SkMask::kVerticalLCD_Format;
1012                FT_Render_Mode mode = isVertical ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD;
1013                FT_Render_Glyph(fFace->glyph, mode);
1014
1015                if (isVertical)
1016                    CopyFreetypeBitmapToVerticalLCDMask(glyph, fFace->glyph->bitmap);
1017                else
1018                    CopyFreetypeBitmapToLCDMask(glyph, fFace->glyph->bitmap);
1019
1020                break;
1021            }
1022#endif
1023
1024            target.width = glyph.fWidth;
1025            target.rows = glyph.fHeight;
1026            target.pitch = glyph.rowBytes();
1027            target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
1028            target.pixel_mode = compute_pixel_mode(
1029                                            (SkMask::Format)fRec.fMaskFormat);
1030            target.num_grays = 256;
1031
1032            memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
1033            FT_Outline_Get_Bitmap(gFTLibrary, outline, &target);
1034        } break;
1035
1036        case FT_GLYPH_FORMAT_BITMAP: {
1037            if (fRec.fFlags & kEmbolden_Flag) {
1038                FT_GlyphSlot_Own_Bitmap(fFace->glyph);
1039                FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
1040            }
1041            SkASSERT_CONTINUE(glyph.fWidth == fFace->glyph->bitmap.width);
1042            SkASSERT_CONTINUE(glyph.fHeight == fFace->glyph->bitmap.rows);
1043            SkASSERT_CONTINUE(glyph.fTop == -fFace->glyph->bitmap_top);
1044            SkASSERT_CONTINUE(glyph.fLeft == fFace->glyph->bitmap_left);
1045
1046            const uint8_t*  src = (const uint8_t*)fFace->glyph->bitmap.buffer;
1047            uint8_t*        dst = (uint8_t*)glyph.fImage;
1048
1049            if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ||
1050                (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO &&
1051                 glyph.fMaskFormat == SkMask::kBW_Format)) {
1052                unsigned    srcRowBytes = fFace->glyph->bitmap.pitch;
1053                unsigned    dstRowBytes = glyph.rowBytes();
1054                unsigned    minRowBytes = SkMin32(srcRowBytes, dstRowBytes);
1055                unsigned    extraRowBytes = dstRowBytes - minRowBytes;
1056
1057                for (int y = fFace->glyph->bitmap.rows - 1; y >= 0; --y) {
1058                    memcpy(dst, src, minRowBytes);
1059                    memset(dst + minRowBytes, 0, extraRowBytes);
1060                    src += srcRowBytes;
1061                    dst += dstRowBytes;
1062                }
1063            } else if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO &&
1064                       (glyph.fMaskFormat == SkMask::kA8_Format ||
1065                        glyph.fMaskFormat == SkMask::kHorizontalLCD_Format ||
1066                        glyph.fMaskFormat == SkMask::kVerticalLCD_Format)) {
1067                for (int y = 0; y < fFace->glyph->bitmap.rows; ++y) {
1068                    uint8_t byte = 0;
1069                    int bits = 0;
1070                    const uint8_t* src_row = src;
1071                    uint8_t* dst_row = dst;
1072
1073                    for (int x = 0; x < fFace->glyph->bitmap.width; ++x) {
1074                        if (!bits) {
1075                            byte = *src_row++;
1076                            bits = 8;
1077                        }
1078
1079                        *dst_row++ = byte & 0x80 ? 0xff : 0;
1080                        bits--;
1081                        byte <<= 1;
1082                    }
1083
1084                    src += fFace->glyph->bitmap.pitch;
1085                    dst += glyph.rowBytes();
1086                }
1087            } else {
1088              SkASSERT(!"unknown glyph bitmap transform needed");
1089            }
1090
1091            if (lcdRenderMode)
1092                glyph.expandA8ToLCD();
1093
1094        } break;
1095
1096    default:
1097        SkASSERT(!"unknown glyph format");
1098        goto ERROR;
1099    }
1100}
1101
1102///////////////////////////////////////////////////////////////////////////////
1103
1104#define ft2sk(x)    SkFixedToScalar((x) << 10)
1105
1106#if FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2
1107    #define CONST_PARAM const
1108#else   // older freetype doesn't use const here
1109    #define CONST_PARAM
1110#endif
1111
1112static int move_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
1113    SkPath* path = (SkPath*)ctx;
1114    path->close();  // to close the previous contour (if any)
1115    path->moveTo(ft2sk(pt->x), -ft2sk(pt->y));
1116    return 0;
1117}
1118
1119static int line_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
1120    SkPath* path = (SkPath*)ctx;
1121    path->lineTo(ft2sk(pt->x), -ft2sk(pt->y));
1122    return 0;
1123}
1124
1125static int quad_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
1126                     void* ctx) {
1127    SkPath* path = (SkPath*)ctx;
1128    path->quadTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), -ft2sk(pt1->y));
1129    return 0;
1130}
1131
1132static int cubic_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
1133                      CONST_PARAM FT_Vector* pt2, void* ctx) {
1134    SkPath* path = (SkPath*)ctx;
1135    path->cubicTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x),
1136                  -ft2sk(pt1->y), ft2sk(pt2->x), -ft2sk(pt2->y));
1137    return 0;
1138}
1139
1140void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
1141                                            SkPath* path) {
1142    SkAutoMutexAcquire  ac(gFTMutex);
1143
1144    SkASSERT(&glyph && path);
1145
1146    if (this->setupSize()) {
1147        path->reset();
1148        return;
1149    }
1150
1151    uint32_t flags = fLoadGlyphFlags;
1152    flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1153    flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1154
1155    FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags);
1156
1157    if (err != 0) {
1158        SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
1159                    glyph.getGlyphID(fBaseGlyphCount), flags, err));
1160        path->reset();
1161        return;
1162    }
1163
1164    if (fRec.fFlags & kEmbolden_Flag) {
1165        emboldenOutline(&fFace->glyph->outline);
1166    }
1167
1168    FT_Outline_Funcs    funcs;
1169
1170    funcs.move_to   = move_proc;
1171    funcs.line_to   = line_proc;
1172    funcs.conic_to  = quad_proc;
1173    funcs.cubic_to  = cubic_proc;
1174    funcs.shift     = 0;
1175    funcs.delta     = 0;
1176
1177    err = FT_Outline_Decompose(&fFace->glyph->outline, &funcs, path);
1178
1179    if (err != 0) {
1180        SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
1181                    glyph.getGlyphID(fBaseGlyphCount), flags, err));
1182        path->reset();
1183        return;
1184    }
1185
1186    path->close();
1187}
1188
1189void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
1190                                                   SkPaint::FontMetrics* my) {
1191    if (NULL == mx && NULL == my) {
1192        return;
1193    }
1194
1195    SkAutoMutexAcquire  ac(gFTMutex);
1196
1197    if (this->setupSize()) {
1198        ERROR:
1199        if (mx) {
1200            sk_bzero(mx, sizeof(SkPaint::FontMetrics));
1201        }
1202        if (my) {
1203            sk_bzero(my, sizeof(SkPaint::FontMetrics));
1204        }
1205        return;
1206    }
1207
1208    FT_Face face = fFace;
1209    int upem = face->units_per_EM;
1210    if (upem <= 0) {
1211        goto ERROR;
1212    }
1213
1214    SkPoint pts[6];
1215    SkFixed ys[6];
1216    SkFixed scaleY = fScaleY;
1217    SkFixed mxy = fMatrix22.xy;
1218    SkFixed myy = fMatrix22.yy;
1219    SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem;
1220    SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem;
1221
1222    int leading = face->height - (face->ascender + -face->descender);
1223    if (leading < 0) {
1224        leading = 0;
1225    }
1226
1227    // Try to get the OS/2 table from the font. This contains the specific
1228    // average font width metrics which Windows uses.
1229    TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1230
1231    ys[0] = -face->bbox.yMax;
1232    ys[1] = -face->ascender;
1233    ys[2] = -face->descender;
1234    ys[3] = -face->bbox.yMin;
1235    ys[4] = leading;
1236    ys[5] = os2 ? os2->xAvgCharWidth : 0;
1237
1238    SkScalar x_height;
1239    if (os2 && os2->sxHeight) {
1240        x_height = SkFixedToScalar(SkMulDiv(fScaleX, os2->sxHeight, upem));
1241    } else {
1242        const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x');
1243        if (x_glyph) {
1244            FT_BBox bbox;
1245            FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
1246            if (fRec.fFlags & kEmbolden_Flag) {
1247                emboldenOutline(&fFace->glyph->outline);
1248            }
1249            FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
1250            x_height = SkIntToScalar(bbox.yMax) / 64;
1251        } else {
1252            x_height = 0;
1253        }
1254    }
1255
1256    // convert upem-y values into scalar points
1257    for (int i = 0; i < 6; i++) {
1258        SkFixed y = SkMulDiv(scaleY, ys[i], upem);
1259        SkFixed x = SkFixedMul(mxy, y);
1260        y = SkFixedMul(myy, y);
1261        pts[i].set(SkFixedToScalar(x), SkFixedToScalar(y));
1262    }
1263
1264    if (mx) {
1265        mx->fTop = pts[0].fX;
1266        mx->fAscent = pts[1].fX;
1267        mx->fDescent = pts[2].fX;
1268        mx->fBottom = pts[3].fX;
1269        mx->fLeading = pts[4].fX;
1270        mx->fAvgCharWidth = pts[5].fX;
1271        mx->fXMin = xmin;
1272        mx->fXMax = xmax;
1273        mx->fXHeight = x_height;
1274    }
1275    if (my) {
1276        my->fTop = pts[0].fY;
1277        my->fAscent = pts[1].fY;
1278        my->fDescent = pts[2].fY;
1279        my->fBottom = pts[3].fY;
1280        my->fLeading = pts[4].fY;
1281        my->fAvgCharWidth = pts[5].fY;
1282        my->fXMin = xmin;
1283        my->fXMax = xmax;
1284        my->fXHeight = x_height;
1285    }
1286}
1287
1288////////////////////////////////////////////////////////////////////////
1289////////////////////////////////////////////////////////////////////////
1290
1291SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
1292    SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, (desc));
1293    if (!c->success()) {
1294        SkDELETE(c);
1295        c = NULL;
1296    }
1297    return c;
1298}
1299
1300///////////////////////////////////////////////////////////////////////////////
1301
1302/*  Export this so that other parts of our FonttHost port can make use of our
1303    ability to extract the name+style from a stream, using FreeType's api.
1304*/
1305SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name) {
1306    FT_Library  library;
1307    if (FT_Init_FreeType(&library)) {
1308        name->set(NULL);
1309        return SkTypeface::kNormal;
1310    }
1311
1312    FT_Open_Args    args;
1313    memset(&args, 0, sizeof(args));
1314
1315    const void* memoryBase = stream->getMemoryBase();
1316    FT_StreamRec    streamRec;
1317
1318    if (NULL != memoryBase) {
1319        args.flags = FT_OPEN_MEMORY;
1320        args.memory_base = (const FT_Byte*)memoryBase;
1321        args.memory_size = stream->getLength();
1322    } else {
1323        memset(&streamRec, 0, sizeof(streamRec));
1324        streamRec.size = stream->read(NULL, 0);
1325        streamRec.descriptor.pointer = stream;
1326        streamRec.read  = sk_stream_read;
1327        streamRec.close = sk_stream_close;
1328
1329        args.flags = FT_OPEN_STREAM;
1330        args.stream = &streamRec;
1331    }
1332
1333    FT_Face face;
1334    if (FT_Open_Face(library, &args, 0, &face)) {
1335        FT_Done_FreeType(library);
1336        name->set(NULL);
1337        return SkTypeface::kNormal;
1338    }
1339
1340    name->set(face->family_name);
1341    int style = SkTypeface::kNormal;
1342
1343    if (face->style_flags & FT_STYLE_FLAG_BOLD) {
1344        style |= SkTypeface::kBold;
1345    }
1346    if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
1347        style |= SkTypeface::kItalic;
1348    }
1349
1350    FT_Done_Face(face);
1351    FT_Done_FreeType(library);
1352    return (SkTypeface::Style)style;
1353}
1354