// AddPathPositionedRun public void AddPathPositionedRun(ReadOnlySpan <ushort> glyphs, SKFont font, ReadOnlySpan <float> glyphWidths, ReadOnlySpan <SKPoint> glyphOffsets, SKPath path, SKTextAlign textAlign = SKTextAlign.Left) { using var pathMeasure = new SKPathMeasure(path); var contourLength = pathMeasure.Length; var textLength = glyphOffsets[glyphs.Length - 1].X + glyphWidths[glyphs.Length - 1]; var alignment = (int)textAlign * 0.5f; var startOffset = glyphOffsets[0].X + (contourLength - textLength) * alignment; var firstGlyphIndex = 0; var pathGlyphCount = 0; using var glyphTransforms = Utils.RentArray <SKRotationScaleMatrix> (glyphs.Length); // TODO: deal with multiple contours? for (var index = 0; index < glyphOffsets.Length; index++) { var glyphOffset = glyphOffsets[index]; var halfWidth = glyphWidths[index] * 0.5f; var pathOffset = startOffset + glyphOffset.X + halfWidth; // TODO: clip glyphs on both ends of paths if (pathOffset >= 0 && pathOffset < contourLength && pathMeasure.GetPositionAndTangent(pathOffset, out var position, out var tangent)) { if (pathGlyphCount == 0) { firstGlyphIndex = index; } var tx = tangent.X; var ty = tangent.Y; var px = position.X; var py = position.Y; // horizontally offset the position using the tangent vector px -= tx * halfWidth; py -= ty * halfWidth; // vertically offset the position using the normal vector (-ty, tx) var dy = glyphOffset.Y; px -= dy * ty; py += dy * tx; glyphTransforms.Span[pathGlyphCount++] = new SKRotationScaleMatrix(tx, ty, px, py); } } var glyphSubset = glyphs.Slice(firstGlyphIndex, pathGlyphCount); var positions = glyphTransforms.Span.Slice(0, pathGlyphCount); AddRotationScaleRun(glyphSubset, font, positions); }
public extern static bool sk_pathmeasure_get_matrix(sk_pathmeasure_t pathMeasure, float distance, out SKMatrix matrix, SKPathMeasure.MatrixFlags flags);