From f68aa8162fd230bcb627cbf34e4ed6c00527c302 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Fri, 24 Sep 2021 16:00:45 +0300 Subject: [PATCH] Upgrade to TinySDF v2 with a fix to CJK performance (#11047) * upgrade to TinySDF v2 * update tiny-sdf to v2.0.2 to address a perf issue --- package.json | 2 +- src/render/glyph_manager.js | 36 ++++++++++++-------------- test/unit/render/glyph_manager.test.js | 32 ++++++++++++++++------- yarn.lock | 8 +++--- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 3312379dbc2..b0c50ca5948 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^2.0.0", "@mapbox/point-geometry": "^0.1.0", - "@mapbox/tiny-sdf": "^1.2.5", + "@mapbox/tiny-sdf": "^2.0.2", "@mapbox/unitbezier": "^0.0.0", "@mapbox/vector-tile": "^1.3.1", "@mapbox/whoots-js": "^3.1.0", diff --git a/src/render/glyph_manager.js b/src/render/glyph_manager.js index ce295d59507..3a48812fdfc 100644 --- a/src/render/glyph_manager.js +++ b/src/render/glyph_manager.js @@ -199,14 +199,8 @@ class GlyphManager { } _tinySDF(entry: Entry, stack: string, id: number): ?StyleGlyph { - const family = this.localFontFamily; - if (!family) { - return; - } - - if (!this._doesCharSupportLocalGlyph(id)) { - return; - } + const fontFamily = this.localFontFamily; + if (!fontFamily || !this._doesCharSupportLocalGlyph(id)) return; let tinySDF = entry.tinySDF; if (!tinySDF) { @@ -218,15 +212,20 @@ class GlyphManager { } else if (/light/i.test(stack)) { fontWeight = '200'; } - tinySDF = entry.tinySDF = new GlyphManager.TinySDF(24 * SDF_SCALE, 3 * SDF_SCALE, 8 * SDF_SCALE, .25, family, fontWeight); + + const fontSize = 24 * SDF_SCALE; + const buffer = 3 * SDF_SCALE; + const radius = 8 * SDF_SCALE; + tinySDF = entry.tinySDF = new GlyphManager.TinySDF({fontFamily, fontWeight, fontSize, buffer, radius}); + tinySDF.fontWeight = fontWeight; } if (this.localGlyphs[tinySDF.fontWeight][id]) { return this.localGlyphs[tinySDF.fontWeight][id]; } - const {data, metrics} = tinySDF.drawWithMetrics(String.fromCharCode(id)); - const {sdfWidth, sdfHeight, width, height, left, top, advance} = metrics; + const char = String.fromCharCode(id); + const {data, width, height, glyphWidth, glyphHeight, glyphLeft, glyphTop, glyphAdvance} = tinySDF.draw(char); /* TinySDF's "top" is the distance from the alphabetic baseline to the top of the glyph. @@ -248,16 +247,13 @@ class GlyphManager { const glyph = this.localGlyphs[tinySDF.fontWeight][id] = { id, - bitmap: new AlphaImage({ - width: sdfWidth, - height: sdfHeight - }, data), + bitmap: new AlphaImage({width, height}, data), metrics: { - width: width / SDF_SCALE, - height: height / SDF_SCALE, - left: left / SDF_SCALE, - top: top / SDF_SCALE - baselineAdjustment, - advance: advance / SDF_SCALE, + width: glyphWidth / SDF_SCALE, + height: glyphHeight / SDF_SCALE, + left: glyphLeft / SDF_SCALE, + top: glyphTop / SDF_SCALE - baselineAdjustment, + advance: glyphAdvance / SDF_SCALE, localGlyph: true } }; diff --git a/test/unit/render/glyph_manager.test.js b/test/unit/render/glyph_manager.test.js index 652c1fe9ee7..0426e42b0d9 100644 --- a/test/unit/render/glyph_manager.test.js +++ b/test/unit/render/glyph_manager.test.js @@ -19,10 +19,14 @@ const TinySDF = class { this.fontWeight = '400'; } // Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer) - drawWithMetrics() { + draw() { return { - alphaChannel: new Uint8ClampedArray(900), - metrics: {width: 48, height: 48, sdfWidth: 30, sdfHeight: 30, advance: 48} + data: new Uint8ClampedArray(900), + glyphWidth: 48, + glyphHeight: 48, + width: 30, + height: 30, + glyphAdvance: 48 }; } }; @@ -168,11 +172,15 @@ test('GlyphManager caches locally generated glyphs', (t) => { this.fontWeight = '400'; } // Return empty 30x30 bitmap (24 fontsize + 3 * 2 buffer) - drawWithMetrics() { + draw() { drawCallCount++; return { - alphaChannel: new Uint8ClampedArray(900), - metrics: {width: 48, height: 48, sdfWidth: 30, sdfHeight: 30, advance: 48} + data: new Uint8ClampedArray(900), + glyphWidth: 48, + glyphHeight: 48, + width: 30, + height: 30, + glyphAdvance: 48 }; } }); @@ -195,11 +203,15 @@ test('GlyphManager locally generates latin glyphs', (t) => { constructor() { this.fontWeight = '400'; } - // Return empty 18x24 bitmap (made up glyph size + 3 * 2 buffer) - drawWithMetrics() { + // Return empty 20x24 bitmap (made up glyph size + 3 * 2 buffer) + draw() { return { - alphaChannel: new Uint8ClampedArray(480), - metrics: {width: 28, height: 36, sdfWidth: 20, sdfHeight: 24, advance: 20} + data: new Uint8ClampedArray(480), + glyphWidth: 28, + glyphHeight: 36, + width: 20, + height: 24, + glyphAdvance: 20 }; } }); diff --git a/yarn.lock b/yarn.lock index ff785f41f6b..c26b12b8e79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1171,10 +1171,10 @@ resolved "https://registry.npmjs.org/@mapbox/sphericalmercator/-/sphericalmercator-1.1.0.tgz" integrity sha512-pEsfZyG4OMThlfFQbCte4gegvHUjxXCjz0KZ4Xk8NdOYTQBLflj6U8PL05RPAiuRAMAQNUUKJuL6qYZ5Y4kAWA== -"@mapbox/tiny-sdf@^1.2.5": - version "1.2.5" - resolved "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz" - integrity sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw== +"@mapbox/tiny-sdf@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.2.tgz#89b477f350c146be84fb263eb67f60f0ee2f59cf" + integrity sha512-XBQG3wvIaya9t2OHcWLFYv8cdg48roqOj8XhKzKSvAIg5D1scC+a+tlq0wGjPZkL+k6dL8TyOBR7RKDGh3kefQ== "@mapbox/unitbezier@^0.0.0": version "0.0.0"