From f3a8201f6d02ec9ea5e4c2e00525d2211f631c19 Mon Sep 17 00:00:00 2001 From: m0rkeulv Date: Sun, 13 Sep 2026 18:09:28 +0200 Subject: [PATCH] Solve performance issues with SWF exporter --- src/swf/data/SWFShape.hx | 66 ++++++--- src/swf/exporters/AnimateLibraryExporter.hx | 152 ++++++++++---------- 2 files changed, 117 insertions(+), 101 deletions(-) diff --git a/src/swf/data/SWFShape.hx b/src/swf/data/SWFShape.hx index fc93214a3..8be5c9e63 100644 --- a/src/swf/data/SWFShape.hx +++ b/src/swf/data/SWFShape.hx @@ -18,6 +18,7 @@ import openfl.display.LineScaleMode; import openfl.geom.Matrix; import openfl.geom.Point; import openfl.errors.Error; +import haxe.ds.ObjectMap; class SWFShape { @@ -655,37 +656,56 @@ class SWFShape var subPath:Array = edgeMap.get(styleIdx); if (subPath != null && subPath.length > 0) { - var idx:Int; - var prevEdge:IEdge = null; + var n = subPath.length; + var nextFree = new Array(); + var prevFree = new Array(); + var edgeIndexMap = new ObjectMap(); + + for (i in 0...n) + { + nextFree.push(i + 1); + prevFree.push(i - 1); + edgeIndexMap.set(subPath[i], i); + } + var tmpPath:Array = new Array(); createCoordMap(subPath); - while (subPath.length > 0) + + var head = 0; + var idx = 0; + var remaining = n; + var prevEdge:IEdge = null; + + while (remaining > 0) { - idx = 0; - while (idx < subPath.length) + var cand = subPath[idx]; + if (prevEdge == null || prevEdge.to.equals(cand.from)) { - if (prevEdge == null || prevEdge.to.equals(subPath[idx].from)) + remaining--; + tmpPath.push(cand); + removeEdgeFromCoordMap(cand); + prevEdge = cand; + + var next = nextFree[idx]; + var prev = prevFree[idx]; + + if (prev >= 0) nextFree[prev] = next; + else head = next; + + if (next < n) prevFree[next] = prev; + idx = next < n ? next : head; + } + else + { + var edge = findNextEdgeInCoordMap(prevEdge); + if (edge != null) { - var edge:IEdge = subPath.splice(idx, 1)[0]; - tmpPath.push(edge); - removeEdgeFromCoordMap(edge); - prevEdge = edge; + idx = edgeIndexMap.get(edge); } else { - var edge = findNextEdgeInCoordMap(prevEdge); - if (edge != null) - { - for (i in 0...subPath.length) - { - if (subPath[i] == edge) idx = i; - } - } - else - { - idx = 0; - prevEdge = null; - } + idx = head; + prevEdge = null; } } } diff --git a/src/swf/exporters/AnimateLibraryExporter.hx b/src/swf/exporters/AnimateLibraryExporter.hx index 1a5e2ee99..681a50fc4 100644 --- a/src/swf/exporters/AnimateLibraryExporter.hx +++ b/src/swf/exporters/AnimateLibraryExporter.hx @@ -600,62 +600,60 @@ class AnimateLibraryExporter } else { - commands = commands.concat([ - SWFShapeCommandType.LINE_STYLE, - thickness, - color, - alpha, - pixelHinting, - scaleMode, - startCaps, - joints, - miterLimit - ]); + commands.push(SWFShapeCommandType.LINE_STYLE); + commands.push(thickness); + commands.push(color); + commands.push(alpha); + commands.push(pixelHinting); + commands.push(scaleMode); + commands.push(startCaps); + commands.push(joints); + commands.push(miterLimit); } case BeginFill(color, alpha): - commands = commands.concat([SWFShapeCommandType.BEGIN_FILL, color, alpha]); + commands.push(SWFShapeCommandType.BEGIN_FILL); + commands.push(color); + commands.push(alpha); case BeginGradientFill(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio): - commands = commands.concat([ - SWFShapeCommandType.BEGIN_GRADIENT_FILL, - type, - colors, - alphas, - ratios, - serializeMatrix(matrix), - spreadMethod, - interpolationMethod, - focalPointRatio - ]); + commands.push(SWFShapeCommandType.BEGIN_GRADIENT_FILL); + commands.push(type); + commands.push(colors); + commands.push(alphas); + commands.push(ratios); + commands.push(serializeMatrix(matrix)); + commands.push(spreadMethod); + commands.push(interpolationMethod); + commands.push(focalPointRatio); case BeginBitmapFill(bitmapID, matrix, repeat, smooth): - commands = commands.concat([ - SWFShapeCommandType.BEGIN_BITMAP_FILL, - bitmapID, - serializeMatrix(matrix), - repeat, - smooth - ]); + commands.push(SWFShapeCommandType.BEGIN_BITMAP_FILL); + commands.push(bitmapID); + commands.push(serializeMatrix(matrix)); + commands.push(repeat); + commands.push(smooth); processTag(cast swfData.getCharacter(bitmapID)); case EndFill: commands.push(SWFShapeCommandType.END_FILL); case MoveTo(x, y): - commands = commands.concat([SWFShapeCommandType.MOVE_TO, twip(x), twip(y)]); + commands.push(SWFShapeCommandType.MOVE_TO); + commands.push(twip(x)); + commands.push(twip(y)); case LineTo(x, y): - commands = commands.concat([SWFShapeCommandType.LINE_TO, twip(x), twip(y)]); + commands.push(SWFShapeCommandType.LINE_TO); + commands.push(twip(x)); + commands.push(twip(y)); case CurveTo(controlX, controlY, anchorX, anchorY): - commands = commands.concat([ - SWFShapeCommandType.CURVE_TO, - twip(controlX), - twip(controlY), - twip(anchorX), - twip(anchorY) - ]); + commands.push(SWFShapeCommandType.CURVE_TO); + commands.push(twip(controlX)); + commands.push(twip(controlY)); + commands.push(twip(anchorX)); + commands.push(twip(anchorY)); default: } @@ -979,62 +977,60 @@ class AnimateLibraryExporter } else { - commands = commands.concat([ - SWFShapeCommandType.LINE_STYLE, - thickness, - color, - alpha, - pixelHinting, - scaleMode, - startCaps, - joints, - miterLimit - ]); + commands.push(SWFShapeCommandType.LINE_STYLE); + commands.push(thickness); + commands.push(color); + commands.push(alpha); + commands.push(pixelHinting); + commands.push(scaleMode); + commands.push(startCaps); + commands.push(joints); + commands.push(miterLimit); } case BeginFill(color, alpha): - commands = commands.concat([SWFShapeCommandType.BEGIN_FILL, color, alpha]); + commands.push(SWFShapeCommandType.BEGIN_FILL); + commands.push(color); + commands.push(alpha); case BeginGradientFill(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio): - commands = commands.concat([ - SWFShapeCommandType.BEGIN_GRADIENT_FILL, - type, - colors, - alphas, - ratios, - serializeMatrix(matrix), - spreadMethod, - interpolationMethod, - focalPointRatio - ]); + commands.push(SWFShapeCommandType.BEGIN_GRADIENT_FILL); + commands.push(type); + commands.push(colors); + commands.push(alphas); + commands.push(ratios); + commands.push(serializeMatrix(matrix)); + commands.push(spreadMethod); + commands.push(interpolationMethod); + commands.push(focalPointRatio); case BeginBitmapFill(bitmapID, matrix, repeat, smooth): - commands = commands.concat([ - SWFShapeCommandType.BEGIN_BITMAP_FILL, - bitmapID, - serializeMatrix(matrix), - repeat, - smooth - ]); + commands.push(SWFShapeCommandType.BEGIN_BITMAP_FILL); + commands.push(bitmapID); + commands.push(serializeMatrix(matrix)); + commands.push(repeat); + commands.push(smooth); processTag(cast swfData.getCharacter(bitmapID)); case EndFill: commands.push(SWFShapeCommandType.END_FILL); case MoveTo(x, y): - commands = commands.concat([SWFShapeCommandType.MOVE_TO, twip(x), twip(y)]); + commands.push(SWFShapeCommandType.MOVE_TO); + commands.push(twip(x)); + commands.push(twip(y)); case LineTo(x, y): - commands = commands.concat([SWFShapeCommandType.LINE_TO, twip(x), twip(y)]); + commands.push(SWFShapeCommandType.LINE_TO); + commands.push(twip(x)); + commands.push(twip(y)); case CurveTo(controlX, controlY, anchorX, anchorY): - commands = commands.concat([ - SWFShapeCommandType.CURVE_TO, - twip(controlX), - twip(controlY), - twip(anchorX), - twip(anchorY) - ]); + commands.push(SWFShapeCommandType.CURVE_TO); + commands.push(twip(controlX)); + commands.push(twip(controlY)); + commands.push(twip(anchorX)); + commands.push(twip(anchorY)); default: }