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 struct OpaquePaintHasher {
operator ()__anon91630c750111::OpaquePaintHasher388   size_t operator()(const FT_OpaquePaint& opaque_paint) {
389       return SkGoodHash()(opaque_paint.p) ^
390              SkGoodHash()(opaque_paint.insert_root_transform);
391   }
392 };
393 
394 using VisitedSet = SkTHashSet<FT_OpaquePaint, OpaquePaintHasher>;
395 
396 bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path);
397 
SkColrV1AlphaToFloat(uint16_t alpha)398 inline float SkColrV1AlphaToFloat(uint16_t alpha) { return (alpha / float(1 << 14)); }
399 
400 
ToSkTileMode(FT_PaintExtend extend_mode)401 inline SkTileMode ToSkTileMode(FT_PaintExtend extend_mode) {
402     switch (extend_mode) {
403         case FT_COLR_PAINT_EXTEND_REPEAT:
404             return SkTileMode::kRepeat;
405         case FT_COLR_PAINT_EXTEND_REFLECT:
406             return SkTileMode::kMirror;
407         default:
408             return SkTileMode::kClamp;
409     }
410 }
411 
ToSkBlendMode(FT_Composite_Mode composite)412 inline SkBlendMode ToSkBlendMode(FT_Composite_Mode composite) {
413     switch (composite) {
414         case FT_COLR_COMPOSITE_CLEAR:
415             return SkBlendMode::kClear;
416         case FT_COLR_COMPOSITE_SRC:
417             return SkBlendMode::kSrc;
418         case FT_COLR_COMPOSITE_DEST:
419             return SkBlendMode::kDst;
420         case FT_COLR_COMPOSITE_SRC_OVER:
421             return SkBlendMode::kSrcOver;
422         case FT_COLR_COMPOSITE_DEST_OVER:
423             return SkBlendMode::kDstOver;
424         case FT_COLR_COMPOSITE_SRC_IN:
425             return SkBlendMode::kSrcIn;
426         case FT_COLR_COMPOSITE_DEST_IN:
427             return SkBlendMode::kDstIn;
428         case FT_COLR_COMPOSITE_SRC_OUT:
429             return SkBlendMode::kSrcOut;
430         case FT_COLR_COMPOSITE_DEST_OUT:
431             return SkBlendMode::kDstOut;
432         case FT_COLR_COMPOSITE_SRC_ATOP:
433             return SkBlendMode::kSrcATop;
434         case FT_COLR_COMPOSITE_DEST_ATOP:
435             return SkBlendMode::kDstATop;
436         case FT_COLR_COMPOSITE_XOR:
437             return SkBlendMode::kXor;
438         case FT_COLR_COMPOSITE_SCREEN:
439             return SkBlendMode::kScreen;
440         case FT_COLR_COMPOSITE_OVERLAY:
441             return SkBlendMode::kOverlay;
442         case FT_COLR_COMPOSITE_DARKEN:
443             return SkBlendMode::kDarken;
444         case FT_COLR_COMPOSITE_LIGHTEN:
445             return SkBlendMode::kLighten;
446         case FT_COLR_COMPOSITE_COLOR_DODGE:
447             return SkBlendMode::kColorDodge;
448         case FT_COLR_COMPOSITE_COLOR_BURN:
449             return SkBlendMode::kColorBurn;
450         case FT_COLR_COMPOSITE_HARD_LIGHT:
451             return SkBlendMode::kHardLight;
452         case FT_COLR_COMPOSITE_SOFT_LIGHT:
453             return SkBlendMode::kSoftLight;
454         case FT_COLR_COMPOSITE_DIFFERENCE:
455             return SkBlendMode::kDifference;
456         case FT_COLR_COMPOSITE_EXCLUSION:
457             return SkBlendMode::kExclusion;
458         case FT_COLR_COMPOSITE_MULTIPLY:
459             return SkBlendMode::kMultiply;
460         case FT_COLR_COMPOSITE_HSL_HUE:
461             return SkBlendMode::kHue;
462         case FT_COLR_COMPOSITE_HSL_SATURATION:
463             return SkBlendMode::kSaturation;
464         case FT_COLR_COMPOSITE_HSL_COLOR:
465             return SkBlendMode::kColor;
466         case FT_COLR_COMPOSITE_HSL_LUMINOSITY:
467             return SkBlendMode::kLuminosity;
468         default:
469             return SkBlendMode::kDst;
470     }
471 }
472 
ToSkMatrix(FT_Affine23 affine23)473 inline SkMatrix ToSkMatrix(FT_Affine23 affine23) {
474     // Adjust order to convert from FreeType's FT_Affine23 column major order to SkMatrix row-major
475     // order.
476     return SkMatrix::MakeAll(
477         SkFixedToScalar(affine23.xx),  -SkFixedToScalar(affine23.xy), SkFixedToScalar(affine23.dx),
478         -SkFixedToScalar(affine23.yx),  SkFixedToScalar(affine23.yy), -SkFixedToScalar(affine23.dy),
479         0,                             0,                             1);
480 }
481 
SkVectorProjection(SkPoint a,SkPoint b)482 inline SkPoint SkVectorProjection(SkPoint a, SkPoint b) {
483     SkScalar length = b.length();
484     if (!length) return SkPoint();
485     SkPoint b_normalized = b;
486     b_normalized.normalize();
487     b_normalized.scale(SkPoint::DotProduct(a, b) / length);
488     return b_normalized;
489 }
490 
colrv1_configure_skpaint(FT_Face face,const FT_Color * palette,FT_COLR_Paint colrv1_paint,SkPaint * paint)491 void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
492                               FT_COLR_Paint colrv1_paint, SkPaint* paint) {
493 
494     auto fetch_color_stops = [&face, &palette](FT_ColorStopIterator& color_stop_iterator,
495                                                std::vector<SkScalar>& stops,
496                                                std::vector<SkColor>& colors) {
497         const FT_UInt num_color_stops = color_stop_iterator.num_color_stops;
498         stops.resize(num_color_stops);
499         colors.resize(num_color_stops);
500 
501         FT_ColorStop color_stop;
502         while (FT_Get_Colorline_Stops(face, &color_stop, &color_stop_iterator)) {
503             FT_UInt index = color_stop_iterator.current_color_stop - 1;
504             stops[index] = color_stop.stop_offset / float(1 << 14);
505             FT_UInt16& palette_index = color_stop.color.palette_index;
506             // TODO(drott): Ensure palette_index is sanitized on the FreeType
507             // side and 0xFFFF foreground color will be handled correctly here.
508             colors[index] = SkColorSetARGB(
509                     palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha),
510                     palette[palette_index].red,
511                     palette[palette_index].green,
512                     palette[palette_index].blue);
513         }
514     };
515 
516     switch (colrv1_paint.format) {
517         case FT_COLR_PAINTFORMAT_SOLID: {
518             SkColor color =
519                     SkColorSetARGB(palette[colrv1_paint.u.solid.color.palette_index].alpha *
520                                            SkColrV1AlphaToFloat(colrv1_paint.u.solid.color.alpha),
521                                    palette[colrv1_paint.u.solid.color.palette_index].red,
522                                    palette[colrv1_paint.u.solid.color.palette_index].green,
523                                    palette[colrv1_paint.u.solid.color.palette_index].blue);
524             paint->setShader(nullptr);
525             paint->setColor(color);
526             break;
527         }
528         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT: {
529             /* retrieve color stop */
530 
531             SkPoint line_positions[2];
532             line_positions[0].fX = colrv1_paint.u.linear_gradient.p0.x;
533             line_positions[0].fY = -colrv1_paint.u.linear_gradient.p0.y;
534             line_positions[1].fX = colrv1_paint.u.linear_gradient.p1.x;
535             line_positions[1].fY = -colrv1_paint.u.linear_gradient.p1.y;
536 
537             SkPoint& p0 = line_positions[0];
538             SkPoint& p1 = line_positions[1];
539             SkPoint p2;
540             p2.set(colrv1_paint.u.linear_gradient.p2.x,
541                    -colrv1_paint.u.linear_gradient.p2.y);
542 
543             // Do not draw the gradient of p0p1 is parallel to p0p2.
544             if (p1 == p0 || p2 == p0 || !SkPoint::CrossProduct(p1 - p0, p2 - p0)) break;
545 
546             // Follow implementation note in nanoemoji:
547             // https://github.com/googlefonts/nanoemoji/blob/0ac6e7bb4d8202db692574d8530a9b643f1b3b3c/src/nanoemoji/svg.py#L188
548             // to compute a new gradient end point as the orthogonal projection of the vector from p0 to p1 onto a line
549             // perpendicular to line p0p2 and passing through p0.
550             SkPoint perpendicular_to_p2_p0 = (p2 - p0);
551             perpendicular_to_p2_p0 = SkPoint::Make(perpendicular_to_p2_p0.y(), -perpendicular_to_p2_p0.x());
552             line_positions[1] = p0 + SkVectorProjection((p1 - p0), perpendicular_to_p2_p0);
553 
554             std::vector<SkScalar> stops;
555             std::vector<SkColor> colors;
556             fetch_color_stops(colrv1_paint.u.linear_gradient.colorline.color_stop_iterator, stops, colors);
557 
558             sk_sp<SkShader> shader(SkGradientShader::MakeLinear(
559                     line_positions, colors.data(), stops.data(), stops.size(),
560                     ToSkTileMode(colrv1_paint.u.linear_gradient.colorline.extend)));
561             SkASSERT(shader);
562             // An opaque color is needed to ensure the gradient's not modulated by alpha.
563             paint->setColor(SK_ColorBLACK);
564             paint->setShader(shader);
565 
566 
567             break;
568         }
569         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT: {
570             SkPoint start =
571                     SkPoint::Make(colrv1_paint.u.radial_gradient.c0.x,
572                                   -colrv1_paint.u.radial_gradient.c0.y);
573             SkScalar radius = colrv1_paint.u.radial_gradient.r0;
574             SkPoint end = SkPoint::Make(colrv1_paint.u.radial_gradient.c1.x,
575                                         -colrv1_paint.u.radial_gradient.c1.y);
576             SkScalar end_radius = colrv1_paint.u.radial_gradient.r1;
577 
578 
579             std::vector<SkScalar> stops;
580             std::vector<SkColor> colors;
581             fetch_color_stops(colrv1_paint.u.radial_gradient.colorline.color_stop_iterator, stops, colors);
582 
583             // An opaque color is needed to ensure the gradient's not modulated by alpha.
584             paint->setColor(SK_ColorBLACK);
585 
586             paint->setShader(SkGradientShader::MakeTwoPointConical(
587                     start, radius, end, end_radius, colors.data(), stops.data(), stops.size(),
588                     ToSkTileMode(colrv1_paint.u.radial_gradient.colorline.extend)));
589             break;
590         }
591         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
592             SkPoint center = SkPoint::Make(colrv1_paint.u.sweep_gradient.center.x,
593                                            -colrv1_paint.u.sweep_gradient.center.y);
594             SkScalar startAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.start_angle);
595             SkScalar endAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.end_angle);
596 
597             std::vector<SkScalar> stops;
598             std::vector<SkColor> colors;
599             fetch_color_stops(colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator, stops, colors);
600 
601             // An opaque color is needed to ensure the gradient's not modulated by alpha.
602             paint->setColor(SK_ColorBLACK);
603 
604             // Prepare angles to be within range for the shader.
605             auto clampAngleToRange= [](SkScalar angle) {
606               SkScalar clamped_angle = SkScalarMod(angle, 360.f);
607               if (clamped_angle < 0)
608                 return clamped_angle + 360.f;
609               return clamped_angle;
610             };
611             startAngle = clampAngleToRange(startAngle);
612             endAngle = clampAngleToRange(endAngle);
613             /* TODO: Spec clarifications on which side of the gradient is to be
614              * painted, repeat modes, how to handle 0 degrees transition, see
615              * https://github.com/googlefonts/colr-gradients-spec/issues/250 */
616             if (startAngle >= endAngle)
617               endAngle += 360.f;
618 
619             // Skia's angles start from the horizontal x-Axis, rotate left 90
620             // degrees and then mirror horizontally to correct for Skia angles
621             // going clockwise, COLR v1 angles going counterclockwise.
622             SkMatrix angle_adjust = SkMatrix::RotateDeg(-90.f, center);
623             angle_adjust.postScale(-1, 1, center.x(), center.y());
624 
625             paint->setShader(SkGradientShader::MakeSweep(
626                     center.x(), center.y(), colors.data(), stops.data(), stops.size(),
627                     SkTileMode::kDecal, startAngle, endAngle, 0, &angle_adjust));
628             break;
629         }
630         default: {
631             SkASSERT(false); /* not reached */
632         }
633     }
634 }
635 
636 
colrv1_draw_paint(SkCanvas * canvas,const FT_Color * palette,FT_Face face,FT_COLR_Paint colrv1_paint)637 void colrv1_draw_paint(SkCanvas* canvas,
638                        const FT_Color* palette,
639                        FT_Face face,
640                        FT_COLR_Paint colrv1_paint) {
641     SkPaint paint;
642 
643     switch (colrv1_paint.format) {
644         case FT_COLR_PAINTFORMAT_GLYPH: {
645             FT_UInt glyphID = colrv1_paint.u.glyph.glyphID;
646             SkPath path;
647             /* TODO: Currently this call retrieves the path at units_per_em size. If we want to get
648              * correct hinting for the scaled size under the transforms at this point in the color
649              * glyph graph, we need to extract at least the requested glyph width and height and
650              * pass that to the path generation. */
651             if (generateFacePathCOLRv1(face, glyphID, &path)) {
652 
653 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
654               SkPaint highlight_paint;
655               highlight_paint.setColor(0x33FF0000);
656               canvas->drawRect(path.getBounds(), highlight_paint);
657 #endif
658               canvas->clipPath(path, true /* doAntiAlias */);
659             }
660             break;
661         }
662         case FT_COLR_PAINTFORMAT_SOLID:
663         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
664         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
665         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
666             SkPaint colrPaint;
667             colrv1_configure_skpaint(face, palette, colrv1_paint, &colrPaint);
668             canvas->drawPaint(colrPaint);
669             break;
670         }
671         case FT_COLR_PAINTFORMAT_TRANSFORMED:
672         case FT_COLR_PAINTFORMAT_TRANSLATE:
673         case FT_COLR_PAINTFORMAT_ROTATE:
674         case FT_COLR_PAINTFORMAT_SKEW:
675             SkASSERT(false);  // Transforms handled in colrv1_transform.
676             break;
677         default:
678             paint.setShader(nullptr);
679             paint.setColor(SK_ColorCYAN);
680             break;
681     }
682 }
683 
colrv1_draw_glyph_with_path(SkCanvas * canvas,const FT_Color * palette,FT_Face face,FT_COLR_Paint glyphPaint,FT_COLR_Paint fillPaint)684 void colrv1_draw_glyph_with_path(SkCanvas* canvas, const FT_Color* palette, FT_Face face,
685                                  FT_COLR_Paint glyphPaint, FT_COLR_Paint fillPaint) {
686     SkASSERT(glyphPaint.format == FT_COLR_PAINTFORMAT_GLYPH);
687     SkASSERT(fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
688              fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
689              fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
690              fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT);
691 
692     SkPaint skiaFillPaint;
693     skiaFillPaint.setAntiAlias(true);
694     colrv1_configure_skpaint(face, palette, fillPaint, &skiaFillPaint);
695 
696     FT_UInt glyphID = glyphPaint.u.glyph.glyphID;
697     SkPath path;
698     /* TODO: Currently this call retrieves the path at units_per_em size. If we want to get
699      * correct hinting for the scaled size under the transforms at this point in the color
700      * glyph graph, we need to extract at least the requested glyph width and height and
701      * pass that to the path generation. */
702     if (generateFacePathCOLRv1(face, glyphID, &path)) {
703 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
704         SkPaint highlight_paint;
705         highlight_paint.setColor(0x33FF0000);
706         canvas->drawRect(path.getBounds(), highlight_paint);
707 #endif
708         {
709             canvas->drawPath(path, skiaFillPaint);
710         }
711     }
712 }
713 
colrv1_transform(SkCanvas * canvas,FT_Face face,FT_COLR_Paint colrv1_paint)714 void colrv1_transform(SkCanvas* canvas, FT_Face face, FT_COLR_Paint colrv1_paint) {
715     SkMatrix transform;
716 
717     switch (colrv1_paint.format) {
718         case FT_COLR_PAINTFORMAT_TRANSFORMED: {
719             transform = ToSkMatrix(colrv1_paint.u.transformed.affine);
720             break;
721         }
722         case FT_COLR_PAINTFORMAT_TRANSLATE: {
723             transform = SkMatrix::Translate(
724                 SkFixedToScalar(colrv1_paint.u.translate.dx),
725                 -SkFixedToScalar(colrv1_paint.u.translate.dy));
726             break;
727         }
728         case FT_COLR_PAINTFORMAT_ROTATE: {
729             transform = SkMatrix::RotateDeg(
730                     SkFixedToScalar(colrv1_paint.u.rotate.angle),
731                     SkPoint::Make(SkFixedToScalar(colrv1_paint.u.rotate.center_x),
732                                   -SkFixedToScalar(colrv1_paint.u.rotate.center_y)));
733             break;
734         }
735         case FT_COLR_PAINTFORMAT_SKEW: {
736             // In the PAINTFORMAT_ROTATE implementation, SkMatrix setRotate
737             // snaps to 0 for values very close to 0. Do the same here.
738 
739             SkScalar rad_x = SkDegreesToRadians(-SkFixedToFloat(colrv1_paint.u.skew.x_skew_angle));
740             float tan_x = SkScalarTan(rad_x);
741             tan_x = SkScalarNearlyZero(tan_x) ? 0.0f : tan_x;
742 
743             SkScalar rad_y = SkDegreesToRadians(-SkFixedToFloat(colrv1_paint.u.skew.y_skew_angle));
744             float tan_y = SkScalarTan(rad_y);
745             tan_y = SkScalarNearlyZero(tan_y) ? 0.0f : tan_y;
746 
747             SkMatrix translate_to_origin = SkMatrix::Translate(
748                     SkFixedToScalar(SkFixedToFloat(colrv1_paint.u.skew.center_x)),
749                     SkFixedToScalar(-SkFixedToFloat(colrv1_paint.u.skew.center_y)));
750 
751             SkMatrix translate_from_origin;
752             SkASSERT(translate_to_origin.invert(&translate_from_origin));
753 
754             SkMatrix skew_x = SkMatrix::MakeAll(
755                 1, tan_x, 0,
756                 0, 1, 0,
757                 0, 0, 1);
758 
759             SkMatrix skew_y = SkMatrix::MakeAll(
760                 1, 0, 0,
761                 tan_y, 1, 0,
762                 0, 0, 1);
763 
764             transform = translate_from_origin.postConcat(skew_x).postConcat(skew_y).postConcat(translate_to_origin);
765             break;
766         }
767         default: {
768             // Only transforms are handled in this function.
769             SkASSERT(false);
770         }
771     }
772     canvas->concat(transform);
773 }
774 
775 
776 bool colrv1_start_glyph(SkCanvas* canvas,
777                         const FT_Color* palette,
778                         FT_Face ft_face,
779                         uint16_t glyph_id,
780                         FT_Color_Root_Transform root_transform);
781 
colrv1_traverse_paint(SkCanvas * canvas,const FT_Color * palette,FT_Face face,FT_OpaquePaint opaque_paint,VisitedSet * visited_set)782 bool colrv1_traverse_paint(SkCanvas* canvas,
783                            const FT_Color* palette,
784                            FT_Face face,
785                            FT_OpaquePaint opaque_paint,
786                            VisitedSet* visited_set) {
787     // Cycle detection, see section "5.7.11.1.9 Color glyphs as a directed acyclic graph".
788     if (visited_set->contains(opaque_paint)) {
789         return false;
790     }
791 
792     visited_set->add(opaque_paint);
793     SK_AT_SCOPE_EXIT(visited_set->remove(opaque_paint));
794 
795     FT_COLR_Paint paint;
796     if (!FT_Get_Paint(face, opaque_paint, &paint)) {
797       return false;
798     }
799 
800     // Keep track of failures to retrieve the FT_COLR_Paint from FreeType in the
801     // recursion, cancel recursion when a paint retrieval fails.
802     bool traverse_result = true;
803     SkAutoCanvasRestore autoRestore(canvas, true /* do_save */);
804     switch (paint.format) {
805         case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
806             FT_LayerIterator& layer_iterator = paint.u.colr_layers.layer_iterator;
807             FT_OpaquePaint opaque_paint_fetch;
808             opaque_paint_fetch.p = nullptr;
809             while (FT_Get_Paint_Layers(face, &layer_iterator, &opaque_paint_fetch)) {
810                 colrv1_traverse_paint(canvas, palette, face, opaque_paint_fetch, visited_set);
811             }
812             break;
813         }
814         case FT_COLR_PAINTFORMAT_GLYPH:
815             // Special case paint graph leaf situations to improve
816             // performance. These are situations in the graph where a GlyphPaint
817             // is followed by either a solid or a gradient fill. Here we can use
818             // drawPath() + SkPaint directly which is faster than setting a
819             // clipPath() followed by a drawPaint().
820             FT_COLR_Paint fillPaint;
821             if (!FT_Get_Paint(face, paint.u.glyph.paint, &fillPaint)) {
822                 return false;
823             }
824             if (fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
825                 fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
826                 fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
827                 fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT) {
828                 colrv1_draw_glyph_with_path(canvas, palette, face, paint, fillPaint);
829             } else {
830                 colrv1_draw_paint(canvas, palette, face, paint);
831                 traverse_result = colrv1_traverse_paint(canvas, palette, face,
832                                                         paint.u.glyph.paint, visited_set);
833             }
834             break;
835         case FT_COLR_PAINTFORMAT_COLR_GLYPH:
836             traverse_result = colrv1_start_glyph(canvas, palette, face, paint.u.colr_glyph.glyphID,
837                                                  FT_COLOR_NO_ROOT_TRANSFORM);
838             break;
839         case FT_COLR_PAINTFORMAT_TRANSFORMED:
840             colrv1_transform(canvas, face, paint);
841             traverse_result = colrv1_traverse_paint(canvas, palette, face,
842                                                     paint.u.transformed.paint, visited_set);
843             break;
844         case FT_COLR_PAINTFORMAT_TRANSLATE:
845             colrv1_transform(canvas, face, paint);
846             traverse_result = colrv1_traverse_paint(canvas, palette, face,
847                                                     paint.u.translate.paint, visited_set);
848             break;
849         case FT_COLR_PAINTFORMAT_ROTATE:
850             colrv1_transform(canvas, face, paint);
851             traverse_result =
852                     colrv1_traverse_paint(canvas, palette, face,
853                                           paint.u.rotate.paint, visited_set);
854             break;
855         case FT_COLR_PAINTFORMAT_SKEW:
856             colrv1_transform(canvas, face, paint);
857             traverse_result =
858                     colrv1_traverse_paint(canvas, palette, face,
859                                           paint.u.skew.paint, visited_set);
860             break;
861         case FT_COLR_PAINTFORMAT_COMPOSITE: {
862             traverse_result = colrv1_traverse_paint(
863                     canvas, palette, face, paint.u.composite.backdrop_paint, visited_set);
864             SkPaint blend_mode_paint;
865             blend_mode_paint.setBlendMode(ToSkBlendMode(paint.u.composite.composite_mode));
866             canvas->saveLayer(nullptr, &blend_mode_paint);
867             traverse_result =
868                     traverse_result &&
869                     colrv1_traverse_paint(
870                             canvas, palette, face, paint.u.composite.source_paint, visited_set);
871             canvas->restore();
872             break;
873         }
874         case FT_COLR_PAINTFORMAT_SOLID:
875         case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
876         case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
877         case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
878             colrv1_draw_paint(canvas, palette, face, paint);
879             break;
880         }
881         default:
882             SkASSERT(false);
883             break;
884     }
885     return traverse_result;
886 }
887 
colrv1_start_glyph(SkCanvas * canvas,const FT_Color * palette,FT_Face ft_face,uint16_t glyph_id,FT_Color_Root_Transform root_transform)888 bool colrv1_start_glyph(SkCanvas* canvas,
889                         const FT_Color* palette,
890                         FT_Face ft_face,
891                         uint16_t glyph_id,
892                         FT_Color_Root_Transform root_transform) {
893     FT_OpaquePaint opaque_paint;
894     opaque_paint.p = nullptr;
895     bool has_colrv1_layers = false;
896     if (FT_Get_Color_Glyph_Paint(ft_face, glyph_id, root_transform, &opaque_paint)) {
897         has_colrv1_layers = true;
898         VisitedSet visited_set;
899         colrv1_traverse_paint(canvas, palette, ft_face, opaque_paint, &visited_set);
900     }
901     return has_colrv1_layers;
902 }
903 #endif // TT_SUPPORT_COLRV1
904 
905 }  // namespace
906 
generateGlyphImage(FT_Face face,const SkGlyph & glyph,const SkMatrix & bitmapTransform)907 void SkScalerContext_FreeType_Base::generateGlyphImage(
908     FT_Face face,
909     const SkGlyph& glyph,
910     const SkMatrix& bitmapTransform)
911 {
912     const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
913     const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
914 
915     switch ( face->glyph->format ) {
916         case FT_GLYPH_FORMAT_OUTLINE: {
917             FT_Outline* outline = &face->glyph->outline;
918 
919             int dx = 0, dy = 0;
920             if (this->isSubpixel()) {
921                 dx = SkFixedToFDot6(glyph.getSubXFixed());
922                 dy = SkFixedToFDot6(glyph.getSubYFixed());
923                 // negate dy since freetype-y-goes-up and skia-y-goes-down
924                 dy = -dy;
925             }
926 
927             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
928 
929 #ifdef FT_COLOR_H
930             if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
931                 SkBitmap dstBitmap;
932                 // TODO: mark this as sRGB when the blits will be sRGB.
933                 dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
934                                                     kN32_SkColorType,
935                                                     kPremul_SkAlphaType),
936                                                     glyph.rowBytes());
937                 dstBitmap.setPixels(glyph.fImage);
938 
939                 // Scale unscaledBitmap into dstBitmap.
940                 SkCanvas canvas(dstBitmap);
941 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
942                 canvas.clear(0x33FF0000);
943 #else
944                 canvas.clear(SK_ColorTRANSPARENT);
945 #endif
946                 canvas.translate(-glyph.fLeft, -glyph.fTop);
947 
948                 if (this->isSubpixel()) {
949                     canvas.translate(SkFixedToScalar(glyph.getSubXFixed()),
950                                      SkFixedToScalar(glyph.getSubYFixed()));
951                 }
952 
953                 SkPaint paint;
954                 paint.setAntiAlias(true);
955 
956                 FT_Color *palette;
957                 FT_Error err = FT_Palette_Select(face, 0, &palette);
958                 if (err) {
959                     SK_TRACEFTR(err, "Could not get palette from %s fontFace.", face->family_name);
960                     return;
961                 }
962 
963                 FT_Bool haveLayers = false;
964 
965 #ifdef TT_SUPPORT_COLRV1
966                 // Only attempt to draw COLRv1 glyph is FreeType is new enough
967                 // to have the COLRv1 additions, as indicated by the
968                 // TT_SUPPORT_COLRV1 flag defined by the FreeType headers in
969                 // that case.
970 
971                 haveLayers = colrv1_start_glyph(&canvas, palette, face, glyph.getGlyphID(),
972                                                 FT_COLOR_INCLUDE_ROOT_TRANSFORM);
973 #else
974                 haveLayers = false;
975 #endif
976                 if (!haveLayers) {
977                     // If we didn't have colr v1 layers, try v0 layers.
978                     FT_LayerIterator layerIterator;
979                     layerIterator.p = NULL;
980                     FT_UInt layerGlyphIndex = 0;
981                     FT_UInt layerColorIndex = 0;
982                     while (FT_Get_Color_Glyph_Layer(face, glyph.getGlyphID(), &layerGlyphIndex,
983                                                     &layerColorIndex, &layerIterator)) {
984                         haveLayers = true;
985                         if (layerColorIndex == 0xFFFF) {
986                             paint.setColor(SK_ColorBLACK);
987                         } else {
988                             SkColor color = SkColorSetARGB(palette[layerColorIndex].alpha,
989                                                            palette[layerColorIndex].red,
990                                                            palette[layerColorIndex].green,
991                                                            palette[layerColorIndex].blue);
992                             paint.setColor(color);
993                         }
994                         SkPath path;
995                         if (this->generateFacePath(face, layerGlyphIndex, &path)) {
996                             canvas.drawPath(path, paint);
997                         }
998                     }
999                 }
1000 
1001                 if (!haveLayers) {
1002                     SK_TRACEFTR(err, "Could not get layers (neither v0, nor v1) from %s fontFace.",
1003                                 face->family_name);
1004                     return;
1005                 }
1006             } else
1007 #endif
1008             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1009                 FT_Outline_Translate(outline, dx, dy);
1010                 FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
1011                                                                      FT_RENDER_MODE_LCD);
1012                 if (err) {
1013                     SK_TRACEFTR(err, "Could not render glyph %x.", face->glyph);
1014                     return;
1015                 }
1016 
1017                 SkMask mask = glyph.mask();
1018 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1019                 memset(mask.fImage, 0x80, mask.fBounds.height() * mask.fRowBytes);
1020 #endif
1021                 FT_GlyphSlotRec& ftGlyph = *face->glyph;
1022 
1023                 if (!SkIRect::Intersects(mask.fBounds,
1024                                          SkIRect::MakeXYWH( ftGlyph.bitmap_left,
1025                                                            -ftGlyph.bitmap_top,
1026                                                             ftGlyph.bitmap.width,
1027                                                             ftGlyph.bitmap.rows)))
1028                 {
1029                     return;
1030                 }
1031 
1032                 // If the FT_Bitmap extent is larger, discard bits of the bitmap outside the mask.
1033                 // If the SkMask extent is larger, shrink mask to fit bitmap (clearing discarded).
1034                 unsigned char* origBuffer = ftGlyph.bitmap.buffer;
1035                 // First align the top left (origin).
1036                 if (-ftGlyph.bitmap_top < mask.fBounds.fTop) {
1037                     int32_t topDiff = mask.fBounds.fTop - (-ftGlyph.bitmap_top);
1038                     ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff;
1039                     ftGlyph.bitmap.rows -= topDiff;
1040                     ftGlyph.bitmap_top = -mask.fBounds.fTop;
1041                 }
1042                 if (ftGlyph.bitmap_left < mask.fBounds.fLeft) {
1043                     int32_t leftDiff = mask.fBounds.fLeft - ftGlyph.bitmap_left;
1044                     ftGlyph.bitmap.buffer += leftDiff;
1045                     ftGlyph.bitmap.width -= leftDiff;
1046                     ftGlyph.bitmap_left = mask.fBounds.fLeft;
1047                 }
1048                 if (mask.fBounds.fTop < -ftGlyph.bitmap_top) {
1049                     mask.fImage += mask.fRowBytes * (-ftGlyph.bitmap_top - mask.fBounds.fTop);
1050                     mask.fBounds.fTop = -ftGlyph.bitmap_top;
1051                 }
1052                 if (mask.fBounds.fLeft < ftGlyph.bitmap_left) {
1053                     mask.fImage += sizeof(uint16_t) * (ftGlyph.bitmap_left - mask.fBounds.fLeft);
1054                     mask.fBounds.fLeft = ftGlyph.bitmap_left;
1055                 }
1056                 // Origins aligned, clean up the width and height.
1057                 int ftVertScale = (doVert ? 3 : 1);
1058                 int ftHoriScale = (doVert ? 1 : 3);
1059                 if (mask.fBounds.height() * ftVertScale < SkToInt(ftGlyph.bitmap.rows)) {
1060                     ftGlyph.bitmap.rows = mask.fBounds.height() * ftVertScale;
1061                 }
1062                 if (mask.fBounds.width() * ftHoriScale < SkToInt(ftGlyph.bitmap.width)) {
1063                     ftGlyph.bitmap.width = mask.fBounds.width() * ftHoriScale;
1064                 }
1065                 if (SkToInt(ftGlyph.bitmap.rows) < mask.fBounds.height() * ftVertScale) {
1066                     mask.fBounds.fBottom = mask.fBounds.fTop + ftGlyph.bitmap.rows / ftVertScale;
1067                 }
1068                 if (SkToInt(ftGlyph.bitmap.width) < mask.fBounds.width() * ftHoriScale) {
1069                     mask.fBounds.fRight = mask.fBounds.fLeft + ftGlyph.bitmap.width / ftHoriScale;
1070                 }
1071                 if (fPreBlend.isApplicable()) {
1072                     copyFT2LCD16<true>(ftGlyph.bitmap, mask, doBGR,
1073                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1074                 } else {
1075                     copyFT2LCD16<false>(ftGlyph.bitmap, mask, doBGR,
1076                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1077                 }
1078                 // Restore the buffer pointer so FreeType can properly free it.
1079                 ftGlyph.bitmap.buffer = origBuffer;
1080             } else {
1081                 FT_BBox     bbox;
1082                 FT_Bitmap   target;
1083                 FT_Outline_Get_CBox(outline, &bbox);
1084                 /*
1085                     what we really want to do for subpixel is
1086                         offset(dx, dy)
1087                         compute_bounds
1088                         offset(bbox & !63)
1089                     but that is two calls to offset, so we do the following, which
1090                     achieves the same thing with only one offset call.
1091                 */
1092                 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
1093                                               dy - ((bbox.yMin + dy) & ~63));
1094 
1095                 target.width = glyph.fWidth;
1096                 target.rows = glyph.fHeight;
1097                 target.pitch = glyph.rowBytes();
1098                 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
1099                 target.pixel_mode = compute_pixel_mode(glyph.fMaskFormat);
1100                 target.num_grays = 256;
1101 
1102                 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
1103 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1104                 for (int y = 0; y < glyph.fHeight; ++y) {
1105                     for (int x = 0; x < glyph.fWidth; ++x) {
1106                         uint8_t& a = ((uint8_t*)glyph.fImage)[(glyph.rowBytes() * y) + x];
1107                         a = std::max<uint8_t>(a, 0x20);
1108                     }
1109                 }
1110 #endif
1111             }
1112         } break;
1113 
1114         case FT_GLYPH_FORMAT_BITMAP: {
1115             FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
1116             SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1117 
1118             // Assume that the other formats do not exist.
1119             SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
1120                      FT_PIXEL_MODE_GRAY == pixel_mode ||
1121                      FT_PIXEL_MODE_BGRA == pixel_mode);
1122 
1123             // These are the only formats this ScalerContext should request.
1124             SkASSERT(SkMask::kBW_Format == maskFormat ||
1125                      SkMask::kA8_Format == maskFormat ||
1126                      SkMask::kARGB32_Format == maskFormat ||
1127                      SkMask::kLCD16_Format == maskFormat);
1128 
1129             // If no scaling needed, directly copy glyph bitmap.
1130             if (bitmapTransform.isIdentity()) {
1131                 SkMask dstMask = glyph.mask();
1132                 copyFTBitmap(face->glyph->bitmap, dstMask);
1133                 break;
1134             }
1135 
1136             // Otherwise, scale the bitmap.
1137 
1138             // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
1139             SkBitmap unscaledBitmap;
1140             // TODO: mark this as sRGB when the blits will be sRGB.
1141             unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
1142                                                          face->glyph->bitmap.rows,
1143                                                          SkColorType_for_FTPixelMode(pixel_mode),
1144                                                          kPremul_SkAlphaType));
1145 
1146             SkMask unscaledBitmapAlias;
1147             unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
1148             unscaledBitmapAlias.fBounds.setWH(unscaledBitmap.width(), unscaledBitmap.height());
1149             unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
1150             unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
1151             copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
1152 
1153             // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
1154             // BW requires an A8 target for resizing, which can then be down sampled.
1155             // LCD should use a 4x A8 target, which will then be down sampled.
1156             // For simplicity, LCD uses A8 and is replicated.
1157             int bitmapRowBytes = 0;
1158             if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) {
1159                 bitmapRowBytes = glyph.rowBytes();
1160             }
1161             SkBitmap dstBitmap;
1162             // TODO: mark this as sRGB when the blits will be sRGB.
1163             dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
1164                                                 SkColorType_for_SkMaskFormat(maskFormat),
1165                                                 kPremul_SkAlphaType),
1166                               bitmapRowBytes);
1167             if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
1168                 dstBitmap.allocPixels();
1169             } else {
1170                 dstBitmap.setPixels(glyph.fImage);
1171             }
1172 
1173             // Scale unscaledBitmap into dstBitmap.
1174             SkCanvas canvas(dstBitmap);
1175 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
1176             canvas.clear(0x33FF0000);
1177 #else
1178             canvas.clear(SK_ColorTRANSPARENT);
1179 #endif
1180             canvas.translate(-glyph.fLeft, -glyph.fTop);
1181             canvas.concat(bitmapTransform);
1182             canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top);
1183 
1184             SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNearest);
1185             canvas.drawImage(unscaledBitmap.asImage().get(), 0, 0, sampling, nullptr);
1186 
1187             // If the destination is BW or LCD, convert from A8.
1188             if (SkMask::kBW_Format == maskFormat) {
1189                 // Copy the A8 dstBitmap into the A1 glyph.fImage.
1190                 SkMask dstMask = glyph.mask();
1191                 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes());
1192             } else if (SkMask::kLCD16_Format == maskFormat) {
1193                 // Copy the A8 dstBitmap into the LCD16 glyph.fImage.
1194                 uint8_t* src = dstBitmap.getAddr8(0, 0);
1195                 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
1196                 for (int y = dstBitmap.height(); y --> 0;) {
1197                     for (int x = 0; x < dstBitmap.width(); ++x) {
1198                         dst[x] = grayToRGB16(src[x]);
1199                     }
1200                     dst = (uint16_t*)((char*)dst + glyph.rowBytes());
1201                     src += dstBitmap.rowBytes();
1202                 }
1203             }
1204 
1205         } break;
1206 
1207         default:
1208             SkDEBUGFAIL("unknown glyph format");
1209             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
1210             return;
1211     }
1212 
1213 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum,
1214 // it is optional
1215 #if defined(SK_GAMMA_APPLY_TO_A8)
1216     if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) {
1217         uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
1218         unsigned rowBytes = glyph.rowBytes();
1219 
1220         for (int y = glyph.fHeight - 1; y >= 0; --y) {
1221             for (int x = glyph.fWidth - 1; x >= 0; --x) {
1222                 dst[x] = fPreBlend.fG[dst[x]];
1223             }
1224             dst += rowBytes;
1225         }
1226     }
1227 #endif
1228 }
1229 
1230 ///////////////////////////////////////////////////////////////////////////////
1231 
1232 namespace {
1233 
1234 class SkFTGeometrySink {
1235     SkPath* fPath;
1236     bool fStarted;
1237     FT_Vector fCurrent;
1238 
goingTo(const FT_Vector * pt)1239     void goingTo(const FT_Vector* pt) {
1240         if (!fStarted) {
1241             fStarted = true;
1242             fPath->moveTo(SkFDot6ToScalar(fCurrent.x), -SkFDot6ToScalar(fCurrent.y));
1243         }
1244         fCurrent = *pt;
1245     }
1246 
currentIsNot(const FT_Vector * pt)1247     bool currentIsNot(const FT_Vector* pt) {
1248         return fCurrent.x != pt->x || fCurrent.y != pt->y;
1249     }
1250 
Move(const FT_Vector * pt,void * ctx)1251     static int Move(const FT_Vector* pt, void* ctx) {
1252         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1253         if (self.fStarted) {
1254             self.fPath->close();
1255             self.fStarted = false;
1256         }
1257         self.fCurrent = *pt;
1258         return 0;
1259     }
1260 
Line(const FT_Vector * pt,void * ctx)1261     static int Line(const FT_Vector* pt, void* ctx) {
1262         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1263         if (self.currentIsNot(pt)) {
1264             self.goingTo(pt);
1265             self.fPath->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
1266         }
1267         return 0;
1268     }
1269 
Quad(const FT_Vector * pt0,const FT_Vector * pt1,void * ctx)1270     static int Quad(const FT_Vector* pt0, const FT_Vector* pt1, void* ctx) {
1271         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1272         if (self.currentIsNot(pt0) || self.currentIsNot(pt1)) {
1273             self.goingTo(pt1);
1274             self.fPath->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
1275                                SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
1276         }
1277         return 0;
1278     }
1279 
Cubic(const FT_Vector * pt0,const FT_Vector * pt1,const FT_Vector * pt2,void * ctx)1280     static int Cubic(const FT_Vector* pt0, const FT_Vector* pt1, const FT_Vector* pt2, void* ctx) {
1281         SkFTGeometrySink& self = *(SkFTGeometrySink*)ctx;
1282         if (self.currentIsNot(pt0) || self.currentIsNot(pt1) || self.currentIsNot(pt2)) {
1283             self.goingTo(pt2);
1284             self.fPath->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
1285                                 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
1286                                 SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
1287         }
1288         return 0;
1289     }
1290 
1291 public:
SkFTGeometrySink(SkPath * path)1292     SkFTGeometrySink(SkPath* path) : fPath{path}, fStarted{false}, fCurrent{0,0} {}
1293 
1294     static constexpr const FT_Outline_Funcs Funcs{
1295         /*move_to =*/ SkFTGeometrySink::Move,
1296         /*line_to =*/ SkFTGeometrySink::Line,
1297         /*conic_to =*/ SkFTGeometrySink::Quad,
1298         /*cubic_to =*/ SkFTGeometrySink::Cubic,
1299         /*shift = */ 0,
1300         /*delta =*/ 0,
1301     };
1302 };
1303 
generateGlyphPathStatic(FT_Face face,SkPath * path)1304 bool generateGlyphPathStatic(FT_Face face, SkPath* path) {
1305     SkFTGeometrySink sink{path};
1306     FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &SkFTGeometrySink::Funcs, &sink);
1307 
1308     if (err != 0) {
1309         path->reset();
1310         return false;
1311     }
1312 
1313     path->close();
1314     return true;
1315 }
1316 
generateFacePathStatic(FT_Face face,SkGlyphID glyphID,SkPath * path)1317 bool generateFacePathStatic(FT_Face face, SkGlyphID glyphID, SkPath* path) {
1318     uint32_t flags = 0; //fLoadGlyphFlags;
1319     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1320     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1321 
1322     FT_Error err = FT_Load_Glyph(face, glyphID, flags);
1323     if (err != 0) {
1324         path->reset();
1325         return false;
1326     }
1327 
1328     if (!generateGlyphPathStatic(face, path)) {
1329         path->reset();
1330         return false;
1331     }
1332     return true;
1333 }
1334 
1335 #ifdef TT_SUPPORT_COLRV1
generateFacePathCOLRv1(FT_Face face,SkGlyphID glyphID,SkPath * path)1336 bool generateFacePathCOLRv1(FT_Face face, SkGlyphID glyphID, SkPath* path) {
1337     uint32_t flags = 0;
1338     flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
1339     flags &= ~FT_LOAD_RENDER;   // don't scan convert (we just want the outline)
1340 
1341     flags |= FT_LOAD_IGNORE_TRANSFORM;
1342 
1343 
1344     using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
1345     std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> unscaledFtSize([face]() -> FT_Size {
1346         FT_Size size;
1347         FT_Error err = FT_New_Size(face, &size);
1348         if (err != 0) {
1349             SK_TRACEFTR(err, "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.", face->family_name);
1350             return nullptr;
1351         }
1352         return size;
1353     }());
1354 
1355     if (!unscaledFtSize) {
1356       return false;
1357     }
1358 
1359     FT_Size oldSize = face->size;
1360 
1361     auto try_generate_path = [face, &unscaledFtSize, glyphID, flags, path]() {
1362         FT_Error err = 0;
1363 
1364         err = FT_Activate_Size(unscaledFtSize.get());
1365         if (err != 0) {
1366           return false;
1367         }
1368 
1369         err = FT_Set_Char_Size(face, SkIntToFDot6(face->units_per_EM),
1370                                SkIntToFDot6(face->units_per_EM), 72, 72);
1371         if (err != 0) {
1372             return false;
1373         }
1374 
1375         err = FT_Load_Glyph(face, glyphID, flags);
1376         if (err != 0) {
1377             path->reset();
1378             return false;
1379         }
1380 
1381         if (!generateGlyphPathStatic(face, path)) {
1382             path->reset();
1383             return false;
1384         }
1385 
1386         return true;
1387     };
1388 
1389     bool path_generation_result = try_generate_path();
1390 
1391     FT_Activate_Size(oldSize);
1392 
1393     return path_generation_result;
1394 }
1395 #endif
1396 
1397 }  // namespace
1398 
generateGlyphPath(FT_Face face,SkPath * path)1399 bool SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
1400     return generateGlyphPathStatic(face, path);
1401 }
1402 
generateFacePath(FT_Face face,SkGlyphID glyphID,SkPath * path)1403 bool SkScalerContext_FreeType_Base::generateFacePath(FT_Face face,
1404                                                      SkGlyphID glyphID,
1405                                                      SkPath* path) {
1406     return generateFacePathStatic(face, glyphID, path);
1407 }
1408