// @flow import {AlphaImage} from '../util/image'; import {register} from '../util/web_worker_transfer'; import potpack from 'potpack'; import type {GlyphMetrics, StyleGlyph} from '../style/style_glyph'; const padding = 1; export type Rect = { x: number, y: number, w: number, h: number }; export type GlyphPosition = { rect: Rect, metrics: GlyphMetrics }; export type GlyphPositions = {[_: string]: {[_: number]: GlyphPosition } } export default class GlyphAtlas { image: AlphaImage; positions: GlyphPositions; constructor(stacks: {[_: string]: {[_: number]: ?StyleGlyph } }) { const positions = {}; const bins = []; for (const stack in stacks) { const glyphs = stacks[stack]; const stackPositions = positions[stack] = {}; for (const id in glyphs) { const src = glyphs[+id]; 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}; } } const {w, h} = potpack(bins); const image = new AlphaImage({width: w || 1, height: h || 1}); 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; } } register('GlyphAtlas', GlyphAtlas);