pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
155 lines (151 loc) • 6.22 kB
JavaScript
;
var Cache = require('../../assets/cache/Cache.js');
var Extensions = require('../../extensions/Extensions.js');
var GCManagedHash = require('../../utils/data/GCManagedHash.js');
var Graphics = require('../graphics/shared/Graphics.js');
var CanvasTextMetrics = require('../text/canvas/CanvasTextMetrics.js');
var SdfShader = require('../text/sdfShader/SdfShader.js');
var BitmapFontManager = require('./BitmapFontManager.js');
var getBitmapTextLayout = require('./utils/getBitmapTextLayout.js');
;
class BitmapTextGraphics extends Graphics.Graphics {
destroy() {
if (this.context.customShader) {
this.context.customShader.destroy();
}
super.destroy();
}
}
class BitmapTextPipe {
constructor(renderer) {
this._renderer = renderer;
this._managedBitmapTexts = new GCManagedHash.GCManagedHash({ renderer, type: "renderable", priority: -2, name: "bitmapText" });
}
validateRenderable(bitmapText) {
const graphicsRenderable = this._getGpuBitmapText(bitmapText);
return this._renderer.renderPipes.graphics.validateRenderable(graphicsRenderable);
}
addRenderable(bitmapText, instructionSet) {
const graphicsRenderable = this._getGpuBitmapText(bitmapText);
syncWithProxy(bitmapText, graphicsRenderable);
if (bitmapText._didTextUpdate) {
bitmapText._didTextUpdate = false;
this._updateContext(bitmapText, graphicsRenderable);
}
this._renderer.renderPipes.graphics.addRenderable(graphicsRenderable, instructionSet);
if (graphicsRenderable.context.customShader) {
this._updateDistanceField(bitmapText);
}
}
updateRenderable(bitmapText) {
const graphicsRenderable = this._getGpuBitmapText(bitmapText);
syncWithProxy(bitmapText, graphicsRenderable);
this._renderer.renderPipes.graphics.updateRenderable(graphicsRenderable);
if (graphicsRenderable.context.customShader) {
this._updateDistanceField(bitmapText);
}
}
_updateContext(bitmapText, proxyGraphics) {
const { context } = proxyGraphics;
const bitmapFont = BitmapFontManager.BitmapFontManager.getFont(bitmapText.text, bitmapText._style);
context.clear();
if (bitmapFont.distanceField.type !== "none") {
if (!context.customShader) {
context.customShader = new SdfShader.SdfShader(this._renderer.limits.maxBatchableTextures);
}
}
const chars = CanvasTextMetrics.CanvasTextMetrics.graphemeSegmenter(bitmapText.text);
const style = bitmapText._style;
let currentY = bitmapFont.baseLineOffset;
const bitmapTextLayout = getBitmapTextLayout.getBitmapTextLayout(chars, style, bitmapFont, true);
const padding = style.padding;
const scale = bitmapTextLayout.scale;
let tx = bitmapTextLayout.width;
let ty = bitmapTextLayout.height + bitmapTextLayout.offsetY;
if (style._stroke) {
tx += style._stroke.width / scale;
ty += style._stroke.width / scale;
}
context.translate(-bitmapText._anchor._x * tx - padding, -bitmapText._anchor._y * ty - padding).scale(scale, scale);
const tint = bitmapFont.applyFillAsTint ? style._fill.color : 16777215;
let fontSize = bitmapFont.fontMetrics.fontSize;
let lineHeight = bitmapFont.lineHeight;
if (style.lineHeight) {
fontSize = style.fontSize / scale;
lineHeight = style.lineHeight / scale;
}
let linePositionYShift = (lineHeight - fontSize) / 2;
if (linePositionYShift - bitmapFont.baseLineOffset < 0) {
linePositionYShift = 0;
}
for (let i = 0; i < bitmapTextLayout.lines.length; i++) {
const line = bitmapTextLayout.lines[i];
for (let j = 0; j < line.charPositions.length; j++) {
const char = line.chars[j];
const charData = bitmapFont.chars[char];
if (charData?.texture) {
const texture = charData.texture;
context.texture(
texture,
tint ? tint : "black",
Math.round(line.charPositions[j] + charData.xOffset),
Math.round(currentY + charData.yOffset + linePositionYShift),
texture.orig.width,
texture.orig.height
);
}
}
currentY += lineHeight;
}
}
_getGpuBitmapText(bitmapText) {
return bitmapText._gpuData[this._renderer.uid] || this.initGpuText(bitmapText);
}
initGpuText(bitmapText) {
const proxyRenderable = new BitmapTextGraphics();
bitmapText._gpuData[this._renderer.uid] = proxyRenderable;
this._updateContext(bitmapText, proxyRenderable);
this._managedBitmapTexts.add(bitmapText);
return proxyRenderable;
}
_updateDistanceField(bitmapText) {
const context = this._getGpuBitmapText(bitmapText).context;
const fontFamily = bitmapText._style.fontFamily;
const dynamicFont = Cache.Cache.get(`${fontFamily}-bitmap`);
const { a, b, c, d } = bitmapText.groupTransform;
const dx = Math.sqrt(a * a + b * b);
const dy = Math.sqrt(c * c + d * d);
const worldScale = (Math.abs(dx) + Math.abs(dy)) / 2;
const fontScale = dynamicFont.baseRenderedFontSize / bitmapText._style.fontSize;
const distance = worldScale * dynamicFont.distanceField.range * (1 / fontScale);
context.customShader.resources.localUniforms.uniforms.uDistance = distance;
}
destroy() {
this._managedBitmapTexts.destroy();
this._renderer = null;
this._managedBitmapTexts = null;
}
}
/** @ignore */
BitmapTextPipe.extension = {
type: [
Extensions.ExtensionType.WebGLPipes,
Extensions.ExtensionType.WebGPUPipes,
Extensions.ExtensionType.CanvasPipes
],
name: "bitmapText"
};
function syncWithProxy(container, proxy) {
proxy.groupTransform = container.groupTransform;
proxy.groupColorAlpha = container.groupColorAlpha;
proxy.groupColor = container.groupColor;
proxy.groupBlendMode = container.groupBlendMode;
proxy.globalDisplayStatus = container.globalDisplayStatus;
proxy.groupTransform = container.groupTransform;
proxy.localDisplayStatus = container.localDisplayStatus;
proxy.groupAlpha = container.groupAlpha;
proxy._roundPixels = container._roundPixels;
}
exports.BitmapTextGraphics = BitmapTextGraphics;
exports.BitmapTextPipe = BitmapTextPipe;
//# sourceMappingURL=BitmapTextPipe.js.map