164 lines
12 KiB
JavaScript
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
|