@lightningjs/renderer
Version:
Lightning 3 Renderer
144 lines • 5.09 kB
JavaScript
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2025 Comcast Cable Communications Management, LLC.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { isZeroWidthSpace } from '../Utils.js';
export const measureText = (context, word, space = 0) => {
if (space === 0) {
return context.measureText(word).width;
}
return word.split('').reduce((acc, char) => {
if (isZeroWidthSpace(char) === true) {
return acc;
}
return acc + context.measureText(char).width + space;
}, 0);
};
// Helper functions
export const wrapWord = (context, word, wordWrapWidth, suffix, letterSpacing) => {
const suffixWidth = measureText(context, suffix, letterSpacing);
const wordLen = word.length;
const wordWidth = measureText(context, word, letterSpacing);
if (wordWidth <= wordWrapWidth) {
return word;
}
let cutoffIndex = Math.floor((wordWrapWidth * wordLen) / wordWidth);
let truncWordWidth = measureText(context, word.substring(0, cutoffIndex), letterSpacing) +
suffixWidth;
if (truncWordWidth > wordWrapWidth) {
while (cutoffIndex > 0) {
truncWordWidth =
measureText(context, word.substring(0, cutoffIndex), letterSpacing) +
suffixWidth;
if (truncWordWidth > wordWrapWidth) {
cutoffIndex -= 1;
}
else {
break;
}
}
}
else {
while (cutoffIndex < wordLen) {
truncWordWidth =
measureText(context, word.substring(0, cutoffIndex), letterSpacing) +
suffixWidth;
if (truncWordWidth < wordWrapWidth) {
cutoffIndex += 1;
}
else {
cutoffIndex -= 1;
break;
}
}
}
return (word.substring(0, cutoffIndex) +
(wordWrapWidth >= suffixWidth ? suffix : ''));
};
export const wrapText = (context, text, wordWrapWidth, letterSpacing, indent) => {
const spaceRegex = / |\u200B/g;
const lines = text.split(/\r?\n/g);
let allLines = [];
const realNewlines = [];
for (let i = 0; i < lines.length; i++) {
const resultLines = [];
let result = '';
let spaceLeft = wordWrapWidth - indent;
const line = lines[i] ?? '';
const words = line.split(spaceRegex);
const spaces = line.match(spaceRegex) || [];
for (let j = 0; j < words.length; j++) {
const space = spaces[j - 1] || '';
const word = words[j] || '';
const wordWidth = measureText(context, word, letterSpacing);
const wordWidthWithSpace = wordWidth + measureText(context, space, letterSpacing);
if (j === 0 || wordWidthWithSpace > spaceLeft) {
if (j > 0) {
resultLines.push(result);
result = '';
}
result += word;
spaceLeft = wordWrapWidth - wordWidth - (j === 0 ? indent : 0);
}
else {
spaceLeft -= wordWidthWithSpace;
// Don't add ZWSP to the output since it's invisible
if (space !== '\u200B') {
result += space + word;
}
else {
result += word;
}
}
}
resultLines.push(result);
result = '';
allLines = allLines.concat(resultLines);
if (i < lines.length - 1) {
realNewlines.push(allLines.length);
}
}
return { l: allLines, n: realNewlines };
};
export const isNormalizedFontMetrics = (obj) => {
return (typeof obj === 'object' &&
obj !== null &&
'ascender' in obj &&
typeof obj.ascender === 'number' &&
'descender' in obj &&
typeof obj.descender === 'number' &&
'lineGap' in obj &&
typeof obj.lineGap === 'number');
};
/**
* Calculate height for the canvas
*
* @param textBaseline
* @param fontSize
* @param lineHeight
* @param numLines
* @param offsetY
* @returns
*/
export const calcHeight = (textBaseline, fontSize, lineHeight, numLines, offsetY) => {
const baselineOffset = textBaseline !== 'bottom' ? 0.5 * fontSize : 0;
return (lineHeight * (numLines - 1) +
baselineOffset +
Math.max(lineHeight, fontSize) +
offsetY);
};
//# sourceMappingURL=Utils.js.map