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