• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006-2012 The Android Open Source Project
3  * Copyright 2012 Mozilla Foundation
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkPath.h"
13 #include "include/effects/SkGradientShader.h"
14 #include "include/private/SkColorData.h"
15 #include "include/private/SkTo.h"
16 #include "src/core/SkFDot6.h"
17 #include "src/ports/SkFontHost_FreeType_common.h"
18 
19 #include <utility>
20 
21 #include <ft2build.h>
22 #include FT_FREETYPE_H
23 #include FT_BITMAP_H
24 #ifdef FT_COLOR_H
25 #   include FT_COLOR_H
26 #endif
27 #include FT_IMAGE_H
28 #include FT_OUTLINE_H
29 #include FT_SIZES_H
30 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
31 #include FT_SYNTHESIS_H
32 
33 #ifdef TT_SUPPORT_COLRV1
34 #include "src/core/SkScopeExit.h"
35 #endif
36 
37 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
38 // were introduced in FreeType 2.5.0.
39 // The following may be removed once FreeType 2.5.0 is required to build.
40 #ifndef FT_LOAD_COLOR
41 #    define FT_LOAD_COLOR ( 1L << 20 )
42 #    define FT_PIXEL_MODE_BGRA 7
43 #endif
44 
45 #ifdef SK_DEBUG
SkTraceFtrGetError(int e)46 const char* SkTraceFtrGetError(int e) {
47     switch ((FT_Error)e) {
48         #undef FTERRORS_H_
49         #define FT_ERRORDEF( e, v, s ) case v: return s;
50         #define FT_ERROR_START_LIST
51         #define FT_ERROR_END_LIST
52         #include FT_ERRORS_H
53         #undef FT_ERRORDEF
54         #undef FT_ERROR_START_LIST
55         #undef FT_ERROR_END_LIST
56         default: return "";
57     }
58 }
59 #endif  // SK_DEBUG
60 
61 #ifdef TT_SUPPORT_COLRV1
operator ==(const FT_OpaquePaint & a,const FT_OpaquePaint & b)62 bool operator==(const FT_OpaquePaint& a, const FT_OpaquePaint& b) {
63     return a.p == b.p && a.insert_root_transform == b.insert_root_transform;
64 }
65 #endif
66 
67 namespace {
68 
compute_pixel_mode(SkMask::Format format)69 FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
70     switch (format) {
71         case SkMask::kBW_Format:
72             return FT_PIXEL_MODE_MONO;
73         case SkMask::kA8_Format:
74         default:
75             return FT_PIXEL_MODE_GRAY;
76     }
77 }
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 
packTriple(U8CPU r,U8CPU g,U8CPU b)81 uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
82 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
83     r = std::max(r, (U8CPU)0x40);
84     g = std::max(g, (U8CPU)0x40);
85     b = std::max(b, (U8CPU)0x40);
86 #endif
87     return SkPack888ToRGB16(r, g, b);
88 }
89 
grayToRGB16(U8CPU gray)90 uint16_t grayToRGB16(U8CPU gray) {
91 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
92     gray = std::max(gray, (U8CPU)0x40);
93 #endif
94     return SkPack888ToRGB16(gray, gray, gray);
95 }
96 
bittst(const uint8_t data[],int bitOffset)97 int bittst(const uint8_t data[], int bitOffset) {
98     SkASSERT(bitOffset >= 0);
99     int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7);
100     return lowBit & 1;
101 }
102 
103 /**
104  *  Copies a FT_Bitmap into an SkMask with the same dimensions.
105  *
106  *  FT_PIXEL_MODE_MONO
107  *  FT_PIXEL_MODE_GRAY
108  *  FT_PIXEL_MODE_LCD
109  *  FT_PIXEL_MODE_LCD_V
110  */
111 template<bool APPLY_PREBLEND>
copyFT2LCD16(const FT_Bitmap & bitmap,const SkMask & mask,int lcdIsBGR,const uint8_t * tableR,const uint8_t * tableG,const uint8_t * tableB)112 void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR,
113                   const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB)
114 {
115     SkASSERT(SkMask::kLCD16_Format == mask.fFormat);
116     if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) {
117         SkASSERT(mask.fBounds.width() == static_cast<int>(bitmap.width));
118     }
119     if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) {
120         SkASSERT(mask.fBounds.height() == static_cast<int>(bitmap.rows));
121     }
122 
123     const uint8_t* src = bitmap.buffer;
124     uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage);
125     const size_t dstRB = mask.fRowBytes;
126 
127     const int width = mask.fBounds.width();
128     const int height = mask.fBounds.height();
129 
130     switch (bitmap.pixel_mode) {
131         case FT_PIXEL_MODE_MONO:
132             for (int y = height; y --> 0;) {
133                 for (int x = 0; x < width; ++x) {
134                     dst[x] = -bittst(src, x);
135                 }
136                 dst = (uint16_t*)((char*)dst + dstRB);
137                 src += bitmap.pitch;
138             }
139             break;
140         case FT_PIXEL_MODE_GRAY:
141             for (int y = height; y --> 0;) {
142                 for (int x = 0; x < width; ++x) {
143                     dst[x] = grayToRGB16(src[x]);
144                 }
145                 dst = (uint16_t*)((char*)dst + dstRB);
146                 src += bitmap.pitch;
147             }
148             break;
149         case FT_PIXEL_MODE_LCD:
150             SkASSERT(3 * mask.fBounds.width() == static_cast<int>(bitmap.width));
151             for (int y = height; y --> 0;) {
152                 const uint8_t* triple = src;
153                 if (lcdIsBGR) {
154                     for (int x = 0; x < width; x++) {
155                         dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR),
156                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
157                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB));
158                         triple += 3;
159                     }
160                 } else {
161                     for (int x = 0; x < width; x++) {
162                         dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR),
163                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
164                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB));
165                         triple += 3;
166                     }
167                 }
168                 src += bitmap.pitch;
169                 dst = (uint16_t*)((char*)dst + dstRB);
170             }
171             break;
172         case FT_PIXEL_MODE_LCD_V:
173             SkASSERT(3 * mask.fBounds.height() == static_cast<int>(bitmap.rows));
174             for (int y = height; y --> 0;) {
175                 const uint8_t* srcR = src;
176                 const uint8_t* srcG = srcR + bitmap.pitch;
177                 const uint8_t* srcB = srcG + bitmap.pitch;
178                 if (lcdIsBGR) {
179                     using std::swap;
180                     swap(srcR, srcB);
181                 }
182                 for (int x = 0; x < width; x++) {
183                     dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR),
184                                         sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG),
185                                         sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB));
186                 }
187                 src += 3 * bitmap.pitch;
188                 dst = (uint16_t*)((char*)dst + dstRB);
189             }
190             break;
191         default:
192             SkDEBUGF("FT_Pixel_Mode %d", bitmap.pixel_mode);
193             SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16");
194             break;
195     }
196 }
197 
198 /**
199  *  Copies a FT_Bitmap into an SkMask with the same dimensions.
200  *
201  *  Yes, No, Never Requested, Never Produced
202  *
203  *                        kBW kA8 k3D kARGB32 kLCD16
204  *  FT_PIXEL_MODE_MONO     Y   Y  NR     N       Y
205  *  FT_PIXEL_MODE_GRAY     N   Y  NR     N       Y
206  *  FT_PIXEL_MODE_GRAY2   NP  NP  NR    NP      NP
207  *  FT_PIXEL_MODE_GRAY4   NP  NP  NR    NP      NP
208  *  FT_PIXEL_MODE_LCD     NP  NP  NR    NP      NP
209  *  FT_PIXEL_MODE_LCD_V   NP  NP  NR    NP      NP
210  *  FT_PIXEL_MODE_BGRA     N   N  NR     Y       N
211  *
212  *  TODO: All of these N need to be Y or otherwise ruled out.
213  */
copyFTBitmap(const FT_Bitmap & srcFTBitmap,SkMask & dstMask)214 void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
215     SkASSERTF(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width),
216               "dstMask.fBounds.width() = %d\n"
217               "static_cast<int>(srcFTBitmap.width) = %d",
218               dstMask.fBounds.width(),
219               static_cast<int>(srcFTBitmap.width)
220     );
221     SkASSERTF(dstMask.fBounds.height() == static_cast<int>(srcFTBitmap.rows),
222               "dstMask.fBounds.height() = %d\n"
223               "static_cast<int>(srcFTBitmap.rows) = %d",
224               dstMask.fBounds.height(),
225               static_cast<int>(srcFTBitmap.rows)
226     );
227 
228     const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer);
229     const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel_mode);
230     // FT_Bitmap::pitch is an int and allowed to be negative.
231     const int srcPitch = srcFTBitmap.pitch;
232     const size_t srcRowBytes = SkTAbs(srcPitch);
233 
234     uint8_t* dst = dstMask.fImage;
235     const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat);
236     const size_t dstRowBytes = dstMask.fRowBytes;
237 
238     const size_t width = srcFTBitmap.width;
239     const size_t height = srcFTBitmap.rows;
240 
241     if (SkMask::kLCD16_Format == dstFormat) {
242         copyFT2LCD16<false>(srcFTBitmap, dstMask, false, nullptr, nullptr, nullptr);
243         return;
244     }
245 
246     if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) ||
247         (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat))
248     {
249         size_t commonRowBytes = std::min(srcRowBytes, dstRowBytes);
250         for (size_t y = height; y --> 0;) {
251             memcpy(dst, src, commonRowBytes);
252             src += srcPitch;
253             dst += dstRowBytes;
254         }
255     } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) {
256         for (size_t y = height; y --> 0;) {
257             uint8_t byte = 0;
258             int bits = 0;
259             const uint8_t* src_row = src;
260             uint8_t* dst_row = dst;
261             for (size_t x = width; x --> 0;) {
262                 if (0 == bits) {
263                     byte = *src_row++;
264                     bits = 8;
265                 }
266                 *dst_row++ = byte & 0x80 ? 0xff : 0x00;
267                 bits--;
268                 byte <<= 1;
269             }
270             src += srcPitch;
271             dst += dstRowBytes;
272         }
273     } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) {
274         // FT_PIXEL_MODE_BGRA is pre-multiplied.
275         for (size_t y = height; y --> 0;) {
276             const uint8_t* src_row = src;
277             SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst);
278             for (size_t x = 0; x < width; ++x) {
279                 uint8_t b = *src_row++;
280                 uint8_t g = *src_row++;
281                 uint8_t r = *src_row++;
282                 uint8_t a = *src_row++;
283                 *dst_row++ = SkPackARGB32(a, r, g, b);
284 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
285                 *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE, 0x40);
286 #endif
287             }
288             src += srcPitch;
289             dst += dstRowBytes;
290         }
291     } else {
292         SkDEBUGF("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat);
293         SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format");
294     }
295 }
296 
convert_8_to_1(unsigned byte)297 inline int convert_8_to_1(unsigned byte) {
298     SkASSERT(byte <= 0xFF);
299     // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better.
300     return (byte >> 6) != 0;
301 }
302 
pack_8_to_1(const uint8_t alpha[8])303 uint8_t pack_8_to_1(const uint8_t alpha[8]) {
304     unsigned bits = 0;
305     for (int i = 0; i < 8; ++i) {
306         bits <<= 1;
307         bits |= convert_8_to_1(alpha[i]);
308     }
309     return SkToU8(bits);
310 }
311 
packA8ToA1(const SkMask & mask,const uint8_t * src,size_t srcRB)312 void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
313     const int height = mask.fBounds.height();
314     const int width = mask.fBounds.width();
315     const int octs = width >> 3;
316     const int leftOverBits = width & 7;
317 
318     uint8_t* dst = mask.fImage;
319     const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
320     SkASSERT(dstPad >= 0);
321 
322     const int srcPad = srcRB - width;
323     SkASSERT(srcPad >= 0);
324 
325     for (int y = 0; y < height; ++y) {
326         for (int i = 0; i < octs; ++i) {
327             *dst++ = pack_8_to_1(src);
328             src += 8;
329         }
330         if (leftOverBits > 0) {
331             unsigned bits = 0;
332             int shift = 7;
333             for (int i = 0; i < leftOverBits; ++i, --shift) {
334                 bits |= convert_8_to_1(*src++) << shift;
335             }
336             *dst++ = bits;
337         }
338         src += srcPad;
339         dst += dstPad;
340     }
341 }
342 
SkMaskFormat_for_SkColorType(SkColorType colorType)343 inline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) {
344     switch (colorType) {
345         case kAlpha_8_SkColorType:
346             return SkMask::kA8_Format;
347         case kN32_SkColorType:
348             return SkMask::kARGB32_Format;
349         default:
350             SkDEBUGFAIL("unsupported SkBitmap::Config");
351             return SkMask::kA8_Format;
352     }
353 }
354 
SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode)355 inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
356     switch (pixel_mode) {
357         case FT_PIXEL_MODE_MONO:
358         case FT_PIXEL_MODE_GRAY:
359             return kAlpha_8_SkColorType;
360         case FT_PIXEL_MODE_BGRA:
361             return kN32_SkColorType;
362         default:
363             SkDEBUGFAIL("unsupported FT_PIXEL_MODE");
364             return kAlpha_8_SkColorType;
365     }
366 }
367 
SkColorType_for_SkMaskFormat(SkMask::Format format)368 inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) {
369     switch (format) {
370         case SkMask::kBW_Format:
371         case SkMask::kA8_Format:
372         case SkMask::kLCD16_Format:
373             return kAlpha_8_SkColorType;
374         case SkMask::kARGB32_Format:
375             return kN32_SkColorType;
376         default:
377             SkDEBUGFAIL("unsupported destination SkBitmap::Config");
378             return kAlpha_8_SkColorType;
379     }
380 }
381 
382 // Only build COLRv1 rendering code if FreeType is new enough to have COLRv1
383 // additions. FreeType defines a macro in the ftoption header to tell us whether
384 // it does support these features.
385 #ifdef TT_SUPPORT_COLRV1
386 
387 const uint16_t kForegroundColorPaletteIndex = 0xFFFF;
388 
389 struct OpaquePaintHasher {
operator ()__anone9b393860111::OpaquePaintHasher390   size_t operator()(const FT_OpaquePaint& opaque_paint) {
391       return SkGoodHash()(opaque_paint.p) ^
392              SkGoodHash()(opaque_paint.insert_root_transform);
393   }
394 };
395 
396 using VisitedSet = SkTHashSet<FT_OpaquePaint, OpaquePaintHasher>;
397 
398 bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path);
399 
SkColrV1AlphaToFloat(uint16_t alpha)400 inline float SkColrV1AlphaToFloat(uint16_t alpha) { return (alpha / float(1 << 14)); }
401 
402 
ToSkTileMode(FT_PaintExtend extend_mode)403 inline SkTileMode ToSkTileMode(FT_PaintExtend extend_mode) {
404     switch (extend_mode) {
405         case FT_COLR_PAINT_EXTEND_REPEAT:
406             return SkTileMode::kRepeat;
407         case FT_COLR_PAINT_EXTEND_REFLECT:
408             return SkTileMode::kMirror;
409         default:
410             return SkTileMode::kClamp;
411     }
412 }
413 
ToSkBlendMode(FT_Composite_Mode composite)414 inline SkBlendMode ToSkBlendMode(FT_Composite_Mode composite) {
415     switch (composite) {
416         case FT_COLR_COMPOSITE_CLEAR:
417             return SkBlendMode::kClear;
418         case FT_COLR_COMPOSITE_SRC:
419             return SkBlendMode::kSrc;
420         case FT_COLR_COMPOSITE_DEST:
421             return SkBlendMode::kDst;
422         case FT_COLR_COMPOSITE_SRC_OVER:
423             return SkBlendMode::kSrcOver;
424         case FT_COLR_COMPOSITE_DEST_OVER:
425             return SkBlendMode::kDstOver;
426         case FT_COLR_COMPOSITE_SRC_IN:
427             return SkBlendMode::kSrcIn;
428         case FT_COLR_COMPOSITE_DEST_IN:
429             return SkBlendMode::kDstIn;
430         case FT_COLR_COMPOSITE_SRC_OUT:
431             return SkBlendMode::kSrcOut;
432         case FT_COLR_COMPOSITE_DEST_OUT:
433             return SkBlendMode::kDstOut;
434         case FT_COLR_COMPOSITE_SRC_ATOP:
435             return SkBlendMode::kSrcATop;
436         case FT_COLR_COMPOSITE_DEST_ATOP:
437             return SkBlendMode::kDstATop;
438         case FT_COLR_COMPOSITE_XOR:
439             return SkBlendMode::kXor;
440         case FT_COLR_COMPOSITE_PLUS:
441             return SkBlendMode::kPlus;
442         case FT_COLR_COMPOSITE_SCREEN:
443             return SkBlendMode::kScreen;
444         case FT_COLR_COMPOSITE_OVERLAY:
445             return SkBlendMode::kOverlay;
446         case FT_COLR_COMPOSITE_DARKEN:
447             return SkBlendMode::kDarken;
448         case FT_COLR_COMPOSITE_LIGHTEN:
449             return SkBlendMode::kLighten;
450         case FT_COLR_COMPOSITE_COLOR_DODGE:
451             return SkBlendMode::kColorDodge;
452         case FT_COLR_COMPOSITE_COLOR_BURN:
453             return SkBlendMode::kColorBurn;
454         case FT_COLR_COMPOSITE_HARD_LIGHT:
455             return SkBlendMode::kHardLight;
456         case FT_COLR_COMPOSITE_SOFT_LIGHT:
457             return SkBlendMode::kSoftLight;
458         case FT_COLR_COMPOSITE_DIFFERENCE:
459             return SkBlendMode::kDifference;
460         case FT_COLR_COMPOSITE_EXCLUSION:
461             return SkBlendMode::kExclusion;
462         case FT_COLR_COMPOSITE_MULTIPLY:
463             return SkBlendMode::kMultiply;
464         case FT_COLR_COMPOSITE_HSL_HUE:
465             return SkBlendMode::kHue;
466         case FT_COLR_COMPOSITE_HSL_SATURATION:
467             return SkBlendMode::kSaturation;
468         case FT_COLR_COMPOSITE_HSL_COLOR:
469             return SkBlendMode::kColor;
470         case FT_COLR_COMPOSITE_HSL_LUMINOSITY:
471             return SkBlendMode::kLuminosity;
472         default:
473             return SkBlendMode::kDst;
474     }
475 }
476 
ToSkMatrix(FT_Affine23 affine23)477 inline SkMatrix ToSkMatrix(FT_Affine23 affine23) {
478     // Adjust order to convert from FreeType's FT_Affine23 column major order to SkMatrix row-major
479     // order.
480     return SkMatrix::MakeAll(
481         SkFixedToScalar(affine23.xx),  -SkFixedToScalar(affine23.xy), SkFixedToScalar(affine23.dx),
482         -SkFixedToScalar(affine23.yx),  SkFixedToScalar(affine23.yy), -SkFixedToScalar(affine23.dy),
483         0,                             0,                             1);
484 }
485 
SkVectorProjection(SkPoint a,SkPoint b)486 inline SkPoint SkVectorProjection(SkPoint a, SkPoint b) {
487     SkScalar length = b.length();
488     if (!length) return SkPoint();
489     SkPoint b_normalized = b;
490     b_normalized.normalize();
491     b_normalized.scale(SkPoint::DotProduct(a, b) / length);
492     return b_normalized;
493 }
494 
colrv1_configure_skpaint(FT_Face face,const SkSpan<FT_Color> & palette,const SkColor foregroundColor,FT_COLR_Paint colrv1_paint,SkPaint * paint)495 bool colrv1_configure_skpaint(FT_Face face,
496                               const SkSpan<FT_Color>& palette,
497                               const SkColor foregroundColor,
498                               FT_COLR_Paint colrv1_paint,
499                               SkPaint* paint) {
500     auto fetch_color_stops = [&face, &palette, &foregroundColor](
501                                                FT_ColorStopIterator& color_stop_iterator,
502                                                std::vector<SkScalar>& stops,
503                                                std::vector<SkColor>& colors) -> bool {
504         const FT_UInt num_color_stops = color_stop_iterator.num_color_stops;
505 
506         // 5.7.11.2.4 ColorIndex, ColorStop and ColorLine
507         // "Applications shall apply the colorStops in increasing stopOffset order."
508         struct ColorStop {
509           SkScalar stop_pos;
510           SkColor color;
511         };
512         std::vector<ColorStop> sorted_stops;
513         sorted_stops.resize(num_color_stops);
514 
515         FT_ColorStop color_stop;
516         while (FT_Get_Colorline_Stops(face, &color_stop, &color_stop_iterator)) {
517             FT_UInt index = color_stop_iterator.current_color_stop - 1;
518             sorted_stops[index].stop_pos = color_stop.stop_offset / float(1 << 14);
519             FT_UInt16& palette_index = color_stop.color.palette_index;
520             if (palette_index == kForegroundColorPaletteIndex) {
521                 U8CPU newAlpha = SkColorGetA(foregroundColor) *
522                                  SkColrV1AlphaToFloat(color_stop.color.alpha);
523                 sorted_stops[index].color = SkColorSetA(foregroundColor, newAlpha);
524             } else if (palette_index >= palette.size()) {
525                 return false;
526             } else {
527                 U8CPU newAlpha = palette[palette_index].alpha *
528                                  SkColrV1AlphaToFloat(color_stop.color.alpha);
529                 sorted_stops[index].color = SkColorSetARGB(newAlpha,
530                                                            palette[palette_index].red,
531                                                            palette[palette_index].green,
532                                                            palette[palette_index].blue);
533             }
534         }
535 
536         std::stable_sort(
537                 sorted_stops.begin(),
538                 sorted_stops.end(),
539                 [](const ColorStop& a, const ColorStop& b) { return a.stop_pos < b.stop_pos; });
540 
541         stops.resize(num_color_stops);
542         colors.resize(num_color_stops);
543         for (size_t i = 0; i < num_color_stops; ++i) {
544             stops[i] = sorted_stops[i].stop_pos;
545             colors[i] = sorted_stops[i].color;
546         }
547         return true;
548     };
549 
550     switch (colrv1_paint.format) {
551         case FT_COLR_PAINTFORMAT_SOLID: {
552             FT_PaintSolid solid = colrv1_paint.u.solid;
553 
554             // Dont' draw anything with this color if the palette index is out of bounds.
555             SkColor color = SK_ColorTRANSPARENT;
556             if (solid.color.palette_index == kForegroundColorPaletteIndex) {
557                 U8CPU newAlpha = SkColorGetA(foregroundColor) *
558                                  SkColrV1AlphaToFloat(solid.color.alpha);
559                 color = SkColorSetA(foregroundColor, newAlpha);
560             } else if (solid.color.palette_index >= palette.size()) {
561                 return false;
562             } else {
563                 U8CPU newAlpha = palette[solid.color.palette_index].alpha *
564                                  SkColrV1AlphaToFloat(solid.color.alpha);
565                 color = SkColorSetARGB(newAlpha,
566                                        palette[solid.color.palette_index].red,
567                                        palette[solid.color.palette_index].green,
568                                        palette[solid.color.palette_index].blue);
569             }
570             paint->setShader(nullptr);
571             paint->setColor(color);
572             break;
573         }
574         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT: {
575             FT_PaintLinearGradient& linear_gradient = colrv1_paint.u.linear_gradient;
576             SkPoint line_positions[2] = {SkPoint::Make(SkFixedToScalar(linear_gradient.p0.x),
577                                                        -SkFixedToScalar(linear_gradient.p0.y)),
578                                          SkPoint::Make(SkFixedToScalar(linear_gradient.p1.x),
579                                                        -SkFixedToScalar(linear_gradient.p1.y))};
580             SkPoint p0 = line_positions[0];
581             SkPoint p1 = line_positions[1];
582             SkPoint p2 = SkPoint::Make(SkFixedToScalar(linear_gradient.p2.x),
583                                        -SkFixedToScalar(linear_gradient.p2.y));
584 
585             // Do not draw the gradient if p0p1 is parallel to p0p2.
586             if (p1 == p0 || p2 == p0 || !SkPoint::CrossProduct(p1 - p0, p2 - p0)) break;
587 
588             // Follow implementation note in nanoemoji:
589             // https://github.com/googlefonts/nanoemoji/blob/0ac6e7bb4d8202db692574d8530a9b643f1b3b3c/src/nanoemoji/svg.py#L188
590             // to compute a new gradient end point as the orthogonal projection of the vector from p0 to p1 onto a line
591             // perpendicular to line p0p2 and passing through p0.
592             SkVector perpendicular_to_p2_p0 = (p2 - p0);
593             perpendicular_to_p2_p0 = SkPoint::Make(perpendicular_to_p2_p0.y(), -perpendicular_to_p2_p0.x());
594             line_positions[1] = p0 + SkVectorProjection((p1 - p0), perpendicular_to_p2_p0);
595 
596             std::vector<SkScalar> stops;
597             std::vector<SkColor> colors;
598 
599             if (!fetch_color_stops(linear_gradient.colorline.color_stop_iterator, stops, colors) ||
600                 stops.empty()) {
601                 return false;
602             }
603 
604             if (stops.size() == 1) {
605                 paint->setColor(colors[0]);
606                 break;
607             }
608 
609             // Project/scale points according to stop extrema along p0p1 line,
610             // then scale stops to to [0, 1] range so that repeat modes work.
611             // The Skia linear gradient shader performs the repeat modes over
612             // the 0 to 1 range, that's why we need to scale the stops to within
613             // that range.
614             SkVector p0p1 = p1 - p0;
615             SkVector new_p0_offset = p0p1;
616             new_p0_offset.scale(stops.front());
617             SkVector new_p1_offset = p0p1;
618             new_p1_offset.scale(stops.back());
619 
620             line_positions[0] = p0 + new_p0_offset;
621             line_positions[1] = p0 + new_p1_offset;
622 
623             SkScalar scale_factor = 1 / (stops.back() - stops.front());
624             SkScalar start_offset = stops.front();
625             for (SkScalar& stop : stops) {
626                 stop = (stop - start_offset) * scale_factor;
627             }
628 
629             sk_sp<SkShader> shader(SkGradientShader::MakeLinear(
630                     line_positions,
631                     colors.data(),
632                     stops.data(),
633                     stops.size(),
634                     ToSkTileMode(linear_gradient.colorline.extend)));
635             SkASSERT(shader);
636             // An opaque color is needed to ensure the gradient is not modulated by alpha.
637             paint->setColor(SK_ColorBLACK);
638             paint->setShader(shader);
639 
640             break;
641         }
642         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT: {
643             FT_PaintRadialGradient& radial_gradient = colrv1_paint.u.radial_gradient;
644             SkPoint start = SkPoint::Make(SkFixedToScalar(radial_gradient.c0.x),
645                                           -SkFixedToScalar(radial_gradient.c0.y));
646             SkScalar radius = SkFixedToScalar(radial_gradient.r0);
647             SkPoint end = SkPoint::Make(SkFixedToScalar(radial_gradient.c1.x),
648                                         -SkFixedToScalar(radial_gradient.c1.y));
649             SkScalar end_radius = SkFixedToScalar(radial_gradient.r1);
650 
651 
652             std::vector<SkScalar> stops;
653             std::vector<SkColor> colors;
654             if (!fetch_color_stops(radial_gradient.colorline.color_stop_iterator, stops, colors)) {
655                 return false;
656             }
657 
658             // An opaque color is needed to ensure the gradient is not modulated by alpha.
659             paint->setColor(SK_ColorBLACK);
660 
661             paint->setShader(SkGradientShader::MakeTwoPointConical(
662                     start, radius, end, end_radius, colors.data(), stops.data(), stops.size(),
663                     ToSkTileMode(radial_gradient.colorline.extend)));
664             break;
665         }
666         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
667             FT_PaintSweepGradient& sweep_gradient = colrv1_paint.u.sweep_gradient;
668             SkPoint center = SkPoint::Make(SkFixedToScalar(sweep_gradient.center.x),
669                                            -SkFixedToScalar(sweep_gradient.center.y));
670             SkScalar startAngle = SkFixedToScalar(sweep_gradient.start_angle * 180.0f);
671             SkScalar endAngle = SkFixedToScalar(sweep_gradient.end_angle * 180.0f);
672 
673             std::vector<SkScalar> stops;
674             std::vector<SkColor> colors;
675             if (!fetch_color_stops(sweep_gradient.colorline.color_stop_iterator, stops, colors)) {
676                 return false;
677             }
678 
679             // An opaque color is needed to ensure the gradient is not modulated by alpha.
680             paint->setColor(SK_ColorBLACK);
681 
682             // Prepare angles to be within range for the shader.
683             auto clampAngleToRange= [](SkScalar angle) {
684               SkScalar clamped_angle = SkScalarMod(angle, 360.f);
685               if (clamped_angle < 0)
686                 return clamped_angle + 360.f;
687               return clamped_angle;
688             };
689             startAngle = clampAngleToRange(startAngle);
690             endAngle = clampAngleToRange(endAngle);
691             /* TODO: Spec clarifications on which side of the gradient is to be
692              * painted, repeat modes, how to handle 0 degrees transition, see
693              * https://github.com/googlefonts/colr-gradients-spec/issues/250 */
694             if (startAngle >= endAngle)
695               endAngle += 360.f;
696 
697             // Skia's angles start from the horizontal x-Axis, rotate left 90
698             // degrees and then mirror horizontally to correct for Skia angles
699             // going clockwise, COLR v1 angles going counterclockwise.
700             SkMatrix angle_adjust = SkMatrix::RotateDeg(-90.f, center);
701             angle_adjust.postScale(-1, 1, center.x(), center.y());
702 
703             paint->setShader(SkGradientShader::MakeSweep(
704                     center.x(), center.y(), colors.data(), stops.data(), stops.size(),
705                     SkTileMode::kDecal, startAngle, endAngle, 0, &angle_adjust));
706             break;
707         }
708         default: {
709             SkASSERT(false); /* not reached */
710         }
711     }
712     return true;
713 }
714 
colrv1_draw_paint(SkCanvas * canvas,const SkSpan<FT_Color> & palette,const SkColor foregroundColor,FT_Face face,FT_COLR_Paint colrv1_paint)715 void colrv1_draw_paint(SkCanvas* canvas,
716                        const SkSpan<FT_Color>& palette,
717                        const SkColor foregroundColor,
718                        FT_Face face,
719                        FT_COLR_Paint colrv1_paint) {
720     SkPaint paint;
721 
722     switch (colrv1_paint.format) {
723         case FT_COLR_PAINTFORMAT_GLYPH: {
724             FT_UInt glyphID = colrv1_paint.u.glyph.glyphID;
725             SkPath path;
726             /* TODO: Currently this call retrieves the path at units_per_em size. If we want to get
727              * correct hinting for the scaled size under the transforms at this point in the color
728              * glyph graph, we need to extract at least the requested glyph width and height and
729              * pass that to the path generation. */
730             if (generateFacePathCOLRv1(face, glyphID, &path)) {
731 
732 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
733               SkPaint highlight_paint;
734               highlight_paint.setColor(0x33FF0000);
735               canvas->drawRect(path.getBounds(), highlight_paint);
736 #endif
737               canvas->clipPath(path, true /* doAntiAlias */);
738             }
739             break;
740         }
741         case FT_COLR_PAINTFORMAT_SOLID:
742         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
743         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
744         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
745             SkPaint colrPaint;
746             if (colrv1_configure_skpaint(
747                         face, palette, foregroundColor, colrv1_paint, &colrPaint)) {
748                 canvas->drawPaint(colrPaint);
749             }
750             break;
751         }
752         case FT_COLR_PAINTFORMAT_TRANSFORM:
753         case FT_COLR_PAINTFORMAT_TRANSLATE:
754         case FT_COLR_PAINTFORMAT_SCALE:
755         case FT_COLR_PAINTFORMAT_ROTATE:
756         case FT_COLR_PAINTFORMAT_SKEW:
757             SkASSERT(false);  // Transforms handled in colrv1_transform.
758             break;
759         default:
760             paint.setShader(nullptr);
761             paint.setColor(SK_ColorCYAN);
762             break;
763     }
764 }
765 
colrv1_draw_glyph_with_path(SkCanvas * canvas,const SkSpan<FT_Color> & palette,SkColor foregroundColor,FT_Face face,FT_COLR_Paint glyphPaint,FT_COLR_Paint fillPaint)766 void colrv1_draw_glyph_with_path(SkCanvas* canvas, const SkSpan<FT_Color>& palette, SkColor foregroundColor, FT_Face face,
767                                  FT_COLR_Paint glyphPaint, FT_COLR_Paint fillPaint) {
768     SkASSERT(glyphPaint.format == FT_COLR_PAINTFORMAT_GLYPH);
769     SkASSERT(fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
770              fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
771              fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
772              fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT);
773 
774     SkPaint skiaFillPaint;
775     skiaFillPaint.setAntiAlias(true);
776     if (!colrv1_configure_skpaint(face, palette, foregroundColor, fillPaint, &skiaFillPaint)) {
777       return;
778     }
779 
780     FT_UInt glyphID = glyphPaint.u.glyph.glyphID;
781     SkPath path;
782     /* TODO: Currently this call retrieves the path at units_per_em size. If we want to get
783      * correct hinting for the scaled size under the transforms at this point in the color
784      * glyph graph, we need to extract at least the requested glyph width and height and
785      * pass that to the path generation. */
786     if (generateFacePathCOLRv1(face, glyphID, &path)) {
787 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
788         SkPaint highlight_paint;
789         highlight_paint.setColor(0x33FF0000);
790         canvas->drawRect(path.getBounds(), highlight_paint);
791 #endif
792         {
793             canvas->drawPath(path, skiaFillPaint);
794         }
795     }
796 }
797 
798 
799 /* In drawing mode, concatenates the transforms directly on SkCanvas. In
800  * bounding box calculation mode, no SkCanvas is specified, but we only want to
801  * retrieve the transform from the FreeType paint object. */
colrv1_transform(FT_Face face,FT_COLR_Paint colrv1_paint,SkCanvas * canvas,SkMatrix * out_transform=0)802 void colrv1_transform(FT_Face face,
803                       FT_COLR_Paint colrv1_paint,
804                       SkCanvas* canvas,
805                       SkMatrix* out_transform = 0) {
806     SkMatrix transform;
807 
808     SkASSERT(canvas || out_transform);
809 
810     switch (colrv1_paint.format) {
811         case FT_COLR_PAINTFORMAT_TRANSFORM: {
812             transform = ToSkMatrix(colrv1_paint.u.transform.affine);
813             break;
814         }
815         case FT_COLR_PAINTFORMAT_TRANSLATE: {
816             transform = SkMatrix::Translate(
817                 SkFixedToScalar(colrv1_paint.u.translate.dx),
818                 -SkFixedToScalar(colrv1_paint.u.translate.dy));
819             break;
820         }
821         case FT_COLR_PAINTFORMAT_SCALE: {
822             transform.setScale(SkFixedToScalar(colrv1_paint.u.scale.scale_x),
823                                SkFixedToScalar(colrv1_paint.u.scale.scale_y),
824                                SkFixedToScalar(colrv1_paint.u.scale.center_x),
825                                -SkFixedToScalar(colrv1_paint.u.scale.center_y));
826             break;
827         }
828         case FT_COLR_PAINTFORMAT_ROTATE: {
829             transform = SkMatrix::RotateDeg(
830                     SkFixedToScalar(colrv1_paint.u.rotate.angle) * 180.0f,
831                     SkPoint::Make(SkFixedToScalar(colrv1_paint.u.rotate.center_x),
832                                   -SkFixedToScalar(colrv1_paint.u.rotate.center_y)));
833             break;
834         }
835         case FT_COLR_PAINTFORMAT_SKEW: {
836             // In the PAINTFORMAT_ROTATE implementation, SkMatrix setRotate
837             // snaps to 0 for values very close to 0. Do the same here.
838 
839             SkScalar rad_x =
840                     SkDegreesToRadians(-SkFixedToFloat(colrv1_paint.u.skew.x_skew_angle) * 180.0f);
841             float tan_x = SkScalarTan(rad_x);
842             tan_x = SkScalarNearlyZero(tan_x) ? 0.0f : tan_x;
843 
844             SkScalar rad_y =
845                     SkDegreesToRadians(-SkFixedToFloat(colrv1_paint.u.skew.y_skew_angle) * 180.0f);
846             float tan_y = SkScalarTan(rad_y);
847             tan_y = SkScalarNearlyZero(tan_y) ? 0.0f : tan_y;
848 
849             transform.setSkew(tan_x,
850                               tan_y,
851                               SkFixedToScalar(colrv1_paint.u.skew.center_x),
852                               -SkFixedToFloat(colrv1_paint.u.skew.center_y));
853             break;
854         }
855         default: {
856             // Only transforms are handled in this function.
857             SkASSERT(false);
858         }
859     }
860     if (canvas) {
861         canvas->concat(transform);
862     }
863     if (out_transform) {
864         *out_transform = transform;
865     }
866 }
867 
868 bool colrv1_start_glyph(SkCanvas* canvas,
869                         const SkSpan<FT_Color>& palette,
870                         const SkColor foregroundColor,
871                         FT_Face ft_face,
872                         uint16_t glyph_id,
873                         FT_Color_Root_Transform root_transform);
874 
colrv1_traverse_paint(SkCanvas * canvas,const SkSpan<FT_Color> & palette,const SkColor foregroundColor,FT_Face face,FT_OpaquePaint opaque_paint,VisitedSet * visited_set)875 bool colrv1_traverse_paint(SkCanvas* canvas,
876                            const SkSpan<FT_Color>& palette,
877                            const SkColor foregroundColor,
878                            FT_Face face,
879                            FT_OpaquePaint opaque_paint,
880                            VisitedSet* visited_set) {
881     // Cycle detection, see section "5.7.11.1.9 Color glyphs as a directed acyclic graph".
882     if (visited_set->contains(opaque_paint)) {
883         return false;
884     }
885 
886     visited_set->add(opaque_paint);
887     SK_AT_SCOPE_EXIT(visited_set->remove(opaque_paint));
888 
889     FT_COLR_Paint paint;
890     if (!FT_Get_Paint(face, opaque_paint, &paint)) {
891       return false;
892     }
893 
894     // Keep track of failures to retrieve the FT_COLR_Paint from FreeType in the
895     // recursion, cancel recursion when a paint retrieval fails.
896     bool traverse_result = true;
897     SkAutoCanvasRestore autoRestore(canvas, true /* do_save */);
898     switch (paint.format) {
899         case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
900             FT_LayerIterator& layer_iterator = paint.u.colr_layers.layer_iterator;
901             FT_OpaquePaint opaque_paint_fetch;
902             opaque_paint_fetch.p = nullptr;
903             while (FT_Get_Paint_Layers(face, &layer_iterator, &opaque_paint_fetch)) {
904                 colrv1_traverse_paint(canvas, palette, foregroundColor, face,
905                                       opaque_paint_fetch, visited_set);
906             }
907             break;
908         }
909         case FT_COLR_PAINTFORMAT_GLYPH:
910             // Special case paint graph leaf situations to improve
911             // performance. These are situations in the graph where a GlyphPaint
912             // is followed by either a solid or a gradient fill. Here we can use
913             // drawPath() + SkPaint directly which is faster than setting a
914             // clipPath() followed by a drawPaint().
915             FT_COLR_Paint fillPaint;
916             if (!FT_Get_Paint(face, paint.u.glyph.paint, &fillPaint)) {
917                 return false;
918             }
919             if (fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
920                 fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
921                 fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
922                 fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT) {
923                 colrv1_draw_glyph_with_path(canvas, palette, foregroundColor,
924                                             face, paint, fillPaint);
925             } else {
926                 colrv1_draw_paint(canvas, palette, foregroundColor, face, paint);
927                 traverse_result = colrv1_traverse_paint(canvas, palette,
928                                                         foregroundColor, face,
929                                                         paint.u.glyph.paint,
930                                                         visited_set);
931             }
932             break;
933         case FT_COLR_PAINTFORMAT_COLR_GLYPH:
934             traverse_result = colrv1_start_glyph(canvas, palette, foregroundColor,
935                                                  face, paint.u.colr_glyph.glyphID,
936                                                  FT_COLOR_NO_ROOT_TRANSFORM);
937             break;
938         case FT_COLR_PAINTFORMAT_TRANSFORM:
939             colrv1_transform(face, paint, canvas);
940             traverse_result = colrv1_traverse_paint(canvas, palette, foregroundColor,
941                                                     face, paint.u.transform.paint,
942                                                     visited_set);
943             break;
944         case FT_COLR_PAINTFORMAT_TRANSLATE:
945             colrv1_transform(face, paint, canvas);
946             traverse_result = colrv1_traverse_paint(canvas, palette, foregroundColor,
947                                                     face, paint.u.translate.paint,
948                                                     visited_set);
949             break;
950         case FT_COLR_PAINTFORMAT_SCALE:
951             colrv1_transform(face, paint, canvas);
952             traverse_result = colrv1_traverse_paint(canvas, palette, foregroundColor,
953                                                     face, paint.u.scale.paint,
954                                                     visited_set);
955             break;
956         case FT_COLR_PAINTFORMAT_ROTATE:
957             colrv1_transform(face, paint, canvas);
958             traverse_result =
959                     colrv1_traverse_paint(canvas, palette, foregroundColor, face,
960                                           paint.u.rotate.paint, visited_set);
961             break;
962         case FT_COLR_PAINTFORMAT_SKEW:
963             colrv1_transform(face, paint, canvas);
964             traverse_result =
965                     colrv1_traverse_paint(canvas, palette, foregroundColor, face,
966                                           paint.u.skew.paint, visited_set);
967             break;
968         case FT_COLR_PAINTFORMAT_COMPOSITE: {
969             canvas->saveLayer(nullptr, nullptr);
970             traverse_result = colrv1_traverse_paint(
971                     canvas, palette, foregroundColor, face,
972                     paint.u.composite.backdrop_paint, visited_set);
973             SkPaint blend_mode_paint;
974             blend_mode_paint.setBlendMode(ToSkBlendMode(paint.u.composite.composite_mode));
975             canvas->saveLayer(nullptr, &blend_mode_paint);
976             traverse_result =
977                     traverse_result &&
978                     colrv1_traverse_paint(
979                             canvas, palette, foregroundColor,
980                             face, paint.u.composite.source_paint, visited_set);
981             canvas->restore();
982             canvas->restore();
983             break;
984         }
985         case FT_COLR_PAINTFORMAT_SOLID:
986         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
987         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
988         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
989             colrv1_draw_paint(canvas, palette, foregroundColor, face, paint);
990             break;
991         }
992         default:
993             SkASSERT(false);
994             break;
995     }
996     return traverse_result;
997 }
998 
GetClipBoxPath(FT_Face ft_face,uint16_t glyph_id,bool untransformed)999 SkPath GetClipBoxPath(FT_Face ft_face, uint16_t glyph_id, bool untransformed) {
1000     SkPath resultPath;
1001 
1002     using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
1003     std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> unscaledFtSize = nullptr;
1004 
1005     FT_Size oldSize = ft_face->size;
1006     FT_Matrix oldTransform;
1007     FT_Vector oldDelta;
1008     FT_Error err = 0;
1009 
1010     if (untransformed) {
1011         unscaledFtSize.reset(
1012                 [ft_face]() -> FT_Size {
1013                     FT_Size size;
1014                     FT_Error err = FT_New_Size(ft_face, &size);
1015                     if (err != 0) {
1016                         SK_TRACEFTR(err,
1017                                     "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.",
1018                                     ft_face->family_name);
1019                         return nullptr;
1020                     }
1021                     return size;
1022                 }());
1023         if (!unscaledFtSize) {
1024             return resultPath;
1025         }
1026 
1027         err = FT_Activate_Size(unscaledFtSize.get());
1028         if (err != 0) {
1029           return resultPath;
1030         }
1031 
1032         err = FT_Set_Char_Size(ft_face, SkIntToFDot6(ft_face->units_per_EM), 0, 0, 0);
1033         if (err != 0) {
1034           return resultPath;
1035         }
1036 
1037         FT_Get_Transform(ft_face, &oldTransform, &oldDelta);
1038         FT_Set_Transform(ft_face, nullptr, nullptr);
1039     }
1040 
1041     FT_ClipBox colrGlyphClipBox;
1042     if (FT_Get_Color_Glyph_ClipBox(ft_face, glyph_id, &colrGlyphClipBox)) {
1043         resultPath = SkPath::Polygon({{SkFDot6ToScalar(colrGlyphClipBox.bottom_left.x),
1044                                        -SkFDot6ToScalar(colrGlyphClipBox.bottom_left.y)},
1045                                       {SkFDot6ToScalar(colrGlyphClipBox.top_left.x),
1046                                        -SkFDot6ToScalar(colrGlyphClipBox.top_left.y)},
1047                                       {SkFDot6ToScalar(colrGlyphClipBox.top_right.x),
1048                                        -SkFDot6ToScalar(colrGlyphClipBox.top_right.y)},
1049                                       {SkFDot6ToScalar(colrGlyphClipBox.bottom_right.x),
1050                                        -SkFDot6ToScalar(colrGlyphClipBox.bottom_right.y)}},
1051                                      true);
1052     }
1053 
1054     if (untransformed) {
1055         err = FT_Activate_Size(oldSize);
1056         if (err != 0) {
1057           return resultPath;
1058         }
1059         FT_Set_Transform(ft_face, &oldTransform, &oldDelta);
1060     }
1061 
1062     return resultPath;
1063 }
1064 
colrv1_start_glyph(SkCanvas * canvas,const SkSpan<FT_Color> & palette,const SkColor foregroundColor,FT_Face ft_face,uint16_t glyph_id,FT_Color_Root_Transform root_transform)1065 bool colrv1_start_glyph(SkCanvas* canvas,
1066                         const SkSpan<FT_Color>& palette,
1067                         const SkColor foregroundColor,
1068                         FT_Face ft_face,
1069                         uint16_t glyph_id,
1070                         FT_Color_Root_Transform root_transform) {
1071     FT_OpaquePaint opaque_paint;
1072     opaque_paint.p = nullptr;
1073     bool has_colrv1_layers = false;
1074     if (FT_Get_Color_Glyph_Paint(ft_face, glyph_id, root_transform, &opaque_paint)) {
1075         has_colrv1_layers = true;
1076 
1077         SkPath clipBoxPath =
1078                 GetClipBoxPath(ft_face, glyph_id, root_transform == FT_COLOR_NO_ROOT_TRANSFORM);
1079         if (!clipBoxPath.isEmpty()) {
1080             canvas->clipPath(clipBoxPath, true);
1081         }
1082 
1083         VisitedSet visited_set;
1084         colrv1_traverse_paint(canvas, palette, foregroundColor,
1085                               ft_face, opaque_paint, &visited_set);
1086     }
1087     return has_colrv1_layers;
1088 }
1089 
1090 bool colrv1_start_glyph_bounds(SkMatrix *ctm,
1091                                SkRect* bounds,
1092                                FT_Face ft_face,
1093                                uint16_t glyph_id,
1094                                FT_Color_Root_Transform root_transform);
1095 
colrv1_traverse_paint_bounds(SkMatrix * ctm,SkRect * bounds,FT_Face face,FT_OpaquePaint opaque_paint,VisitedSet * visited_set)1096 bool colrv1_traverse_paint_bounds(SkMatrix* ctm,
1097                                   SkRect* bounds,
1098                                   FT_Face face,
1099                                   FT_OpaquePaint opaque_paint,
1100                                   VisitedSet* visited_set) {
1101     // Cycle detection, see section "5.7.11.1.9 Color glyphs as a directed acyclic graph".
1102     if (visited_set->contains(opaque_paint)) {
1103         return false;
1104     }
1105 
1106     visited_set->add(opaque_paint);
1107     SK_AT_SCOPE_EXIT(visited_set->remove(opaque_paint));
1108 
1109     FT_COLR_Paint paint;
1110     if (!FT_Get_Paint(face, opaque_paint, &paint)) {
1111       return false;
1112     }
1113 
1114     // Keep track of failures to retrieve the FT_COLR_Paint from FreeType in the
1115     // recursion, cancel recursion when a paint retrieval fails.
1116     bool traverse_result = true;
1117     SkMatrix restore_matrix = *ctm;
1118     SK_AT_SCOPE_EXIT(*ctm = restore_matrix);
1119 
1120     switch (paint.format) {
1121         case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
1122             FT_LayerIterator& layer_iterator = paint.u.colr_layers.layer_iterator;
1123             FT_OpaquePaint opaque_paint_fetch;
1124             opaque_paint_fetch.p = nullptr;
1125             while (FT_Get_Paint_Layers(face, &layer_iterator, &opaque_paint_fetch)) {
1126                 colrv1_traverse_paint_bounds(ctm, bounds, face, opaque_paint_fetch, visited_set);
1127             }
1128             break;
1129         }
1130         case FT_COLR_PAINTFORMAT_GLYPH: {
1131             FT_UInt glyphID = paint.u.glyph.glyphID;
1132             SkPath path;
1133             if ((traverse_result = generateFacePathCOLRv1(face, glyphID, &path))) {
1134               path.transform(*ctm);
1135               bounds->join(path.getBounds());
1136             }
1137             break;
1138         }
1139         case FT_COLR_PAINTFORMAT_COLR_GLYPH:
1140             traverse_result = colrv1_start_glyph_bounds(
1141                     ctm, bounds, face, paint.u.colr_glyph.glyphID, FT_COLOR_NO_ROOT_TRANSFORM);
1142             break;
1143 
1144         case FT_COLR_PAINTFORMAT_TRANSFORM: {
1145             SkMatrix transform_matrix;
1146             colrv1_transform(face, paint, nullptr, &transform_matrix);
1147             ctm->preConcat(transform_matrix);
1148             traverse_result = colrv1_traverse_paint_bounds(
1149                     ctm, bounds, face, paint.u.transform.paint, visited_set);
1150             break;
1151         }
1152         case FT_COLR_PAINTFORMAT_TRANSLATE: {
1153             SkMatrix transform_matrix;
1154             colrv1_transform(face, paint, nullptr, &transform_matrix);
1155             ctm->preConcat(transform_matrix);
1156             traverse_result = colrv1_traverse_paint_bounds(
1157                     ctm, bounds, face, paint.u.translate.paint, visited_set);
1158             break;
1159         }
1160         case FT_COLR_PAINTFORMAT_SCALE: {
1161             SkMatrix transform_matrix;
1162             colrv1_transform(face, paint, nullptr, &transform_matrix);
1163             ctm->preConcat(transform_matrix);
1164             traverse_result = colrv1_traverse_paint_bounds(
1165                     ctm, bounds, face, paint.u.scale.paint, visited_set);
1166             break;
1167         }
1168         case FT_COLR_PAINTFORMAT_ROTATE: {
1169             SkMatrix transform_matrix;
1170             colrv1_transform(face, paint, nullptr, &transform_matrix);
1171             ctm->preConcat(transform_matrix);
1172             traverse_result = colrv1_traverse_paint_bounds(
1173                     ctm, bounds, face, paint.u.rotate.paint, visited_set);
1174             break;
1175         }
1176         case FT_COLR_PAINTFORMAT_SKEW: {
1177             SkMatrix transform_matrix;
1178             colrv1_transform(face, paint, nullptr, &transform_matrix);
1179             ctm->preConcat(transform_matrix);
1180             traverse_result = colrv1_traverse_paint_bounds(
1181                     ctm, bounds, face, paint.u.skew.paint, visited_set);
1182             break;
1183         }
1184         case FT_COLR_PAINTFORMAT_COMPOSITE: {
1185             traverse_result = colrv1_traverse_paint_bounds(
1186                     ctm, bounds, face, paint.u.composite.backdrop_paint, visited_set);
1187             traverse_result = colrv1_traverse_paint_bounds(
1188                     ctm, bounds, face, paint.u.composite.source_paint, visited_set);
1189             break;
1190         }
1191         case FT_COLR_PAINTFORMAT_SOLID:
1192         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
1193         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
1194         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
1195             break;
1196         }
1197         default:
1198             SkASSERT(false);
1199             break;
1200 }
1201     return traverse_result;
1202 }
1203 
1204 
colrv1_start_glyph_bounds(SkMatrix * ctm,SkRect * bounds,FT_Face ft_face,uint16_t glyph_id,FT_Color_Root_Transform root_transform)1205 bool colrv1_start_glyph_bounds(SkMatrix *ctm,
1206                                SkRect* bounds,
1207                                FT_Face ft_face,
1208                                uint16_t glyph_id,
1209                                FT_Color_Root_Transform root_transform) {
1210     FT_OpaquePaint opaque_paint;
1211     opaque_paint.p = nullptr;
1212     bool has_colrv1_layers = false;
1213     if (FT_Get_Color_Glyph_Paint(ft_face, glyph_id, root_transform, &opaque_paint)) {
1214         has_colrv1_layers = true;
1215         VisitedSet visited_set;
1216         colrv1_traverse_paint_bounds(ctm, bounds, ft_face, opaque_paint, &visited_set);
1217     }
1218     return has_colrv1_layers;
1219 }
1220 #endif // TT_SUPPORT_COLRV1
1221 
1222 }  // namespace
1223 
generateGlyphImage(FT_Face face,const SkGlyph & glyph,const SkMatrix & bitmapTransform)1224 void SkScalerContext_FreeType_Base::generateGlyphImage(
1225     FT_Face face,
1226     const SkGlyph& glyph,
1227     const SkMatrix& bitmapTransform)
1228 {
1229     const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
1230     const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
1231 
1232     switch ( face->glyph->format ) {
1233         case FT_GLYPH_FORMAT_OUTLINE: {
1234             FT_Outline* outline = &face->glyph->outline;
1235 
1236             int dx = 0, dy = 0;
1237             if (this->isSubpixel()) {
1238                 dx = SkFixedToFDot6(glyph.getSubXFixed());
1239                 dy = SkFixedToFDot6(glyph.getSubYFixed());
1240                 // negate dy since freetype-y-goes-up and skia-y-goes-down
1241                 dy = -dy;
1242             }
1243 
1244             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
1245 
1246 #ifdef FT_COLOR_H
1247             if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
1248                 SkBitmap dstBitmap;
1249                 // TODO: mark this as sRGB when the blits will be sRGB.
1250                 dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
1251                                                     kN32_SkColorType,
1252                                                     kPremul_SkAlphaType),
1253                                                     glyph.rowBytes());
1254                 dstBitmap.setPixels(glyph.fImage);
1255 
1256                 // Scale unscaledBitmap into dstBitmap.
1257                 SkCanvas canvas(dstBitmap);
1258 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1259                 canvas.clear(0x33FF0000);
1260 #else
1261                 canvas.clear(SK_ColorTRANSPARENT);
1262 #endif
1263                 canvas.translate(-glyph.fLeft, -glyph.fTop);
1264 
1265                 if (this->isSubpixel()) {
1266                     canvas.translate(SkFixedToScalar(glyph.getSubXFixed()),
1267                                      SkFixedToScalar(glyph.getSubYFixed()));
1268                 }
1269 
1270                 SkPaint paint;
1271                 paint.setAntiAlias(true);
1272 
1273                 FT_Color *palette;
1274                 FT_Palette_Data palette_data;
1275 
1276                 FT_Error err = FT_Palette_Data_Get(face, &palette_data);
1277                 if (err) {
1278                     SK_TRACEFTR(err, "Could not get palette data from %s fontFace.", face->family_name);
1279                     return;
1280                 }
1281 
1282                 err = FT_Palette_Select(face, 0, &palette);
1283                 if (err) {
1284                     SK_TRACEFTR(err, "Could not get palette from %s fontFace.", face->family_name);
1285                     return;
1286                 }
1287 
1288                 SkSpan<FT_Color> paletteSpan(palette, palette_data.num_palette_entries);
1289 
1290                 FT_Bool haveLayers = false;
1291 
1292 #ifdef TT_SUPPORT_COLRV1
1293                 // Only attempt to draw COLRv1 glyph is FreeType is new enough
1294                 // to have the COLRv1 additions, as indicated by the
1295                 // TT_SUPPORT_COLRV1 flag defined by the FreeType headers in
1296                 // that case.
1297 
1298                 haveLayers = colrv1_start_glyph(&canvas, paletteSpan,
1299                                                 fRec.fForegroundColor,
1300                                                 face, glyph.getGlyphID(),
1301                                                 FT_COLOR_INCLUDE_ROOT_TRANSFORM);
1302 #else
1303                 haveLayers = false;
1304 #endif
1305                 if (!haveLayers) {
1306                     // If we didn't have colr v1 layers, try v0 layers.
1307                     FT_LayerIterator layerIterator;
1308                     layerIterator.p = NULL;
1309                     FT_UInt layerGlyphIndex = 0;
1310                     FT_UInt layerColorIndex = 0;
1311                     while (FT_Get_Color_Glyph_Layer(face, glyph.getGlyphID(), &layerGlyphIndex,
1312                                                     &layerColorIndex, &layerIterator)) {
1313                         haveLayers = true;
1314                         if (layerColorIndex == 0xFFFF) {
1315                             paint.setColor(fRec.fForegroundColor);
1316                         } else {
1317                             SkColor color = SkColorSetARGB(palette[layerColorIndex].alpha,
1318                                                            palette[layerColorIndex].red,
1319                                                            palette[layerColorIndex].green,
1320                                                            palette[layerColorIndex].blue);
1321                             paint.setColor(color);
1322                         }
1323                         SkPath path;
1324                         if (this->generateFacePath(face, layerGlyphIndex, &path)) {
1325                             canvas.drawPath(path, paint);
1326                         }
1327                     }
1328                 }
1329 
1330                 if (!haveLayers) {
1331                     SK_TRACEFTR(err, "Could not get layers (neither v0, nor v1) from %s fontFace.",
1332                                 face->family_name);
1333                     return;
1334                 }
1335             } else
1336 #endif
1337             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1338                 FT_Outline_Translate(outline, dx, dy);
1339                 FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
1340                                                                      FT_RENDER_MODE_LCD);
1341                 if (err) {
1342                     SK_TRACEFTR(err, "Could not render glyph %p.", face->glyph);
1343                     return;
1344                 }
1345 
1346                 SkMask mask = glyph.mask();
1347 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1348                 memset(mask.fImage, 0x80, mask.fBounds.height() * mask.fRowBytes);
1349 #endif
1350                 FT_GlyphSlotRec& ftGlyph = *face->glyph;
1351 
1352                 if (!SkIRect::Intersects(mask.fBounds,
1353                                          SkIRect::MakeXYWH( ftGlyph.bitmap_left,
1354                                                            -ftGlyph.bitmap_top,
1355                                                             ftGlyph.bitmap.width,
1356                                                             ftGlyph.bitmap.rows)))
1357                 {
1358                     return;
1359                 }
1360 
1361                 // If the FT_Bitmap extent is larger, discard bits of the bitmap outside the mask.
1362                 // If the SkMask extent is larger, shrink mask to fit bitmap (clearing discarded).
1363                 unsigned char* origBuffer = ftGlyph.bitmap.buffer;
1364                 // First align the top left (origin).
1365                 if (-ftGlyph.bitmap_top < mask.fBounds.fTop) {
1366                     int32_t topDiff = mask.fBounds.fTop - (-ftGlyph.bitmap_top);
1367                     ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff;
1368                     ftGlyph.bitmap.rows -= topDiff;
1369                     ftGlyph.bitmap_top = -mask.fBounds.fTop;
1370                 }
1371                 if (ftGlyph.bitmap_left < mask.fBounds.fLeft) {
1372                     int32_t leftDiff = mask.fBounds.fLeft - ftGlyph.bitmap_left;
1373                     ftGlyph.bitmap.buffer += leftDiff;
1374                     ftGlyph.bitmap.width -= leftDiff;
1375                     ftGlyph.bitmap_left = mask.fBounds.fLeft;
1376                 }
1377                 if (mask.fBounds.fTop < -ftGlyph.bitmap_top) {
1378                     mask.fImage += mask.fRowBytes * (-ftGlyph.bitmap_top - mask.fBounds.fTop);
1379                     mask.fBounds.fTop = -ftGlyph.bitmap_top;
1380                 }
1381                 if (mask.fBounds.fLeft < ftGlyph.bitmap_left) {
1382                     mask.fImage += sizeof(uint16_t) * (ftGlyph.bitmap_left - mask.fBounds.fLeft);
1383                     mask.fBounds.fLeft = ftGlyph.bitmap_left;
1384                 }
1385                 // Origins aligned, clean up the width and height.
1386                 int ftVertScale = (doVert ? 3 : 1);
1387                 int ftHoriScale = (doVert ? 1 : 3);
1388                 if (mask.fBounds.height() * ftVertScale < SkToInt(ftGlyph.bitmap.rows)) {
1389                     ftGlyph.bitmap.rows = mask.fBounds.height() * ftVertScale;
1390                 }
1391                 if (mask.fBounds.width() * ftHoriScale < SkToInt(ftGlyph.bitmap.width)) {
1392                     ftGlyph.bitmap.width = mask.fBounds.width() * ftHoriScale;
1393                 }
1394                 if (SkToInt(ftGlyph.bitmap.rows) < mask.fBounds.height() * ftVertScale) {
1395                     mask.fBounds.fBottom = mask.fBounds.fTop + ftGlyph.bitmap.rows / ftVertScale;
1396                 }
1397                 if (SkToInt(ftGlyph.bitmap.width) < mask.fBounds.width() * ftHoriScale) {
1398                     mask.fBounds.fRight = mask.fBounds.fLeft + ftGlyph.bitmap.width / ftHoriScale;
1399                 }
1400                 if (fPreBlend.isApplicable()) {
1401                     copyFT2LCD16<true>(ftGlyph.bitmap, mask, doBGR,
1402                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1403                 } else {
1404                     copyFT2LCD16<false>(ftGlyph.bitmap, mask, doBGR,
1405                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1406                 }
1407                 // Restore the buffer pointer so FreeType can properly free it.
1408                 ftGlyph.bitmap.buffer = origBuffer;
1409             } else {
1410                 FT_BBox     bbox;
1411                 FT_Bitmap   target;
1412                 FT_Outline_Get_CBox(outline, &bbox);
1413                 /*
1414                     what we really want to do for subpixel is
1415                         offset(dx, dy)
1416                         compute_bounds
1417                         offset(bbox & !63)
1418                     but that is two calls to offset, so we do the following, which
1419                     achieves the same thing with only one offset call.
1420                 */
1421                 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
1422                                               dy - ((bbox.yMin + dy) & ~63));
1423 
1424                 target.width = glyph.fWidth;
1425                 target.rows = glyph.fHeight;
1426                 target.pitch = glyph.rowBytes();
1427                 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
1428                 target.pixel_mode = compute_pixel_mode(glyph.fMaskFormat);
1429                 target.num_grays = 256;
1430 
1431                 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
1432 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1433                 for (int y = 0; y < glyph.fHeight; ++y) {
1434                     for (int x = 0; x < glyph.fWidth; ++x) {
1435                         uint8_t& a = ((uint8_t*)glyph.fImage)[(glyph.rowBytes() * y) + x];
1436                         a = std::max<uint8_t>(a, 0x20);
1437                     }
1438                 }
1439 #endif
1440             }
1441         } break;
1442 
1443         case FT_GLYPH_FORMAT_BITMAP: {
1444             FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
1445             SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1446 
1447             // Assume that the other formats do not exist.
1448             SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
1449                      FT_PIXEL_MODE_GRAY == pixel_mode ||
1450                      FT_PIXEL_MODE_BGRA == pixel_mode);
1451 
1452             // These are the only formats this ScalerContext should request.
1453             SkASSERT(SkMask::kBW_Format == maskFormat ||
1454                      SkMask::kA8_Format == maskFormat ||
1455                      SkMask::kARGB32_Format == maskFormat ||
1456                      SkMask::kLCD16_Format == maskFormat);
1457 
1458             // If no scaling needed, directly copy glyph bitmap.
1459             if (bitmapTransform.isIdentity()) {
1460                 SkMask dstMask = glyph.mask();
1461                 copyFTBitmap(face->glyph->bitmap, dstMask);
1462                 break;
1463             }
1464 
1465             // Otherwise, scale the bitmap.
1466 
1467             // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
1468             SkBitmap unscaledBitmap;
1469             // TODO: mark this as sRGB when the blits will be sRGB.
1470             unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
1471                                                          face->glyph->bitmap.rows,
1472                                                          SkColorType_for_FTPixelMode(pixel_mode),
1473                                                          kPremul_SkAlphaType));
1474 
1475             SkMask unscaledBitmapAlias;
1476             unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
1477             unscaledBitmapAlias.fBounds.setWH(unscaledBitmap.width(), unscaledBitmap.height());
1478             unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
1479             unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
1480             copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
1481 
1482             // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
1483             // BW requires an A8 target for resizing, which can then be down sampled.
1484             // LCD should use a 4x A8 target, which will then be down sampled.
1485             // For simplicity, LCD uses A8 and is replicated.
1486             int bitmapRowBytes = 0;
1487             if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) {
1488                 bitmapRowBytes = glyph.rowBytes();
1489             }
1490             SkBitmap dstBitmap;
1491             // TODO: mark this as sRGB when the blits will be sRGB.
1492             dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
1493                                                 SkColorType_for_SkMaskFormat(maskFormat),
1494                                                 kPremul_SkAlphaType),
1495                               bitmapRowBytes);
1496             if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
1497                 dstBitmap.allocPixels();
1498             } else {
1499                 dstBitmap.setPixels(glyph.fImage);
1500             }
1501 
1502             // Scale unscaledBitmap into dstBitmap.
1503             SkCanvas canvas(dstBitmap);
1504 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1505             canvas.clear(0x33FF0000);
1506 #else
1507             canvas.clear(SK_ColorTRANSPARENT);
1508 #endif
1509             canvas.translate(-glyph.fLeft, -glyph.fTop);
1510             canvas.concat(bitmapTransform);
1511             canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top);
1512 
1513             SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNearest);
1514             canvas.drawImage(unscaledBitmap.asImage().get(), 0, 0, sampling, nullptr);
1515 
1516             // If the destination is BW or LCD, convert from A8.
1517             if (SkMask::kBW_Format == maskFormat) {
1518                 // Copy the A8 dstBitmap into the A1 glyph.fImage.
1519                 SkMask dstMask = glyph.mask();
1520                 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes());
1521             } else if (SkMask::kLCD16_Format == maskFormat) {
1522                 // Copy the A8 dstBitmap into the LCD16 glyph.fImage.
1523                 uint8_t* src = dstBitmap.getAddr8(0, 0);
1524                 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
1525                 for (int y = dstBitmap.height(); y --> 0;) {
1526                     for (int x = 0; x < dstBitmap.width(); ++x) {
1527                         dst[x] = grayToRGB16(src[x]);
1528                     }
1529                     dst = (uint16_t*)((char*)dst + glyph.rowBytes());
1530                     src += dstBitmap.rowBytes();
1531                 }
1532             }
1533 
1534         } break;
1535 
1536         default:
1537             SkDEBUGFAIL("unknown glyph format");
1538             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
1539             return;
1540     }
1541 
1542 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum,
1543 // it is optional
1544 #if defined(SK_GAMMA_APPLY_TO_A8)
1545     if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) {
1546         uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
1547         unsigned rowBytes = glyph.rowBytes();
1548 
1549         for (int y = glyph.fHeight - 1; y >= 0; --y) {
1550             for (int x = glyph.fWidth - 1; x >= 0; --x) {
1551                 dst[x] = fPreBlend.fG[dst[x]];
1552             }
1553             dst += rowBytes;
1554         }
1555     }
1556 #endif
1557 }
1558 
1559 ///////////////////////////////////////////////////////////////////////////////
1560 
1561 namespace {
1562 
1563 class SkFTGeometrySink {
1564     SkPath* fPath;
1565     bool fStarted;
1566     FT_Vector fCurrent;
1567 
goingTo(const FT_Vector * pt)1568     void goingTo(const FT_Vector* pt) {
1569         if (!fStarted) {
1570             fStarted = true;
1571             fPath->moveTo(SkFDot6ToScalar(fCurrent.x), -SkFDot6ToScalar(fCurrent.y));
1572         }
1573         fCurrent = *pt;
1574     }
1575 
currentIsNot(const FT_Vector * pt)1576     bool currentIsNot(const FT_Vector* pt) {
1577         return fCurrent.x != pt->x || fCurrent.y != pt->y;
1578     }
1579 
Move(const FT_Vector * pt,void * ctx)1580     static int Move(const FT_Vector* pt, void* ctx) {
1581         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1582         if (self.fStarted) {
1583             self.fPath->close();
1584             self.fStarted = false;
1585         }
1586         self.fCurrent = *pt;
1587         return 0;
1588     }
1589 
Line(const FT_Vector * pt,void * ctx)1590     static int Line(const FT_Vector* pt, void* ctx) {
1591         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1592         if (self.currentIsNot(pt)) {
1593             self.goingTo(pt);
1594             self.fPath->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
1595         }
1596         return 0;
1597     }
1598 
Quad(const FT_Vector * pt0,const FT_Vector * pt1,void * ctx)1599     static int Quad(const FT_Vector* pt0, const FT_Vector* pt1, void* ctx) {
1600         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1601         if (self.currentIsNot(pt0) || self.currentIsNot(pt1)) {
1602             self.goingTo(pt1);
1603             self.fPath->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
1604                                SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
1605         }
1606         return 0;
1607     }
1608 
Cubic(const FT_Vector * pt0,const FT_Vector * pt1,const FT_Vector * pt2,void * ctx)1609     static int Cubic(const FT_Vector* pt0, const FT_Vector* pt1, const FT_Vector* pt2, void* ctx) {
1610         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1611         if (self.currentIsNot(pt0) || self.currentIsNot(pt1) || self.currentIsNot(pt2)) {
1612             self.goingTo(pt2);
1613             self.fPath->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
1614                                 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
1615                                 SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
1616         }
1617         return 0;
1618     }
1619 
1620 public:
SkFTGeometrySink(SkPath * path)1621     SkFTGeometrySink(SkPath* path) : fPath{path}, fStarted{false}, fCurrent{0,0} {}
1622 
1623     inline static constexpr const FT_Outline_Funcs Funcs{
1624         /*move_to =*/ SkFTGeometrySink::Move,
1625         /*line_to =*/ SkFTGeometrySink::Line,
1626         /*conic_to =*/ SkFTGeometrySink::Quad,
1627         /*cubic_to =*/ SkFTGeometrySink::Cubic,
1628         /*shift = */ 0,
1629         /*delta =*/ 0,
1630     };
1631 };
1632 
generateGlyphPathStatic(FT_Face face,SkPath * path)1633 bool generateGlyphPathStatic(FT_Face face, SkPath* path) {
1634     SkFTGeometrySink sink{path};
1635     FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &SkFTGeometrySink::Funcs, &sink);
1636 
1637     if (err != 0) {
1638         path->reset();
1639         return false;
1640     }
1641 
1642     path->close();
1643     return true;
1644 }
1645 
generateFacePathStatic(FT_Face face,SkGlyphID glyphID,SkPath * path)1646 bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, SkPath* path) {
1647     uint32_t flags = 0; //fLoadGlyphFlags;
1648     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1649     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1650 
1651     FT_Error err = FT_Load_Glyph(face, glyphID, flags);
1652     if (err != 0) {
1653         path->reset();
1654         return false;
1655     }
1656 
1657     if (!generateGlyphPathStatic(face, path)) {
1658         path->reset();
1659         return false;
1660     }
1661     return true;
1662 }
1663 
1664 #ifdef TT_SUPPORT_COLRV1
generateFacePathCOLRv1(FT_Face face,SkGlyphID glyphID,SkPath * path)1665 bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path) {
1666     uint32_t flags = 0;
1667     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1668     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1669 
1670     flags |= FT_LOAD_IGNORE_TRANSFORM;
1671 
1672 
1673     using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
1674     std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> unscaledFtSize([face]() -> FT_Size {
1675         FT_Size size;
1676         FT_Error err = FT_New_Size(face, &size);
1677         if (err != 0) {
1678             SK_TRACEFTR(err, "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.", face->family_name);
1679             return nullptr;
1680         }
1681         return size;
1682     }());
1683 
1684     if (!unscaledFtSize) {
1685       return false;
1686     }
1687 
1688     FT_Size oldSize = face->size;
1689 
1690     auto try_generate_path = [face, &unscaledFtSize, glyphID, flags, path]() {
1691         FT_Error err = 0;
1692 
1693         err = FT_Activate_Size(unscaledFtSize.get());
1694         if (err != 0) {
1695           return false;
1696         }
1697 
1698         err = FT_Set_Char_Size(face, SkIntToFDot6(face->units_per_EM),
1699                                SkIntToFDot6(face->units_per_EM), 72, 72);
1700         if (err != 0) {
1701             return false;
1702         }
1703 
1704         err = FT_Load_Glyph(face, glyphID, flags);
1705         if (err != 0) {
1706             path->reset();
1707             return false;
1708         }
1709 
1710         if (!generateGlyphPathStatic(face, path)) {
1711             path->reset();
1712             return false;
1713         }
1714 
1715         return true;
1716     };
1717 
1718     bool path_generation_result = try_generate_path();
1719 
1720     FT_Activate_Size(oldSize);
1721 
1722     return path_generation_result;
1723 }
1724 #endif
1725 
1726 }  // namespace
1727 
generateGlyphPath(FT_Face face,SkPath * path)1728 bool SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
1729     return generateGlyphPathStatic(face, path);
1730 }
1731 
generateFacePath(FT_Face face,SkGlyphID glyphID,SkPath * path)1732 bool SkScalerContext_FreeType_Base::generateFacePath(FT_Face face,
1733                                                      SkGlyphID glyphID,
1734                                                      SkPath* path) {
1735     return generateFacePathStatic(face, glyphID, path);
1736 }
1737 
computeColrV1GlyphBoundingBox(FT_Face face,SkGlyphID glyphID,FT_BBox * boundingBox)1738 bool SkScalerContext_FreeType_Base::computeColrV1GlyphBoundingBox(FT_Face face,
1739                                                                   SkGlyphID glyphID,
1740                                                                   FT_BBox* boundingBox) {
1741 #ifdef TT_SUPPORT_COLRV1
1742     SkMatrix ctm;
1743     SkRect bounds = SkRect::MakeEmpty();
1744     if (!colrv1_start_glyph_bounds(&ctm, &bounds, face, glyphID, FT_COLOR_INCLUDE_ROOT_TRANSFORM)) {
1745         return false;
1746     }
1747 
1748     /* Convert back to FT_BBox as caller needs it in this format. */
1749     bounds.sort();
1750     boundingBox->xMin = SkScalarToFDot6(bounds.left());
1751     boundingBox->xMax = SkScalarToFDot6(bounds.right());
1752     boundingBox->yMin = SkScalarToFDot6(-bounds.bottom());
1753     boundingBox->yMax = SkScalarToFDot6(-bounds.top());
1754 
1755     return true;
1756 #else
1757     SkASSERT(false);
1758     return false;
1759 #endif
1760 }
1761