UNPKG

@itwin/core-backend

Version:
142 lines 6.53 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module ElementGeometry */ Object.defineProperty(exports, "__esModule", { value: true }); exports.produceTextBlockGeometry = produceTextBlockGeometry; const core_common_1 = require("@itwin/core-common"); const core_geometry_1 = require("@itwin/core-geometry"); const core_bentley_1 = require("@itwin/core-bentley"); function setColor(color, context) { if (color !== context.curColor) { context.curColor = color; context.entries.push({ color }); } } function createTextString(text, run, origin) { (0, core_bentley_1.assert)(text.length > 0); const { lineHeight, widthFactor, isBold, isItalic, isUnderlined } = run.style; return new core_common_1.TextString({ text, font: run.fontId, height: lineHeight, widthFactor, bold: isBold, italic: isItalic, underline: isUnderlined, origin, }); } function processTextRun(run, transform, context) { (0, core_bentley_1.assert)(run.source.type === "text"); const text = run.source.content.substring(run.charOffset, run.charOffset + run.numChars); if (text.length === 0) { return; } const ts = createTextString(text, run); if ("none" !== run.source.baselineShift) { const isSub = "subscript" === run.source.baselineShift; const offsetFactor = run.style[isSub ? "subScriptOffsetFactor" : "superScriptOffsetFactor"]; const scale = run.style[isSub ? "subScriptScale" : "superScriptScale"]; ts.origin.y += offsetFactor * ts.height; ts.height *= scale; } ts.transformInPlace(transform); setColor(run.style.color, context); context.entries.push({ text: ts }); } function processFieldRun(run, transform, context) { (0, core_bentley_1.assert)(run.source.type === "field"); const text = run.source.cachedContent.substring(run.charOffset, run.charOffset + run.numChars); if (text.length === 0) { return; } const ts = createTextString(text, run); ts.transformInPlace(transform); setColor(run.style.color, context); context.entries.push({ text: ts }); } function createFractionTextString(text, run, origin, transform) { const ts = createTextString(text, run, origin); (0, core_bentley_1.assert)(undefined !== ts.widthFactor); ts.height *= run.style.stackedFractionScale; ts.transformInPlace(transform); return ts; } function processFractionRun(run, transform, context) { const source = run.source; (0, core_bentley_1.assert)(source.type === "fraction"); if (source.numerator.length === 0 && source.denominator.length === 0) { return; } (0, core_bentley_1.assert)(undefined !== run.numeratorRange && undefined !== run.denominatorRange); const fontSize = new core_geometry_1.Vector2d(run.style.lineHeight * run.style.widthFactor, run.style.lineHeight); fontSize.scale(run.style.stackedFractionScale, fontSize); const numeratorOffset = new core_geometry_1.Point3d(run.numeratorRange.low.x, run.numeratorRange.low.y, 0); const denominatorOffset = new core_geometry_1.Point3d(run.denominatorRange.low.x, run.denominatorRange.low.y, 0); setColor(run.style.color, context); if (source.numerator.length > 0) { context.entries.push({ text: createFractionTextString(source.numerator, run, numeratorOffset, transform) }); } const numeratorRange = core_geometry_1.Range2d.fromJSON(run.numeratorRange); const denominatorRange = core_geometry_1.Range2d.fromJSON(run.denominatorRange); let separator; if (run.style.stackedFractionType === "horizontal") { const fractionWidth = Math.max(numeratorRange.xLength(), denominatorRange.xLength()); const y = 1.25 * denominatorRange.yLength(); separator = core_geometry_1.LineSegment3d.createXYXY(0, y, fractionWidth, y); } else { const p0 = new core_geometry_1.Point3d(denominatorRange.low.x - fontSize.x / 2, denominatorRange.low.y + fontSize.y * (1 / 3), 0); const p1 = new core_geometry_1.Point3d(p0.x + fontSize.x, p0.y + fontSize.y * 1.5, 0); separator = core_geometry_1.LineSegment3d.createCapture(p0, p1); } separator.tryTransformInPlace(transform); context.entries.push({ separator: { startPoint: separator.point0Ref.toJSON(), endPoint: separator.point1Ref.toJSON(), }, }); if (source.denominator.length > 0) { context.entries.push({ text: createFractionTextString(source.denominator, run, denominatorOffset, transform) }); } } /** * Produces the geometry for a text block in a way that can be interpreted by a [[GeometryStreamBuilder]] or [[ElementBuilder.Geometry]]. * To build the geometry for a whole [[TextAnnotation]], use [[appendTextAnnotationGeometry]] instead. * @param layout of the text block as computed by [[layoutTextBlock]]. * @param documentTransform that positions the text block in world coordinates. * @returns TextBlockGeometryProps. * @beta */ function produceTextBlockGeometry(layout, documentTransform) { const context = { entries: [] }; for (const line of layout.lines) { const lineTrans = core_geometry_1.Transform.createTranslationXYZ(line.offsetFromDocument.x, line.offsetFromDocument.y, 0); for (const run of line.runs) { // Skip runs that are solely whitespace if (run.source.isWhitespace) { continue; } const runTrans = core_geometry_1.Transform.createTranslationXYZ(run.offsetFromLine.x, run.offsetFromLine.y, 0); lineTrans.multiplyTransformTransform(runTrans, runTrans); documentTransform.multiplyTransformTransform(runTrans, runTrans); if ("text" === run.source.type) { processTextRun(run, runTrans, context); } else if ("fraction" === run.source.type) { processFractionRun(run, runTrans, context); } else { processFieldRun(run, runTrans, context); } } } return { entries: context.entries }; } //# sourceMappingURL=TextBlockGeometry.js.map