From c35b5b2a9ec49bd709d63df7caee398ac33da238 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 7 Aug 2018 14:53:13 +0200 Subject: [PATCH] avoid expensive resizing in image/glyph atlases --- src/render/glyph_atlas.js | 54 ++++++++++++++++++--------------------- src/render/image_atlas.js | 44 ++++++++++++------------------- 2 files changed, 42 insertions(+), 56 deletions(-) diff --git a/src/render/glyph_atlas.js b/src/render/glyph_atlas.js index d4bdecc6315..06df12acf04 100644 --- a/src/render/glyph_atlas.js +++ b/src/render/glyph_atlas.js @@ -26,10 +26,9 @@ export default class GlyphAtlas { positions: { [string]: { [number]: GlyphPosition } }; constructor(stacks: { [string]: { [number]: ?StyleGlyph } }) { - const image = new AlphaImage({width: 0, height: 0}); const positions = {}; - const pack = new ShelfPack(0, 0, {autoResize: true}); + const bins = []; for (const stack in stacks) { const glyphs = stacks[stack]; @@ -37,36 +36,33 @@ export default class GlyphAtlas { for (const id in glyphs) { const src = glyphs[+id]; - if (src && src.bitmap.width !== 0 && src.bitmap.height !== 0) { - const bin = pack.packOne( - src.bitmap.width + 2 * padding, - src.bitmap.height + 2 * padding); - - image.resize({ - width: pack.w, - height: pack.h - }); - - AlphaImage.copy( - src.bitmap, - image, - {x: 0, y: 0}, - { - x: bin.x + padding, - y: bin.y + padding - }, - src.bitmap); - - stackPositions[id] = {rect: bin, metrics: src.metrics}; - } + if (!src || src.bitmap.width === 0 || src.bitmap.height === 0) continue; + + const bin = { + x: 0, + y: 0, + w: src.bitmap.width + 2 * padding, + h: src.bitmap.height + 2 * padding + }; + bins.push(bin); + stackPositions[id] = {rect: bin, metrics: src.metrics}; } } - pack.shrink(); - image.resize({ - width: pack.w, - height: pack.h - }); + pack.pack(bins, {inPlace: true}); + + const image = new AlphaImage({width: pack.w, height: pack.h}); + + for (const stack in stacks) { + const glyphs = stacks[stack]; + + for (const id in glyphs) { + const src = glyphs[+id]; + if (!src || src.bitmap.width === 0 || src.bitmap.height === 0) continue; + const bin = positions[stack][id].rect; + AlphaImage.copy(src.bitmap, image, {x: 0, y: 0}, {x: bin.x + padding, y: bin.y + padding}, src.bitmap); + } + } this.image = image; this.positions = positions; diff --git a/src/render/image_atlas.js b/src/render/image_atlas.js index fb87efed1c1..647a4b5dcbb 100644 --- a/src/render/image_atlas.js +++ b/src/render/image_atlas.js @@ -52,41 +52,31 @@ export default class ImageAtlas { positions: {[string]: ImagePosition}; constructor(images: {[string]: StyleImage}) { - const image = new RGBAImage({width: 0, height: 0}); const positions = {}; - const pack = new ShelfPack(0, 0, {autoResize: true}); + const bins = []; for (const id in images) { const src = images[id]; - - const bin = pack.packOne( - src.data.width + 2 * padding, - src.data.height + 2 * padding); - - image.resize({ - width: pack.w, - height: pack.h - }); - - RGBAImage.copy( - src.data, - image, - { x: 0, y: 0 }, - { - x: bin.x + padding, - y: bin.y + padding - }, - src.data); - + const bin = { + x: 0, + y: 0, + w: src.data.width + 2 * padding, + h: src.data.height + 2 * padding, + }; + bins.push(bin); positions[id] = new ImagePosition(bin, src); } - pack.shrink(); - image.resize({ - width: pack.w, - height: pack.h - }); + pack.pack(bins, {inPlace: true}); + + const image = new RGBAImage({width: pack.w, height: pack.h}); + + for (const id in images) { + const src = images[id]; + const bin = positions[id].paddedRect; + RGBAImage.copy(src.data, image, {x: 0, y: 0}, {x: bin.x + padding, y: bin.y + padding}, src.data); + } this.image = image; this.positions = positions;