From a5d48a99f297b2183f7d429526788584aab3046d Mon Sep 17 00:00:00 2001 From: Connum Date: Thu, 16 Nov 2023 11:04:21 +0100 Subject: [PATCH] performance: implement caching for roundDecimal() and prevent unnecessary recalculations --- src/path.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/path.js b/src/path.js index 47442b7b..02f9bdff 100644 --- a/src/path.js +++ b/src/path.js @@ -16,8 +16,25 @@ function Path() { this.strokeWidth = 1; } +const decimalRoundingCache = {}; + function roundDecimal(float, places) { - return +(Math.round(float + 'e+' + places) + 'e-' + places); + const integerPart = Math.floor(float); + const decimalPart = float - integerPart; + + if (!decimalRoundingCache[places]) { + decimalRoundingCache[places] = {}; + } + + if (decimalRoundingCache[places][decimalPart] !== undefined) { + const roundedDecimalPart = decimalRoundingCache[places][decimalPart]; + return integerPart + roundedDecimalPart; + } + + const roundedDecimalPart = +(Math.round(decimalPart + 'e+' + places) + 'e-' + places); + decimalRoundingCache[places][decimalPart] = roundedDecimalPart; + + return integerPart + roundedDecimalPart; } function optimizeCommands(commands) { @@ -525,10 +542,11 @@ Path.prototype.toPathData = function(options) { options = createSVGOutputOptions(options); function floatToString(v) { - if (Math.round(v) === roundDecimal(v, options.decimalPlaces)) { - return '' + roundDecimal(v, options.decimalPlaces); + const rounded = roundDecimal(v, options.decimalPlaces); + if (Math.round(v) === rounded) { + return '' + rounded; } else { - return roundDecimal(v, options.decimalPlaces).toFixed(options.decimalPlaces); + return rounded.toFixed(options.decimalPlaces); } }