import Glyph from './Glyph'; import BBox from './BBox'; class COLRLayer { constructor(glyph, color) { this.glyph = glyph; this.color = color; } } /** * Represents a color (e.g. emoji) glyph in Microsoft's COLR format. * Each glyph in this format contain a list of colored layers, each * of which is another vector glyph. */ export default class COLRGlyph extends Glyph { _getBBox() { let bbox = new BBox; for (let i = 0; i < this.layers.length; i++) { let layer = this.layers[i]; let b = layer.glyph.bbox; bbox.addPoint(b.minX, b.minY); bbox.addPoint(b.maxX, b.maxY); } return bbox; } /** * Returns an array of objects containing the glyph and color for * each layer in the composite color glyph. * @type {object[]} */ get layers() { let cpal = this._font.CPAL; let colr = this._font.COLR; let low = 0; let high = colr.baseGlyphRecord.length - 1; while (low <= high) { let mid = (low + high) >> 1; var rec = colr.baseGlyphRecord[mid]; if (this.id < rec.gid) { high = mid - 1; } else if (this.id > rec.gid) { low = mid + 1; } else { var baseLayer = rec; break; } } // if base glyph not found in COLR table, // default to normal glyph from glyf or CFF if (baseLayer == null) { var g = this._font._getBaseGlyph(this.id); var color = { red: 0, green: 0, blue: 0, alpha: 255 }; return [new COLRLayer(g, color)]; } // otherwise, return an array of all the layers let layers = []; for (let i = baseLayer.firstLayerIndex; i < baseLayer.firstLayerIndex + baseLayer.numLayers; i++) { var rec = colr.layerRecords[i]; var color = cpal.colorRecords[rec.paletteIndex]; var g = this._font._getBaseGlyph(rec.gid); layers.push(new COLRLayer(g, color)); } return layers; } render(ctx, size) { for (let {glyph, color} of this.layers) { ctx.fillColor([color.red, color.green, color.blue], color.alpha / 255 * 100); glyph.render(ctx, size); } return; } }