Files
il/resources/public/js/cljs-runtime/module$node_modules$pixi_DOT_js$lib$scene$text$utils$canvasTextSplit.js
2026-07-01 22:38:29 -06:00

164 lines
12 KiB
JavaScript

shadow$provide.module$node_modules$pixi_DOT_js$lib$scene$text$utils$canvasTextSplit = function(global, require, module, exports) {
function getAlignmentOffset(alignment, lineWidth, largestLine) {
switch(alignment) {
case "center":
return (largestLine - lineWidth) / 2;
case "right":
return largestLine - lineWidth;
default:
return 0;
}
}
function isNewlineCharacter(char) {
return "\r" === char || "\n" === char || "\r\n" === char;
}
function groupTextSegments(segments, measuredText) {
const groupedSegments = [];
let currentLine = measuredText.lines[0], matchedLine = "", chars = [], lineCount = 0;
segments.forEach(segment => {
const isWhitespace = whitespaceRegex.test(segment), isNewline = isNewlineCharacter(segment), isSpaceAtStart = 0 === matchedLine.length && isWhitespace;
if (!isWhitespace || isNewline || !isSpaceAtStart || currentLine && currentLine.startsWith(segment)) {
isNewline || (matchedLine += segment), chars.push(segment), matchedLine.length >= currentLine.length && (groupedSegments.push({line:matchedLine, chars}), chars = [], matchedLine = "", lineCount++, currentLine = measuredText.lines[lineCount]);
}
});
return groupedSegments;
}
function canvasTaggedTextSplitFromRuns(measuredText, textStyle, existingChars, text) {
const {runsByLine} = measuredText, alignment = textStyle.align, maxLineWidth = measuredText.lineWidths.reduce((max, line) => Math.max(max, line), 0);
let trimOffsetX = 0, trimOffsetY = 0;
if (textStyle.trim) {
const {frame, canvasAndContext} = CanvasTextGenerator.CanvasTextGenerator.getCanvasAndContext({text, style:textStyle, resolution:1});
CanvasTextGenerator.CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);
trimOffsetX = -frame.x;
trimOffsetY = -frame.y;
}
const chars = [], lineContainers = [], wordContainers = [];
let yOffset = 0, existingCharIndex = 0;
runsByLine.forEach((lineRuns, lineIndex) => {
var lineContainer = new Container.Container({label:`line-${lineIndex}`});
lineContainer.y = yOffset + trimOffsetY;
lineContainers.push(lineContainer);
var lineWidth = measuredText.lineWidths[lineIndex], xOffset = getAlignmentOffset(alignment, lineWidth, maxLineWidth);
let currentWordContainer = new Container.Container({label:"word"});
currentWordContainer.x = xOffset + trimOffsetX;
for (const run of lineRuns) {
lineRuns = run.style;
var fillGradient = lineRuns._fill?.fill, strokeGradient = lineRuns._stroke?.fill, hasFillGradient = fillGradient instanceof FillGradient.FillGradient, hasStrokeGradient = strokeGradient instanceof FillGradient.FillGradient;
const hasGradient = hasFillGradient || hasStrokeGradient;
fillGradient = hasFillGradient && "local" === fillGradient.textureSpace || hasStrokeGradient && "local" === strokeGradient.textureSpace;
var graphemes = CanvasTextMetrics.CanvasTextMetrics.graphemeSegmenter(run.text);
strokeGradient = lineRuns.clone();
strokeGradient.align = "left";
strokeGradient.wordWrap = !1;
strokeGradient.trim && (strokeGradient.trim = !1);
strokeGradient.tagStyles = void 0;
strokeGradient._lineHeight = 0;
hasFillGradient = CanvasTextMetrics.CanvasTextMetrics._context;
hasFillGradient.font = strokeGradient._fontString;
CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacingSupported && (hasFillGradient.letterSpacing = "0px", hasFillGradient.textLetterSpacing = "0px");
hasStrokeGradient = run.text;
let previousRemainingWidth = hasFillGradient.measureText(hasStrokeGradient).width;
const runStartX = xOffset;
var runTextWidth = previousRemainingWidth, runFontProps = CanvasTextMetrics.CanvasTextMetrics.measureFont(strokeGradient._fontString);
runFontProps = lineRuns.lineHeight || runFontProps.fontSize;
runTextWidth = fillGradient ? {width:runTextWidth, height:runFontProps} : null;
for (const grapheme of graphemes) {
if (hasStrokeGradient = hasStrokeGradient.slice(grapheme.length), runFontProps = 0 < hasStrokeGradient.length ? hasFillGradient.measureText(hasStrokeGradient).width : 0, graphemes = previousRemainingWidth - runFontProps, previousRemainingWidth = runFontProps, !isNewlineCharacter(grapheme) && 0 !== graphemes) {
if (" " === grapheme) {
0 < currentWordContainer.children.length && (wordContainers.push(currentWordContainer), lineContainer.addChild(currentWordContainer)), xOffset += graphemes + lineRuns.letterSpacing, currentWordContainer = new Container.Container({label:"word"}), currentWordContainer.x = xOffset + trimOffsetX;
} else {
runFontProps = strokeGradient;
hasGradient && (runFontProps = strokeGradient.clone(), fillGradient ? (runFontProps._gradientOffset = {x:-(xOffset - runStartX), y:0}, runFontProps._gradientBounds = runTextWidth) : runFontProps._gradientOffset = {x:-(xOffset - runStartX), y:0});
let char;
existingCharIndex < existingChars.length ? (char = existingChars[existingCharIndex++], char.text = grapheme, char.style = runFontProps, char.setFromMatrix(Matrix.Matrix.IDENTITY), char.x = xOffset - currentWordContainer.x + trimOffsetX) : char = new Text.Text({text:grapheme, style:runFontProps, x:xOffset - currentWordContainer.x + trimOffsetX});
chars.push(char);
currentWordContainer.addChild(char);
xOffset += graphemes + lineRuns.letterSpacing;
}
}
}
}
0 < currentWordContainer.children.length && (wordContainers.push(currentWordContainer), lineContainer.addChild(currentWordContainer));
if ("justify" === alignment && textStyle.wordWrap && lineIndex < runsByLine.length - 1 && (lineContainer = lineContainer.children, xOffset = lineContainer.length - 1, 0 < xOffset)) {
for (lineWidth = (maxLineWidth - lineWidth) / xOffset, xOffset = 1; xOffset < lineContainer.length; xOffset++) {
lineContainer[xOffset].x += xOffset * lineWidth;
}
}
yOffset += measuredText.lineHeights?.[lineIndex] ?? measuredText.lineHeight;
});
return {chars, lines:lineContainers, words:wordContainers};
}
var Matrix = require("module$node_modules$pixi_DOT_js$lib$maths$matrix$Matrix"), Container = require("module$node_modules$pixi_DOT_js$lib$scene$container$Container"), FillGradient = require("module$node_modules$pixi_DOT_js$lib$scene$graphics$shared$fill$FillGradient"), CanvasTextGenerator = require("module$node_modules$pixi_DOT_js$lib$scene$text$canvas$CanvasTextGenerator"), CanvasTextMetrics = require("module$node_modules$pixi_DOT_js$lib$scene$text$canvas$CanvasTextMetrics"), Text = require("module$node_modules$pixi_DOT_js$lib$scene$text$Text");
"use strict";
const whitespaceRegex = /^\s*$/;
exports.canvasTextSplit = function(options) {
const {text, style, chars:existingChars} = options, measuredText = CanvasTextMetrics.CanvasTextMetrics.measureText(text, style);
if (measuredText.runsByLine && 0 < measuredText.runsByLine.length) {
return canvasTaggedTextSplitFromRuns(measuredText, style, existingChars, text);
}
options = CanvasTextMetrics.CanvasTextMetrics.graphemeSegmenter(text);
const groupedSegments = groupTextSegments(options, measuredText), alignment = style.align, maxLineWidth = measuredText.lineWidths.reduce((max, line) => Math.max(max, line), 0);
options = style._fill?.fill;
var strokeGradient = style._stroke?.fill, hasFillGradient = options instanceof FillGradient.FillGradient;
const hasStrokeGradient = strokeGradient instanceof FillGradient.FillGradient, hasGradient = hasFillGradient || hasStrokeGradient;
options = hasFillGradient && "local" === options.textureSpace || hasStrokeGradient && "local" === strokeGradient.textureSpace;
strokeGradient = measuredText.width;
hasFillGradient = measuredText.height;
const baseCharStyle = style.clone();
baseCharStyle.align = "left";
let trimOffsetX = 0, trimOffsetY = 0;
if (baseCharStyle.trim) {
const {frame, canvasAndContext} = CanvasTextGenerator.CanvasTextGenerator.getCanvasAndContext({text, style, resolution:1});
CanvasTextGenerator.CanvasTextGenerator.returnCanvasAndContext(canvasAndContext);
trimOffsetX = -frame.x;
trimOffsetY = -frame.y;
baseCharStyle.trim = !1;
}
const chars = [], lineContainers = [], wordContainers = [];
let yOffset = 0, existingCharIndex = 0;
const gradientBounds = options ? {width:strokeGradient, height:hasFillGradient} : null;
groupedSegments.forEach((group, lineIndex) => {
const lineContainer = new Container.Container({label:`line-${lineIndex}`});
lineContainer.y = yOffset + trimOffsetY;
lineContainers.push(lineContainer);
var lineWidth = measuredText.lineWidths[lineIndex];
let xOffset = getAlignmentOffset(alignment, lineWidth, maxLineWidth), currentWordContainer = new Container.Container({label:"word"});
currentWordContainer.x = xOffset + trimOffsetX;
const context = CanvasTextMetrics.CanvasTextMetrics._context;
context.font = baseCharStyle._fontString;
CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacingSupported && (context.letterSpacing = "0px", context.textLetterSpacing = "0px");
let remainingLineText = group.line, previousRemainingWidth = context.measureText(remainingLineText).width;
group.chars.forEach(segment => {
if (!isNewlineCharacter(segment)) {
remainingLineText = remainingLineText.slice(segment.length);
var currentRemainingWidth = 0 < remainingLineText.length ? context.measureText(remainingLineText).width : 0, charAdvance = previousRemainingWidth - currentRemainingWidth;
previousRemainingWidth = currentRemainingWidth;
if (0 !== charAdvance) {
if (" " === segment) {
0 < currentWordContainer.children.length && (wordContainers.push(currentWordContainer), lineContainer.addChild(currentWordContainer)), xOffset += charAdvance + style.letterSpacing, currentWordContainer = new Container.Container({label:"word"}), currentWordContainer.x = xOffset + trimOffsetX;
} else {
currentRemainingWidth = baseCharStyle;
hasGradient && (currentRemainingWidth = baseCharStyle.clone(), currentRemainingWidth._gradientOffset = {x:-xOffset, y:-yOffset}, gradientBounds && (currentRemainingWidth._gradientBounds = gradientBounds));
let char;
existingCharIndex < existingChars.length ? (char = existingChars[existingCharIndex++], char.text = segment, char.style = currentRemainingWidth, char.setFromMatrix(Matrix.Matrix.IDENTITY), char.x = xOffset - currentWordContainer.x + trimOffsetX) : char = new Text.Text({text:segment, style:currentRemainingWidth, x:xOffset - currentWordContainer.x + trimOffsetX});
chars.push(char);
currentWordContainer.addChild(char);
xOffset += charAdvance + style.letterSpacing;
}
}
}
});
0 < currentWordContainer.children.length && (wordContainers.push(currentWordContainer), lineContainer.addChild(currentWordContainer));
if ("justify" === alignment && style.wordWrap && lineIndex < groupedSegments.length - 1 && (group = lineContainer.children, lineIndex = group.length - 1, 0 < lineIndex)) {
for (lineWidth = (maxLineWidth - lineWidth) / lineIndex, lineIndex = 1; lineIndex < group.length; lineIndex++) {
group[lineIndex].x += lineIndex * lineWidth;
}
}
yOffset += measuredText.lineHeight;
});
return {chars, lines:lineContainers, words:wordContainers};
};
};
//# sourceMappingURL=module$node_modules$pixi_DOT_js$lib$scene$text$utils$canvasTextSplit.js.map