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