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