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