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