• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkScalerContext.h"
19 #include "SkBitmap.h"
20 #include "SkCanvas.h"
21 #include "SkDescriptor.h"
22 #include "SkFDot6.h"
23 #include "SkFontHost.h"
24 #include "SkMask.h"
25 #include "SkStream.h"
26 #include "SkString.h"
27 #include "SkThread.h"
28 #include "SkTemplates.h"
29 
30 #include <ft2build.h>
31 #include FT_FREETYPE_H
32 #include FT_OUTLINE_H
33 #include FT_SIZES_H
34 #ifdef   FT_ADVANCES_H
35 #include FT_ADVANCES_H
36 #endif
37 
38 //#define ENABLE_GLYPH_SPEW     // for tracing calls
39 //#define DUMP_STRIKE_CREATION
40 
41 #ifdef SK_DEBUG
42     #define SkASSERT_CONTINUE(pred)                                                         \
43         do {                                                                                \
44             if (!(pred))                                                                    \
45                 SkDebugf("file %s:%d: assert failed '" #pred "'\n", __FILE__, __LINE__);    \
46         } while (false)
47 #else
48     #define SkASSERT_CONTINUE(pred)
49 #endif
50 
51 //////////////////////////////////////////////////////////////////////////
52 
53 struct SkFaceRec;
54 
55 static SkMutex      gFTMutex;
56 static int          gFTCount;
57 static FT_Library   gFTLibrary;
58 static SkFaceRec*   gFaceRecHead;
59 
60 /////////////////////////////////////////////////////////////////////////
61 
62 class SkScalerContext_FreeType : public SkScalerContext {
63 public:
64     SkScalerContext_FreeType(const SkDescriptor* desc);
65     virtual ~SkScalerContext_FreeType();
66 
success() const67     bool success() const {
68         return fFaceRec != NULL && fFTSize != NULL;
69     }
70 
71 protected:
72     virtual unsigned generateGlyphCount() const;
73     virtual uint16_t generateCharToGlyph(SkUnichar uni);
74     virtual void generateAdvance(SkGlyph* glyph);
75     virtual void generateMetrics(SkGlyph* glyph);
76     virtual void generateImage(const SkGlyph& glyph);
77     virtual void generatePath(const SkGlyph& glyph, SkPath* path);
78     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
79                                      SkPaint::FontMetrics* my);
80 
81 private:
82     SkFaceRec*  fFaceRec;
83     FT_Face     fFace;              // reference to shared face in gFaceRecHead
84     FT_Size     fFTSize;            // our own copy
85     SkFixed     fScaleX, fScaleY;
86     FT_Matrix   fMatrix22;
87     uint32_t    fLoadGlyphFlags;
88 
89     FT_Error setupSize();
90 };
91 
92 ///////////////////////////////////////////////////////////////////////////
93 ///////////////////////////////////////////////////////////////////////////
94 
95 #include "SkStream.h"
96 
97 struct SkFaceRec {
98     SkFaceRec*      fNext;
99     FT_Face         fFace;
100     FT_StreamRec    fFTStream;
101     SkStream*       fSkStream;
102     uint32_t        fRefCnt;
103     uint32_t        fFontID;
104 
105     // assumes ownership of the stream, will call unref() when its done
106     SkFaceRec(SkStream* strm, uint32_t fontID);
~SkFaceRecSkFaceRec107     ~SkFaceRec() {
108         fSkStream->unref();
109     }
110 };
111 
112 extern "C" {
sk_stream_read(FT_Stream stream,unsigned long offset,unsigned char * buffer,unsigned long count)113     static unsigned long sk_stream_read(FT_Stream       stream,
114                                         unsigned long   offset,
115                                         unsigned char*  buffer,
116                                         unsigned long   count ) {
117         SkStream* str = (SkStream*)stream->descriptor.pointer;
118 
119         if (count) {
120             if (!str->rewind()) {
121                 return 0;
122             } else {
123                 unsigned long ret;
124                 if (offset) {
125                     ret = str->read(NULL, offset);
126                     if (ret != offset) {
127                         return 0;
128                     }
129                 }
130                 ret = str->read(buffer, count);
131                 if (ret != count) {
132                     return 0;
133                 }
134                 count = ret;
135             }
136         }
137         return count;
138     }
139 
sk_stream_close(FT_Stream stream)140     static void sk_stream_close( FT_Stream stream) {}
141 }
142 
SkFaceRec(SkStream * strm,uint32_t fontID)143 SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID)
144         : fSkStream(strm), fFontID(fontID) {
145 //    SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm));
146 
147     bzero(&fFTStream, sizeof(fFTStream));
148     fFTStream.size = fSkStream->getLength();
149     fFTStream.descriptor.pointer = fSkStream;
150     fFTStream.read  = sk_stream_read;
151     fFTStream.close = sk_stream_close;
152 }
153 
154 // Will return 0 on failure
ref_ft_face(uint32_t fontID)155 static SkFaceRec* ref_ft_face(uint32_t fontID) {
156     SkFaceRec* rec = gFaceRecHead;
157     while (rec) {
158         if (rec->fFontID == fontID) {
159             SkASSERT(rec->fFace);
160             rec->fRefCnt += 1;
161             return rec;
162         }
163         rec = rec->fNext;
164     }
165 
166     SkStream* strm = SkFontHost::OpenStream(fontID);
167     if (NULL == strm) {
168         SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID));
169         return 0;
170     }
171 
172     // this passes ownership of strm to the rec
173     rec = SkNEW_ARGS(SkFaceRec, (strm, fontID));
174 
175     FT_Open_Args    args;
176     memset(&args, 0, sizeof(args));
177     const void* memoryBase = strm->getMemoryBase();
178 
179     if (NULL != memoryBase) {
180 //printf("mmap(%s)\n", keyString.c_str());
181         args.flags = FT_OPEN_MEMORY;
182         args.memory_base = (const FT_Byte*)memoryBase;
183         args.memory_size = strm->getLength();
184     } else {
185 //printf("fopen(%s)\n", keyString.c_str());
186         args.flags = FT_OPEN_STREAM;
187         args.stream = &rec->fFTStream;
188     }
189 
190     FT_Error err = FT_Open_Face(gFTLibrary, &args, 0, &rec->fFace);
191 
192     if (err) {    // bad filename, try the default font
193         fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID);
194         SkDELETE(rec);
195         return 0;
196     } else {
197         SkASSERT(rec->fFace);
198         //fprintf(stderr, "Opened font '%s'\n", filename.c_str());
199         rec->fNext = gFaceRecHead;
200         gFaceRecHead = rec;
201         rec->fRefCnt = 1;
202         return rec;
203     }
204 }
205 
unref_ft_face(FT_Face face)206 static void unref_ft_face(FT_Face face) {
207     SkFaceRec*  rec = gFaceRecHead;
208     SkFaceRec*  prev = NULL;
209     while (rec) {
210         SkFaceRec* next = rec->fNext;
211         if (rec->fFace == face) {
212             if (--rec->fRefCnt == 0) {
213                 if (prev) {
214                     prev->fNext = next;
215                 } else {
216                     gFaceRecHead = next;
217                 }
218                 FT_Done_Face(face);
219                 SkDELETE(rec);
220             }
221             return;
222         }
223         prev = rec;
224         rec = next;
225     }
226     SkASSERT("shouldn't get here, face not in list");
227 }
228 
229 ///////////////////////////////////////////////////////////////////////////
230 
SkScalerContext_FreeType(const SkDescriptor * desc)231 SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
232         : SkScalerContext(desc) {
233     SkAutoMutexAcquire  ac(gFTMutex);
234 
235     FT_Error    err;
236 
237     if (gFTCount == 0) {
238         err = FT_Init_FreeType(&gFTLibrary);
239 //        SkDEBUGF(("FT_Init_FreeType returned %d\n", err));
240         SkASSERT(err == 0);
241     }
242     ++gFTCount;
243 
244     // load the font file
245     fFTSize = NULL;
246     fFace = NULL;
247     fFaceRec = ref_ft_face(fRec.fFontID);
248     if (NULL == fFaceRec) {
249         return;
250     }
251     fFace = fFaceRec->fFace;
252 
253     // compute our factors from the record
254 
255     SkMatrix    m;
256 
257     fRec.getSingleMatrix(&m);
258 
259 #ifdef DUMP_STRIKE_CREATION
260     SkString     keyString;
261     SkFontHost::GetDescriptorKeyString(desc, &keyString);
262     printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
263            SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
264            SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
265            SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
266            fRec.fHints, fRec.fMaskFormat, keyString.c_str());
267 #endif
268 
269     //  now compute our scale factors
270     SkScalar    sx = m.getScaleX();
271     SkScalar    sy = m.getScaleY();
272 
273     if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
274         // sort of give up on hinting
275         sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
276         sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
277         sx = sy = SkScalarAve(sx, sy);
278 
279         SkScalar inv = SkScalarInvert(sx);
280 
281         // flip the skew elements to go from our Y-down system to FreeType's
282         fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
283         fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
284         fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
285         fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
286     } else {
287         fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
288         fMatrix22.xy = fMatrix22.yx = 0;
289     }
290 
291     fScaleX = SkScalarToFixed(sx);
292     fScaleY = SkScalarToFixed(sy);
293 
294     // compute the flags we send to Load_Glyph
295     {
296         uint32_t flags = FT_LOAD_DEFAULT;
297         uint32_t render_flags = FT_LOAD_TARGET_NORMAL;
298 
299         // we force autohinting at the moment
300 
301         switch (fRec.fHints) {
302         case kNo_Hints:
303             flags |= FT_LOAD_NO_HINTING;
304             break;
305         case kSubpixel_Hints:
306             flags |= FT_LOAD_FORCE_AUTOHINT;
307             render_flags = FT_LOAD_TARGET_LIGHT;
308             break;
309         case kNormal_Hints:
310             flags |= FT_LOAD_FORCE_AUTOHINT;
311 #ifdef ANDROID
312             /*  Switch to light hinting (vertical only) to address some chars
313                 that behaved poorly with NORMAL. In the future we could consider
314                 making this choice exposed at runtime to the caller.
315             */
316             render_flags = FT_LOAD_TARGET_LIGHT;
317 #endif
318             break;
319         }
320 
321         if (SkMask::kBW_Format == fRec.fMaskFormat)
322             render_flags = FT_LOAD_TARGET_MONO;
323         else if (SkMask::kLCD_Format == fRec.fMaskFormat)
324             render_flags = FT_LOAD_TARGET_LCD;
325 
326         fLoadGlyphFlags = flags | render_flags;
327     }
328 
329     // now create the FT_Size
330 
331     {
332         FT_Error    err;
333 
334         err = FT_New_Size(fFace, &fFTSize);
335         if (err != 0) {
336             SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n",
337                         fFaceRec->fFontID, fScaleX, fScaleY, err));
338             fFace = NULL;
339             return;
340         }
341 
342         err = FT_Activate_Size(fFTSize);
343         if (err != 0) {
344             SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
345                         fFaceRec->fFontID, fScaleX, fScaleY, err));
346             fFTSize = NULL;
347         }
348 
349         err = FT_Set_Char_Size( fFace,
350                                 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY),
351                                 72, 72);
352         if (err != 0) {
353             SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
354                         fFaceRec->fFontID, fScaleX, fScaleY, err));
355             fFace = NULL;
356             return;
357         }
358 
359         FT_Set_Transform( fFace, &fMatrix22, NULL);
360     }
361 }
362 
~SkScalerContext_FreeType()363 SkScalerContext_FreeType::~SkScalerContext_FreeType() {
364     if (fFTSize != NULL) {
365         FT_Done_Size(fFTSize);
366     }
367 
368     SkAutoMutexAcquire  ac(gFTMutex);
369 
370     if (fFace != NULL) {
371         unref_ft_face(fFace);
372     }
373     if (--gFTCount == 0) {
374 //        SkDEBUGF(("FT_Done_FreeType\n"));
375         FT_Done_FreeType(gFTLibrary);
376         SkDEBUGCODE(gFTLibrary = NULL;)
377     }
378 }
379 
380 /*  We call this before each use of the fFace, since we may be sharing
381     this face with other context (at different sizes).
382 */
setupSize()383 FT_Error SkScalerContext_FreeType::setupSize() {
384     /*  In the off-chance that a font has been removed, we want to error out
385         right away, so call resolve just to be sure.
386 
387         TODO: perhaps we can skip this, by walking the global font cache and
388         killing all of the contexts when we know that a given fontID is going
389         away...
390      */
391     if (!SkFontHost::ValidFontID(fRec.fFontID)) {
392         return (FT_Error)-1;
393     }
394 
395     FT_Error    err = FT_Activate_Size(fFTSize);
396 
397     if (err != 0) {
398         SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
399                     fFaceRec->fFontID, fScaleX, fScaleY, err));
400         fFTSize = NULL;
401     } else {
402         // seems we need to reset this every time (not sure why, but without it
403         // I get random italics from some other fFTSize)
404         FT_Set_Transform( fFace, &fMatrix22, NULL);
405     }
406     return err;
407 }
408 
generateGlyphCount() const409 unsigned SkScalerContext_FreeType::generateGlyphCount() const {
410     return fFace->num_glyphs;
411 }
412 
generateCharToGlyph(SkUnichar uni)413 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) {
414     return SkToU16(FT_Get_Char_Index( fFace, uni ));
415 }
416 
compute_pixel_mode(SkMask::Format format)417 static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
418     switch (format) {
419         case SkMask::kBW_Format:
420             return FT_PIXEL_MODE_MONO;
421         case SkMask::kLCD_Format:
422             return FT_PIXEL_MODE_LCD;
423         case SkMask::kA8_Format:
424         default:
425             return FT_PIXEL_MODE_GRAY;
426     }
427 }
428 
generateAdvance(SkGlyph * glyph)429 void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
430 #ifdef FT_ADVANCES_H
431    /* unhinted and light hinted text have linearly scaled advances
432     * which are very cheap to compute with some font formats...
433     */
434     {
435         SkAutoMutexAcquire  ac(gFTMutex);
436 
437         if (this->setupSize()) {
438             glyph->zeroMetrics();
439             return;
440         }
441 
442         FT_Error    error;
443         FT_Fixed    advance;
444 
445         error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount),
446                                 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
447                                 &advance );
448         if (0 == error) {
449             glyph->fRsbDelta = 0;
450             glyph->fLsbDelta = 0;
451             glyph->fAdvanceX = advance;  // advance *2/3; //DEBUG
452             glyph->fAdvanceY = 0;
453             return;
454         }
455     }
456 #endif /* FT_ADVANCES_H */
457     /* otherwise, we need to load/hint the glyph, which is slower */
458     this->generateMetrics(glyph);
459     return;
460 }
461 
generateMetrics(SkGlyph * glyph)462 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
463     SkAutoMutexAcquire  ac(gFTMutex);
464 
465     glyph->fRsbDelta = 0;
466     glyph->fLsbDelta = 0;
467 
468     FT_Error    err;
469 
470     if (this->setupSize()) {
471         goto ERROR;
472     }
473 
474     err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
475     if (err != 0) {
476         SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
477                     fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
478     ERROR:
479         glyph->zeroMetrics();
480         return;
481     }
482 
483     switch ( fFace->glyph->format ) {
484       case FT_GLYPH_FORMAT_OUTLINE:
485         FT_BBox bbox;
486 
487         FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
488 
489         if (kSubpixel_Hints == fRec.fHints) {
490             int dx = glyph->getSubXFixed() >> 10;
491             int dy = glyph->getSubYFixed() >> 10;
492             // negate dy since freetype-y-goes-up and skia-y-goes-down
493             bbox.xMin += dx;
494             bbox.yMin -= dy;
495             bbox.xMax += dx;
496             bbox.yMax -= dy;
497         }
498 
499         bbox.xMin &= ~63;
500         bbox.yMin &= ~63;
501         bbox.xMax  = (bbox.xMax + 63) & ~63;
502         bbox.yMax  = (bbox.yMax + 63) & ~63;
503 
504         glyph->fWidth   = SkToU16((bbox.xMax - bbox.xMin) >> 6);
505         glyph->fHeight  = SkToU16((bbox.yMax - bbox.yMin) >> 6);
506         glyph->fTop     = -SkToS16(bbox.yMax >> 6);
507         glyph->fLeft    = SkToS16(bbox.xMin >> 6);
508         break;
509 
510       case FT_GLYPH_FORMAT_BITMAP:
511         glyph->fWidth   = SkToU16(fFace->glyph->bitmap.width);
512         glyph->fHeight  = SkToU16(fFace->glyph->bitmap.rows);
513         glyph->fTop     = -SkToS16(fFace->glyph->bitmap_top);
514         glyph->fLeft    = SkToS16(fFace->glyph->bitmap_left);
515         break;
516 
517       default:
518         SkASSERT(!"unknown glyph format");
519         goto ERROR;
520     }
521 
522     if (kNormal_Hints == fRec.fHints) {
523         glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
524         glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
525         if (fRec.fFlags & kDevKernText_Flag) {
526             glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
527             glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
528         }
529     } else {
530         glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
531         glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
532     }
533 
534 #ifdef ENABLE_GLYPH_SPEW
535     SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
536     SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth));
537 #endif
538 }
539 
generateImage(const SkGlyph & glyph)540 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
541     SkAutoMutexAcquire  ac(gFTMutex);
542 
543     FT_Error    err;
544 
545     if (this->setupSize()) {
546         goto ERROR;
547     }
548 
549     err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
550     if (err != 0) {
551         SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
552                     glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
553     ERROR:
554         memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
555         return;
556     }
557 
558     switch ( fFace->glyph->format ) {
559         case FT_GLYPH_FORMAT_OUTLINE: {
560             FT_Outline* outline = &fFace->glyph->outline;
561             FT_BBox     bbox;
562             FT_Bitmap   target;
563 
564             int dx = 0, dy = 0;
565             if (kSubpixel_Hints == fRec.fHints) {
566                 dx = glyph.getSubXFixed() >> 10;
567                 dy = glyph.getSubYFixed() >> 10;
568                 // negate dy since freetype-y-goes-up and skia-y-goes-down
569                 dy = -dy;
570             }
571             FT_Outline_Get_CBox(outline, &bbox);
572             /*
573                 what we really want to do for subpixel is
574                     offset(dx, dy)
575                     compute_bounds
576                     offset(bbox & !63)
577                 but that is two calls to offset, so we do the following, which
578                 achieves the same thing with only one offset call.
579             */
580             FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
581                                           dy - ((bbox.yMin + dy) & ~63));
582 
583             target.width = glyph.fWidth;
584             target.rows = glyph.fHeight;
585             target.pitch = glyph.rowBytes();
586             target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
587             target.pixel_mode = compute_pixel_mode(
588                                             (SkMask::Format)fRec.fMaskFormat);
589             target.num_grays = 256;
590 
591             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
592             FT_Outline_Get_Bitmap(gFTLibrary, outline, &target);
593         } break;
594 
595         case FT_GLYPH_FORMAT_BITMAP: {
596             SkASSERT_CONTINUE(glyph.fWidth == fFace->glyph->bitmap.width);
597             SkASSERT_CONTINUE(glyph.fHeight == fFace->glyph->bitmap.rows);
598             SkASSERT_CONTINUE(glyph.fTop == -fFace->glyph->bitmap_top);
599             SkASSERT_CONTINUE(glyph.fLeft == fFace->glyph->bitmap_left);
600 
601             const uint8_t*  src = (const uint8_t*)fFace->glyph->bitmap.buffer;
602             uint8_t*        dst = (uint8_t*)glyph.fImage;
603             unsigned    srcRowBytes = fFace->glyph->bitmap.pitch;
604             unsigned    dstRowBytes = glyph.rowBytes();
605             unsigned    minRowBytes = SkMin32(srcRowBytes, dstRowBytes);
606             unsigned    extraRowBytes = dstRowBytes - minRowBytes;
607 
608             for (int y = fFace->glyph->bitmap.rows - 1; y >= 0; --y) {
609                 memcpy(dst, src, minRowBytes);
610                 memset(dst + minRowBytes, 0, extraRowBytes);
611                 src += srcRowBytes;
612                 dst += dstRowBytes;
613             }
614         } break;
615 
616     default:
617         SkASSERT(!"unknown glyph format");
618         goto ERROR;
619     }
620 }
621 
622 ///////////////////////////////////////////////////////////////////////////////
623 
624 #define ft2sk(x)    SkFixedToScalar((x) << 10)
625 
626 #if FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2
627     #define CONST_PARAM const
628 #else   // older freetype doesn't use const here
629     #define CONST_PARAM
630 #endif
631 
move_proc(CONST_PARAM FT_Vector * pt,void * ctx)632 static int move_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
633     SkPath* path = (SkPath*)ctx;
634     path->close();  // to close the previous contour (if any)
635     path->moveTo(ft2sk(pt->x), -ft2sk(pt->y));
636     return 0;
637 }
638 
line_proc(CONST_PARAM FT_Vector * pt,void * ctx)639 static int line_proc(CONST_PARAM FT_Vector* pt, void* ctx) {
640     SkPath* path = (SkPath*)ctx;
641     path->lineTo(ft2sk(pt->x), -ft2sk(pt->y));
642     return 0;
643 }
644 
quad_proc(CONST_PARAM FT_Vector * pt0,CONST_PARAM FT_Vector * pt1,void * ctx)645 static int quad_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
646                      void* ctx) {
647     SkPath* path = (SkPath*)ctx;
648     path->quadTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), -ft2sk(pt1->y));
649     return 0;
650 }
651 
cubic_proc(CONST_PARAM FT_Vector * pt0,CONST_PARAM FT_Vector * pt1,CONST_PARAM FT_Vector * pt2,void * ctx)652 static int cubic_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1,
653                       CONST_PARAM FT_Vector* pt2, void* ctx) {
654     SkPath* path = (SkPath*)ctx;
655     path->cubicTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x),
656                   -ft2sk(pt1->y), ft2sk(pt2->x), -ft2sk(pt2->y));
657     return 0;
658 }
659 
generatePath(const SkGlyph & glyph,SkPath * path)660 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
661                                             SkPath* path) {
662     SkAutoMutexAcquire  ac(gFTMutex);
663 
664     SkASSERT(&glyph && path);
665 
666     if (this->setupSize()) {
667         path->reset();
668         return;
669     }
670 
671     uint32_t flags = fLoadGlyphFlags;
672     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
673     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
674 
675     FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags);
676 
677     if (err != 0) {
678         SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
679                     glyph.getGlyphID(fBaseGlyphCount), flags, err));
680         path->reset();
681         return;
682     }
683 
684     FT_Outline_Funcs    funcs;
685 
686     funcs.move_to   = move_proc;
687     funcs.line_to   = line_proc;
688     funcs.conic_to  = quad_proc;
689     funcs.cubic_to  = cubic_proc;
690     funcs.shift     = 0;
691     funcs.delta     = 0;
692 
693     err = FT_Outline_Decompose(&fFace->glyph->outline, &funcs, path);
694 
695     if (err != 0) {
696         SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
697                     glyph.getGlyphID(fBaseGlyphCount), flags, err));
698         path->reset();
699         return;
700     }
701 
702     path->close();
703 }
704 
generateFontMetrics(SkPaint::FontMetrics * mx,SkPaint::FontMetrics * my)705 void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
706                                                    SkPaint::FontMetrics* my) {
707     if (NULL == mx && NULL == my) {
708         return;
709     }
710 
711     SkAutoMutexAcquire  ac(gFTMutex);
712 
713     if (this->setupSize()) {
714         if (mx) {
715             bzero(mx, sizeof(SkPaint::FontMetrics));
716         }
717         if (my) {
718             bzero(my, sizeof(SkPaint::FontMetrics));
719         }
720         return;
721     }
722 
723     SkPoint pts[5];
724     SkFixed ys[5];
725     FT_Face face = fFace;
726     int     upem = face->units_per_EM;
727     SkFixed scaleY = fScaleY;
728     SkFixed mxy = fMatrix22.xy;
729     SkFixed myy = fMatrix22.yy;
730 
731     int leading = face->height - face->ascender + face->descender;
732     if (leading < 0) {
733         leading = 0;
734     }
735 
736     ys[0] = -face->bbox.yMax;
737     ys[1] = -face->ascender;
738     ys[2] = -face->descender;
739     ys[3] = -face->bbox.yMin;
740     ys[4] = leading;
741 
742     // convert upem-y values into scalar points
743     for (int i = 0; i < 5; i++) {
744         SkFixed y = SkMulDiv(scaleY, ys[i], upem);
745         SkFixed x = SkFixedMul(mxy, y);
746         y = SkFixedMul(myy, y);
747         pts[i].set(SkFixedToScalar(x), SkFixedToScalar(y));
748     }
749 
750     if (mx) {
751         mx->fTop = pts[0].fX;
752         mx->fAscent = pts[1].fX;
753         mx->fDescent = pts[2].fX;
754         mx->fBottom = pts[3].fX;
755         mx->fLeading = pts[4].fX;
756     }
757     if (my) {
758         my->fTop = pts[0].fY;
759         my->fAscent = pts[1].fY;
760         my->fDescent = pts[2].fY;
761         my->fBottom = pts[3].fY;
762         my->fLeading = pts[4].fY;
763     }
764 }
765 
766 ////////////////////////////////////////////////////////////////////////
767 ////////////////////////////////////////////////////////////////////////
768 
CreateScalerContext(const SkDescriptor * desc)769 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
770     SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, (desc));
771     if (!c->success()) {
772         SkDELETE(c);
773         c = NULL;
774     }
775     return c;
776 }
777 
778 ///////////////////////////////////////////////////////////////////////////////
779 
780 /*  Export this so that other parts of our FonttHost port can make use of our
781     ability to extract the name+style from a stream, using FreeType's api.
782 */
find_name_and_style(SkStream * stream,SkString * name)783 SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name) {
784     FT_Library  library;
785     if (FT_Init_FreeType(&library)) {
786         name->set(NULL);
787         return SkTypeface::kNormal;
788     }
789 
790     FT_Open_Args    args;
791     memset(&args, 0, sizeof(args));
792 
793     const void* memoryBase = stream->getMemoryBase();
794     FT_StreamRec    streamRec;
795 
796     if (NULL != memoryBase) {
797         args.flags = FT_OPEN_MEMORY;
798         args.memory_base = (const FT_Byte*)memoryBase;
799         args.memory_size = stream->getLength();
800     } else {
801         memset(&streamRec, 0, sizeof(streamRec));
802         streamRec.size = stream->read(NULL, 0);
803         streamRec.descriptor.pointer = stream;
804         streamRec.read  = sk_stream_read;
805         streamRec.close = sk_stream_close;
806 
807         args.flags = FT_OPEN_STREAM;
808         args.stream = &streamRec;
809     }
810 
811     FT_Face face;
812     if (FT_Open_Face(library, &args, 0, &face)) {
813         FT_Done_FreeType(library);
814         name->set(NULL);
815         return SkTypeface::kNormal;
816     }
817 
818     name->set(face->family_name);
819     int style = SkTypeface::kNormal;
820 
821     if (face->style_flags & FT_STYLE_FLAG_BOLD) {
822         style |= SkTypeface::kBold;
823     }
824     if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
825         style |= SkTypeface::kItalic;
826     }
827 
828     FT_Done_Face(face);
829     FT_Done_FreeType(library);
830     return (SkTypeface::Style)style;
831 }
832 
833