32#include <freetype/freetype.h>
33#include <freetype/ftbitmap.h>
35# include <freetype/ftcolor.h>
37#include <freetype/ftimage.h>
38#include <freetype/ftoutln.h>
39#include <freetype/ftsizes.h>
41#include <freetype/ftsynth.h>
46[[maybe_unused]]
static inline const constexpr bool kSkShowTextBlitCoverage =
false;
49#if defined(FT_CONFIG_OPTION_SVG)
50# include <freetype/otsvg.h>
53#ifdef TT_SUPPORT_COLRV1
60#if (((FREETYPE_MAJOR) < 2) || \
61 ((FREETYPE_MAJOR) == 2 && (FREETYPE_MINOR) < 11) || \
62 ((FREETYPE_MAJOR) == 2 && (FREETYPE_MINOR) == 11 && (FREETYPE_PATCH) < 1)) && \
63 !defined(FT_STATIC_CAST)
64# undef TT_SUPPORT_COLRV1
71#ifndef FT_OUTLINE_OVERLAP
72# define FT_OUTLINE_OVERLAP 0x40
79# define FT_LOAD_COLOR ( 1L << 20 )
80# define FT_PIXEL_MODE_BGRA 7
84const char* SkTraceFtrGetError(
int e) {
85 switch ((FT_Error)
e) {
87 #define FT_ERRORDEF( e, v, s ) case v: return s;
88 #define FT_ERROR_START_LIST
89 #define FT_ERROR_END_LIST
92 #undef FT_ERROR_START_LIST
93 #undef FT_ERROR_END_LIST
99#ifdef TT_SUPPORT_COLRV1
100bool operator==(
const FT_OpaquePaint&
a,
const FT_OpaquePaint&
b) {
101 return a.p ==
b.p &&
a.insert_root_transform ==
b.insert_root_transform;
106static_assert(
sizeof(FT_Fixed) !=
sizeof(FT_F2Dot14));
107constexpr float kColorStopShift =
108 sizeof(FT_ColorStop::stop_offset) ==
sizeof(FT_F2Dot14) ? 1 << 14 : 1 << 16;
112using SkUniqueFTSize = std::unique_ptr<FT_SizeRec, SkFunctionObject<FT_Done_Size>>;
117 return FT_PIXEL_MODE_MONO;
120 return FT_PIXEL_MODE_GRAY;
127 if constexpr (kSkShowTextBlitCoverage) {
135uint16_t grayToRGB16(
U8CPU gray) {
136 if constexpr (kSkShowTextBlitCoverage) {
142int bittst(
const uint8_t
data[],
int bitOffset) {
144 int lowBit =
data[bitOffset >> 3] >> (~bitOffset & 7);
156template<
bool APPLY_PREBLEND>
158 const uint8_t* tableR,
const uint8_t* tableG,
const uint8_t* tableB)
161 if (FT_PIXEL_MODE_LCD !=
bitmap.pixel_mode) {
164 if (FT_PIXEL_MODE_LCD_V !=
bitmap.pixel_mode) {
169 uint16_t*
dst =
reinterpret_cast<uint16_t*
>(dstMask->
image());
175 switch (
bitmap.pixel_mode) {
176 case FT_PIXEL_MODE_MONO:
181 dst = (uint16_t*)((
char*)
dst + dstRB);
185 case FT_PIXEL_MODE_GRAY:
190 dst = (uint16_t*)((
char*)
dst + dstRB);
194 case FT_PIXEL_MODE_LCD:
197 const uint8_t* triple =
src;
200 dst[
x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR),
201 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
202 sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB));
207 dst[
x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR),
208 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
209 sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB));
214 dst = (uint16_t*)((
char*)
dst + dstRB);
217 case FT_PIXEL_MODE_LCD_V:
220 const uint8_t* srcR =
src;
221 const uint8_t* srcG = srcR +
bitmap.pitch;
222 const uint8_t* srcB = srcG +
bitmap.pitch;
228 dst[
x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR),
229 sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG),
230 sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB));
233 dst = (uint16_t*)((
char*)
dst + dstRB);
238 SkDEBUGFAIL(
"unsupported FT_Pixel_Mode for LCD16");
259void copyFTBitmap(
const FT_Bitmap& srcFTBitmap,
SkMaskBuilder* dstMask) {
261 "dstMask.fBounds.width() = %d\n"
262 "static_cast<int>(srcFTBitmap.width) = %d",
264 static_cast<int>(srcFTBitmap.width)
267 "dstMask.fBounds.height() = %d\n"
268 "static_cast<int>(srcFTBitmap.rows) = %d",
270 static_cast<int>(srcFTBitmap.rows)
273 const uint8_t*
src =
reinterpret_cast<const uint8_t*
>(srcFTBitmap.buffer);
274 const FT_Pixel_Mode srcFormat =
static_cast<FT_Pixel_Mode
>(srcFTBitmap.pixel_mode);
276 const int srcPitch = srcFTBitmap.pitch;
277 const size_t srcRowBytes =
SkTAbs(srcPitch);
281 const size_t dstRowBytes = dstMask->
fRowBytes;
283 const size_t width = srcFTBitmap.width;
284 const size_t height = srcFTBitmap.rows;
287 copyFT2LCD16<false>(srcFTBitmap, dstMask,
false,
nullptr,
nullptr,
nullptr);
294 size_t commonRowBytes =
std::min(srcRowBytes, dstRowBytes);
296 memcpy(
dst,
src, commonRowBytes);
304 const uint8_t* src_row =
src;
305 uint8_t* dst_row =
dst;
306 for (
size_t x =
width;
x --> 0;) {
311 *dst_row++ =
byte & 0x80 ? 0xff : 0x00;
321 const uint8_t* src_row =
src;
323 for (
size_t x = 0;
x <
width; ++
x) {
324 uint8_t
b = *src_row++;
325 uint8_t g = *src_row++;
326 uint8_t r = *src_row++;
327 uint8_t
a = *src_row++;
329 if constexpr (kSkShowTextBlitCoverage) {
337 SkDEBUGF(
"FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat);
338 SkDEBUGFAIL(
"unsupported combination of FT_Pixel_Mode and SkMask::Format");
345 return (
byte >> 6) != 0;
350 for (
int i = 0;
i < 8; ++
i) {
360 const int octs =
width >> 3;
361 const int leftOverBits =
width & 7;
367 const int srcPad = srcRB -
width;
371 for (
int i = 0;
i < octs; ++
i) {
375 if (leftOverBits > 0) {
378 for (
int i = 0;
i < leftOverBits; ++
i, --shift) {
392 case kN32_SkColorType:
400inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
401 switch (pixel_mode) {
402 case FT_PIXEL_MODE_MONO:
403 case FT_PIXEL_MODE_GRAY:
406 return kN32_SkColorType;
420 return kN32_SkColorType;
422 SkDEBUGFAIL(
"unsupported destination SkBitmap::Config");
430#ifdef TT_SUPPORT_COLRV1
432const uint16_t kForegroundColorPaletteIndex = 0xFFFF;
451 const auto c_4f = c0_4f + (c1_4f - c0_4f) * t;
465void truncateToStopInterpolating(
SkScalar zeroRadiusStop,
466 std::vector<SkColor4f>&
colors,
467 std::vector<SkScalar>& stops,
468 TruncateStops truncateStops) {
469 if (stops.size() <= 1u ||
470 zeroRadiusStop < stops.front() || stops.back() < zeroRadiusStop)
475 size_t afterIndex = (truncateStops == TruncateStart)
476 ? std::lower_bound(stops.begin(), stops.end(), zeroRadiusStop) - stops.begin()
477 : std::upper_bound(stops.begin(), stops.end(), zeroRadiusStop) - stops.begin();
479 const float t = (zeroRadiusStop - stops[afterIndex - 1]) /
480 (stops[afterIndex] - stops[afterIndex - 1]);
483 if (truncateStops == TruncateStart) {
484 stops.erase(stops.begin(), stops.begin() + afterIndex);
486 stops.insert(stops.begin(), 0);
489 stops.erase(stops.begin() + afterIndex, stops.end());
491 stops.insert(stops.end(), 1);
496struct OpaquePaintHasher {
497 size_t operator()(
const FT_OpaquePaint& opaquePaint) {
499 SkGoodHash()(opaquePaint.insert_root_transform);
507inline float SkColrV1AlphaToFloat(uint16_t alpha) {
return (alpha /
float(1 << 14)); }
510inline SkTileMode ToSkTileMode(FT_PaintExtend extendMode) {
511 switch (extendMode) {
512 case FT_COLR_PAINT_EXTEND_REPEAT:
514 case FT_COLR_PAINT_EXTEND_REFLECT:
521inline SkBlendMode ToSkBlendMode(FT_Composite_Mode compositeMode) {
522 switch (compositeMode) {
523 case FT_COLR_COMPOSITE_CLEAR:
525 case FT_COLR_COMPOSITE_SRC:
527 case FT_COLR_COMPOSITE_DEST:
529 case FT_COLR_COMPOSITE_SRC_OVER:
531 case FT_COLR_COMPOSITE_DEST_OVER:
533 case FT_COLR_COMPOSITE_SRC_IN:
535 case FT_COLR_COMPOSITE_DEST_IN:
537 case FT_COLR_COMPOSITE_SRC_OUT:
539 case FT_COLR_COMPOSITE_DEST_OUT:
541 case FT_COLR_COMPOSITE_SRC_ATOP:
543 case FT_COLR_COMPOSITE_DEST_ATOP:
545 case FT_COLR_COMPOSITE_XOR:
547 case FT_COLR_COMPOSITE_PLUS:
549 case FT_COLR_COMPOSITE_SCREEN:
551 case FT_COLR_COMPOSITE_OVERLAY:
553 case FT_COLR_COMPOSITE_DARKEN:
555 case FT_COLR_COMPOSITE_LIGHTEN:
557 case FT_COLR_COMPOSITE_COLOR_DODGE:
559 case FT_COLR_COMPOSITE_COLOR_BURN:
561 case FT_COLR_COMPOSITE_HARD_LIGHT:
563 case FT_COLR_COMPOSITE_SOFT_LIGHT:
565 case FT_COLR_COMPOSITE_DIFFERENCE:
567 case FT_COLR_COMPOSITE_EXCLUSION:
569 case FT_COLR_COMPOSITE_MULTIPLY:
571 case FT_COLR_COMPOSITE_HSL_HUE:
573 case FT_COLR_COMPOSITE_HSL_SATURATION:
575 case FT_COLR_COMPOSITE_HSL_COLOR:
577 case FT_COLR_COMPOSITE_HSL_LUMINOSITY:
603bool colrv1_configure_skpaint(
FT_Face face,
606 const FT_COLR_Paint& colrPaint,
608 auto fetchColorStops = [&face, &palette, &foregroundColor](
609 const FT_ColorStopIterator& colorStopIterator,
610 std::vector<SkScalar>& stops,
611 std::vector<SkColor4f>&
colors) ->
bool {
612 const FT_UInt colorStopCount = colorStopIterator.num_color_stops;
613 if (colorStopCount == 0) {
623 std::vector<ColorStop> colorStopsSorted;
624 colorStopsSorted.resize(colorStopCount);
627 FT_ColorStopIterator mutable_color_stop_iterator = colorStopIterator;
628 while (FT_Get_Colorline_Stops(face, &ftStop, &mutable_color_stop_iterator)) {
629 FT_UInt index = mutable_color_stop_iterator.current_color_stop - 1;
630 ColorStop& skStop = colorStopsSorted[index];
631 skStop.pos = ftStop.stop_offset / kColorStopShift;
632 FT_UInt16& palette_index = ftStop.color.palette_index;
633 if (palette_index == kForegroundColorPaletteIndex) {
634 skStop.color = SkColor4f::FromColor(foregroundColor);
635 }
else if (palette_index >= palette.
size()) {
638 skStop.color = SkColor4f::FromColor(palette[palette_index]);
640 skStop.color.fA *= SkColrV1AlphaToFloat(ftStop.color.alpha);
643 std::stable_sort(colorStopsSorted.begin(), colorStopsSorted.end(),
644 [](
const ColorStop&
a,
const ColorStop&
b) { return a.pos < b.pos; });
646 stops.resize(colorStopCount);
647 colors.resize(colorStopCount);
648 for (
size_t i = 0;
i < colorStopCount; ++
i) {
649 stops[
i] = colorStopsSorted[
i].pos;
650 colors[
i] = colorStopsSorted[
i].color;
655 switch (colrPaint.format) {
656 case FT_COLR_PAINTFORMAT_SOLID: {
657 FT_PaintSolid solid = colrPaint.u.solid;
661 if (solid.color.palette_index == kForegroundColorPaletteIndex) {
662 color = SkColor4f::FromColor(foregroundColor);
663 }
else if (solid.color.palette_index >= palette.
size()) {
666 color = SkColor4f::FromColor(palette[solid.color.palette_index]);
668 color.fA *= SkColrV1AlphaToFloat(solid.color.alpha);
669 paint->setShader(
nullptr);
673 case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT: {
674 const FT_PaintLinearGradient& linearGradient = colrPaint.u.linear_gradient;
675 std::vector<SkScalar> stops;
676 std::vector<SkColor4f>
colors;
678 if (!fetchColorStops(linearGradient.colorline.color_stop_iterator, stops,
colors)) {
682 if (stops.size() == 1) {
710 SkVector perpendicularToP2P0 = (p2 - p0);
712 -perpendicularToP2P0.
x());
713 SkVector p3 = p0 + SkVectorProjection((p1 - p0), perpendicularToP2P0);
714 linePositions[1] = p3;
721 SkTileMode tileMode = ToSkTileMode(linearGradient.colorline.extend);
722 SkScalar colorStopRange = stops.back() - stops.front();
725 if (colorStopRange == 0.f) {
737 stops.push_back(stops.back() + 1.0f);
739 colorStopRange = 1.0f;
748 if ((colorStopRange != 1 || stops.front() != 0.f)) {
751 p0Offset.
scale(stops.front());
753 p1Offset.
scale(stops.back());
755 linePositions[0] = p0 + p0Offset;
756 linePositions[1] = p0 + p1Offset;
758 SkScalar scaleFactor = 1 / colorStopRange;
759 SkScalar startOffset = stops.front();
761 stop = (stop - startOffset) * scaleFactor;
770 SkGradientShader::Interpolation::InPremul::kNo,
771 SkGradientShader::Interpolation::ColorSpace::kSRGB,
772 SkGradientShader::Interpolation::HueMethod::kShorter
779 paint->setShader(shader);
782 case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT: {
783 const FT_PaintRadialGradient& radialGradient = colrPaint.u.radial_gradient;
792 std::vector<SkScalar> stops;
793 std::vector<SkColor4f>
colors;
794 if (!fetchColorStops(radialGradient.colorline.color_stop_iterator, stops,
colors)) {
798 if (stops.size() == 1) {
803 SkScalar colorStopRange = stops.back() - stops.front();
804 SkTileMode tileMode = ToSkTileMode(radialGradient.colorline.extend);
806 if (colorStopRange == 0.f) {
818 stops.push_back(stops.back() + 1.0f);
820 colorStopRange = 1.0f;
829 if (colorStopRange != 1 || stops.front() != 0.f) {
837 SkScalar radiusDiff = endRadius - startRadius;
838 SkScalar scaleFactor = 1 / colorStopRange;
839 SkScalar stopsStartOffset = stops.front();
842 startOffset.
scale(stops.front());
844 endOffset.
scale(stops.back());
850 endRadius = startRadius + radiusDiff * stops.back();
851 startRadius = startRadius + radiusDiff * stops.front();
853 for (
auto& stop : stops) {
854 stop = (stop - stopsStartOffset) * scaleFactor;
863 if (startRadius < 0 || endRadius < 0) {
864 if (startRadius == endRadius && startRadius < 0) {
871 SkScalar radiusDiff = endRadius - startRadius;
873 TruncateStops truncateSide = TruncateStart;
874 if (startRadius < 0) {
875 truncateSide = TruncateStart;
882 zeroRadiusStop = -startRadius / (endRadius - startRadius);
885 startEndDiff.
scale(zeroRadiusStop);
890 truncateSide = TruncateEnd;
891 zeroRadiusStop = -startRadius / (endRadius - startRadius);
894 startEndDiff.
scale(1 - zeroRadiusStop);
898 if (!(startRadius == 0 && endRadius == 0)) {
899 truncateToStopInterpolating(
900 zeroRadiusStop,
colors, stops, truncateSide);
905 if (radiusDiff > 0) {
907 endRadius = radiusDiff;
909 stops.erase(stops.begin(), stops.end() - 1);
912 startRadius = -radiusDiff;
914 stops.erase(stops.begin() + 1, stops.end());
918 if (startRadius < 0 || endRadius < 0) {
919 auto roundIntegerMultiple = [](
SkScalar factorZeroCrossing,
921 int roundedMultiple = factorZeroCrossing > 0
922 ? ceilf(factorZeroCrossing)
923 : floorf(factorZeroCrossing) - 1;
925 roundedMultiple += roundedMultiple < 0 ? -1 : 1;
927 return roundedMultiple;
931 SkScalar radiusDiff = endRadius - startRadius;
932 SkScalar factorZeroCrossing = (startRadius / (startRadius - endRadius));
933 bool inRange = 0.f <= factorZeroCrossing && factorZeroCrossing <= 1.0f;
934 SkScalar direction = inRange && radiusDiff < 0 ? -1.0f : 1.0f;
936 roundIntegerMultiple(factorZeroCrossing * direction, tileMode);
937 startToEnd.
scale(circleProjectionFactor);
938 startRadius += circleProjectionFactor * radiusDiff;
939 endRadius += circleProjectionFactor * radiusDiff;
954 SkGradientShader::Interpolation::InPremul::kNo,
955 SkGradientShader::Interpolation::ColorSpace::kSRGB,
956 SkGradientShader::Interpolation::HueMethod::kShorter
962 case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
963 const FT_PaintSweepGradient& sweepGradient = colrPaint.u.sweep_gradient;
975 std::vector<SkScalar> stops;
976 std::vector<SkColor4f>
colors;
977 if (!fetchColorStops(sweepGradient.colorline.color_stop_iterator, stops,
colors)) {
981 if (stops.size() == 1) {
999 SkTileMode tileMode = ToSkTileMode(sweepGradient.colorline.extend);
1013 float colorStopRange = stops.back() - stops.front();
1014 if (colorStopRange == 0.f) {
1026 stops.push_back(stops.back() + 1.0f);
1028 colorStopRange = 1.0f;
1032 SkScalar scaleFactor = 1 / colorStopRange;
1033 SkScalar startOffset = stops.front();
1036 stop = (stop - startOffset) * scaleFactor;
1047 startAngleScaled = 360.f - startAngleScaled;
1048 endAngleScaled = 360.f - endAngleScaled;
1049 if (startAngleScaled >= endAngleScaled) {
1050 std::swap(startAngleScaled, endAngleScaled);
1053 for (
auto& stop : stops) {
1062 startAngleScaled, endAngleScaled,
1064 SkGradientShader::Interpolation::InPremul::kNo,
1065 SkGradientShader::Interpolation::ColorSpace::kSRGB,
1066 SkGradientShader::Interpolation::HueMethod::kShorter
1080bool colrv1_draw_paint(
SkCanvas* canvas,
1082 const SkColor foregroundColor,
1084 const FT_COLR_Paint& colrPaint) {
1085 switch (colrPaint.format) {
1086 case FT_COLR_PAINTFORMAT_GLYPH: {
1087 FT_UInt glyphID = colrPaint.u.glyph.glyphID;
1093 if (!generateFacePathCOLRv1(face, glyphID, &
path)) {
1096 if constexpr (kSkShowTextBlitCoverage) {
1098 highlight_paint.
setColor(0x33FF0000);
1104 case FT_COLR_PAINTFORMAT_SOLID:
1105 case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
1106 case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
1107 case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
1109 if (!colrv1_configure_skpaint(face, palette, foregroundColor, colrPaint, &skPaint)) {
1115 case FT_COLR_PAINTFORMAT_TRANSFORM:
1116 case FT_COLR_PAINTFORMAT_TRANSLATE:
1117 case FT_COLR_PAINTFORMAT_SCALE:
1118 case FT_COLR_PAINTFORMAT_ROTATE:
1119 case FT_COLR_PAINTFORMAT_SKEW:
1128bool colrv1_draw_glyph_with_path(
SkCanvas* canvas,
1131 const FT_COLR_Paint& glyphPaint,
const FT_COLR_Paint& fillPaint) {
1132 SkASSERT(glyphPaint.format == FT_COLR_PAINTFORMAT_GLYPH);
1133 SkASSERT(fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
1134 fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
1135 fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
1136 fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT);
1140 if (!colrv1_configure_skpaint(face, palette, foregroundColor, fillPaint, &skiaFillPaint)) {
1144 FT_UInt glyphID = glyphPaint.u.glyph.glyphID;
1150 if (!generateFacePathCOLRv1(face, glyphID, &
path)) {
1153 if constexpr (kSkShowTextBlitCoverage) {
1155 highlightPaint.
setColor(0x33FF0000);
1166void colrv1_transform(
FT_Face face,
1167 const FT_COLR_Paint& colrPaint,
1169 SkMatrix* outTransform =
nullptr) {
1174 switch (colrPaint.format) {
1175 case FT_COLR_PAINTFORMAT_TRANSFORM: {
1179 case FT_COLR_PAINTFORMAT_TRANSLATE: {
1184 case FT_COLR_PAINTFORMAT_SCALE: {
1191 case FT_COLR_PAINTFORMAT_ROTATE: {
1200 case FT_COLR_PAINTFORMAT_SKEW: {
1233bool colrv1_start_glyph(
SkCanvas* canvas,
1235 const SkColor foregroundColor,
1238 FT_Color_Root_Transform rootTransform,
1239 VisitedSet* activePaints);
1241bool colrv1_traverse_paint(
SkCanvas* canvas,
1243 const SkColor foregroundColor,
1245 FT_OpaquePaint opaquePaint,
1246 VisitedSet* activePaints) {
1248 if (activePaints->contains(opaquePaint)) {
1252 activePaints->add(opaquePaint);
1255 FT_COLR_Paint
paint;
1256 if (!FT_Get_Paint(face, opaquePaint, &
paint)) {
1261 switch (
paint.format) {
1262 case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
1263 FT_LayerIterator& layerIterator =
paint.u.colr_layers.layer_iterator;
1264 FT_OpaquePaint layerPaint{
nullptr, 1};
1265 while (FT_Get_Paint_Layers(face, &layerIterator, &layerPaint)) {
1266 if (!colrv1_traverse_paint(canvas, palette, foregroundColor, face,
1267 layerPaint, activePaints)) {
1273 case FT_COLR_PAINTFORMAT_GLYPH:
1279 FT_COLR_Paint fillPaint;
1280 if (!FT_Get_Paint(face,
paint.u.glyph.paint, &fillPaint)) {
1283 if (fillPaint.format == FT_COLR_PAINTFORMAT_SOLID ||
1284 fillPaint.format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
1285 fillPaint.format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
1286 fillPaint.format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT)
1288 return colrv1_draw_glyph_with_path(canvas, palette, foregroundColor,
1289 face,
paint, fillPaint);
1291 if (!colrv1_draw_paint(canvas, palette, foregroundColor, face,
paint)) {
1294 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1295 face,
paint.u.glyph.paint, activePaints);
1296 case FT_COLR_PAINTFORMAT_COLR_GLYPH:
1297 return colrv1_start_glyph(canvas, palette, foregroundColor,
1298 face,
paint.u.colr_glyph.glyphID, FT_COLOR_NO_ROOT_TRANSFORM,
1300 case FT_COLR_PAINTFORMAT_TRANSFORM:
1301 colrv1_transform(face,
paint, canvas);
1302 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1303 face,
paint.u.transform.paint, activePaints);
1304 case FT_COLR_PAINTFORMAT_TRANSLATE:
1305 colrv1_transform(face,
paint, canvas);
1306 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1307 face,
paint.u.translate.paint, activePaints);
1308 case FT_COLR_PAINTFORMAT_SCALE:
1309 colrv1_transform(face,
paint, canvas);
1310 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1311 face,
paint.u.scale.paint, activePaints);
1312 case FT_COLR_PAINTFORMAT_ROTATE:
1313 colrv1_transform(face,
paint, canvas);
1314 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1315 face,
paint.u.rotate.paint, activePaints);
1316 case FT_COLR_PAINTFORMAT_SKEW:
1317 colrv1_transform(face,
paint, canvas);
1318 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1319 face,
paint.u.skew.paint, activePaints);
1320 case FT_COLR_PAINTFORMAT_COMPOSITE: {
1323 if (!colrv1_traverse_paint(canvas, palette, foregroundColor,
1324 face,
paint.u.composite.backdrop_paint, activePaints)) {
1329 canvas->
saveLayer(
nullptr, &blendModePaint);
1330 return colrv1_traverse_paint(canvas, palette, foregroundColor,
1331 face,
paint.u.composite.source_paint, activePaints);
1333 case FT_COLR_PAINTFORMAT_SOLID:
1334 case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
1335 case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
1336 case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
1337 return colrv1_draw_paint(canvas, palette, foregroundColor, face,
paint);
1346SkPath GetClipBoxPath(
FT_Face face, uint16_t glyphId,
bool untransformed) {
1348 SkUniqueFTSize unscaledFtSize =
nullptr;
1349 FT_Size oldSize = face->size;
1350 FT_Matrix oldTransform;
1354 if (untransformed) {
1355 unscaledFtSize.
reset(
1356 [face]() -> FT_Size {
1358 FT_Error err = FT_New_Size(face, &
size);
1361 "FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.",
1367 if (!unscaledFtSize) {
1371 err = FT_Activate_Size(unscaledFtSize.get());
1376 err = FT_Set_Char_Size(face,
SkIntToFDot6(face->units_per_EM), 0, 0, 0);
1381 FT_Get_Transform(face, &oldTransform, &oldDelta);
1382 FT_Set_Transform(face,
nullptr,
nullptr);
1385 FT_ClipBox colrGlyphClipBox;
1386 if (FT_Get_Color_Glyph_ClipBox(face, glyphId, &colrGlyphClipBox)) {
1398 if (untransformed) {
1399 err = FT_Activate_Size(oldSize);
1403 FT_Set_Transform(face, &oldTransform, &oldDelta);
1409bool colrv1_start_glyph(
SkCanvas* canvas,
1411 const SkColor foregroundColor,
1414 FT_Color_Root_Transform rootTransform,
1415 VisitedSet* activePaints) {
1416 FT_OpaquePaint opaquePaint{
nullptr, 1};
1417 if (!FT_Get_Color_Glyph_Paint(face, glyphId, rootTransform, &opaquePaint)) {
1421 bool untransformed = rootTransform == FT_COLOR_NO_ROOT_TRANSFORM;
1422 SkPath clipBoxPath = GetClipBoxPath(face, glyphId, untransformed);
1424 canvas->
clipPath(clipBoxPath,
true);
1427 if (!colrv1_traverse_paint(canvas, palette, foregroundColor,
1428 face, opaquePaint, activePaints)) {
1435bool colrv1_start_glyph_bounds(
SkMatrix *ctm,
1439 FT_Color_Root_Transform rootTransform,
1440 VisitedSet* activePaints);
1442bool colrv1_traverse_paint_bounds(
SkMatrix* ctm,
1445 FT_OpaquePaint opaquePaint,
1446 VisitedSet* activePaints) {
1448 if (activePaints->contains(opaquePaint)) {
1452 activePaints->add(opaquePaint);
1455 FT_COLR_Paint
paint;
1456 if (!FT_Get_Paint(face, opaquePaint, &
paint)) {
1463 switch (
paint.format) {
1464 case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
1465 FT_LayerIterator& layerIterator =
paint.u.colr_layers.layer_iterator;
1466 FT_OpaquePaint layerPaint{
nullptr, 1};
1467 while (FT_Get_Paint_Layers(face, &layerIterator, &layerPaint)) {
1468 if (!colrv1_traverse_paint_bounds(ctm,
bounds, face, layerPaint, activePaints)) {
1474 case FT_COLR_PAINTFORMAT_GLYPH: {
1475 FT_UInt glyphID =
paint.u.glyph.glyphID;
1477 if (!generateFacePathCOLRv1(face, glyphID, &
path)) {
1480 path.transform(*ctm);
1484 case FT_COLR_PAINTFORMAT_COLR_GLYPH: {
1485 FT_UInt glyphID =
paint.u.colr_glyph.glyphID;
1486 return colrv1_start_glyph_bounds(ctm,
bounds, face, glyphID, FT_COLOR_NO_ROOT_TRANSFORM,
1489 case FT_COLR_PAINTFORMAT_TRANSFORM: {
1491 colrv1_transform(face,
paint,
nullptr, &transformMatrix);
1493 FT_OpaquePaint& transformPaint =
paint.u.transform.paint;
1494 return colrv1_traverse_paint_bounds(ctm,
bounds, face, transformPaint, activePaints);
1496 case FT_COLR_PAINTFORMAT_TRANSLATE: {
1498 colrv1_transform(face,
paint,
nullptr, &transformMatrix);
1500 FT_OpaquePaint& translatePaint =
paint.u.translate.paint;
1501 return colrv1_traverse_paint_bounds(ctm,
bounds, face, translatePaint, activePaints);
1503 case FT_COLR_PAINTFORMAT_SCALE: {
1505 colrv1_transform(face,
paint,
nullptr, &transformMatrix);
1507 FT_OpaquePaint& scalePaint =
paint.u.scale.paint;
1508 return colrv1_traverse_paint_bounds(ctm,
bounds, face, scalePaint, activePaints);
1510 case FT_COLR_PAINTFORMAT_ROTATE: {
1512 colrv1_transform(face,
paint,
nullptr, &transformMatrix);
1514 FT_OpaquePaint& rotatePaint =
paint.u.rotate.paint;
1515 return colrv1_traverse_paint_bounds(ctm,
bounds, face, rotatePaint, activePaints);
1517 case FT_COLR_PAINTFORMAT_SKEW: {
1519 colrv1_transform(face,
paint,
nullptr, &transformMatrix);
1521 FT_OpaquePaint& skewPaint =
paint.u.skew.paint;
1522 return colrv1_traverse_paint_bounds(ctm,
bounds, face, skewPaint, activePaints);
1524 case FT_COLR_PAINTFORMAT_COMPOSITE: {
1525 FT_OpaquePaint& backdropPaint =
paint.u.composite.backdrop_paint;
1526 FT_OpaquePaint& sourcePaint =
paint.u.composite. source_paint;
1527 return colrv1_traverse_paint_bounds(ctm,
bounds, face, backdropPaint, activePaints) &&
1528 colrv1_traverse_paint_bounds(ctm,
bounds, face, sourcePaint, activePaints);
1530 case FT_COLR_PAINTFORMAT_SOLID:
1531 case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
1532 case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
1533 case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
1544bool colrv1_start_glyph_bounds(
SkMatrix *ctm,
1548 FT_Color_Root_Transform rootTransform,
1549 VisitedSet* activePaints) {
1550 FT_OpaquePaint opaquePaint{
nullptr, 1};
1551 return FT_Get_Color_Glyph_Paint(face, glyphId, rootTransform, &opaquePaint) &&
1552 colrv1_traverse_paint_bounds(ctm,
bounds, face, opaquePaint, activePaints);
1565#ifdef TT_SUPPORT_COLRV1
1573 VisitedSet activePaints;
1576 FT_COLOR_INCLUDE_ROOT_TRANSFORM, &activePaints);
1588 bool haveLayers =
false;
1589 FT_LayerIterator layerIterator;
1590 layerIterator.p =
nullptr;
1591 FT_UInt layerGlyphIndex = 0;
1592 FT_UInt layerColorIndex = 0;
1594 paint.setAntiAlias(!(
flags & FT_LOAD_TARGET_MONO));
1595 while (FT_Get_Color_Glyph_Layer(face, glyph.
getGlyphID(), &layerGlyphIndex,
1596 &layerColorIndex, &layerIterator)) {
1598 if (layerColorIndex == 0xFFFF) {
1601 paint.setColor(palette[layerColorIndex]);
1604 if (this->generateFacePath(face, layerGlyphIndex,
flags, &
path)) {
1608 SkASSERTF(haveLayers,
"Could not get COLRv0 layers from '%s'.", face->family_name);
1613#if defined(FT_CONFIG_OPTION_SVG)
1616 SkASSERT(face->glyph->format == FT_GLYPH_FORMAT_SVG);
1618 FT_SVG_Document ftSvg = (FT_SVG_Document)face->glyph->other;
1620 FT_Matrix ftMatrix = ftSvg->transform;
1621 FT_Vector ftOffset = ftSvg->delta;
1638 auto svgDecoder = svgFactory(ftSvg->svg_document, ftSvg->svg_document_length);
1642 return svgDecoder->render(*canvas, ftSvg->units_per_EM, glyph.
getGlyphID(),
1650 switch ( face->glyph->format ) {
1651 case FT_GLYPH_FORMAT_OUTLINE: {
1652 FT_Outline* outline = &face->glyph->outline;
1668 FT_Outline_Translate(outline,
dx, dy);
1669 FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
1670 FT_RENDER_MODE_LCD);
1672 SK_TRACEFTR(err,
"Could not render glyph %p.", face->glyph);
1679 if constexpr (kSkShowTextBlitCoverage) {
1682 FT_GlyphSlotRec& ftGlyph = *face->glyph;
1686 -ftGlyph.bitmap_top,
1687 ftGlyph.bitmap.width,
1688 ftGlyph.bitmap.rows)))
1695 unsigned char* origBuffer = ftGlyph.bitmap.buffer;
1698 int32_t topDiff = mask.
fBounds.
fTop - (-ftGlyph.bitmap_top);
1699 ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff;
1700 ftGlyph.bitmap.rows -= topDiff;
1704 int32_t leftDiff = mask.
fBounds.
fLeft - ftGlyph.bitmap_left;
1705 ftGlyph.bitmap.buffer += leftDiff;
1706 ftGlyph.bitmap.width -= leftDiff;
1718 int ftVertScale = (doVert ? 3 : 1);
1719 int ftHoriScale = (doVert ? 1 : 3);
1724 ftGlyph.bitmap.width = mask.
fBounds.
width() * ftHoriScale;
1733 copyFT2LCD16<true>(ftGlyph.bitmap, &mask, doBGR,
1734 preBlend.
fR, preBlend.
fG, preBlend.
fB);
1736 copyFT2LCD16<false>(ftGlyph.bitmap, &mask, doBGR,
1737 preBlend.
fR, preBlend.
fG, preBlend.
fB);
1740 ftGlyph.bitmap.buffer = origBuffer;
1744 FT_Outline_Get_CBox(outline, &bbox);
1753 FT_Outline_Translate(outline,
dx - ((bbox.xMin +
dx) & ~63),
1754 dy - ((bbox.yMin + dy) & ~63));
1759 target.buffer =
static_cast<uint8_t*
>(imageBuffer);
1763 FT_Outline_Get_Bitmap(face->glyph->library, outline, &
target);
1764 if constexpr (kSkShowTextBlitCoverage) {
1766 for (
unsigned y = 0;
y <
target.rows;
y += 2) {
1767 for (
unsigned x = (
y & 0x2);
x <
target.width;
x+=4) {
1769 b =
b ^ (1 << (0x7 - (
x & 0x7)));
1773 for (
unsigned y = 0;
y <
target.rows; ++
y) {
1774 for (
unsigned x = 0;
x <
target.width; ++
x) {
1776 a = std::max<uint8_t>(
a, 0x20);
1784 case FT_GLYPH_FORMAT_BITMAP: {
1785 FT_Pixel_Mode pixel_mode =
static_cast<FT_Pixel_Mode
>(face->glyph->bitmap.pixel_mode);
1789 SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
1790 FT_PIXEL_MODE_GRAY == pixel_mode ||
1804 copyFTBitmap(face->glyph->bitmap, &dstMask);
1814 face->glyph->bitmap.rows,
1815 SkColorType_for_FTPixelMode(pixel_mode),
1824 reinterpret_cast<uint8_t*
>(unscaledBitmap.
getPixels()),
1827 SkMaskFormat_for_SkColorType(unscaledBitmap.
colorType()));
1828 copyFTBitmap(face->glyph->bitmap, &unscaledBitmapAlias);
1834 int bitmapRowBytes = 0;
1841 SkColorType_for_SkMaskFormat(maskFormat),
1856 if constexpr (kSkShowTextBlitCoverage) {
1857 canvas.
clear(0x33FF0000);
1862 canvas.
concat(bitmapTransform);
1863 canvas.
translate(face->glyph->bitmap_left, -face->glyph->bitmap_top);
1877 uint16_t*
dst =
reinterpret_cast<uint16_t*
>(imageBuffer);
1878 for (
int y = dstBitmap.
height();
y --> 0;) {
1879 for (
int x = 0;
x < dstBitmap.
width(); ++
x) {
1896#if defined(SK_GAMMA_APPLY_TO_A8)
1899 unsigned rowBytes = glyph.
rowBytes();
1901 for (
int y = glyph.
height() - 1;
y >= 0; --
y) {
1902 for (
int x = glyph.
width() - 1;
x >= 0; --
x) {
1915class SkFTGeometrySink {
1920 void goingTo(
const FT_Vector* pt) {
1928 bool currentIsNot(
const FT_Vector* pt) {
1929 return fCurrent.x != pt->x || fCurrent.y != pt->y;
1932 static int Move(
const FT_Vector* pt,
void* ctx) {
1933 SkFTGeometrySink&
self = *(SkFTGeometrySink*)ctx;
1934 if (
self.fStarted) {
1935 self.fPath->close();
1936 self.fStarted =
false;
1938 self.fCurrent = *pt;
1942 static int Line(
const FT_Vector* pt,
void* ctx) {
1943 SkFTGeometrySink&
self = *(SkFTGeometrySink*)ctx;
1944 if (
self.currentIsNot(pt)) {
1951 static int Quad(
const FT_Vector* pt0,
const FT_Vector* pt1,
void* ctx) {
1952 SkFTGeometrySink&
self = *(SkFTGeometrySink*)ctx;
1953 if (
self.currentIsNot(pt0) ||
self.currentIsNot(pt1)) {
1961 static int Cubic(
const FT_Vector* pt0,
const FT_Vector* pt1,
const FT_Vector* pt2,
void* ctx) {
1962 SkFTGeometrySink&
self = *(SkFTGeometrySink*)ctx;
1963 if (
self.currentIsNot(pt0) ||
self.currentIsNot(pt1) ||
self.currentIsNot(pt2)) {
1975 inline static constexpr const FT_Outline_Funcs Funcs{
1976 SkFTGeometrySink::Move,
1979 SkFTGeometrySink::Cubic,
1986 SkFTGeometrySink sink{
path};
1987 if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ||
1988 FT_Outline_Decompose(&face->glyph->outline, &SkFTGeometrySink::Funcs, &sink))
1999 flags |= FT_LOAD_BITMAP_METRICS_ONLY;
2000 flags |= FT_LOAD_NO_BITMAP;
2001 flags &= ~FT_LOAD_RENDER;
2002 flags &= ~FT_LOAD_COLOR;
2003 if (FT_Load_Glyph(face, glyphID,
flags)) {
2007 return generateGlyphPathStatic(face,
path);
2010#ifdef TT_SUPPORT_COLRV1
2013 flags |= FT_LOAD_BITMAP_METRICS_ONLY;
2014 flags |= FT_LOAD_NO_BITMAP;
2015 flags &= ~FT_LOAD_RENDER;
2016 flags &= ~FT_LOAD_COLOR;
2017 flags |= FT_LOAD_NO_HINTING;
2018 flags |= FT_LOAD_NO_AUTOHINT;
2019 flags |= FT_LOAD_IGNORE_TRANSFORM;
2021 SkUniqueFTSize unscaledFtSize([face]() -> FT_Size {
2023 FT_Error err = FT_New_Size(face, &
size);
2025 SK_TRACEFTR(err,
"FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.",
2032 if (!unscaledFtSize) {
2036 FT_Size oldSize = face->size;
2038 auto tryGeneratePath = [face, &unscaledFtSize, glyphID,
flags,
path]() {
2041 err = FT_Activate_Size(unscaledFtSize.get());
2046 err = FT_Set_Char_Size(face,
SkIntToFDot6(face->units_per_EM),
2052 err = FT_Load_Glyph(face, glyphID,
flags);
2058 if (!generateGlyphPathStatic(face,
path)) {
2066 bool pathGenerationResult = tryGeneratePath();
2068 FT_Activate_Size(oldSize);
2070 return pathGenerationResult;
2077 if (!generateGlyphPathStatic(face,
path)) {
2092 return generateFacePathStatic(face, glyphID,
flags,
path);
2095#ifdef TT_SUPPORT_COLRV1
2100 VisitedSet activePaints;
2101 return colrv1_start_glyph_bounds(&ctm,
bounds, face, glyphID,
2102 FT_COLOR_INCLUDE_ROOT_TRANSFORM, &activePaints);
GrTriangulator::Line Line
static constexpr T SkAlign8(T x)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkDEBUGFAIL(message)
#define SkASSERTF(cond, fmt,...)
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kSaturation
saturation of source with hue and luminosity of destination
@ kColorBurn
darken destination to reflect source
@ kLighten
rc = s + d - min(s*da, d*sa), ra = kSrcOver
@ kHue
hue of source with saturation and luminosity of destination
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kColorDodge
brighten destination to reflect source
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
@ kLuminosity
luminosity of source with hue and saturation of destination
@ kSoftLight
lighten or darken, depending on source
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOverlay
multiply or screen, depending on destination
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOver
r = d + (1-da)*s
@ kColor
hue and saturation of source with luminosity of destination
@ kHardLight
multiply or screen, depending on source
@ kDarken
rc = s + d - max(s*da, d*sa), ra = kSrcOver
static U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
static SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst, int scale)
static SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
constexpr SkColor SK_ColorTRANSPARENT
constexpr SkColor SK_ColorBLACK
constexpr SkColor SK_ColorWHITE
#define SkFDot6ToScalar(x)
#define SkFixedToFDot6(x)
#define SkFixedToScalar(x)
#define SkFixedToFloat(x)
#define FT_OUTLINE_OVERLAP
#define FT_PIXEL_MODE_BGRA
#define SK_TRACEFTR(ERR,...)
struct FT_FaceRec_ * FT_Face
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
bool SK_API AsWinding(const SkPath &path, SkPath *result)
bool SK_API Simplify(const SkPath &path, SkPath *result)
void swap(sk_sp< T > &a, sk_sp< T > &b)
#define SkDegreesToRadians(degrees)
#define SkScalarTan(radians)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
static int convert_8_to_1(unsigned byte)
static uint8_t pack_8_to_1(const uint8_t alpha[8])
static void packA8ToA1(SkMaskBuilder &dstMask, const uint8_t *src, size_t srcRB)
#define SK_AT_SCOPE_EXIT(stmt)
constexpr int SkToInt(S x)
static constexpr bool SkToBool(const T &x)
constexpr uint8_t SkToU8(S x)
static SkScalar center(float pos0, float pos1)
sk_sp< SkImage > asImage() const
uint8_t * getAddr8(int x, int y) const
SkColorType colorType() const
void setPixels(void *pixels)
bool setInfo(const SkImageInfo &imageInfo, size_t rowBytes=0)
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
void drawRect(const SkRect &rect, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
void drawPaint(const SkPaint &paint)
void clear(SkColor color)
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
void drawPath(const SkPath &path, const SkPaint &paint)
void concat(const SkMatrix &matrix)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorSpace > MakeSRGB()
SkGlyphID getGlyphID() const
SkMask::Format maskFormat() const
SkFixed getSubYFixed() const
SkFixed getSubXFixed() const
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, SkScalar startAngle, SkScalar endAngle, uint32_t flags, const SkMatrix *localMatrix)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
std::unique_ptr< SkOpenTypeSVGDecoder >(*)(const uint8_t *svg, size_t length) OpenTypeSVGDecoderFactory
static OpenTypeSVGDecoderFactory GetOpenTypeSVGDecoderFactory()
static SkMatrix RotateDeg(SkScalar deg)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
SkMatrix & preConcat(const SkMatrix &other)
void setColor(SkColor color)
void setAntiAlias(bool aa)
void setBlendMode(SkBlendMode mode)
SkPath & moveTo(SkScalar x, SkScalar y)
static SkPath Polygon(const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
constexpr size_t size() const
bool isApplicable() const
FlutterSemanticsFlag flags
uint32_t uint32_t * format
static float max(float r, float g, float b)
static float min(float r, float g, float b)
constexpr SkColor4f kTransparent
Optional< SkRect > bounds
PODArray< SkColor > colors
SkSamplingOptions sampling
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
constexpr SkMatrix ToSkMatrix(const DlMatrix &matrix)
bool operator==(C p1, const scoped_nsprotocol< C > &p2)
std::array< Point, 4 > Quad
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
static bool Intersects(const SkIRect &a, const SkIRect &b)
int32_t fBottom
larger y-axis bounds
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
constexpr int32_t width() const
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
int32_t fLeft
smaller x-axis bounds
int32_t fRight
larger x-axis bounds
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
@ kLCD16_Format
565 alpha for r/g/b
@ kARGB32_Format
SkPMColor.
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
static float CrossProduct(const SkVector &a, const SkVector &b)
static float DotProduct(const SkVector &a, const SkVector &b)
static constexpr SkPoint Make(float x, float y)
void scale(float scale, SkPoint *dst) const
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeEmpty()
bool drawCOLRv1Glyph(FT_Face, const SkGlyph &, LoadGlyphFlags, SkSpan< SkColor > palette, SkCanvas *) const
bool drawSVGGlyph(FT_Face, const SkGlyph &, LoadGlyphFlags, SkSpan< SkColor > palette, SkCanvas *) const
SkScalerContext::Flags fFlags
static bool computeColrV1GlyphBoundingBox(FT_Face, SkGlyphID, SkRect *bounds)
void generateGlyphImage(FT_Face, const SkGlyph &, void *, const SkMatrix &bitmapTransform, const SkMaskGamma::PreBlend &) const
bool generateGlyphPath(FT_Face, SkPath *) const
void init(SkColor fgColor, SkScalerContext::Flags)
bool drawCOLRv0Glyph(FT_Face, const SkGlyph &, LoadGlyphFlags, SkSpan< SkColor > palette, SkCanvas *) const
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
std::shared_ptr< const fml::Mapping > data