27[[maybe_unused]]
static inline const constexpr bool kSkShowTextBlitCoverage =
false;
29sk_sp<SkData> streamToData(
const std::unique_ptr<SkStreamAsset>& font_data) {
37rust::Box<::fontations_ffi::BridgeFontRef> make_bridge_font_ref(
sk_sp<SkData> fontData,
39 rust::Slice<const uint8_t> slice{fontData->bytes(), fontData->size()};
40 return fontations_ffi::make_font_ref(slice, index);
43static_assert(
sizeof(fontations_ffi::SkiaDesignCoordinate) ==
45 sizeof(fontations_ffi::SkiaDesignCoordinate::axis) ==
47 sizeof(fontations_ffi::SkiaDesignCoordinate::value) ==
49 offsetof(fontations_ffi::SkiaDesignCoordinate, axis) ==
51 offsetof(fontations_ffi::SkiaDesignCoordinate, value) ==
53 "Struct fontations_ffi::SkiaDesignCoordinate must match "
54 "SkFontArguments::VariationPosition::Coordinate.");
56rust::Box<fontations_ffi::BridgeNormalizedCoords> make_normalized_coords(
57 fontations_ffi::BridgeFontRef
const& bridgeFontRef,
60 rust::Slice<const fontations_ffi::SkiaDesignCoordinate> coordinates(
61 reinterpret_cast<const fontations_ffi::SkiaDesignCoordinate*
>(
64 return resolve_into_normalized_coords(bridgeFontRef, coordinates);
67SkMatrix SkMatrixFromFontationsTransform(
const fontations_ffi::Transform& transformArg) {
86SkTypeface_Fontations::SkTypeface_Fontations(
90 rust::Box<fontations_ffi::BridgeFontRef>&& fontRef,
91 rust::Box<fontations_ffi::BridgeMappingIndex>&& mappingIndex,
92 rust::Box<fontations_ffi::BridgeNormalizedCoords>&& normalizedCoords,
93 rust::Box<fontations_ffi::BridgeOutlineCollection>&& outlines,
94 rust::Vec<uint32_t>&& palette)
96 , fFontData(
std::move(fontData))
98 , fBridgeFontRef(
std::move(fontRef))
99 , fMappingIndex(
std::move(mappingIndex))
100 , fBridgeNormalizedCoords(
std::move(normalizedCoords))
101 , fOutlines(
std::move(outlines))
102 , fPalette(
std::move(palette)) {}
111 uint32_t ttcIndex =
args.getCollectionIndex();
112 rust::Box<fontations_ffi::BridgeFontRef> bridgeFontRef = make_bridge_font_ref(data, ttcIndex);
113 if (!fontations_ffi::font_ref_is_valid(*bridgeFontRef)) {
118 fontations_ffi::BridgeFontStyle
fontStyle;
119 if (fontations_ffi::get_font_style(*bridgeFontRef,
fontStyle)) {
124 rust::Box<fontations_ffi::BridgeMappingIndex> mappingIndex =
125 fontations_ffi::make_mapping_index(*bridgeFontRef);
128 std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> concatenatedCoords =
nullptr;
134 if (
args.getCollectionIndex() & 0xFFFF0000) {
135 size_t numNamedInstanceCoords =
136 fontations_ffi::coordinates_for_shifted_named_instance_index(
138 args.getCollectionIndex(),
139 rust::cxxbridge1::Slice<fontations_ffi::SkiaDesignCoordinate>());
140 concatenatedCoords.reset(
144 rust::cxxbridge1::Slice<fontations_ffi::SkiaDesignCoordinate> targetSlice(
145 reinterpret_cast<fontations_ffi::SkiaDesignCoordinate*
>(concatenatedCoords.get()),
146 numNamedInstanceCoords);
147 size_t retrievedNamedInstanceCoords =
148 fontations_ffi::coordinates_for_shifted_named_instance_index(
149 *bridgeFontRef,
args.getCollectionIndex(), targetSlice);
150 if (numNamedInstanceCoords != retrievedNamedInstanceCoords) {
154 concatenatedCoords[numNamedInstanceCoords + i] = variationPosition.
coordinates[i];
157 variationPosition.
coordinates = concatenatedCoords.get();
160 rust::Box<fontations_ffi::BridgeNormalizedCoords> normalizedCoords =
161 make_normalized_coords(*bridgeFontRef, variationPosition);
162 rust::Box<fontations_ffi::BridgeOutlineCollection> outlines =
163 fontations_ffi::get_outline_collection(*bridgeFontRef);
165 rust::Slice<const fontations_ffi::PaletteOverride> paletteOverrides(
166 reinterpret_cast<const ::fontations_ffi::PaletteOverride*
>(
args.getPalette().overrides),
167 args.getPalette().overrideCount);
168 rust::Vec<uint32_t> palette =
169 resolve_palette(*bridgeFontRef,
args.getPalette().index, paletteOverrides);
174 std::move(bridgeFontRef),
175 std::move(mappingIndex),
176 std::move(normalizedCoords),
178 std::move(palette)));
184void PathGeometrySink::going_to(
SkPoint point) {
192bool PathGeometrySink::current_is_not(
SkPoint point) {
return fCurrent != point; }
204 if (current_is_not(pt0)) {
213 if (current_is_not(pt0) || current_is_not(pt1)) {
222 if (current_is_not(pt0) || current_is_not(pt1) || current_is_not(pt2)) {
233 : fAxisArray(axisArray), fAxisCount(axisCount) {}
236 size_t i, uint32_t axisTag,
float min,
float def,
float max,
bool hidden) {
237 if (i >= fAxisCount) {
254 return fontations_ffi::units_per_em_or_zero(*fBridgeFontRef);
258 rust::String readFamilyName = fontations_ffi::family_name(*fBridgeFontRef);
259 *familyName =
SkString(readFamilyName.data(), readFamilyName.size());
263 rust::String readPsName;
264 if (fontations_ffi::postscript_name(*fBridgeFontRef, readPsName)) {
265 if (postscriptName) {
266 *postscriptName =
SkString(readPsName.data(), readPsName.size());
275 fGlyphMasksMayNeedCurrentColorOnce([
this] {
277 fGlyphMasksMayNeedCurrentColor = this->
getTableSize(COLRTag) > 0;
279 return fGlyphMasksMayNeedCurrentColor;
287 for (
int i = 0; i <
count; ++i) {
288 glyphs[i] = fontations_ffi::lookup_glyph_or_zero(*fBridgeFontRef, *fMappingIndex, chars[i]);
292 return fontations_ffi::num_glyphs(*fBridgeFontRef);
297 if (!codepointForGlyphMap) {
300 rust::Slice<uint32_t> codepointForGlyphSlice{
reinterpret_cast<uint32_t*
>(codepointForGlyphMap),
302 fontations_ffi::fill_glyph_to_unicode_map(*fBridgeFontRef, codepointForGlyphSlice);
312 rust::Box<::fontations_ffi::BridgeLocalizedStrings> bridge_localized_strings)
313 : fBridgeLocalizedStrings(
std::move(bridge_localized_strings)) {}
315 fontations_ffi::BridgeLocalizedName localizedName;
316 if (!fontations_ffi::localized_name_next(*fBridgeLocalizedStrings, localizedName)) {
320 SkString(localizedName.string.data(), localizedName.string.size());
322 SkString(localizedName.language.data(), localizedName.language.size());
327 rust::Box<::fontations_ffi::BridgeLocalizedStrings> fBridgeLocalizedStrings;
343 ->getBridgeNormalizedCoords())
352 fontations_ffi::BridgeScalerMetrics scalerMetrics;
354 if (!fontations_ffi::get_path(fOutlines,
357 fBridgeNormalizedCoords,
362 *path = std::move(pathWrapper).into_inner();
363 if (scalerMetrics.has_overlaps) {
389 float x_advance = 0.0f;
390 x_advance = fontations_ffi::advance_width_or_zero(
391 fBridgeFontRef,
scale.y(), fBridgeNormalizedCoords, glyph.
getGlyphID());
402 bool has_colrv1_glyph =
403 fontations_ffi::has_colrv1_glyph(fBridgeFontRef, glyph.
getGlyphID());
404 bool has_colrv0_glyph =
405 fontations_ffi::has_colrv0_glyph(fBridgeFontRef, glyph.
getGlyphID());
406 bool has_bitmap_glyph =
407 fontations_ffi::has_bitmap_glyph(fBridgeFontRef, glyph.
getGlyphID());
409 if (has_colrv1_glyph || has_colrv0_glyph) {
414 fontations_ffi::ClipBox clipBox;
415 if (has_colrv1_glyph && fontations_ffi::get_colrv1_clip_box(fBridgeFontRef,
416 fBridgeNormalizedCoords,
422 clipBox.x_min, -clipBox.y_max, clipBox.x_max, -clipBox.y_min);
433 uint16_t upem = fontations_ffi::units_per_em_or_zero(fBridgeFontRef);
439 fullTransform.
preScale(1.f / upem, 1.f / upem);
442 bool result = fontations_ffi::draw_colr_glyph(fBridgeFontRef,
443 fBridgeNormalizedCoords,
453 }
else if (has_bitmap_glyph) {
458 rust::cxxbridge1::Box<fontations_ffi::BridgeBitmapGlyph> bitmap_glyph =
459 fontations_ffi::bitmap_glyph(fBridgeFontRef, glyph.
getGlyphID(),
scale.fY);
460 rust::cxxbridge1::Slice<const uint8_t> png_data =
461 fontations_ffi::png_data(*bitmap_glyph);
464 const fontations_ffi::BitmapMetrics bitmapMetrics =
465 fontations_ffi::bitmap_metrics(*bitmap_glyph);
483 float fontUnitsToSize =
scale.fY / fontations_ffi::units_per_em_or_zero(fBridgeFontRef);
488 if (!std::isinf(bitmapMetrics.width) && !std::isinf(bitmapMetrics.height)) {
492 bitmapMetrics.width * fontUnitsToSize / imageToSize,
493 bitmapMetrics.height * fontUnitsToSize / imageToSize);
494 if (modifiedBounds.
isEmpty()) {
497 bounds = modifiedBounds;
503 matrix.preTranslate(bitmapMetrics.bearing_x * fontUnitsToSize,
504 -bitmapMetrics.bearing_y * fontUnitsToSize);
506 matrix.preScale(imageToSize, imageToSize);
508 float heightAdjustment =
509 bitmapMetrics.placement_origin_bottom_left ? bounds.height() : 0;
510 matrix.preTranslate(0, -heightAdjustment);
516 matrix.mapRect(&bounds);
547 rust::cxxbridge1::Box<fontations_ffi::BridgeBitmapGlyph> bitmap_glyph =
548 fontations_ffi::bitmap_glyph(fBridgeFontRef, glyph.
getGlyphID(),
scale.fY);
549 rust::cxxbridge1::Slice<const uint8_t> png_data = fontations_ffi::png_data(*bitmap_glyph);
559 auto [glyph_image,
result] = codec->getImage();
565 canvas.
concat(remainingMatrix);
571 const fontations_ffi::BitmapMetrics bitmapMetrics =
572 fontations_ffi::bitmap_metrics(*bitmap_glyph);
578 float fontUnitsToSize =
scale.fY / fontations_ffi::units_per_em_or_zero(fBridgeFontRef);
579 canvas.
translate(bitmapMetrics.bearing_x * fontUnitsToSize,
580 -bitmapMetrics.bearing_y * fontUnitsToSize);
581 canvas.
scale(imageScaleFactor, imageScaleFactor);
582 canvas.
translate(bitmapMetrics.inner_bearing_x, -bitmapMetrics.inner_bearing_y);
584 float heightAdjustment =
585 bitmapMetrics.placement_origin_bottom_left ? glyph_image->height() : 0;
590 canvas.
drawImage(glyph_image, 0, 0, sampling);
619 if constexpr (kSkShowTextBlitCoverage) {
620 canvas.
clear(0x33FF0000);
648 *path = path->makeTransform(remainingMatrix);
653 uint16_t upem = fontations_ffi::units_per_em_or_zero(fBridgeFontRef);
665 canvas->
concat(scalerMatrix);
670 bool result = fontations_ffi::draw_colr_glyph(
671 fBridgeFontRef, fBridgeNormalizedCoords, glyph.
getGlyphID(), colorPainter);
680 : fSelf(
self), fGlyph(glyph) {}
681 SkRect onGetBounds()
override {
return fGlyph.
rect(); }
682 size_t onApproximateBytesUsed()
override {
return sizeof(GlyphDrawable); }
683 void maybeShowTextBlitCoverage(
SkCanvas* canvas) {
684 if constexpr (kSkShowTextBlitCoverage) {
686 paint.setColor(0x3300FF00);
692 struct ColrGlyphDrawable :
public GlyphDrawable {
693 using GlyphDrawable::GlyphDrawable;
694 void onDraw(
SkCanvas* canvas)
override {
695 this->maybeShowTextBlitCoverage(canvas);
696 fSelf->drawCOLRGlyph(fGlyph, fSelf->fRec.fForegroundColor, canvas);
711 fontations_ffi::Metrics metrics =
712 fontations_ffi::get_skia_metrics(fBridgeFontRef,
scale.fY, fBridgeNormalizedCoords);
713 out_metrics->
fTop = -metrics.top;
714 out_metrics->
fAscent = -metrics.ascent;
715 out_metrics->
fDescent = -metrics.descent;
716 out_metrics->
fBottom = -metrics.bottom;
717 out_metrics->
fLeading = metrics.leading;
720 out_metrics->
fXMin = metrics.x_min;
721 out_metrics->
fXMax = metrics.x_max;
722 out_metrics->
fXHeight = -metrics.x_height;
723 out_metrics->
fCapHeight = -metrics.cap_height;
725 if (fontations_ffi::table_data(fBridgeFontRef,
728 rust::Slice<uint8_t>())) {
731 auto setMetric = [](
float& dstMetric,
const float srcMetric,
734 if (std::isnan(srcMetric)) {
737 dstMetric = srcMetric;
755 const fontations_ffi::BridgeFontRef& fBridgeFontRef;
756 const fontations_ffi::BridgeNormalizedCoords& fBridgeNormalizedCoords;
757 const fontations_ffi::BridgeOutlineCollection& fOutlines;
763 *ttcIndex = fTtcIndex;
764 return std::make_unique<SkMemoryStream>(fFontData);
769 if (fTtcIndex != SkTo<uint32_t>(
args.getCollectionIndex())) {
774 auto fusedDesignPosition =
775 std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>(numAxes);
777 if (numAxes != retrievedAxes) {
783 for (
int i = 0; i < numAxes; ++i) {
796 rust::cxxbridge1::Box<fontations_ffi::BridgeNormalizedCoords> normalized_args =
799 if (!fontations_ffi::normalized_coords_equal(*normalized_args, *fBridgeNormalizedCoords)) {
804 rust::Slice<const fontations_ffi::PaletteOverride> argPaletteOverrides(
805 reinterpret_cast<const fontations_ffi::PaletteOverride*
>(
args.getPalette().overrides),
806 args.getPalette().overrideCount);
807 rust::Vec<uint32_t> newPalette =
808 resolve_palette(*fBridgeFontRef,
args.getPalette().index, argPaletteOverrides);
810 if (fPalette.size() != newPalette.size() ||
811 memcmp(fPalette.data(), newPalette.data(), fPalette.size() *
sizeof(fPalette[0]))) {
820 return std::make_unique<SkFontationsScalerContext>(
827 if (!fontations_ffi::is_embeddable(*fBridgeFontRef)) {
831 if (!fontations_ffi::is_subsettable(*fBridgeFontRef)) {
835 if (fontations_ffi::table_data(
836 *fBridgeFontRef,
SkSetFourByteTag(
'f',
'v',
'a',
'r'), 0, rust::Slice<uint8_t>())) {
841 fontations_ffi::Metrics metrics =
842 fontations_ffi::get_unscaled_metrics(*fBridgeFontRef, *fBridgeNormalizedCoords);
843 info->fAscent = metrics.ascent;
844 info->fDescent = metrics.descent;
845 info->fCapHeight = metrics.cap_height;
848 (int32_t)metrics.top,
849 (int32_t)metrics.x_max,
850 (int32_t)metrics.bottom);
853 if (fontations_ffi::is_fixed_pitch(*fBridgeFontRef)) {
857 fontations_ffi::BridgeFontStyle
fontStyle;
858 if (fontations_ffi::get_font_style(*fBridgeFontRef,
fontStyle)) {
864 if (fontations_ffi::is_serif_style(*fBridgeFontRef)) {
866 }
else if (fontations_ffi::is_script_style(*fBridgeFontRef)) {
870 info->fItalicAngle = fontations_ffi::italic_angle(*fBridgeFontRef);
878 desc->setFamilyName(familyName.
c_str());
888 rust::Slice<uint8_t> dataSlice;
890 dataSlice = rust::Slice<uint8_t>(
reinterpret_cast<uint8_t*
>(data),
length);
892 size_t copied = fontations_ffi::table_data(*fBridgeFontRef, tag,
offset, dataSlice);
894 return std::min(copied,
length);
898 uint16_t numTables = fontations_ffi::table_tags(*fBridgeFontRef, rust::Slice<uint32_t>());
902 rust::Slice<uint32_t> copyToTags(tags, numTables);
903 return fontations_ffi::table_tags(*fBridgeFontRef, copyToTags);
908 rust::Slice<fontations_ffi::SkiaDesignCoordinate> copyToCoordinates;
910 copyToCoordinates = rust::Slice<fontations_ffi::SkiaDesignCoordinate>(
911 reinterpret_cast<fontations_ffi::SkiaDesignCoordinate*
>(coordinates),
914 return fontations_ffi::variation_position(*fBridgeNormalizedCoords, copyToCoordinates);
920 return fontations_ffi::populate_axes(*fBridgeFontRef, axisWrapper);
927const uint16_t kForegroundColorPaletteIndex = 0xFFFF;
929void populateStopsAndColors(std::vector<SkScalar>& dest_stops,
930 std::vector<SkColor4f>& dest_colors,
933 fontations_ffi::BridgeColorStops& color_stops) {
936 size_t num_color_stops = fontations_ffi::num_color_stops(color_stops);
937 dest_stops.reserve(num_color_stops);
938 dest_colors.reserve(num_color_stops);
940 fontations_ffi::ColorStop color_stop;
941 while (fontations_ffi::next_color_stop(color_stops, color_stop)) {
942 dest_stops.push_back(color_stop.stop);
944 if (color_stop.palette_index == kForegroundColorPaletteIndex) {
949 dest_color.fA *= color_stop.alpha;
950 dest_colors.push_back(dest_color);
966 const auto c_4f = c0_4f + (c1_4f - c0_4f) * t;
973enum TruncateStops { TruncateStart, TruncateEnd };
977void truncateToStopInterpolating(
SkScalar zeroRadiusStop,
978 std::vector<SkColor4f>& colors,
979 std::vector<SkScalar>& stops,
980 TruncateStops truncateStops) {
981 if (stops.size() <= 1u || zeroRadiusStop < stops.front() || stops.back() < zeroRadiusStop) {
986 (truncateStops == TruncateStart)
987 ? std::lower_bound(stops.begin(), stops.end(), zeroRadiusStop) - stops.begin()
988 : std::upper_bound(stops.begin(), stops.end(), zeroRadiusStop) - stops.begin();
991 (zeroRadiusStop - stops[afterIndex - 1]) / (stops[afterIndex] - stops[afterIndex - 1]);
992 SkColor4f lerpColor = lerpSkColor(colors[afterIndex - 1], colors[afterIndex], t);
994 if (truncateStops == TruncateStart) {
995 stops.erase(stops.begin(), stops.begin() + afterIndex);
997 stops.insert(stops.begin(), 0);
1000 stops.erase(stops.begin() + afterIndex, stops.end());
1002 stops.insert(stops.end(), 1);
1008inline SkBlendMode ToSkBlendMode(uint16_t colrV1CompositeMode) {
1009 switch (colrV1CompositeMode) {
1071inline SkTileMode ToSkTileMode(uint8_t extendMode) {
1072 switch (extendMode) {
1089 : fScalerContext(scaler_context)
1092 , fForegroundColor(foregroundColor)
1093 , fAntialias(antialias)
1098 fCanvas.
concat(SkMatrixFromFontationsTransform(transform_arg));
1107 fCanvas.
clipPath(path, fAntialias);
1113 fCanvas.
clipRect(clipRect, fAntialias);
1118void ColorPainter::configure_solid_paint(uint16_t palette_index,
float alpha,
SkPaint&
paint) {
1119 paint.setAntiAlias(fAntialias);
1121 if (palette_index == kForegroundColorPaletteIndex) {
1127 paint.setShader(
nullptr);
1133 configure_solid_paint(palette_index, alpha,
paint);
1142 configure_solid_paint(palette_index, alpha,
paint);
1146void ColorPainter::configure_linear_paint(
const fontations_ffi::FillLinearParams& linear_params,
1147 fontations_ffi::BridgeColorStops& bridge_stops,
1148 uint8_t extend_mode,
1151 paint.setAntiAlias(fAntialias);
1153 std::vector<SkScalar> stops;
1154 std::vector<SkColor4f> colors;
1156 populateStopsAndColors(stops, colors, fPalette, fForegroundColor, bridge_stops);
1158 if (stops.size() == 1) {
1159 paint.setColor(colors[0]);
1166 SkTileMode tileMode = ToSkTileMode(extend_mode);
1176 SkGradientShader::Interpolation::ColorSpace::kSRGB,
1177 SkGradientShader::Interpolation::HueMethod::kShorter},
1183 paint.setShader(shader);
1187 fontations_ffi::BridgeColorStops& bridge_stops,
1188 uint8_t extend_mode) {
1191 configure_linear_paint(linear_params, bridge_stops, extend_mode,
paint);
1197 const fontations_ffi::Transform&
transform,
1198 const fontations_ffi::FillLinearParams& linear_params,
1199 fontations_ffi::BridgeColorStops& bridge_stops,
1200 uint8_t extend_mode) {
1206 configure_linear_paint(linear_params, bridge_stops, extend_mode,
paint, &paintTransform);
1210void ColorPainter::configure_radial_paint(
1211 const fontations_ffi::FillRadialParams& fill_radial_params,
1212 fontations_ffi::BridgeColorStops& bridge_stops,
1213 uint8_t extend_mode,
1216 paint.setAntiAlias(fAntialias);
1221 float startRadius = fill_radial_params.r0;
1222 float endRadius = fill_radial_params.r1;
1224 std::vector<SkScalar> stops;
1225 std::vector<SkColor4f> colors;
1227 populateStopsAndColors(stops, colors, fPalette, fForegroundColor, bridge_stops);
1230 if (stops.size() == 1) {
1231 paint.setColor(colors[0]);
1236 SkTileMode tileMode = ToSkTileMode(extend_mode);
1243 if (startRadius < 0 || endRadius < 0) {
1244 if (startRadius == endRadius && startRadius < 0) {
1252 SkScalar radiusDiff = endRadius - startRadius;
1254 TruncateStops truncateSide = TruncateStart;
1255 if (startRadius < 0) {
1256 truncateSide = TruncateStart;
1263 zeroRadiusStop = -startRadius / (endRadius - startRadius);
1266 startEndDiff.
scale(zeroRadiusStop);
1270 if (endRadius < 0) {
1271 truncateSide = TruncateEnd;
1272 zeroRadiusStop = -startRadius / (endRadius - startRadius);
1275 startEndDiff.
scale(1 - zeroRadiusStop);
1276 end =
end - startEndDiff;
1279 if (!(startRadius == 0 && endRadius == 0)) {
1280 truncateToStopInterpolating(zeroRadiusStop, colors, stops, truncateSide);
1285 if (radiusDiff > 0) {
1287 endRadius = radiusDiff;
1289 stops.erase(stops.begin(), stops.end() - 1);
1291 start -= startToEnd;
1292 startRadius = -radiusDiff;
1294 stops.erase(stops.begin() + 1, stops.end());
1298 if (startRadius < 0 || endRadius < 0) {
1300 int roundedMultiple = factorZeroCrossing > 0 ? ceilf(factorZeroCrossing)
1301 : floorf(factorZeroCrossing) - 1;
1303 roundedMultiple += roundedMultiple < 0 ? -1 : 1;
1305 return roundedMultiple;
1309 SkScalar radiusDiff = endRadius - startRadius;
1310 SkScalar factorZeroCrossing = (startRadius / (startRadius - endRadius));
1311 bool inRange = 0.f <= factorZeroCrossing && factorZeroCrossing <= 1.0f;
1312 SkScalar direction = inRange && radiusDiff < 0 ? -1.0f : 1.0f;
1314 roundIntegerMultiple(factorZeroCrossing * direction, tileMode);
1315 startToEnd.
scale(circleProjectionFactor);
1316 startRadius += circleProjectionFactor * radiusDiff;
1317 endRadius += circleProjectionFactor * radiusDiff;
1318 start += startToEnd;
1338 SkGradientShader::Interpolation::ColorSpace::kSRGB,
1339 SkGradientShader::Interpolation::HueMethod::kShorter},
1344 fontations_ffi::BridgeColorStops& bridge_stops,
1345 uint8_t extend_mode) {
1348 configure_radial_paint(fill_radial_params, bridge_stops, extend_mode,
paint);
1354 const fontations_ffi::Transform&
transform,
1355 const fontations_ffi::FillRadialParams& fill_radial_params,
1356 fontations_ffi::BridgeColorStops& bridge_stops,
1357 uint8_t extend_mode) {
1363 configure_radial_paint(fill_radial_params, bridge_stops, extend_mode,
paint, &paintTransform);
1367void ColorPainter::configure_sweep_paint(
const fontations_ffi::FillSweepParams& sweep_params,
1368 fontations_ffi::BridgeColorStops& bridge_stops,
1369 uint8_t extend_mode,
1372 paint.setAntiAlias(fAntialias);
1376 std::vector<SkScalar> stops;
1377 std::vector<SkColor4f> colors;
1379 populateStopsAndColors(stops, colors, fPalette, fForegroundColor, bridge_stops);
1381 if (stops.size() == 1) {
1382 paint.setColor(colors[0]);
1389 SkTileMode tileMode = ToSkTileMode(extend_mode);
1400 sweep_params.start_angle,
1401 sweep_params.end_angle,
1403 SkGradientShader::Interpolation::ColorSpace::kSRGB,
1404 SkGradientShader::Interpolation::HueMethod::kShorter},
1409 fontations_ffi::BridgeColorStops& bridge_stops,
1410 uint8_t extend_mode) {
1413 configure_sweep_paint(sweep_params, bridge_stops, extend_mode,
paint);
1419 const fontations_ffi::Transform&
transform,
1420 const fontations_ffi::FillSweepParams& sweep_params,
1421 fontations_ffi::BridgeColorStops& bridge_stops,
1422 uint8_t extend_mode) {
1428 configure_sweep_paint(sweep_params, bridge_stops, extend_mode,
paint, &paintTransform);
1434 paint.setBlendMode(ToSkBlendMode(compositeMode));
1443 : fScalerContext(scaler_context)
1444 , fCurrentTransform(initialTransfom)
1462 bool invertResult =
transform.invert(&fStackTopTransformInverse);
1466 fCurrentTransform.
preConcat(fStackTopTransformInverse);
1467 fStackTopTransformInverse =
SkMatrix();
1473 path.transform(fCurrentTransform);
1474 fBounds.
join(path.getBounds());
1490 const fontations_ffi::Transform&,
1491 const fontations_ffi::FillRadialParams&,
1492 fontations_ffi::BridgeColorStops&,
1498 const fontations_ffi::Transform&,
1499 const fontations_ffi::FillLinearParams&,
1500 fontations_ffi::BridgeColorStops&,
1507 const fontations_ffi::Transform&,
1508 const fontations_ffi::FillSweepParams&,
1509 fontations_ffi::BridgeColorStops&,
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SK_ABORT(message,...)
#define SkASSERT_RELEASE(cond)
@ 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
constexpr SkColor SK_ColorTRANSPARENT
constexpr SkColor SK_ColorRED
constexpr SkColor SK_ColorBLACK
#define SkFixedToScalar(x)
@ kNone
glyph outlines unchanged
static void sk_bzero(void *buffer, size_t size)
bool SK_API AsWinding(const SkPath &path, SkPath *result)
bool SK_API Simplify(const SkPath &path, SkPath *result)
sk_sp< T > sk_ref_sp(T *obj)
#define SkFloatToScalar(x)
constexpr size_t SkToSizeT(S x)
constexpr int SkToInt(S x)
static constexpr bool SkToBool(const T &x)
sk_sp< SkTypeface > SkTypeface_Make_Fontations(std::unique_ptr< SkStreamAsset > fontData, const SkFontArguments &args)
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
static SkScalar center(float pos0, float pos1)
void setPixels(void *pixels)
bool setInfo(const SkImageInfo &imageInfo, size_t rowBytes=0)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
void drawRect(const SkRect &rect, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
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 scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
static sk_sp< SkData > MakeFromStream(SkStream *, size_t size)
void setFactoryId(SkTypeface::FactoryId factoryId)
sk_sp< SkDrawable > generateDrawable(const SkGlyph &glyph) override
void generateImage(const SkGlyph &glyph, void *imageBuffer) override
bool drawCOLRGlyph(const SkGlyph &glyph, SkColor foregroundColor, SkCanvas *canvas)
void generatePngImage(const SkGlyph &glyph, void *imageBuffer)
SkFontationsScalerContext(sk_sp< SkTypeface_Fontations > face, const SkScalerContextEffects &effects, const SkDescriptor *desc)
void generateFontMetrics(SkFontMetrics *out_metrics) override
bool generateYScalePathForGlyphId(uint16_t glyphId, SkPath *path, float yScale)
GlyphMetrics generateMetrics(const SkGlyph &glyph, SkArenaAlloc *) override
bool generatePath(const SkGlyph &glyph, SkPath *path) override
uint16_t extraBits() const
SkGlyphID getGlyphID() const
const SkPath * path() const
SkMask::Format maskFormat() const
bool pathIsHairline() 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)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
SkMatrix & postTranslate(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)
void mapXY(SkScalar x, SkScalar y, SkPoint *result) const
SkMatrix & preConcat(const SkMatrix &other)
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
void setColor(SkColor color)
@ kFill_Style
set to fill geometry
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
SkPath & moveTo(SkScalar x, SkScalar y)
SkPath & lineTo(SkScalar x, SkScalar y)
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
const SkRect & getBounds() const
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static void GenerateImageFromPath(SkMaskBuilder &dst, const SkPath &path, const SkMaskGamma::PreBlend &maskPreBlend, bool doBGR, bool verticalLCD, bool a8FromLCD, bool hairline)
const SkMaskGamma::PreBlend fPreBlend
SkTypeface * getTypeface() const
const char * c_str() const
void onGetFontDescriptor(SkFontDescriptor *, bool *) const override
int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const override
static sk_sp< SkTypeface > MakeFromStream(std::unique_ptr< SkStreamAsset >, const SkFontArguments &)
int onCountGlyphs() const override
int onGetUPEM() const override
void onCharsToGlyphs(const SkUnichar *chars, int count, SkGlyphID glyphs[]) const override
std::unique_ptr< SkAdvancedTypefaceMetrics > onGetAdvancedMetrics() const override
bool onGlyphMaskNeedsCurrentColor() const override
int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[], int parameterCount) const override
sk_sp< SkTypeface > onMakeClone(const SkFontArguments &args) const override
void onFilterRec(SkScalerContextRec *) const override
int onGetTableTags(SkFontTableTag tags[]) const override
void getGlyphToUnicodeMap(SkUnichar *) const override
std::unique_ptr< SkScalerContext > onCreateScalerContext(const SkScalerContextEffects &effects, const SkDescriptor *desc) const override
void onGetFamilyName(SkString *familyName) const override
static sk_sp< SkTypeface > MakeFromData(sk_sp< SkData > fontData, const SkFontArguments &)
size_t onGetTableData(SkFontTableTag, size_t, size_t, void *) const override
std::unique_ptr< SkStreamAsset > onOpenStream(int *ttcIndex) const override
bool onGetPostScriptName(SkString *) const override
SkTypeface::LocalizedStrings * onCreateFamilyNameIterator() const override
SkFontStyle fontStyle() const
void serialize(SkWStream *, SerializeBehavior=SerializeBehavior::kIncludeDataIfLocal) const
size_t getTableSize(SkFontTableTag) const
SkrifaLocalizedStrings(rust::Box<::fontations_ffi::BridgeLocalizedStrings > bridge_localized_strings)
bool next(SkTypeface::LocalizedString *localized_string) override
size_t size() const override
bool populate_axis(size_t i, uint32_t axisTag, float min, float def, float max, bool hidden) override
virtual void fill_glyph_radial(uint16_t glyph_id, const fontations_ffi::Transform &, const fontations_ffi::FillRadialParams &, fontations_ffi::BridgeColorStops &, uint8_t) override
virtual void push_transform(const fontations_ffi::Transform &transform) override
virtual void push_clip_rectangle(float x_min, float y_min, float x_max, float y_max) override
virtual void fill_glyph_linear(uint16_t glyph_id, const fontations_ffi::Transform &, const fontations_ffi::FillLinearParams &, fontations_ffi::BridgeColorStops &, uint8_t) override
virtual void fill_glyph_sweep(uint16_t glyph_id, const fontations_ffi::Transform &, const fontations_ffi::FillSweepParams &, fontations_ffi::BridgeColorStops &, uint8_t) override
virtual void pop_clip() override
virtual void fill_glyph_solid(uint16_t glyph_id, uint16_t, float) override
virtual void push_clip_glyph(uint16_t glyph_id) override
virtual void pop_transform() override
virtual void fill_radial(const fontations_ffi::FillRadialParams &fill_radial_params, fontations_ffi::BridgeColorStops &, uint8_t extend_mode) override
virtual void fill_glyph_radial(uint16_t glyph_id, const fontations_ffi::Transform &transform, const fontations_ffi::FillRadialParams &fill_radial_params, fontations_ffi::BridgeColorStops &stops, uint8_t) override
virtual void pop_clip() override
virtual void fill_glyph_linear(uint16_t glyph_id, const fontations_ffi::Transform &transform, const fontations_ffi::FillLinearParams &fill_linear_params, fontations_ffi::BridgeColorStops &stops, uint8_t) override
virtual void fill_solid(uint16_t palette_index, float alpha) override
virtual void fill_glyph_sweep(uint16_t glyph_id, const fontations_ffi::Transform &transform, const fontations_ffi::FillSweepParams &fill_sweep_params, fontations_ffi::BridgeColorStops &stops, uint8_t) override
virtual void pop_layer() override
virtual void push_layer(uint8_t compositeMode) override
virtual void pop_transform() override
virtual void fill_sweep(const fontations_ffi::FillSweepParams &fill_sweep_params, fontations_ffi::BridgeColorStops &, uint8_t extend_mode) override
virtual void fill_linear(const fontations_ffi::FillLinearParams &fill_linear_params, fontations_ffi::BridgeColorStops &, uint8_t extend_mode) override
virtual void fill_glyph_solid(uint16_t glyph_id, uint16_t palette_index, float alpha) override
virtual void push_clip_rectangle(float x_min, float y_min, float x_max, float y_max) override
virtual void push_transform(const fontations_ffi::Transform &transform) override
virtual void push_clip_glyph(uint16_t glyph_id) override
void line_to(float x, float y) override
void move_to(float x, float y) override
void curve_to(float cx0, float cy0, float cx1, float cy1, float x, float y) override
void quad_to(float cx0, float cy0, float x, float y) override
FlutterSemanticsFlag flag
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t uint32_t * format
static float max(float r, float g, float b)
static float min(float r, float g, float b)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
PODArray< SkColor > colors
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
@ kNotEmbeddable_FontFlag
May not be embedded.
@ kNotSubsettable_FontFlag
May not be subset.
@ kVariable_FontFlag
May be true for Type1, CFF, or TrueType fonts.
const Coordinate * coordinates
SkFontArguments & setVariationDesignPosition(VariationPosition position)
SkFontArguments & setPalette(Palette palette)
VariationPosition getVariationDesignPosition() const
SkScalar fTop
greatest extent above origin of any glyph bounding box, typically negative; deprecated with variable ...
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fAvgCharWidth
average character width, zero if unknown
SkScalar fStrikeoutPosition
distance from baseline to bottom of stroke, typically negative
SkScalar fStrikeoutThickness
strikeout thickness
SkScalar fMaxCharWidth
maximum character width, zero if unknown
SkScalar fBottom
greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable ...
uint32_t fFlags
FontMetricsFlags indicating which metrics are valid.
SkScalar fAscent
distance to reserve above baseline, typically negative
SkScalar fXHeight
height of lower-case 'x', zero if unknown, typically negative
SkScalar fUnderlineThickness
underline thickness
@ kStrikeoutPositionIsValid_Flag
set if fStrikeoutPosition is valid
@ kStrikeoutThicknessIsValid_Flag
set if fStrikeoutThickness is valid
@ kUnderlinePositionIsValid_Flag
set if fUnderlinePosition is valid
@ kUnderlineThicknessIsValid_Flag
set if fUnderlineThickness is valid
@ kBoundsInvalid_Flag
set if fTop, fBottom, fXMin, fXMax invalid
SkScalar fDescent
distance to reserve below baseline, typically positive
SkScalar fCapHeight
height of an upper-case letter, zero if unknown, typically negative
SkScalar fXMin
greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with vari...
SkScalar fUnderlinePosition
distance from baseline to top of stroke, typically positive
SkScalar fXMax
greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with var...
void setHidden(bool hidden)
static const constexpr value_type COLRv1
static const constexpr value_type PATH
static const constexpr value_type COLRv0
static const constexpr value_type BITMAP
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
@ kARGB32_Format
SkPMColor.
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
static constexpr SkPoint Make(float x, float y)
void scale(float scale, SkPoint *dst) const
static SkRGBA4f FromColor(SkColor color)
static SkRect Make(const SkISize &size)
static constexpr SkRect MakeEmpty()
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
void roundOut(SkIRect *dst) const
void join(const SkRect &r)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
void getSingleMatrix(SkMatrix *) const
uint32_t fForegroundColor
SkMask::Format fMaskFormat
bool computeMatrices(PreMatrixScale preMatrixScale, SkVector *scale, SkMatrix *remaining, SkMatrix *remainingWithoutRotation=nullptr, SkMatrix *remainingRotation=nullptr, SkMatrix *total=nullptr)
void setHinting(SkFontHinting)
SkMask::Format maskFormat
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)