• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkBitmap.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkData.h"
11 #include "include/core/SkDrawable.h"
12 #include "include/core/SkFontMetrics.h"
13 #include "include/core/SkPath.h"
14 #include "include/core/SkStream.h"
15 #include "include/core/SkString.h"
16 #include "include/private/SkColorData.h"
17 #include "include/private/SkMalloc.h"
18 #include "include/private/SkMutex.h"
19 #include "include/private/SkTPin.h"
20 #include "include/private/SkTemplates.h"
21 #include "include/private/SkTo.h"
22 #include "src/core/SkAdvancedTypefaceMetrics.h"
23 #include "src/core/SkDescriptor.h"
24 #include "src/core/SkFDot6.h"
25 #include "src/core/SkFontDescriptor.h"
26 #include "src/core/SkGlyph.h"
27 #include "src/core/SkMask.h"
28 #include "src/core/SkMaskGamma.h"
29 #include "src/core/SkScalerContext.h"
30 #include "src/core/SkTSearch.h"
31 #include "src/ports/SkFontHost_FreeType_common.h"
32 #include "src/sfnt/SkOTUtils.h"
33 #include "src/utils/SkCallableTraits.h"
34 #include "src/utils/SkMatrix22.h"
35 
36 #include <memory>
37 #include <optional>
38 #include <tuple>
39 
40 #include <ft2build.h>
41 #include <freetype/ftadvanc.h>
42 #include <freetype/ftimage.h>
43 #include <freetype/ftbitmap.h>
44 #ifdef FT_COLOR_H  // 2.10.0
45 #   include <freetype/ftcolor.h>
46 #endif
47 #include <freetype/freetype.h>
48 #include <freetype/ftlcdfil.h>
49 #include <freetype/ftmodapi.h>
50 #include <freetype/ftmm.h>
51 #include <freetype/ftoutln.h>
52 #include <freetype/ftsizes.h>
53 #include <freetype/ftsystem.h>
54 #include <freetype/tttables.h>
55 #include <freetype/t1tables.h>
56 #include <freetype/ftfntfmt.h>
57 
58 // SK_FREETYPE_MINIMUM_RUNTIME_VERSION 0x<major><minor><patch><flags>
59 // Flag SK_FREETYPE_DLOPEN: also try dlopen to get newer features.
60 #define SK_FREETYPE_DLOPEN (0x1)
61 #ifndef SK_FREETYPE_MINIMUM_RUNTIME_VERSION
62 #  if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) || defined (SK_BUILD_FOR_GOOGLE3)
63 #    define SK_FREETYPE_MINIMUM_RUNTIME_VERSION (((FREETYPE_MAJOR) << 24) | ((FREETYPE_MINOR) << 16) | ((FREETYPE_PATCH) << 8))
64 #  else
65 #    define SK_FREETYPE_MINIMUM_RUNTIME_VERSION ((2 << 24) | (8 << 16) | (1 << 8) | (SK_FREETYPE_DLOPEN))
66 #  endif
67 #endif
68 #if SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN
69 #  include <dlfcn.h>
70 #endif
71 
72 #ifdef TT_SUPPORT_COLRV1
73 // FT_ClipBox and FT_Get_Color_Glyph_ClipBox introduced VER-2-11-0-18-g47cf8ebf4
74 // FT_COLR_COMPOSITE_PLUS and renumbering introduced VER-2-11-0-21-ge40ae7569
75 // FT_SIZEOF_LONG_LONG introduced VER-2-11-0-31-gffdac8d67
76 // FT_PaintRadialGradient changed size and layout at VER-2-11-0-147-gd3d3ff76d
77 // FT_STATIC_CAST introduced VER-2-11-0-172-g9079c5d91
78 // So undefine TT_SUPPORT_COLRV1 before 2.11.1 but not if FT_STATIC_CAST is defined.
79 #if (((FREETYPE_MAJOR)  < 2) || \
80      ((FREETYPE_MAJOR) == 2 && (FREETYPE_MINOR)  < 11) || \
81      ((FREETYPE_MAJOR) == 2 && (FREETYPE_MINOR) == 11 && (FREETYPE_PATCH) < 1)) && \
82     !defined(FT_STATIC_CAST)
83 #    undef TT_SUPPORT_COLRV1
84 #endif
85 #endif
86 
87 //#define ENABLE_GLYPH_SPEW     // for tracing calls
88 //#define DUMP_STRIKE_CREATION
89 //#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION
90 //#define SK_GAMMA_APPLY_TO_A8
91 
92 #if 1
93     #define LOG_INFO(...)
94 #else
95     #define LOG_INFO SkDEBUGF
96 #endif
97 
isLCD(const SkScalerContextRec & rec)98 static bool isLCD(const SkScalerContextRec& rec) {
99     return SkMask::kLCD16_Format == rec.fMaskFormat;
100 }
101 
SkFT_FixedToScalar(FT_Fixed x)102 static SkScalar SkFT_FixedToScalar(FT_Fixed x) {
103   return SkFixedToScalar(x);
104 }
105 
106 using SkUniqueFTFace =
107         std::unique_ptr<FT_FaceRec, SkFunctionWrapper<decltype(FT_Done_Face), FT_Done_Face>>;
108 
109 //////////////////////////////////////////////////////////////////////////
110 
111 using FT_Alloc_size_t = SkCallableTraits<FT_Alloc_Func>::argument<1>::type;
112 static_assert(std::is_same<FT_Alloc_size_t, long  >::value ||
113               std::is_same<FT_Alloc_size_t, size_t>::value,"");
114 
115 extern "C" {
sk_ft_alloc(FT_Memory,FT_Alloc_size_t size)116     static void* sk_ft_alloc(FT_Memory, FT_Alloc_size_t size) {
117         return sk_malloc_throw(size);
118     }
sk_ft_free(FT_Memory,void * block)119     static void sk_ft_free(FT_Memory, void* block) {
120         sk_free(block);
121     }
sk_ft_realloc(FT_Memory,FT_Alloc_size_t cur_size,FT_Alloc_size_t new_size,void * block)122     static void* sk_ft_realloc(FT_Memory, FT_Alloc_size_t cur_size,
123                                           FT_Alloc_size_t new_size, void* block) {
124         return sk_realloc_throw(block, new_size);
125     }
126 };
127 FT_MemoryRec_ gFTMemory = { nullptr, sk_ft_alloc, sk_ft_free, sk_ft_realloc };
128 
129 class FreeTypeLibrary : SkNoncopyable {
130 public:
FreeTypeLibrary()131     FreeTypeLibrary() : fLibrary(nullptr) {
132         if (FT_New_Library(&gFTMemory, &fLibrary)) {
133             return;
134         }
135         FT_Add_Default_Modules(fLibrary);
136         FT_Set_Default_Properties(fLibrary);
137 
138         // Subpixel anti-aliasing may be unfiltered until the LCD filter is set.
139         // Newer versions may still need this, so this test with side effects must come first.
140         // The default has changed over time, so this doesn't mean the same thing to all users.
141         FT_Library_SetLcdFilter(fLibrary, FT_LCD_FILTER_DEFAULT);
142     }
~FreeTypeLibrary()143     ~FreeTypeLibrary() {
144         if (fLibrary) {
145             FT_Done_Library(fLibrary);
146         }
147     }
148 
library()149     FT_Library library() { return fLibrary; }
150 
151 private:
152     FT_Library fLibrary;
153 
154     // FT_Library_SetLcdFilterWeights 2.4.0
155     // FT_LOAD_COLOR 2.5.0
156     // FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 2.5.0
157     // Thread safety in 2.6.0
158     // freetype/ftfntfmt.h (rename) 2.6.0
159     // Direct header inclusion 2.6.1
160     // FT_Get_Var_Design_Coordinates 2.7.1
161     // FT_LOAD_BITMAP_METRICS_ONLY 2.7.1
162     // FT_Set_Default_Properties 2.7.2
163     // The 'light' hinting is vertical only from 2.8.0
164     // FT_Get_Var_Axis_Flags 2.8.1
165     // FT_VAR_AXIS_FLAG_HIDDEN was introduced in FreeType 2.8.1
166     // --------------------
167     // FT_Done_MM_Var 2.9.0 (Currenty setting ft_free to a known allocator.)
168     // freetype/ftcolor.h 2.10.0 (Currently assuming if compiled with FT_COLOR_H runtime available.)
169 
170     // Ubuntu 18.04       2.8.1
171     // Debian 10          2.9.1
172     // openSUSE Leap 15.2 2.10.1
173     // Fedora 32          2.10.4
174     // RHEL 8             2.9.1
175 };
176 
f_t_mutex()177 static SkMutex& f_t_mutex() {
178     static SkMutex& mutex = *(new SkMutex);
179     return mutex;
180 }
181 
182 static FreeTypeLibrary* gFTLibrary;
183 
184 ///////////////////////////////////////////////////////////////////////////
185 
186 class SkTypeface_FreeType::FaceRec {
187 public:
188     SkUniqueFTFace fFace;
189     FT_StreamRec fFTStream;
190     std::unique_ptr<SkStreamAsset> fSkStream;
191     FT_UShort fFTPaletteEntryCount = 0;
192     std::unique_ptr<SkColor[]> fSkPalette;
193 
194     static std::unique_ptr<FaceRec> Make(const SkTypeface_FreeType* typeface);
195     ~FaceRec();
196 
197 private:
198     FaceRec(std::unique_ptr<SkStreamAsset> stream);
199     void setupAxes(const SkFontData& data);
200     void setupPalette(const SkFontData& data);
201 
202     // Private to ref_ft_library and unref_ft_library
203     static int gFTCount;
204 
205     // Caller must lock f_t_mutex() before calling this function.
ref_ft_library()206     static bool ref_ft_library() {
207         f_t_mutex().assertHeld();
208         SkASSERT(gFTCount >= 0);
209 
210         if (0 == gFTCount) {
211             SkASSERT(nullptr == gFTLibrary);
212             gFTLibrary = new FreeTypeLibrary;
213         }
214         ++gFTCount;
215         return gFTLibrary->library();
216     }
217 
218     // Caller must lock f_t_mutex() before calling this function.
unref_ft_library()219     static void unref_ft_library() {
220         f_t_mutex().assertHeld();
221         SkASSERT(gFTCount > 0);
222 
223         --gFTCount;
224         if (0 == gFTCount) {
225             SkASSERT(nullptr != gFTLibrary);
226             delete gFTLibrary;
227             SkDEBUGCODE(gFTLibrary = nullptr;)
228         }
229     }
230 };
231 int SkTypeface_FreeType::FaceRec::gFTCount;
232 
233 extern "C" {
sk_ft_stream_io(FT_Stream ftStream,unsigned long offset,unsigned char * buffer,unsigned long count)234     static unsigned long sk_ft_stream_io(FT_Stream ftStream,
235                                          unsigned long offset,
236                                          unsigned char* buffer,
237                                          unsigned long count)
238     {
239         SkStreamAsset* stream = static_cast<SkStreamAsset*>(ftStream->descriptor.pointer);
240 
241         if (count) {
242             if (!stream->seek(offset)) {
243                 return 0;
244             }
245             count = stream->read(buffer, count);
246         }
247         return count;
248     }
249 
sk_ft_stream_close(FT_Stream)250     static void sk_ft_stream_close(FT_Stream) {}
251 }
252 
FaceRec(std::unique_ptr<SkStreamAsset> stream)253 SkTypeface_FreeType::FaceRec::FaceRec(std::unique_ptr<SkStreamAsset> stream)
254         : fSkStream(std::move(stream))
255 {
256     sk_bzero(&fFTStream, sizeof(fFTStream));
257     fFTStream.size = fSkStream->getLength();
258     fFTStream.descriptor.pointer = fSkStream.get();
259     fFTStream.read  = sk_ft_stream_io;
260     fFTStream.close = sk_ft_stream_close;
261 
262     f_t_mutex().assertHeld();
263     ref_ft_library();
264 }
265 
~FaceRec()266 SkTypeface_FreeType::FaceRec::~FaceRec() {
267     f_t_mutex().assertHeld();
268     fFace.reset(); // Must release face before the library, the library frees existing faces.
269     unref_ft_library();
270 }
271 
setupAxes(const SkFontData & data)272 void SkTypeface_FreeType::FaceRec::setupAxes(const SkFontData& data) {
273     if (!(fFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
274         return;
275     }
276 
277     // If a named variation is requested, don't overwrite the named variation's position.
278     if (data.getIndex() > 0xFFFF) {
279         return;
280     }
281 
282     SkDEBUGCODE(
283         FT_MM_Var* variations = nullptr;
284         if (FT_Get_MM_Var(fFace.get(), &variations)) {
285             LOG_INFO("INFO: font %s claims variations, but none found.\n",
286                      rec->fFace->family_name);
287             return;
288         }
289         SkAutoFree autoFreeVariations(variations);
290 
291         if (static_cast<FT_UInt>(data.getAxisCount()) != variations->num_axis) {
292             LOG_INFO("INFO: font %s has %d variations, but %d were specified.\n",
293                      rec->fFace->family_name, variations->num_axis, data.getAxisCount());
294             return;
295         }
296     )
297 
298     SkAutoSTMalloc<4, FT_Fixed> coords(data.getAxisCount());
299     for (int i = 0; i < data.getAxisCount(); ++i) {
300         coords[i] = data.getAxis()[i];
301     }
302     if (FT_Set_Var_Design_Coordinates(fFace.get(), data.getAxisCount(), coords.get())) {
303         LOG_INFO("INFO: font %s has variations, but specified variations could not be set.\n",
304                  rec->fFace->family_name);
305         return;
306     }
307 }
308 
setupPalette(const SkFontData & data)309 void SkTypeface_FreeType::FaceRec::setupPalette(const SkFontData& data) {
310 #ifdef FT_COLOR_H
311     FT_Palette_Data paletteData;
312     if (FT_Palette_Data_Get(fFace.get(), &paletteData)) {
313         return;
314     }
315     if (paletteData.num_palettes < data.getPaletteIndex() ) {
316         return;
317     }
318     FT_Color* ftPalette = nullptr;
319     if (FT_Palette_Select(fFace.get(), data.getPaletteIndex(), &ftPalette)) {
320         return;
321     }
322     fFTPaletteEntryCount = paletteData.num_palette_entries;
323 
324     for (int i = 0; i < data.getPaletteOverrideCount(); ++i) {
325         const SkFontArguments::Palette::Override& paletteOverride = data.getPaletteOverrides()[i];
326         if (paletteOverride.index < 0 || fFTPaletteEntryCount <= paletteOverride.index) {
327             continue;
328         }
329         const SkColor& skColor = paletteOverride.color;
330         FT_Color& ftColor = ftPalette[paletteOverride.index];
331         ftColor.blue  = SkColorGetB(skColor);
332         ftColor.green = SkColorGetG(skColor);
333         ftColor.red   = SkColorGetR(skColor);
334         ftColor.alpha = SkColorGetA(skColor);
335     }
336 
337     fSkPalette.reset(new SkColor[fFTPaletteEntryCount]);
338     for (int i = 0; i < fFTPaletteEntryCount; ++i) {
339         fSkPalette[i] = SkColorSetARGB(ftPalette[i].alpha,
340                                        ftPalette[i].red,
341                                        ftPalette[i].green,
342                                        ftPalette[i].blue);
343     }
344 #endif
345 }
346 
347 // Will return nullptr on failure
348 // Caller must lock f_t_mutex() before calling this function.
349 std::unique_ptr<SkTypeface_FreeType::FaceRec>
Make(const SkTypeface_FreeType * typeface)350 SkTypeface_FreeType::FaceRec::Make(const SkTypeface_FreeType* typeface) {
351     f_t_mutex().assertHeld();
352 
353     std::unique_ptr<SkFontData> data = typeface->makeFontData();
354     if (nullptr == data || !data->hasStream()) {
355         return nullptr;
356     }
357 
358     std::unique_ptr<FaceRec> rec(new FaceRec(data->detachStream()));
359 
360     FT_Open_Args args;
361     memset(&args, 0, sizeof(args));
362     const void* memoryBase = rec->fSkStream->getMemoryBase();
363     if (memoryBase) {
364         args.flags = FT_OPEN_MEMORY;
365         args.memory_base = (const FT_Byte*)memoryBase;
366         args.memory_size = rec->fSkStream->getLength();
367     } else {
368         args.flags = FT_OPEN_STREAM;
369         args.stream = &rec->fFTStream;
370     }
371 
372     {
373         FT_Face rawFace;
374         FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, data->getIndex(), &rawFace);
375         if (err) {
376             SK_TRACEFTR(err, "unable to open font '%x'", typeface->uniqueID());
377             return nullptr;
378         }
379         rec->fFace.reset(rawFace);
380     }
381     SkASSERT(rec->fFace);
382 
383     rec->setupAxes(*data);
384     rec->setupPalette(*data);
385 
386     // FreeType will set the charmap to the "most unicode" cmap if it exists.
387     // If there are no unicode cmaps, the charmap is set to nullptr.
388     // However, "symbol" cmaps should also be considered "fallback unicode" cmaps
389     // because they are effectively private use area only (even if they aren't).
390     // This is the last on the fallback list at
391     // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html
392     if (!rec->fFace->charmap) {
393         FT_Select_Charmap(rec->fFace.get(), FT_ENCODING_MS_SYMBOL);
394     }
395 
396     return rec;
397 }
398 
399 class AutoFTAccess {
400 public:
AutoFTAccess(const SkTypeface_FreeType * tf)401     AutoFTAccess(const SkTypeface_FreeType* tf) : fFaceRec(nullptr) {
402         f_t_mutex().acquire();
403         fFaceRec = tf->getFaceRec();
404     }
405 
~AutoFTAccess()406     ~AutoFTAccess() {
407         f_t_mutex().release();
408     }
409 
face()410     FT_Face face() { return fFaceRec ? fFaceRec->fFace.get() : nullptr; }
411 
412 private:
413     SkTypeface_FreeType::FaceRec* fFaceRec;
414 };
415 
416 ///////////////////////////////////////////////////////////////////////////
417 
418 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base {
419 public:
420     SkScalerContext_FreeType(sk_sp<SkTypeface_FreeType>,
421                              const SkScalerContextEffects&,
422                              const SkDescriptor* desc);
423     ~SkScalerContext_FreeType() override;
424 
success() const425     bool success() const {
426         return fFTSize != nullptr && fFace != nullptr;
427     }
428 
429 protected:
430     bool generateAdvance(SkGlyph* glyph) override;
431     void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override;
432     void generateImage(const SkGlyph& glyph) override;
433     bool generatePath(const SkGlyph& glyph, SkPath* path) override;
434     sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
435     void generateFontMetrics(SkFontMetrics*) override;
436 
437 private:
438     SkTypeface_FreeType::FaceRec* fFaceRec; // Borrowed face from the typeface's FaceRec.
439     FT_Face   fFace;  // Borrowed face from fFaceRec.
440     FT_Size   fFTSize;  // The size to apply to the fFace.
441     FT_Int    fStrikeIndex; // The bitmap strike for the fFace (or -1 if none).
442 
443     /** The rest of the matrix after FreeType handles the size.
444      *  With outline font rasterization this is handled by FreeType with FT_Set_Transform.
445      *  With bitmap only fonts this matrix must be applied to scale the bitmap.
446      */
447     SkMatrix  fMatrix22Scalar;
448     /** Same as fMatrix22Scalar, but in FreeType units and space. */
449     FT_Matrix fMatrix22;
450     /** The actual size requested. */
451     SkVector  fScale;
452 
453     uint32_t  fLoadGlyphFlags;
454     bool      fDoLinearMetrics;
455     bool      fLCDIsVert;
456 
457     FT_Error setupSize();
458     void getBBoxForCurrentGlyph(const SkGlyph* glyph, FT_BBox* bbox,
459                                 bool snapToPixelBoundary = false);
460     bool getCBoxForLetter(char letter, FT_BBox* bbox);
461     // Caller must lock f_t_mutex() before calling this function.
462     void updateGlyphIfLCD(SkGlyph* glyph);
463     // Caller must lock f_t_mutex() before calling this function.
464     // update FreeType2 glyph slot with glyph emboldened
465     void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid);
466     bool shouldSubpixelBitmap(const SkGlyph&, const SkMatrix&);
467 };
468 
469 ///////////////////////////////////////////////////////////////////////////
470 
canEmbed(FT_Face face)471 static bool canEmbed(FT_Face face) {
472     FT_UShort fsType = FT_Get_FSType_Flags(face);
473     return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
474                       FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0;
475 }
476 
canSubset(FT_Face face)477 static bool canSubset(FT_Face face) {
478     FT_UShort fsType = FT_Get_FSType_Flags(face);
479     return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0;
480 }
481 
get_font_type(FT_Face face)482 static SkAdvancedTypefaceMetrics::FontType get_font_type(FT_Face face) {
483     const char* fontType = FT_Get_X11_Font_Format(face);
484     static struct { const char* s; SkAdvancedTypefaceMetrics::FontType t; } values[] = {
485         { "Type 1",     SkAdvancedTypefaceMetrics::kType1_Font    },
486         { "CID Type 1", SkAdvancedTypefaceMetrics::kType1CID_Font },
487         { "CFF",        SkAdvancedTypefaceMetrics::kCFF_Font      },
488         { "TrueType",   SkAdvancedTypefaceMetrics::kTrueType_Font },
489     };
490     for(const auto& v : values) { if (strcmp(fontType, v.s) == 0) { return v.t; } }
491     return SkAdvancedTypefaceMetrics::kOther_Font;
492 }
493 
onGetAdvancedMetrics() const494 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMetrics() const {
495     AutoFTAccess fta(this);
496     FT_Face face = fta.face();
497     if (!face) {
498         return nullptr;
499     }
500 
501     std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
502     info->fPostScriptName.set(FT_Get_Postscript_Name(face));
503     info->fFontName = info->fPostScriptName;
504 
505     if (FT_HAS_MULTIPLE_MASTERS(face)) {
506         info->fFlags |= SkAdvancedTypefaceMetrics::kVariable_FontFlag;
507     }
508     if (!canEmbed(face)) {
509         info->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag;
510     }
511     if (!canSubset(face)) {
512         info->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag;
513     }
514 
515     info->fType = get_font_type(face);
516     info->fStyle = (SkAdvancedTypefaceMetrics::StyleFlags)0;
517     if (FT_IS_FIXED_WIDTH(face)) {
518         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
519     }
520     if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
521         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
522     }
523 
524     PS_FontInfoRec psFontInfo;
525     TT_Postscript* postTable;
526     if (FT_Get_PS_Font_Info(face, &psFontInfo) == 0) {
527         info->fItalicAngle = psFontInfo.italic_angle;
528     } else if ((postTable = (TT_Postscript*)FT_Get_Sfnt_Table(face, ft_sfnt_post)) != nullptr) {
529         info->fItalicAngle = SkFixedFloorToInt(postTable->italicAngle);
530     } else {
531         info->fItalicAngle = 0;
532     }
533 
534     info->fAscent = face->ascender;
535     info->fDescent = face->descender;
536 
537     TT_PCLT* pcltTable;
538     TT_OS2* os2Table;
539     if ((pcltTable = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr) {
540         info->fCapHeight = pcltTable->CapHeight;
541         uint8_t serif_style = pcltTable->SerifStyle & 0x3F;
542         if (2 <= serif_style && serif_style <= 6) {
543             info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
544         } else if (9 <= serif_style && serif_style <= 12) {
545             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
546         }
547     } else if (((os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nullptr) &&
548                // sCapHeight is available only when version 2 or later.
549                os2Table->version != 0xFFFF &&
550                os2Table->version >= 2)
551     {
552         info->fCapHeight = os2Table->sCapHeight;
553     }
554     info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
555                                     face->bbox.xMax, face->bbox.yMin);
556     return info;
557 }
558 
getGlyphToUnicodeMap(SkUnichar * dstArray) const559 void SkTypeface_FreeType::getGlyphToUnicodeMap(SkUnichar* dstArray) const {
560     AutoFTAccess fta(this);
561     FT_Face face = fta.face();
562     if (!face) {
563         return;
564     }
565 
566     FT_Long numGlyphs = face->num_glyphs;
567     if (!dstArray) { SkASSERT(numGlyphs == 0); }
568     sk_bzero(dstArray, sizeof(SkUnichar) * numGlyphs);
569 
570     FT_UInt glyphIndex;
571     SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
572     while (glyphIndex) {
573         SkASSERT(glyphIndex < SkToUInt(numGlyphs));
574         // Use the first character that maps to this glyphID. https://crbug.com/359065
575         if (0 == dstArray[glyphIndex]) {
576             dstArray[glyphIndex] = charCode;
577         }
578         charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
579     }
580 }
581 
getPostScriptGlyphNames(SkString * dstArray) const582 void SkTypeface_FreeType::getPostScriptGlyphNames(SkString* dstArray) const {
583     AutoFTAccess fta(this);
584     FT_Face face = fta.face();
585     if (!face) {
586         return;
587     }
588 
589     FT_Long numGlyphs = face->num_glyphs;
590     if (!dstArray) { SkASSERT(numGlyphs == 0); }
591 
592     if (FT_HAS_GLYPH_NAMES(face)) {
593         for (int gID = 0; gID < numGlyphs; ++gID) {
594             char glyphName[128];  // PS limit for names is 127 bytes.
595             FT_Get_Glyph_Name(face, gID, glyphName, 128);
596             dstArray[gID] = glyphName;
597         }
598     }
599 }
600 
onGetPostScriptName(SkString * skPostScriptName) const601 bool SkTypeface_FreeType::onGetPostScriptName(SkString* skPostScriptName) const {
602     AutoFTAccess fta(this);
603     FT_Face face = fta.face();
604     if (!face) {
605         return false;
606     }
607 
608     const char* ftPostScriptName = FT_Get_Postscript_Name(face);
609     if (!ftPostScriptName) {
610         return false;
611     }
612     if (skPostScriptName) {
613         *skPostScriptName = ftPostScriptName;
614     }
615     return true;
616 }
617 
618 ///////////////////////////////////////////////////////////////////////////
619 
bothZero(SkScalar a,SkScalar b)620 static bool bothZero(SkScalar a, SkScalar b) {
621     return 0 == a && 0 == b;
622 }
623 
624 // returns false if there is any non-90-rotation or skew
isAxisAligned(const SkScalerContextRec & rec)625 static bool isAxisAligned(const SkScalerContextRec& rec) {
626     return 0 == rec.fPreSkewX &&
627            (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
628             bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
629 }
630 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const631 std::unique_ptr<SkScalerContext> SkTypeface_FreeType::onCreateScalerContext(
632     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
633 {
634     auto c = std::make_unique<SkScalerContext_FreeType>(
635             sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
636     if (c->success()) {
637         return std::move(c);
638     }
639     return SkScalerContext::MakeEmpty(
640             sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
641 }
642 
643 /** Copy the design variation coordinates into 'coordinates'.
644  *
645  *  @param coordinates the buffer into which to write the design variation coordinates.
646  *  @param coordinateCount the number of entries available through 'coordinates'.
647  *
648  *  @return The number of axes, or -1 if there is an error.
649  *  If 'coordinates != nullptr' and 'coordinateCount >= numAxes' then 'coordinates' will be
650  *  filled with the variation coordinates describing the position of this typeface in design
651  *  variation space. It is possible the number of axes can be retrieved but actual position
652  *  cannot.
653  */
GetVariationDesignPosition(AutoFTAccess & fta,SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount)654 static int GetVariationDesignPosition(AutoFTAccess& fta,
655     SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount)
656 {
657     FT_Face face = fta.face();
658     if (!face) {
659         return -1;
660     }
661 
662     if (!(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
663         return 0;
664     }
665 
666     FT_MM_Var* variations = nullptr;
667     if (FT_Get_MM_Var(face, &variations)) {
668         return -1;
669     }
670     SkAutoFree autoFreeVariations(variations);
671 
672     if (!coordinates || coordinateCount < SkToInt(variations->num_axis)) {
673         return variations->num_axis;
674     }
675 
676     SkAutoSTMalloc<4, FT_Fixed> coords(variations->num_axis);
677     if (FT_Get_Var_Design_Coordinates(face, variations->num_axis, coords.get())) {
678         return -1;
679     }
680     for (FT_UInt i = 0; i < variations->num_axis; ++i) {
681         coordinates[i].axis = variations->axis[i].tag;
682         coordinates[i].value = SkFixedToScalar(coords[i]);
683     }
684 
685     return variations->num_axis;
686 }
687 
cloneFontData(const SkFontArguments & args) const688 std::unique_ptr<SkFontData> SkTypeface_FreeType::cloneFontData(const SkFontArguments& args) const {
689     AutoFTAccess fta(this);
690     FT_Face face = fta.face();
691     if (!face) {
692         return nullptr;
693     }
694 
695     Scanner::AxisDefinitions axisDefinitions;
696     if (!Scanner::GetAxes(face, &axisDefinitions)) {
697         return nullptr;
698     }
699     int axisCount = axisDefinitions.count();
700 
701     SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> currentPosition(axisCount);
702     int currentAxisCount = GetVariationDesignPosition(fta, currentPosition, axisCount);
703 
704     SkString name;
705     SkAutoSTMalloc<4, SkFixed> axisValues(axisCount);
706     Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(), axisValues, name,
707                                currentAxisCount == axisCount ? currentPosition.get() : nullptr);
708 
709     int ttcIndex;
710     std::unique_ptr<SkStreamAsset> stream = this->openStream(&ttcIndex);
711 
712     return std::make_unique<SkFontData>(std::move(stream),
713                                         ttcIndex,
714                                         args.getPalette().index,
715                                         axisValues.get(),
716                                         axisCount,
717                                         args.getPalette().overrides,
718                                         args.getPalette().overrideCount);
719 }
720 
onFilterRec(SkScalerContextRec * rec) const721 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const {
722     //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119
723     //Cap the requested size as larger sizes give bogus values.
724     //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed.
725     //Note that this also currently only protects against large text size requests,
726     //the total matrix is not taken into account here.
727     if (rec->fTextSize > SkIntToScalar(1 << 14)) {
728         rec->fTextSize = SkIntToScalar(1 << 14);
729     }
730 
731     SkFontHinting h = rec->getHinting();
732     if (SkFontHinting::kFull == h && !isLCD(*rec)) {
733         // collapse full->normal hinting if we're not doing LCD
734         h = SkFontHinting::kNormal;
735     }
736 
737     // rotated text looks bad with hinting, so we disable it as needed
738     if (!isAxisAligned(*rec)) {
739         h = SkFontHinting::kNone;
740     }
741     rec->setHinting(h);
742 
743 #ifndef SK_GAMMA_APPLY_TO_A8
744     if (!isLCD(*rec)) {
745         // SRGBTODO: Is this correct? Do we want contrast boost?
746         rec->ignorePreBlend();
747     }
748 #endif
749 }
750 
GetUnitsPerEm(FT_Face face)751 int SkTypeface_FreeType::GetUnitsPerEm(FT_Face face) {
752     SkASSERT(face);
753 
754     SkScalar upem = SkIntToScalar(face->units_per_EM);
755     // At least some versions of FreeType set face->units_per_EM to 0 for bitmap only fonts.
756     if (upem == 0) {
757         TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
758         if (ttHeader) {
759             upem = SkIntToScalar(ttHeader->Units_Per_EM);
760         }
761     }
762     return upem;
763 }
764 
onGetUPEM() const765 int SkTypeface_FreeType::onGetUPEM() const {
766     AutoFTAccess fta(this);
767     FT_Face face = fta.face();
768     if (!face) {
769         return 0;
770     }
771     return GetUnitsPerEm(face);
772 }
773 
onGetKerningPairAdjustments(const uint16_t glyphs[],int count,int32_t adjustments[]) const774 bool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[],
775                                       int count, int32_t adjustments[]) const {
776     AutoFTAccess fta(this);
777     FT_Face face = fta.face();
778     if (!face || !FT_HAS_KERNING(face)) {
779         return false;
780     }
781 
782     for (int i = 0; i < count - 1; ++i) {
783         FT_Vector delta;
784         FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1],
785                                       FT_KERNING_UNSCALED, &delta);
786         if (err) {
787             return false;
788         }
789         adjustments[i] = delta.x;
790     }
791     return true;
792 }
793 
794 /** Returns the bitmap strike equal to or just larger than the requested size. */
chooseBitmapStrike(FT_Face face,FT_F26Dot6 scaleY)795 static FT_Int chooseBitmapStrike(FT_Face face, FT_F26Dot6 scaleY) {
796     if (face == nullptr) {
797         LOG_INFO("chooseBitmapStrike aborted due to nullptr face.\n");
798         return -1;
799     }
800 
801     FT_Pos requestedPPEM = scaleY;  // FT_Bitmap_Size::y_ppem is in 26.6 format.
802     FT_Int chosenStrikeIndex = -1;
803     FT_Pos chosenPPEM = 0;
804     for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) {
805         FT_Pos strikePPEM = face->available_sizes[strikeIndex].y_ppem;
806         if (strikePPEM == requestedPPEM) {
807             // exact match - our search stops here
808             return strikeIndex;
809         } else if (chosenPPEM < requestedPPEM) {
810             // attempt to increase chosenPPEM
811             if (chosenPPEM < strikePPEM) {
812                 chosenPPEM = strikePPEM;
813                 chosenStrikeIndex = strikeIndex;
814             }
815         } else {
816             // attempt to decrease chosenPPEM, but not below requestedPPEM
817             if (requestedPPEM < strikePPEM && strikePPEM < chosenPPEM) {
818                 chosenPPEM = strikePPEM;
819                 chosenStrikeIndex = strikeIndex;
820             }
821         }
822     }
823     return chosenStrikeIndex;
824 }
825 
SkScalerContext_FreeType(sk_sp<SkTypeface_FreeType> typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc)826 SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface_FreeType> typeface,
827                                                    const SkScalerContextEffects& effects,
828                                                    const SkDescriptor* desc)
829     : SkScalerContext_FreeType_Base(std::move(typeface), effects, desc)
830     , fFace(nullptr)
831     , fFTSize(nullptr)
832     , fStrikeIndex(-1)
833 {
834     SkAutoMutexExclusive  ac(f_t_mutex());
835     fFaceRec = static_cast<SkTypeface_FreeType*>(this->getTypeface())->getFaceRec();
836 
837     // load the font file
838     if (nullptr == fFaceRec) {
839         LOG_INFO("Could not create FT_Face.\n");
840         return;
841     }
842 
843     fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
844 
845     // compute the flags we send to Load_Glyph
846     bool linearMetrics = this->isLinearMetrics();
847     {
848         FT_Int32 loadFlags = FT_LOAD_DEFAULT;
849 
850         if (SkMask::kBW_Format == fRec.fMaskFormat) {
851             // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
852             loadFlags = FT_LOAD_TARGET_MONO;
853             if (fRec.getHinting() == SkFontHinting::kNone) {
854                 loadFlags = FT_LOAD_NO_HINTING;
855                 linearMetrics = true;
856             }
857         } else {
858             switch (fRec.getHinting()) {
859             case SkFontHinting::kNone:
860                 loadFlags = FT_LOAD_NO_HINTING;
861                 linearMetrics = true;
862                 break;
863             case SkFontHinting::kSlight:
864                 loadFlags = FT_LOAD_TARGET_LIGHT;  // This implies FORCE_AUTOHINT
865                 linearMetrics = true;
866                 break;
867             case SkFontHinting::kNormal:
868                 loadFlags = FT_LOAD_TARGET_NORMAL;
869                 break;
870             case SkFontHinting::kFull:
871                 loadFlags = FT_LOAD_TARGET_NORMAL;
872                 if (isLCD(fRec)) {
873                     if (fLCDIsVert) {
874                         loadFlags = FT_LOAD_TARGET_LCD_V;
875                     } else {
876                         loadFlags = FT_LOAD_TARGET_LCD;
877                     }
878                 }
879                 break;
880             default:
881                 LOG_INFO("---------- UNKNOWN hinting %d\n", fRec.getHinting());
882                 break;
883             }
884         }
885 
886         if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
887             loadFlags |= FT_LOAD_FORCE_AUTOHINT;
888 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
889         } else {
890             loadFlags |= FT_LOAD_NO_AUTOHINT;
891 #endif
892         }
893 
894         if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
895             loadFlags |= FT_LOAD_NO_BITMAP;
896         }
897 
898         // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
899         // advances, as fontconfig and cairo do.
900         // See http://code.google.com/p/skia/issues/detail?id=222.
901         loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
902 
903         // Use vertical layout if requested.
904         if (this->isVertical()) {
905             loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
906         }
907 
908         loadFlags |= FT_LOAD_COLOR;
909 
910         fLoadGlyphFlags = loadFlags;
911     }
912 
913     using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
914     std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([this]() -> FT_Size {
915         FT_Size size;
916         FT_Error err = FT_New_Size(fFaceRec->fFace.get(), &size);
917         if (err != 0) {
918             SK_TRACEFTR(err, "FT_New_Size(%s) failed.", fFaceRec->fFace->family_name);
919             return nullptr;
920         }
921         return size;
922     }());
923     if (nullptr == ftSize) {
924         LOG_INFO("Could not create FT_Size.\n");
925         return;
926     }
927 
928     FT_Error err = FT_Activate_Size(ftSize.get());
929     if (err != 0) {
930         SK_TRACEFTR(err, "FT_Activate_Size(%s) failed.", fFaceRec->fFace->family_name);
931         return;
932     }
933 
934     fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMatrix22Scalar);
935     FT_F26Dot6 scaleX = SkScalarToFDot6(fScale.fX);
936     FT_F26Dot6 scaleY = SkScalarToFDot6(fScale.fY);
937 
938     if (FT_IS_SCALABLE(fFaceRec->fFace)) {
939         err = FT_Set_Char_Size(fFaceRec->fFace.get(), scaleX, scaleY, 72, 72);
940         if (err != 0) {
941             SK_TRACEFTR(err, "FT_Set_CharSize(%s, %f, %f) failed.",
942                         fFaceRec->fFace->family_name, fScale.fX, fScale.fY);
943             return;
944         }
945 
946         // Adjust the matrix to reflect the actually chosen scale.
947         // FreeType currently does not allow requesting sizes less than 1, this allow for scaling.
948         // Don't do this at all sizes as that will interfere with hinting.
949         if (fScale.fX < 1 || fScale.fY < 1) {
950             SkScalar upem = fFaceRec->fFace->units_per_EM;
951             FT_Size_Metrics& ftmetrics = fFaceRec->fFace->size->metrics;
952             SkScalar x_ppem = upem * SkFT_FixedToScalar(ftmetrics.x_scale) / 64.0f;
953             SkScalar y_ppem = upem * SkFT_FixedToScalar(ftmetrics.y_scale) / 64.0f;
954             fMatrix22Scalar.preScale(fScale.x() / x_ppem, fScale.y() / y_ppem);
955         }
956 
957     } else if (FT_HAS_FIXED_SIZES(fFaceRec->fFace)) {
958         fStrikeIndex = chooseBitmapStrike(fFaceRec->fFace.get(), scaleY);
959         if (fStrikeIndex == -1) {
960             LOG_INFO("No glyphs for font \"%s\" size %f.\n",
961                      fFaceRec->fFace->family_name, fScale.fY);
962             return;
963         }
964 
965         err = FT_Select_Size(fFaceRec->fFace.get(), fStrikeIndex);
966         if (err != 0) {
967             SK_TRACEFTR(err, "FT_Select_Size(%s, %d) failed.",
968                         fFaceRec->fFace->family_name, fStrikeIndex);
969             fStrikeIndex = -1;
970             return;
971         }
972 
973         // Adjust the matrix to reflect the actually chosen scale.
974         // It is likely that the ppem chosen was not the one requested, this allows for scaling.
975         fMatrix22Scalar.preScale(fScale.x() / fFaceRec->fFace->size->metrics.x_ppem,
976                                  fScale.y() / fFaceRec->fFace->size->metrics.y_ppem);
977 
978         // FreeType does not provide linear metrics for bitmap fonts.
979         linearMetrics = false;
980 
981         // FreeType documentation says:
982         // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading.
983         // Bitmap-only fonts ignore this flag.
984         //
985         // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag.
986         // Force this flag off for bitmap only fonts.
987         fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP;
988     } else {
989         LOG_INFO("Unknown kind of font \"%s\" size %f.\n", fFaceRec->fFace->family_name, fScale.fY);
990         return;
991     }
992 
993     fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX());
994     fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX());
995     fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY());
996     fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
997 
998     fFTSize = ftSize.release();
999     fFace = fFaceRec->fFace.get();
1000     fDoLinearMetrics = linearMetrics;
1001 }
1002 
~SkScalerContext_FreeType()1003 SkScalerContext_FreeType::~SkScalerContext_FreeType() {
1004     SkAutoMutexExclusive  ac(f_t_mutex());
1005 
1006     if (fFTSize != nullptr) {
1007         FT_Done_Size(fFTSize);
1008     }
1009 
1010     fFaceRec = nullptr;
1011 }
1012 
1013 /*  We call this before each use of the fFace, since we may be sharing
1014     this face with other context (at different sizes).
1015 */
setupSize()1016 FT_Error SkScalerContext_FreeType::setupSize() {
1017     f_t_mutex().assertHeld();
1018     FT_Error err = FT_Activate_Size(fFTSize);
1019     if (err != 0) {
1020         return err;
1021     }
1022     FT_Set_Transform(fFace, &fMatrix22, nullptr);
1023     return 0;
1024 }
1025 
generateAdvance(SkGlyph * glyph)1026 bool SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
1027    /* unhinted and light hinted text have linearly scaled advances
1028     * which are very cheap to compute with some font formats...
1029     */
1030     if (!fDoLinearMetrics) {
1031         return false;
1032     }
1033 
1034     SkAutoMutexExclusive  ac(f_t_mutex());
1035 
1036     if (this->setupSize()) {
1037         glyph->zeroMetrics();
1038         return true;
1039     }
1040 
1041     FT_Error    error;
1042     FT_Fixed    advance;
1043 
1044     error = FT_Get_Advance( fFace, glyph->getGlyphID(),
1045                             fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
1046                             &advance );
1047 
1048     if (error != 0) {
1049         return false;
1050     }
1051 
1052     const SkScalar advanceScalar = SkFT_FixedToScalar(advance);
1053     glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar);
1054     glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar);
1055     return true;
1056 }
1057 
getBBoxForCurrentGlyph(const SkGlyph * glyph,FT_BBox * bbox,bool snapToPixelBoundary)1058 void SkScalerContext_FreeType::getBBoxForCurrentGlyph(const SkGlyph* glyph,
1059                                                       FT_BBox* bbox,
1060                                                       bool snapToPixelBoundary) {
1061 
1062     FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
1063 
1064     if (this->isSubpixel()) {
1065         int dx = SkFixedToFDot6(glyph->getSubXFixed());
1066         int dy = SkFixedToFDot6(glyph->getSubYFixed());
1067         // negate dy since freetype-y-goes-up and skia-y-goes-down
1068         bbox->xMin += dx;
1069         bbox->yMin -= dy;
1070         bbox->xMax += dx;
1071         bbox->yMax -= dy;
1072     }
1073 
1074     // outset the box to integral boundaries
1075     if (snapToPixelBoundary) {
1076         bbox->xMin &= ~63;
1077         bbox->yMin &= ~63;
1078         bbox->xMax  = (bbox->xMax + 63) & ~63;
1079         bbox->yMax  = (bbox->yMax + 63) & ~63;
1080     }
1081 
1082     // Must come after snapToPixelBoundary so that the width and height are
1083     // consistent. Otherwise asserts will fire later on when generating the
1084     // glyph image.
1085     if (this->isVertical()) {
1086         FT_Vector vector;
1087         vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1088         vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1089         FT_Vector_Transform(&vector, &fMatrix22);
1090         bbox->xMin += vector.x;
1091         bbox->xMax += vector.x;
1092         bbox->yMin += vector.y;
1093         bbox->yMax += vector.y;
1094     }
1095 }
1096 
getCBoxForLetter(char letter,FT_BBox * bbox)1097 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
1098     const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter);
1099     if (!glyph_id) {
1100         return false;
1101     }
1102     if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) {
1103         return false;
1104     }
1105     emboldenIfNeeded(fFace, fFace->glyph, SkTo<SkGlyphID>(glyph_id));
1106     FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
1107     return true;
1108 }
1109 
updateGlyphIfLCD(SkGlyph * glyph)1110 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
1111     if (glyph->fMaskFormat == SkMask::kLCD16_Format) {
1112         if (fLCDIsVert) {
1113             glyph->fHeight += 2;
1114             glyph->fTop -= 1;
1115         } else {
1116             glyph->fWidth += 2;
1117             glyph->fLeft -= 1;
1118         }
1119     }
1120 }
1121 
shouldSubpixelBitmap(const SkGlyph & glyph,const SkMatrix & matrix)1122 bool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const SkMatrix& matrix) {
1123     // If subpixel rendering of a bitmap *can* be done.
1124     bool mechanism = fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP &&
1125                      this->isSubpixel() &&
1126                      (glyph.getSubXFixed() || glyph.getSubYFixed());
1127 
1128     // If subpixel rendering of a bitmap *should* be done.
1129     // 1. If the face is not scalable then always allow subpixel rendering.
1130     //    Otherwise, if the font has an 8ppem strike 7 will subpixel render but 8 won't.
1131     // 2. If the matrix is already not identity the bitmap will already be resampled,
1132     //    so resampling slightly differently shouldn't make much difference.
1133     bool policy = !FT_IS_SCALABLE(fFace) || !matrix.isIdentity();
1134 
1135     return mechanism && policy;
1136 }
1137 
generateMetrics(SkGlyph * glyph,SkArenaAlloc * alloc)1138 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) {
1139     SkAutoMutexExclusive  ac(f_t_mutex());
1140 
1141     if (this->setupSize()) {
1142         glyph->zeroMetrics();
1143         return;
1144     }
1145 
1146     FT_Error    err;
1147     err = FT_Load_Glyph( fFace, glyph->getGlyphID(),
1148                          fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY );
1149     if (err != 0) {
1150         glyph->zeroMetrics();
1151         return;
1152     }
1153     emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID());
1154 
1155     if (fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1156         using FT_PosLimits = std::numeric_limits<FT_Pos>;
1157         FT_BBox bounds = { FT_PosLimits::max(), FT_PosLimits::max(),
1158                            FT_PosLimits::min(), FT_PosLimits::min() };
1159 #ifdef FT_COLOR_H
1160         FT_Bool haveLayers = false;
1161         FT_LayerIterator layerIterator = { 0, 0, nullptr };
1162         FT_UInt layerGlyphIndex;
1163         FT_UInt layerColorIndex;
1164 
1165 #ifdef TT_SUPPORT_COLRV1
1166         FT_OpaquePaint opaqueLayerPaint;
1167         opaqueLayerPaint.p = nullptr;
1168         if (FT_Get_Color_Glyph_Paint(fFace, glyph->getGlyphID(),
1169                                      FT_COLOR_INCLUDE_ROOT_TRANSFORM, &opaqueLayerPaint)) {
1170             haveLayers = true;
1171 
1172             FT_ClipBox colrGlyphBbox;
1173 
1174             // COLRv1 optionally provides a ClipBox that we can use for allocation.
1175             if (FT_Get_Color_Glyph_ClipBox(fFace, glyph->getGlyphID(), &colrGlyphBbox)) {
1176                 // Find enclosing bounding box of clip box corner points, needed
1177                 // when clipbox is transformed.
1178                 bounds.xMin = colrGlyphBbox.bottom_left.x;
1179                 bounds.xMax = colrGlyphBbox.bottom_left.x;
1180                 bounds.yMin = colrGlyphBbox.bottom_left.y;
1181                 bounds.yMax = colrGlyphBbox.bottom_left.y;
1182 
1183                 for (auto& corner : {colrGlyphBbox.top_left,
1184                                      colrGlyphBbox.top_right,
1185                                      colrGlyphBbox.bottom_right}) {
1186                     if (corner.x < bounds.xMin) {
1187                         bounds.xMin = corner.x;
1188                     }
1189                     if (corner.y < bounds.yMin) {
1190                         bounds.yMin = corner.y;
1191                     }
1192                     if (corner.x > bounds.xMax) {
1193                         bounds.xMax = corner.x;
1194                     }
1195                     if (corner.y > bounds.yMax) {
1196                         bounds.yMax = corner.y;
1197                     }
1198                 }
1199           } else {
1200               // Otherwise we need to traverse the glyph graph with a focus on measuring the
1201               // required bounding box.
1202               FT_BBox computed_bounds;
1203               if (!computeColrV1GlyphBoundingBox(fFace, glyph->getGlyphID(), &computed_bounds)) {
1204                   glyph->zeroMetrics();
1205                   return;
1206               }
1207 
1208               // Reset face so the main glyph slot contains information about the
1209               // base glyph again, for usage for computing and copying horizontal
1210               // metrics from FreeType to Skia below.
1211               if (this->setupSize()) {
1212                   glyph->zeroMetrics();
1213                   return;
1214               }
1215 
1216               err = FT_Load_Glyph(
1217                       fFace, glyph->getGlyphID(), fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
1218               if (err != 0) {
1219                   glyph->zeroMetrics();
1220                   return;
1221               }
1222 
1223               bounds = computed_bounds;
1224           }
1225         }
1226 #endif // #TT_SUPPORT_COLRV1
1227 
1228         if (!haveLayers) {
1229             // For COLRv0 compute the glyph bounding box from the union of layer bounding boxes.
1230             while (FT_Get_Color_Glyph_Layer(fFace, glyph->getGlyphID(), &layerGlyphIndex,
1231                                             &layerColorIndex, &layerIterator)) {
1232                 haveLayers = true;
1233                 err = FT_Load_Glyph(fFace, layerGlyphIndex,
1234                                     fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
1235                 if (err != 0) {
1236                     glyph->zeroMetrics();
1237                     return;
1238                 }
1239                 emboldenIfNeeded(fFace, fFace->glyph, layerGlyphIndex);
1240 
1241                 if (0 < fFace->glyph->outline.n_contours) {
1242                     FT_BBox bbox;
1243                     getBBoxForCurrentGlyph(glyph, &bbox, true);
1244 
1245                     // Union
1246                     bounds.xMin = std::min(bbox.xMin, bounds.xMin);
1247                     bounds.yMin = std::min(bbox.yMin, bounds.yMin);
1248                     bounds.xMax = std::max(bbox.xMax, bounds.xMax);
1249                     bounds.yMax = std::max(bbox.yMax, bounds.yMax);
1250                 }
1251             }
1252         }
1253 
1254         if (haveLayers) {
1255             glyph->fMaskFormat = SkMask::kARGB32_Format;
1256             glyph->setPath(alloc, nullptr, false);
1257             if (!(bounds.xMin < bounds.xMax && bounds.yMin < bounds.yMax)) {
1258                 bounds = { 0, 0, 0, 0 };
1259             }
1260         } else {
1261 #endif
1262             if (0 < fFace->glyph->outline.n_contours) {
1263                 getBBoxForCurrentGlyph(glyph, &bounds, true);
1264             } else {
1265                 bounds = { 0, 0, 0, 0 };
1266             }
1267 #ifdef FT_COLOR_H
1268         }
1269 #endif
1270         // Round out, no longer dot6.
1271         bounds.xMin = SkFDot6Floor(bounds.xMin);
1272         bounds.yMin = SkFDot6Floor(bounds.yMin);
1273         bounds.xMax = SkFDot6Ceil (bounds.xMax);
1274         bounds.yMax = SkFDot6Ceil (bounds.yMax);
1275 
1276         FT_Pos width  =  bounds.xMax - bounds.xMin;
1277         FT_Pos height =  bounds.yMax - bounds.yMin;
1278         FT_Pos top    = -bounds.yMax;  // Freetype y-up, Skia y-down.
1279         FT_Pos left   =  bounds.xMin;
1280         if (!SkTFitsIn<decltype(glyph->fWidth )>(width ) ||
1281             !SkTFitsIn<decltype(glyph->fHeight)>(height) ||
1282             !SkTFitsIn<decltype(glyph->fTop   )>(top   ) ||
1283             !SkTFitsIn<decltype(glyph->fLeft  )>(left  )  )
1284         {
1285             width = height = top = left = 0;
1286         }
1287 
1288         glyph->fWidth  = SkToU16(width );
1289         glyph->fHeight = SkToU16(height);
1290         glyph->fTop    = SkToS16(top   );
1291         glyph->fLeft   = SkToS16(left  );
1292         updateGlyphIfLCD(glyph);
1293 
1294     } else if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
1295         if (this->isVertical()) {
1296             FT_Vector vector;
1297             vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1298             vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1299             FT_Vector_Transform(&vector, &fMatrix22);
1300             fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
1301             fFace->glyph->bitmap_top  += SkFDot6Floor(vector.y);
1302         }
1303 
1304         if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
1305             glyph->fMaskFormat = SkMask::kARGB32_Format;
1306         }
1307 
1308         {
1309             SkRect rect = SkRect::MakeXYWH(SkIntToScalar(fFace->glyph->bitmap_left),
1310                                           -SkIntToScalar(fFace->glyph->bitmap_top),
1311                                            SkIntToScalar(fFace->glyph->bitmap.width),
1312                                            SkIntToScalar(fFace->glyph->bitmap.rows));
1313             fMatrix22Scalar.mapRect(&rect);
1314             if (this->shouldSubpixelBitmap(*glyph, fMatrix22Scalar)) {
1315                 rect.offset(SkFixedToScalar(glyph->getSubXFixed()),
1316                             SkFixedToScalar(glyph->getSubYFixed()));
1317             }
1318             SkIRect irect = rect.roundOut();
1319             glyph->fWidth   = SkToU16(irect.width());
1320             glyph->fHeight  = SkToU16(irect.height());
1321             glyph->fTop     = SkToS16(irect.top());
1322             glyph->fLeft    = SkToS16(irect.left());
1323         }
1324     } else {
1325         SkDEBUGFAIL("unknown glyph format");
1326         glyph->zeroMetrics();
1327         return;
1328     }
1329 
1330     if (this->isVertical()) {
1331         if (fDoLinearMetrics) {
1332             const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearVertAdvance);
1333             glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * advanceScalar);
1334             glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * advanceScalar);
1335         } else {
1336             glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x);
1337             glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y);
1338         }
1339     } else {
1340         if (fDoLinearMetrics) {
1341             const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearHoriAdvance);
1342             glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar);
1343             glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar);
1344         } else {
1345             glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x);
1346             glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y);
1347         }
1348     }
1349 
1350 #ifdef ENABLE_GLYPH_SPEW
1351     LOG_INFO("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadGlyphFlags, glyph->fWidth);
1352 #endif
1353 }
1354 
generateImage(const SkGlyph & glyph)1355 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
1356     SkAutoMutexExclusive  ac(f_t_mutex());
1357 
1358     if (this->setupSize()) {
1359         sk_bzero(glyph.fImage, glyph.imageSize());
1360         return;
1361     }
1362 
1363     FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags);
1364     if (err != 0) {
1365         SK_TRACEFTR(err, "SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d "
1366                      "width:%d height:%d rb:%zu flags:%d) failed.",
1367                      glyph.getGlyphID(), glyph.width(), glyph.height(), glyph.rowBytes(),
1368                      fLoadGlyphFlags);
1369         sk_bzero(glyph.fImage, glyph.imageSize());
1370         return;
1371     }
1372 
1373     emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID());
1374     SkMatrix* bitmapMatrix = &fMatrix22Scalar;
1375     SkMatrix subpixelBitmapMatrix;
1376     if (this->shouldSubpixelBitmap(glyph, *bitmapMatrix)) {
1377         subpixelBitmapMatrix = fMatrix22Scalar;
1378         subpixelBitmapMatrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()),
1379                                            SkFixedToScalar(glyph.getSubYFixed()));
1380         bitmapMatrix = &subpixelBitmapMatrix;
1381     }
1382 
1383     SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
1384     generateGlyphImage(fFace, palette, glyph, *bitmapMatrix);
1385 }
1386 
generateDrawable(const SkGlyph & glyph)1387 sk_sp<SkDrawable> SkScalerContext_FreeType::generateDrawable(const SkGlyph& glyph) {
1388     // Because FreeType's FT_Face is stateful (not thread safe) and the current design of this
1389     // SkTypeface and SkScalerContext does not work around this, it is necessary lock at least the
1390     // FT_Face when using it (this implementation currently locks the whole FT_Library).
1391     // It should be possible to draw the drawable straight out of the FT_Face. However, this would
1392     // mean locking each time any such drawable is drawn. To avoid locking, this implementation
1393     // creates drawables backed as pictures so that they can be played back later without locking.
1394     SkAutoMutexExclusive  ac(f_t_mutex());
1395 
1396     if (this->setupSize()) {
1397         sk_bzero(glyph.fImage, glyph.imageSize());
1398         return nullptr;
1399     }
1400 
1401     FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags);
1402     if (err != 0) {
1403         SK_TRACEFTR(err, "SkScalerContext_FreeType::generateDrawable: FT_Load_Glyph(glyph:%d "
1404                      "width:%d height:%d rb:%zu flags:%d) failed.",
1405                      glyph.getGlyphID(), glyph.width(), glyph.height(), glyph.rowBytes(),
1406                      fLoadGlyphFlags);
1407         return nullptr;
1408     }
1409 
1410     emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID());
1411     SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
1412     return generateGlyphDrawable(fFace, palette, glyph);
1413 }
1414 
generatePath(const SkGlyph & glyph,SkPath * path)1415 bool SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) {
1416     SkASSERT(path);
1417 
1418     SkAutoMutexExclusive  ac(f_t_mutex());
1419 
1420     SkGlyphID glyphID = glyph.getGlyphID();
1421     // FT_IS_SCALABLE is documented to mean the face contains outline glyphs.
1422     if (!FT_IS_SCALABLE(fFace) || this->setupSize()) {
1423         path->reset();
1424         return false;
1425     }
1426 
1427     uint32_t flags = fLoadGlyphFlags;
1428     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1429     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1430 
1431     FT_Error err = FT_Load_Glyph(fFace, glyphID, flags);
1432     if (err != 0 || fFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE) {
1433         path->reset();
1434         return false;
1435     }
1436     emboldenIfNeeded(fFace, fFace->glyph, glyphID);
1437 
1438     if (!generateGlyphPath(fFace, path)) {
1439         path->reset();
1440         return false;
1441     }
1442 
1443     // The path's origin from FreeType is always the horizontal layout origin.
1444     // Offset the path so that it is relative to the vertical origin if needed.
1445     if (this->isVertical()) {
1446         FT_Vector vector;
1447         vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
1448         vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
1449         FT_Vector_Transform(&vector, &fMatrix22);
1450         path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y));
1451     }
1452     return true;
1453 }
1454 
generateFontMetrics(SkFontMetrics * metrics)1455 void SkScalerContext_FreeType::generateFontMetrics(SkFontMetrics* metrics) {
1456     if (nullptr == metrics) {
1457         return;
1458     }
1459 
1460     SkAutoMutexExclusive ac(f_t_mutex());
1461 
1462     if (this->setupSize()) {
1463         sk_bzero(metrics, sizeof(*metrics));
1464         return;
1465     }
1466 
1467     FT_Face face = fFace;
1468     metrics->fFlags = 0;
1469 
1470     SkScalar upem = SkIntToScalar(SkTypeface_FreeType::GetUnitsPerEm(face));
1471 
1472     // use the os/2 table as a source of reasonable defaults.
1473     SkScalar x_height = 0.0f;
1474     SkScalar avgCharWidth = 0.0f;
1475     SkScalar cap_height = 0.0f;
1476     SkScalar strikeoutThickness = 0.0f, strikeoutPosition = 0.0f;
1477     TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1478     if (os2) {
1479         x_height = SkIntToScalar(os2->sxHeight) / upem * fScale.y();
1480         avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem;
1481         strikeoutThickness = SkIntToScalar(os2->yStrikeoutSize) / upem;
1482         strikeoutPosition = -SkIntToScalar(os2->yStrikeoutPosition) / upem;
1483         metrics->fFlags |= SkFontMetrics::kStrikeoutThicknessIsValid_Flag;
1484         metrics->fFlags |= SkFontMetrics::kStrikeoutPositionIsValid_Flag;
1485         if (os2->version != 0xFFFF && os2->version >= 2) {
1486             cap_height = SkIntToScalar(os2->sCapHeight) / upem * fScale.y();
1487         }
1488     }
1489 
1490     // pull from format-specific metrics as needed
1491     SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
1492     SkScalar underlineThickness, underlinePosition;
1493     if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
1494         // FreeType will always use HHEA metrics if they're not zero.
1495         // It completely ignores the OS/2 fsSelection::UseTypoMetrics bit.
1496         // It also ignores the VDMX tables, which are also of interest here
1497         // (and override everything else when they apply).
1498         static const int kUseTypoMetricsMask = (1 << 7);
1499         if (os2 && os2->version != 0xFFFF && (os2->fsSelection & kUseTypoMetricsMask)) {
1500             ascent = -SkIntToScalar(os2->sTypoAscender) / upem;
1501             descent = -SkIntToScalar(os2->sTypoDescender) / upem;
1502             leading = SkIntToScalar(os2->sTypoLineGap) / upem;
1503         } else {
1504             ascent = -SkIntToScalar(face->ascender) / upem;
1505             descent = -SkIntToScalar(face->descender) / upem;
1506             leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem;
1507         }
1508         xmin = SkIntToScalar(face->bbox.xMin) / upem;
1509         xmax = SkIntToScalar(face->bbox.xMax) / upem;
1510         ymin = -SkIntToScalar(face->bbox.yMin) / upem;
1511         ymax = -SkIntToScalar(face->bbox.yMax) / upem;
1512         underlineThickness = SkIntToScalar(face->underline_thickness) / upem;
1513         underlinePosition = -SkIntToScalar(face->underline_position +
1514                                            face->underline_thickness / 2) / upem;
1515 
1516         metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
1517         metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
1518 
1519         // we may be able to synthesize x_height and cap_height from outline
1520         if (!x_height) {
1521             FT_BBox bbox;
1522             if (getCBoxForLetter('x', &bbox)) {
1523                 x_height = SkIntToScalar(bbox.yMax) / 64.0f;
1524             }
1525         }
1526         if (!cap_height) {
1527             FT_BBox bbox;
1528             if (getCBoxForLetter('H', &bbox)) {
1529                 cap_height = SkIntToScalar(bbox.yMax) / 64.0f;
1530             }
1531         }
1532     } else if (fStrikeIndex != -1) { // bitmap strike metrics
1533         SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem);
1534         SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem);
1535         ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f);
1536         descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f);
1537         leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) + ascent - descent;
1538 
1539         xmin = 0.0f;
1540         xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
1541         ymin = descent;
1542         ymax = ascent;
1543         // The actual bitmaps may be any size and placed at any offset.
1544         metrics->fFlags |= SkFontMetrics::kBoundsInvalid_Flag;
1545 
1546         underlineThickness = 0;
1547         underlinePosition = 0;
1548         metrics->fFlags &= ~SkFontMetrics::kUnderlineThicknessIsValid_Flag;
1549         metrics->fFlags &= ~SkFontMetrics::kUnderlinePositionIsValid_Flag;
1550 
1551         TT_Postscript* post = (TT_Postscript*) FT_Get_Sfnt_Table(face, ft_sfnt_post);
1552         if (post) {
1553             underlineThickness = SkIntToScalar(post->underlineThickness) / upem;
1554             underlinePosition = -SkIntToScalar(post->underlinePosition) / upem;
1555             metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
1556             metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
1557         }
1558     } else {
1559         sk_bzero(metrics, sizeof(*metrics));
1560         return;
1561     }
1562 
1563     // synthesize elements that were not provided by the os/2 table or format-specific metrics
1564     if (!x_height) {
1565         x_height = -ascent * fScale.y();
1566     }
1567     if (!avgCharWidth) {
1568         avgCharWidth = xmax - xmin;
1569     }
1570     if (!cap_height) {
1571       cap_height = -ascent * fScale.y();
1572     }
1573 
1574     // disallow negative linespacing
1575     if (leading < 0.0f) {
1576         leading = 0.0f;
1577     }
1578 
1579     metrics->fTop = ymax * fScale.y();
1580     metrics->fAscent = ascent * fScale.y();
1581     metrics->fDescent = descent * fScale.y();
1582     metrics->fBottom = ymin * fScale.y();
1583     metrics->fLeading = leading * fScale.y();
1584     metrics->fAvgCharWidth = avgCharWidth * fScale.y();
1585     metrics->fXMin = xmin * fScale.y();
1586     metrics->fXMax = xmax * fScale.y();
1587     metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
1588     metrics->fXHeight = x_height;
1589     metrics->fCapHeight = cap_height;
1590     metrics->fUnderlineThickness = underlineThickness * fScale.y();
1591     metrics->fUnderlinePosition = underlinePosition * fScale.y();
1592     metrics->fStrikeoutThickness = strikeoutThickness * fScale.y();
1593     metrics->fStrikeoutPosition = strikeoutPosition * fScale.y();
1594 
1595     if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
1596         // The bounds are only valid for the default variation.
1597         metrics->fFlags |= SkFontMetrics::kBoundsInvalid_Flag;
1598     }
1599 }
1600 
1601 ///////////////////////////////////////////////////////////////////////////////
1602 
1603 // hand-tuned value to reduce outline embolden strength
1604 #ifndef SK_OUTLINE_EMBOLDEN_DIVISOR
1605     #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1606         #define SK_OUTLINE_EMBOLDEN_DIVISOR   34
1607     #else
1608         #define SK_OUTLINE_EMBOLDEN_DIVISOR   24
1609     #endif
1610 #endif
1611 
1612 ///////////////////////////////////////////////////////////////////////////////
1613 
emboldenIfNeeded(FT_Face face,FT_GlyphSlot glyph,SkGlyphID gid)1614 void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid) {
1615     // check to see if the embolden bit is set
1616     if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) {
1617         return;
1618     }
1619 
1620     switch (glyph->format) {
1621         case FT_GLYPH_FORMAT_OUTLINE:
1622             FT_Pos strength;
1623             strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale)
1624                        / SK_OUTLINE_EMBOLDEN_DIVISOR;
1625             FT_Outline_Embolden(&glyph->outline, strength);
1626             break;
1627         case FT_GLYPH_FORMAT_BITMAP:
1628             if (!fFace->glyph->bitmap.buffer) {
1629                 FT_Load_Glyph(fFace, gid, fLoadGlyphFlags);
1630             }
1631             FT_GlyphSlot_Own_Bitmap(glyph);
1632             FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0);
1633             break;
1634         default:
1635             SkDEBUGFAIL("unknown glyph format");
1636     }
1637 }
1638 
1639 ///////////////////////////////////////////////////////////////////////////////
1640 
1641 #include "src/core/SkUtils.h"
1642 
SkTypeface_FreeType(const SkFontStyle & style,bool isFixedPitch)1643 SkTypeface_FreeType::SkTypeface_FreeType(const SkFontStyle& style, bool isFixedPitch)
1644     : INHERITED(style, isFixedPitch)
1645 {}
1646 
~SkTypeface_FreeType()1647 SkTypeface_FreeType::~SkTypeface_FreeType() {
1648     if (fFaceRec) {
1649         SkAutoMutexExclusive ac(f_t_mutex());
1650         fFaceRec.reset();
1651     }
1652 }
1653 
1654 // Just made up, so we don't end up storing 1000s of entries
1655 constexpr int kMaxC2GCacheCount = 512;
1656 
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const1657 void SkTypeface_FreeType::onCharsToGlyphs(const SkUnichar uni[], int count,
1658                                           SkGlyphID glyphs[]) const {
1659     // Try the cache first, *before* accessing freetype lib/face, as that
1660     // can be very slow. If we do need to compute a new glyphID, then
1661     // access those freetype objects and continue the loop.
1662 
1663     int i;
1664     {
1665         // Optimistically use a shared lock.
1666         SkAutoSharedMutexShared ama(fC2GCacheMutex);
1667         for (i = 0; i < count; ++i) {
1668             int index = fC2GCache.findGlyphIndex(uni[i]);
1669             if (index < 0) {
1670                 break;
1671             }
1672             glyphs[i] = SkToU16(index);
1673         }
1674         if (i == count) {
1675             // we're done, no need to access the freetype objects
1676             return;
1677         }
1678     }
1679 
1680     // Need to add more so grab an exclusive lock.
1681     SkAutoSharedMutexExclusive ama(fC2GCacheMutex);
1682     AutoFTAccess fta(this);
1683     FT_Face face = fta.face();
1684     if (!face) {
1685         sk_bzero(glyphs, count * sizeof(glyphs[0]));
1686         return;
1687     }
1688 
1689     for (; i < count; ++i) {
1690         SkUnichar c = uni[i];
1691         int index = fC2GCache.findGlyphIndex(c);
1692         if (index >= 0) {
1693             glyphs[i] = SkToU16(index);
1694         } else {
1695             glyphs[i] = SkToU16(FT_Get_Char_Index(face, c));
1696             fC2GCache.insertCharAndGlyph(~index, c, glyphs[i]);
1697         }
1698     }
1699 
1700     if (fC2GCache.count() > kMaxC2GCacheCount) {
1701         fC2GCache.reset();
1702     }
1703 }
1704 
onCountGlyphs() const1705 int SkTypeface_FreeType::onCountGlyphs() const {
1706     AutoFTAccess fta(this);
1707     FT_Face face = fta.face();
1708     return face ? face->num_glyphs : 0;
1709 }
1710 
onCreateFamilyNameIterator() const1711 SkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const {
1712     sk_sp<SkTypeface::LocalizedStrings> nameIter =
1713         SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
1714     if (!nameIter) {
1715         SkString familyName;
1716         this->getFamilyName(&familyName);
1717         SkString language("und"); //undetermined
1718         nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(familyName, language);
1719     }
1720     return nameIter.release();
1721 }
1722 
onGlyphMaskNeedsCurrentColor() const1723 bool SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const {
1724     fGlyphMasksMayNeedCurrentColorOnce([this]{
1725         static constexpr SkFourByteTag COLRTag = SkSetFourByteTag('C', 'O', 'L', 'R');
1726         fGlyphMasksMayNeedCurrentColor = this->getTableSize(COLRTag) > 0;
1727     });
1728     return fGlyphMasksMayNeedCurrentColor;
1729 }
1730 
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const1731 int SkTypeface_FreeType::onGetVariationDesignPosition(
1732     SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
1733 {
1734     AutoFTAccess fta(this);
1735     return GetVariationDesignPosition(fta, coordinates, coordinateCount);
1736 }
1737 
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const1738 int SkTypeface_FreeType::onGetVariationDesignParameters(
1739     SkFontParameters::Variation::Axis parameters[], int parameterCount) const
1740 {
1741     AutoFTAccess fta(this);
1742     FT_Face face = fta.face();
1743     if (!face) {
1744         return -1;
1745     }
1746 
1747     if (!(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
1748         return 0;
1749     }
1750 
1751     FT_MM_Var* variations = nullptr;
1752     if (FT_Get_MM_Var(face, &variations)) {
1753         return -1;
1754     }
1755     SkAutoFree autoFreeVariations(variations);
1756 
1757     if (!parameters || parameterCount < SkToInt(variations->num_axis)) {
1758         return variations->num_axis;
1759     }
1760 
1761     for (FT_UInt i = 0; i < variations->num_axis; ++i) {
1762         parameters[i].tag = variations->axis[i].tag;
1763         parameters[i].min = SkFixedToScalar(variations->axis[i].minimum);
1764         parameters[i].def = SkFixedToScalar(variations->axis[i].def);
1765         parameters[i].max = SkFixedToScalar(variations->axis[i].maximum);
1766         FT_UInt flags = 0;
1767         bool hidden = !FT_Get_Var_Axis_Flags(variations, i, &flags) &&
1768                       (flags & FT_VAR_AXIS_FLAG_HIDDEN);
1769         parameters[i].setHidden(hidden);
1770     }
1771 
1772     return variations->num_axis;
1773 }
1774 
onGetTableTags(SkFontTableTag tags[]) const1775 int SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const {
1776     AutoFTAccess fta(this);
1777     FT_Face face = fta.face();
1778     if (!face) {
1779         return 0;
1780     }
1781 
1782     FT_ULong tableCount = 0;
1783     FT_Error error;
1784 
1785     // When 'tag' is nullptr, returns number of tables in 'length'.
1786     error = FT_Sfnt_Table_Info(face, 0, nullptr, &tableCount);
1787     if (error) {
1788         return 0;
1789     }
1790 
1791     if (tags) {
1792         for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) {
1793             FT_ULong tableTag;
1794             FT_ULong tablelength;
1795             error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength);
1796             if (error) {
1797                 return 0;
1798             }
1799             tags[tableIndex] = static_cast<SkFontTableTag>(tableTag);
1800         }
1801     }
1802     return tableCount;
1803 }
1804 
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const1805 size_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset,
1806                                            size_t length, void* data) const
1807 {
1808     AutoFTAccess fta(this);
1809     FT_Face face = fta.face();
1810     if (!face) {
1811         return 0;
1812     }
1813 
1814     FT_ULong tableLength = 0;
1815     FT_Error error;
1816 
1817     // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored.
1818     error = FT_Load_Sfnt_Table(face, tag, 0, nullptr, &tableLength);
1819     if (error) {
1820         return 0;
1821     }
1822 
1823     if (offset > tableLength) {
1824         return 0;
1825     }
1826     FT_ULong size = std::min((FT_ULong)length, tableLength - (FT_ULong)offset);
1827     if (data) {
1828         error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size);
1829         if (error) {
1830             return 0;
1831         }
1832     }
1833 
1834     return size;
1835 }
1836 
onCopyTableData(SkFontTableTag tag) const1837 sk_sp<SkData> SkTypeface_FreeType::onCopyTableData(SkFontTableTag tag) const {
1838     AutoFTAccess fta(this);
1839     FT_Face face = fta.face();
1840     if (!face) {
1841         return nullptr;
1842     }
1843 
1844     FT_ULong tableLength = 0;
1845     FT_Error error;
1846 
1847     // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored.
1848     error = FT_Load_Sfnt_Table(face, tag, 0, nullptr, &tableLength);
1849     if (error) {
1850         return nullptr;
1851     }
1852 
1853     sk_sp<SkData> data = SkData::MakeUninitialized(tableLength);
1854     if (data) {
1855         error = FT_Load_Sfnt_Table(face, tag, 0,
1856                                    reinterpret_cast<FT_Byte*>(data->writable_data()), &tableLength);
1857         if (error) {
1858             data.reset();
1859         }
1860     }
1861     return data;
1862 }
1863 
getFaceRec() const1864 SkTypeface_FreeType::FaceRec* SkTypeface_FreeType::getFaceRec() const {
1865     f_t_mutex().assertHeld();
1866     fFTFaceOnce([this]{ fFaceRec = SkTypeface_FreeType::FaceRec::Make(this); });
1867     return fFaceRec.get();
1868 }
1869 
makeFontData() const1870 std::unique_ptr<SkFontData> SkTypeface_FreeType::makeFontData() const {
1871     return this->onMakeFontData();
1872 }
1873 
FontDataPaletteToDescriptorPalette(const SkFontData & fontData,SkFontDescriptor * desc)1874 void SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(const SkFontData& fontData,
1875                                                              SkFontDescriptor* desc) {
1876     desc->setPaleteIndex(fontData.getPaletteIndex());
1877     int paletteOverrideCount = fontData.getPaletteOverrideCount();
1878     auto overrides = desc->setPaletteEntryOverrides(paletteOverrideCount);
1879     for (int i = 0; i < paletteOverrideCount; ++i) {
1880         overrides[i] = fontData.getPaletteOverrides()[i];
1881     }
1882 }
1883 
1884 ///////////////////////////////////////////////////////////////////////////////
1885 ///////////////////////////////////////////////////////////////////////////////
1886 
Scanner()1887 SkTypeface_FreeType::Scanner::Scanner() : fLibrary(nullptr) {
1888     if (FT_New_Library(&gFTMemory, &fLibrary)) {
1889         return;
1890     }
1891     FT_Add_Default_Modules(fLibrary);
1892     FT_Set_Default_Properties(fLibrary);
1893 }
~Scanner()1894 SkTypeface_FreeType::Scanner::~Scanner() {
1895     if (fLibrary) {
1896         FT_Done_Library(fLibrary);
1897     }
1898 }
1899 
openFace(SkStreamAsset * stream,int ttcIndex,FT_Stream ftStream) const1900 FT_Face SkTypeface_FreeType::Scanner::openFace(SkStreamAsset* stream, int ttcIndex,
1901                                                FT_Stream ftStream) const
1902 {
1903     if (fLibrary == nullptr || stream == nullptr) {
1904         return nullptr;
1905     }
1906 
1907     FT_Open_Args args;
1908     memset(&args, 0, sizeof(args));
1909 
1910     const void* memoryBase = stream->getMemoryBase();
1911 
1912     if (memoryBase) {
1913         args.flags = FT_OPEN_MEMORY;
1914         args.memory_base = (const FT_Byte*)memoryBase;
1915         args.memory_size = stream->getLength();
1916     } else {
1917         memset(ftStream, 0, sizeof(*ftStream));
1918         ftStream->size = stream->getLength();
1919         ftStream->descriptor.pointer = stream;
1920         ftStream->read  = sk_ft_stream_io;
1921         ftStream->close = sk_ft_stream_close;
1922 
1923         args.flags = FT_OPEN_STREAM;
1924         args.stream = ftStream;
1925     }
1926 
1927     FT_Face face;
1928     if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) {
1929         return nullptr;
1930     }
1931     return face;
1932 }
1933 
recognizedFont(SkStreamAsset * stream,int * numFaces) const1934 bool SkTypeface_FreeType::Scanner::recognizedFont(SkStreamAsset* stream, int* numFaces) const {
1935     SkAutoMutexExclusive libraryLock(fLibraryMutex);
1936 
1937     FT_StreamRec streamRec;
1938     SkUniqueFTFace face(this->openFace(stream, -1, &streamRec));
1939     if (!face) {
1940         return false;
1941     }
1942 
1943     *numFaces = face->num_faces;
1944     return true;
1945 }
1946 
scanFont(SkStreamAsset * stream,int ttcIndex,SkString * name,SkFontStyle * style,bool * isFixedPitch,AxisDefinitions * axes) const1947 bool SkTypeface_FreeType::Scanner::scanFont(
1948     SkStreamAsset* stream, int ttcIndex,
1949     SkString* name, SkFontStyle* style, bool* isFixedPitch, AxisDefinitions* axes) const
1950 {
1951     SkAutoMutexExclusive libraryLock(fLibraryMutex);
1952 
1953     FT_StreamRec streamRec;
1954     SkUniqueFTFace face(this->openFace(stream, ttcIndex, &streamRec));
1955     if (!face) {
1956         return false;
1957     }
1958 
1959     int weight = SkFontStyle::kNormal_Weight;
1960     int width = SkFontStyle::kNormal_Width;
1961     SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
1962     if (face->style_flags & FT_STYLE_FLAG_BOLD) {
1963         weight = SkFontStyle::kBold_Weight;
1964     }
1965     if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
1966         slant = SkFontStyle::kItalic_Slant;
1967     }
1968 
1969     bool hasAxes = face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
1970     TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face.get(), ft_sfnt_os2));
1971     bool hasOs2 = os2 && os2->version != 0xffff;
1972 
1973     PS_FontInfoRec psFontInfo;
1974 
1975     if (hasOs2) {
1976         weight = os2->usWeightClass;
1977         width = os2->usWidthClass;
1978 
1979         // OS/2::fsSelection bit 9 indicates oblique.
1980         if (SkToBool(os2->fsSelection & (1u << 9))) {
1981             slant = SkFontStyle::kOblique_Slant;
1982         }
1983     }
1984 
1985     // Let variable axes override properties from the OS/2 table.
1986     if (hasAxes) {
1987       AxisDefinitions axisDefinitions;
1988       if (GetAxes(face.get(), &axisDefinitions)) {
1989         size_t numAxes = axisDefinitions.size();
1990         static constexpr SkFourByteTag wghtTag = SkSetFourByteTag('w', 'g', 'h', 't');
1991         static constexpr SkFourByteTag wdthTag = SkSetFourByteTag('w', 'd', 't', 'h');
1992         static constexpr SkFourByteTag slntTag = SkSetFourByteTag('s', 'l', 'n', 't');
1993         std::optional<size_t> wghtIndex;
1994         std::optional<size_t> wdthIndex;
1995         std::optional<size_t> slntIndex;
1996         for(size_t i = 0; i < numAxes; ++i) {
1997           if (axisDefinitions[i].fTag == wghtTag) {
1998               // Rough validity check, is there sufficient spread and are ranges
1999               // within 0-1000.
2000               int wghtRange = SkFixedToScalar(axisDefinitions[i].fMaximum) -
2001                               SkFixedToScalar(axisDefinitions[i].fMinimum);
2002               if (wghtRange > 5 && wghtRange <= 1000 &&
2003                   SkFixedToScalar(axisDefinitions[i].fMaximum) <= 1000) {
2004                   wghtIndex = i;
2005               }
2006           }
2007           if (axisDefinitions[i].fTag == wdthTag) {
2008               // Rough validity check, is there a spread and are ranges within
2009               // 0-500.
2010               int widthRange = SkFixedToScalar(axisDefinitions[i].fMaximum) -
2011                                SkFixedToScalar(axisDefinitions[i].fMinimum);
2012               if (widthRange > 0 && widthRange <= 500 &&
2013                   SkFixedToScalar(axisDefinitions[i].fMaximum) <= 500)
2014                   wdthIndex = i;
2015           }
2016           if (axisDefinitions[i].fTag == slntTag)
2017             slntIndex = i;
2018         }
2019         SkAutoSTMalloc<4, FT_Fixed> coords(numAxes);
2020         if ((wghtIndex || wdthIndex || slntIndex) &&
2021             !FT_Get_Var_Design_Coordinates(face.get(), numAxes, coords.get())) {
2022             if (wghtIndex) {
2023                 SkASSERT(*wghtIndex < numAxes);
2024                 weight = SkScalarRoundToInt(SkFixedToScalar(coords[*wghtIndex]));
2025             }
2026             if (wdthIndex) {
2027                 SkASSERT(*wdthIndex < numAxes);
2028                 SkScalar wdthValue = SkFixedToScalar(coords[*wdthIndex]);
2029                 width = SkFontDescriptor::SkFontStyleWidthForWidthAxisValue(wdthValue);
2030             }
2031             if (slntIndex) {
2032                 SkASSERT(*slntIndex < numAxes);
2033                 // https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_slnt
2034                 // "Scale interpretation: Values can be interpreted as the angle,
2035                 // in counter-clockwise degrees, of oblique slant from whatever
2036                 // the designer considers to be upright for that font design."
2037                 if (SkFixedToScalar(coords[*slntIndex]) < 0) {
2038                     slant = SkFontStyle::kOblique_Slant;
2039                 }
2040             }
2041         }
2042       }
2043     }
2044 
2045     if (!hasOs2 && !hasAxes && 0 == FT_Get_PS_Font_Info(face.get(), &psFontInfo) && psFontInfo.weight) {
2046         static const struct {
2047             char const * const name;
2048             int const weight;
2049         } commonWeights [] = {
2050             // There are probably more common names, but these are known to exist.
2051             { "all", SkFontStyle::kNormal_Weight }, // Multiple Masters usually default to normal.
2052             { "black", SkFontStyle::kBlack_Weight },
2053             { "bold", SkFontStyle::kBold_Weight },
2054             { "book", (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight)/2 },
2055             { "demi", SkFontStyle::kSemiBold_Weight },
2056             { "demibold", SkFontStyle::kSemiBold_Weight },
2057             { "extra", SkFontStyle::kExtraBold_Weight },
2058             { "extrabold", SkFontStyle::kExtraBold_Weight },
2059             { "extralight", SkFontStyle::kExtraLight_Weight },
2060             { "hairline", SkFontStyle::kThin_Weight },
2061             { "heavy", SkFontStyle::kBlack_Weight },
2062             { "light", SkFontStyle::kLight_Weight },
2063             { "medium", SkFontStyle::kMedium_Weight },
2064             { "normal", SkFontStyle::kNormal_Weight },
2065             { "plain", SkFontStyle::kNormal_Weight },
2066             { "regular", SkFontStyle::kNormal_Weight },
2067             { "roman", SkFontStyle::kNormal_Weight },
2068             { "semibold", SkFontStyle::kSemiBold_Weight },
2069             { "standard", SkFontStyle::kNormal_Weight },
2070             { "thin", SkFontStyle::kThin_Weight },
2071             { "ultra", SkFontStyle::kExtraBold_Weight },
2072             { "ultrablack", SkFontStyle::kExtraBlack_Weight },
2073             { "ultrabold", SkFontStyle::kExtraBold_Weight },
2074             { "ultraheavy", SkFontStyle::kExtraBlack_Weight },
2075             { "ultralight", SkFontStyle::kExtraLight_Weight },
2076         };
2077         int const index = SkStrLCSearch(&commonWeights[0].name, SK_ARRAY_COUNT(commonWeights),
2078                                         psFontInfo.weight, sizeof(commonWeights[0]));
2079         if (index >= 0) {
2080             weight = commonWeights[index].weight;
2081         } else {
2082             LOG_INFO("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight);
2083         }
2084     }
2085 
2086     if (name != nullptr) {
2087         name->set(face->family_name);
2088     }
2089     if (style != nullptr) {
2090         *style = SkFontStyle(weight, width, slant);
2091     }
2092     if (isFixedPitch != nullptr) {
2093         *isFixedPitch = FT_IS_FIXED_WIDTH(face);
2094     }
2095 
2096     if (axes != nullptr && !GetAxes(face.get(), axes)) {
2097         return false;
2098     }
2099     return true;
2100 }
2101 
GetAxes(FT_Face face,AxisDefinitions * axes)2102 bool SkTypeface_FreeType::Scanner::GetAxes(FT_Face face, AxisDefinitions* axes) {
2103     SkASSERT(face && axes);
2104     if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
2105         FT_MM_Var* variations = nullptr;
2106         FT_Error err = FT_Get_MM_Var(face, &variations);
2107         if (err) {
2108             LOG_INFO("INFO: font %s claims to have variations, but none found.\n",
2109                      face->family_name);
2110             return false;
2111         }
2112         SkAutoFree autoFreeVariations(variations);
2113 
2114         axes->reset(variations->num_axis);
2115         for (FT_UInt i = 0; i < variations->num_axis; ++i) {
2116             const FT_Var_Axis& ftAxis = variations->axis[i];
2117             (*axes)[i].fTag = ftAxis.tag;
2118             (*axes)[i].fMinimum = ftAxis.minimum;
2119             (*axes)[i].fDefault = ftAxis.def;
2120             (*axes)[i].fMaximum = ftAxis.maximum;
2121         }
2122     }
2123     return true;
2124 }
2125 
computeAxisValues(AxisDefinitions axisDefinitions,const SkFontArguments::VariationPosition position,SkFixed * axisValues,const SkString & name,const SkFontArguments::VariationPosition::Coordinate * current)2126 /*static*/ void SkTypeface_FreeType::Scanner::computeAxisValues(
2127     AxisDefinitions axisDefinitions,
2128     const SkFontArguments::VariationPosition position,
2129     SkFixed* axisValues,
2130     const SkString& name,
2131     const SkFontArguments::VariationPosition::Coordinate* current)
2132 {
2133     for (int i = 0; i < axisDefinitions.count(); ++i) {
2134         const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i];
2135         const SkScalar axisMin = SkFixedToScalar(axisDefinition.fMinimum);
2136         const SkScalar axisMax = SkFixedToScalar(axisDefinition.fMaximum);
2137 
2138         // Start with the default value.
2139         axisValues[i] = axisDefinition.fDefault;
2140 
2141         // Then the current value.
2142         if (current) {
2143             for (int j = 0; j < axisDefinitions.count(); ++j) {
2144                 const auto& coordinate = current[j];
2145                 if (axisDefinition.fTag == coordinate.axis) {
2146                     const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax);
2147                     axisValues[i] = SkScalarToFixed(axisValue);
2148                     break;
2149                 }
2150             }
2151         }
2152 
2153         // Then the requested value.
2154         // The position may be over specified. If there are multiple values for a given axis,
2155         // use the last one since that's what css-fonts-4 requires.
2156         for (int j = position.coordinateCount; j --> 0;) {
2157             const auto& coordinate = position.coordinates[j];
2158             if (axisDefinition.fTag == coordinate.axis) {
2159                 const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax);
2160                 if (coordinate.value != axisValue) {
2161                     LOG_INFO("Requested font axis value out of range: "
2162                              "%s '%c%c%c%c' %f; pinned to %f.\n",
2163                              name.c_str(),
2164                              (axisDefinition.fTag >> 24) & 0xFF,
2165                              (axisDefinition.fTag >> 16) & 0xFF,
2166                              (axisDefinition.fTag >>  8) & 0xFF,
2167                              (axisDefinition.fTag      ) & 0xFF,
2168                              SkScalarToDouble(coordinate.value),
2169                              SkScalarToDouble(axisValue));
2170                 }
2171                 axisValues[i] = SkScalarToFixed(axisValue);
2172                 break;
2173             }
2174         }
2175         // TODO: warn on defaulted axis?
2176     }
2177 
2178     SkDEBUGCODE(
2179         // Check for axis specified, but not matched in font.
2180         for (int i = 0; i < position.coordinateCount; ++i) {
2181             SkFourByteTag skTag = position.coordinates[i].axis;
2182             bool found = false;
2183             for (int j = 0; j < axisDefinitions.count(); ++j) {
2184                 if (skTag == axisDefinitions[j].fTag) {
2185                     found = true;
2186                     break;
2187                 }
2188             }
2189             if (!found) {
2190                 LOG_INFO("Requested font axis not found: %s '%c%c%c%c'\n",
2191                          name.c_str(),
2192                          (skTag >> 24) & 0xFF,
2193                          (skTag >> 16) & 0xFF,
2194                          (skTag >>  8) & 0xFF,
2195                          (skTag)       & 0xFF);
2196             }
2197         }
2198     )
2199 }
2200