@lightningjs/renderer
Version:
Lightning 3 Renderer
192 lines • 6.93 kB
JavaScript
import {} from "./types";
import {} from "../../../../CoreTextNodeCanvas";
import { assertTruthy } from "../../../../../utils";
import { mergeDefaults } from "./mergeDefaults";
import { calcDefaultLineHeight } from '../../../TextRenderingUtils.js';
import { getWebFontMetrics, wrapText, wrapWord, measureText, calcHeight } from './utils.js';
export const parseRenderInfo = (props, precision, context) => {
const renderInfo = {};
const settings = mergeDefaults(props);
const paddingLeft = settings.paddingLeft * precision;
const paddingRight = settings.paddingRight * precision;
const fontSize = settings.fontSize * precision;
const w = settings.w * precision;
const h = settings.h * precision;
let wordWrapWidth = settings.wordWrapWidth * precision;
const cutSx = settings.cutSx * precision;
const cutEx = settings.cutEx * precision;
const cutSy = settings.cutSy * precision;
const cutEy = settings.cutEy * precision;
const letterSpacing = (settings.letterSpacing || 0) * precision;
const textIndent = settings.textIndent * precision;
const trFontFace = settings.trFontFace;
// Set font properties.
const ff = [settings.fontFamily];
const ffs = [];
for (let i = 0, n = ff.length; i < n; i++) {
if (ff[i] === 'serif' || ff[i] === 'sans-serif') {
ffs.push(ff[i]);
}
else {
ffs.push(`"${ff[i]}"`);
}
}
const fontSetting = `${settings.fontStyle} ${settings.fontSize * precision}px ${ffs.join(',')}`;
context.font = fontSetting;
context.textBaseline = settings.textBaseline;
assertTruthy(trFontFace);
const metrics = getWebFontMetrics(context, trFontFace, fontSize);
const defLineHeight = calcDefaultLineHeight(metrics, fontSize) * precision;
const lineHeight = settings.lineHeight !== null
? settings.lineHeight * precision
: defLineHeight;
const maxHeight = settings.maxHeight;
const containedMaxLines = maxHeight !== null && lineHeight > 0
? Math.floor(maxHeight / lineHeight)
: 0;
const setMaxLines = settings.maxLines;
const calcMaxLines = containedMaxLines > 0 && setMaxLines > 0
? Math.min(containedMaxLines, setMaxLines)
: Math.max(containedMaxLines, setMaxLines);
// Total width.
let width = w || 2048 / precision;
// Inner width.
let innerWidth = width - paddingLeft;
if (innerWidth < 10) {
width += 10 - innerWidth;
innerWidth = 10;
}
if (!wordWrapWidth) {
wordWrapWidth = innerWidth;
}
// Text overflow
if (settings.textOverflow && settings.wordWrap === false) {
let suffix;
switch (settings.textOverflow) {
case 'clip':
suffix = '';
break;
case 'ellipsis':
suffix = settings.overflowSuffix;
break;
default:
suffix = settings.textOverflow;
}
settings.text = wrapWord(settings.text, wordWrapWidth - textIndent, suffix, context);
}
// word wrap
// preserve original text
let linesInfo;
if (settings.wordWrap === true) {
linesInfo = wrapText(settings.text, wordWrapWidth, letterSpacing, textIndent, context);
}
else {
linesInfo = { l: settings.text.split(/(?:\r\n|\r|\n)/), n: [] };
const n = linesInfo.l.length;
for (let i = 0; i < n - 1; i++) {
linesInfo.n.push(i);
}
}
let lines = linesInfo.l;
if (calcMaxLines && lines.length > calcMaxLines) {
const usedLines = lines.slice(0, calcMaxLines);
let otherLines = null;
if (settings.overflowSuffix) {
// Wrap again with max lines suffix enabled.
const w = settings.overflowSuffix
? measureText(settings.overflowSuffix, 0, context)
: 0;
const al = wrapText(usedLines[usedLines.length - 1], wordWrapWidth - w, letterSpacing, textIndent, context);
usedLines[usedLines.length - 1] = `${al.l[0]}${settings.overflowSuffix}`;
otherLines = [al.l.length > 1 ? al.l[1] : ''];
}
else {
otherLines = [''];
}
// Re-assemble the remaining text.
let i;
const n = lines.length;
let j = 0;
const m = linesInfo.n.length;
for (i = calcMaxLines; i < n; i++) {
otherLines[j] += `${otherLines[j] ? ' ' : ''}${lines[i]}`;
if (i + 1 < m && linesInfo.n[i + 1]) {
j++;
}
}
renderInfo.remainingText = otherLines.join('\n');
renderInfo.moreTextLines = true;
lines = usedLines;
}
else {
renderInfo.moreTextLines = false;
renderInfo.remainingText = '';
}
// calculate text width
let maxLineWidth = 0;
const lineWidths = [];
for (let i = 0; i < lines.length; i++) {
const lineWidth = measureText(lines[i], letterSpacing, context) + (i === 0 ? textIndent : 0);
lineWidths.push(lineWidth);
maxLineWidth = Math.max(maxLineWidth, lineWidth);
}
renderInfo.lineWidths = lineWidths;
if (!w) {
// Auto-set width to max text length.
width = maxLineWidth + paddingLeft + paddingRight;
innerWidth = maxLineWidth;
}
// If word wrap is enabled the width needs to be the width of the text.
if (settings.wordWrap &&
w > maxLineWidth &&
settings.textAlign === 'left' &&
lines.length === 1) {
width = maxLineWidth + paddingLeft + paddingRight;
}
let height;
if (h) {
height = h;
}
else {
height = calcHeight(settings.textBaseline, fontSize, lineHeight, lines.length);
}
renderInfo.w = width;
renderInfo.h = height;
renderInfo.lines = lines;
renderInfo.precision = precision;
if (!width) {
// To prevent canvas errors.
width = 1;
}
if (!height) {
// To prevent canvas errors.
height = 1;
}
if (cutSx || cutEx) {
width = Math.min(width, cutEx - cutSx);
}
if (cutSy || cutEy) {
height = Math.min(height, cutEy - cutSy);
}
renderInfo.width = width;
renderInfo.innerWidth = innerWidth;
renderInfo.height = height;
renderInfo.fontSize = fontSize;
renderInfo.cutSx = cutSx;
renderInfo.cutSy = cutSy;
renderInfo.cutEx = cutEx;
renderInfo.cutEy = cutEy;
renderInfo.lineHeight = lineHeight;
renderInfo.defLineHeight = defLineHeight;
renderInfo.lineWidths = lineWidths;
renderInfo.paddingLeft = paddingLeft;
renderInfo.paddingRight = paddingRight;
renderInfo.letterSpacing = letterSpacing;
renderInfo.textIndent = textIndent;
renderInfo.metrics = metrics;
return {
renderInfo: renderInfo,
settings: settings,
};
};
//# sourceMappingURL=renderInfo.js.map