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