[ts][canvaskit] Fix memory access error with clipping.

This commit is contained in:
Davide Tantillo 2025-07-18 10:26:43 +02:00
parent ac344759d1
commit 0b42677299

View File

@ -53,12 +53,10 @@ import {
} from "@esotericsoftware/spine-core"; } from "@esotericsoftware/spine-core";
import { import {
Canvas, Canvas,
Surface,
CanvasKit, CanvasKit,
Image, Image,
Paint, Paint,
Shader, Shader,
BlendMode as CanvasKitBlendMode,
} from "canvaskit-wasm"; } from "canvaskit-wasm";
Skeleton.yDown = true; Skeleton.yDown = true;
@ -275,7 +273,7 @@ export class SkeletonRenderer {
let numVertices = 0; let numVertices = 0;
if (attachment instanceof RegionAttachment) { if (attachment instanceof RegionAttachment) {
let region = attachment as RegionAttachment; let region = attachment as RegionAttachment;
positions = positions.length < 8 ? Utils.newFloatArray(8) : positions; if (positions.length < 8) this.scratchPositions = positions = Utils.newFloatArray(8);
numVertices = 4; numVertices = 4;
region.computeWorldVertices(slot, positions, 0, 2); region.computeWorldVertices(slot, positions, 0, 2);
triangles = SkeletonRenderer.QUAD_TRIANGLES; triangles = SkeletonRenderer.QUAD_TRIANGLES;
@ -284,10 +282,8 @@ export class SkeletonRenderer {
attachmentColor = region.color; attachmentColor = region.color;
} else if (attachment instanceof MeshAttachment) { } else if (attachment instanceof MeshAttachment) {
let mesh = attachment as MeshAttachment; let mesh = attachment as MeshAttachment;
positions = if (positions.length < mesh.worldVerticesLength)
positions.length < mesh.worldVerticesLength this.scratchPositions = positions = Utils.newFloatArray(mesh.worldVerticesLength);
? Utils.newFloatArray(mesh.worldVerticesLength)
: positions;
numVertices = mesh.worldVerticesLength >> 1; numVertices = mesh.worldVerticesLength >> 1;
mesh.computeWorldVertices( mesh.computeWorldVertices(
slot, slot,
@ -318,9 +314,23 @@ export class SkeletonRenderer {
triangles.length, triangles.length,
uvs uvs
); );
positions = clipper.clippedVertices;
uvs = clipper.clippedUVs; if (clipper.clippedVertices.length > 0) {
triangles = clipper.clippedTriangles; // clipping eventually "erases" clippedVertices array (set length to 0 at next clip)
// it's necessary to keep the array alive until canvaskit paints,
// otherwise a memory access occurs
if (positions.length < clipper.clippedVertices.length)
this.scratchPositions = positions = Utils.newFloatArray(clipper.clippedVertices.length);
numVertices = clipper.clippedVertices.length / 2;
for (let i = 0; i < clipper.clippedVertices.length; i++)
positions[i] = clipper.clippedVertices[i];
uvs = clipper.clippedUVs;
triangles = clipper.clippedTriangles;
} else {
clipper.clipEndWithSlot(slot);
continue;
}
} }
let slotColor = slot.color; let slotColor = slot.color;
@ -331,7 +341,7 @@ export class SkeletonRenderer {
finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;
if (colors.length / 4 < numVertices) if (colors.length / 4 < numVertices)
colors = Utils.newFloatArray(numVertices * 4); this.scratchColors = colors = Utils.newFloatArray(numVertices * 4);
for (let i = 0, n = numVertices * 4; i < n; i += 4) { for (let i = 0, n = numVertices * 4; i < n; i += 4) {
colors[i] = finalColor.r; colors[i] = finalColor.r;
colors[i + 1] = finalColor.g; colors[i + 1] = finalColor.g;
@ -339,10 +349,9 @@ export class SkeletonRenderer {
colors[i + 3] = finalColor.a; colors[i + 3] = finalColor.a;
} }
const scaledUvs = const scaledUvs = this.scratchUVs.length < uvs.length
this.scratchUVs.length < uvs.length ? (this.scratchUVs = Utils.newFloatArray(uvs.length))
? Utils.newFloatArray(uvs.length) : this.scratchUVs;
: this.scratchUVs;
const width = texture.getImage().image.width(); const width = texture.getImage().image.width();
const height = texture.getImage().image.height(); const height = texture.getImage().image.height();
for (let i = 0; i < uvs.length; i += 2) { for (let i = 0; i < uvs.length; i += 2) {