@lightningtv/renderer
Version:
Lightning 3 Renderer
118 lines (108 loc) • 3.85 kB
text/typescript
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2023 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 { assertTruthy } from '../../../../../utils.js';
import type { Bound } from '../../../../lib/utils.js';
import type { SdfTrFontFace } from '../../../font-face-types/SdfTrFontFace/SdfTrFontFace.js';
import type { TrProps, TextRendererState } from '../../TextRenderer.js';
import type { SdfTextRendererState } from '../SdfTextRenderer.js';
import type { SdfRenderWindow } from './setRenderWindow.js';
/**
* Gets the start conditions for the layout loop.
*
* @remarks
* Returns `undefined` if the layout loop should not be run.
*
* @param fontSize
* @param fontSizeRatio
* @param sdfLineHeight
* @param renderWindow
* @param lineCache
* @param textH
* @returns
*/
export function getStartConditions(
sdfFontSize: number,
sdfLineHeight: number,
fontFace: SdfTrFontFace,
verticalAlign: TrProps['verticalAlign'],
offsetY: TrProps['offsetY'],
fontSizeRatio: number,
renderWindow: SdfRenderWindow,
lineCache: SdfTextRendererState['lineCache'],
textH: TextRendererState['textH'],
):
| {
sdfX: number;
sdfY: number;
lineIndex: number;
}
| undefined {
// State variables
const startLineIndex = Math.min(
Math.max(renderWindow.firstLineIdx, 0),
lineCache.length,
);
const sdfStartX = 0;
const { metrics } = fontFace;
assertTruthy(metrics, 'Font metrics not loaded');
assertTruthy(fontFace.data, 'Font data not loaded');
/**
* Bare line height is the distance between the ascender and descender of the font.
* without the line gap metric.
*/
const sdfBareLineHeight =
(metrics.ascender - metrics.descender) * sdfFontSize;
let sdfVerticalAlignYOffset = 0;
if (verticalAlign === 'middle') {
sdfVerticalAlignYOffset = (sdfLineHeight - sdfBareLineHeight) / 2;
} else if (verticalAlign === 'bottom') {
sdfVerticalAlignYOffset = sdfLineHeight - sdfBareLineHeight;
}
const sdfOffsetY = offsetY / fontSizeRatio;
/**
* This is the position from the top of the text drawing line to where the
* baseline of the text will be according to the encoded positioning data for
* each glyph in the SDF data. This also happens to be the ascender value
* that is encoded into the font data.
*/
const sdfEncodedAscender = fontFace.data.common.base;
/**
* This is the ascender that is configured and overridable in the font face.
*/
const sdfConfiguredAscender = metrics.ascender * sdfFontSize;
/**
* If the configured ascender is different from the SDF data's encoded
* ascender, the offset of the text will be adjusted by the difference.
*/
const sdfAscenderAdjOffset = sdfConfiguredAscender - sdfEncodedAscender;
const sdfStartY =
sdfOffsetY +
sdfAscenderAdjOffset +
startLineIndex * sdfLineHeight +
sdfVerticalAlignYOffset; // TODO: Figure out what determines the initial y offset of text.
// Don't attempt to render anything if we know we're starting past the established end of the text
if (textH && sdfStartY >= textH / fontSizeRatio) {
return;
}
return {
sdfX: sdfStartX,
sdfY: sdfStartY,
lineIndex: startLineIndex,
};
}