diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-02-25 01:37:56 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-02-25 01:37:56 +0100 |
| commit | f75b5d3fd28349ee69f03be34c1316122992c283 (patch) | |
| tree | 45e233d9b4c83b02be2a7bfe13ea943a676bd9be /apps/web/src/lib/preview | |
| parent | 4d77e3f2bb9884ad9e43761eaf0ede8c1a9cfccc (diff) | |
| download | opencut-f75b5d3fd28349ee69f03be34c1316122992c283.tar.gz | |
fix a ton of issues + improvement
Diffstat (limited to 'apps/web/src/lib/preview')
| -rw-r--r-- | apps/web/src/lib/preview/element-bounds.ts | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/apps/web/src/lib/preview/element-bounds.ts b/apps/web/src/lib/preview/element-bounds.ts index ec26c14d..9e58ec52 100644 --- a/apps/web/src/lib/preview/element-bounds.ts +++ b/apps/web/src/lib/preview/element-bounds.ts @@ -2,9 +2,11 @@ import type { TimelineTrack, TimelineElement } from "@/types/timeline"; import type { MediaAsset } from "@/types/assets"; import { isMainTrack } from "@/lib/timeline"; import { + DEFAULT_TEXT_ELEMENT, DEFAULT_LINE_HEIGHT, FONT_SIZE_SCALE_REFERENCE, } from "@/constants/text-constants"; +import { getTextVisualRect, measureTextBlock } from "@/lib/text/layout"; export interface ElementBounds { cx: number; @@ -121,27 +123,36 @@ export function getElementBounds({ const lines = element.content.split("\n"); const lineMetrics = lines.map((line) => ctx.measureText(line)); - - let top = Number.POSITIVE_INFINITY; - let bottom = Number.NEGATIVE_INFINITY; - let maxWidth = 0; - - for (let i = 0; i < lineMetrics.length; i++) { - const metrics = lineMetrics[i]; - const y = i * lineHeightPx; - top = Math.min( - top, - y - (metrics.actualBoundingBoxAscent ?? scaledFontSize * 0.8), - ); - bottom = Math.max( - bottom, - y + (metrics.actualBoundingBoxDescent ?? scaledFontSize * 0.2), - ); - maxWidth = Math.max(maxWidth, metrics.width); - } - - measuredWidth = maxWidth; - measuredHeight = bottom - top; + const block = measureTextBlock({ + lineMetrics, + lineHeightPx, + fallbackFontSize: scaledFontSize, + }); + const fontSizeRatio = element.fontSize / DEFAULT_TEXT_ELEMENT.fontSize; + const visualRect = getTextVisualRect({ + textAlign: element.textAlign, + block, + background: element.background, + fontSizeRatio, + }); + measuredWidth = visualRect.width; + measuredHeight = visualRect.height; + const localCenterX = visualRect.left + visualRect.width / 2; + const localCenterY = visualRect.top + visualRect.height / 2; + const scaledCenterX = localCenterX * element.transform.scale; + const scaledCenterY = localCenterY * element.transform.scale; + const rotationRad = (element.transform.rotate * Math.PI) / 180; + const cos = Math.cos(rotationRad); + const sin = Math.sin(rotationRad); + const rotatedCenterX = scaledCenterX * cos - scaledCenterY * sin; + const rotatedCenterY = scaledCenterX * sin + scaledCenterY * cos; + return { + cx: canvasWidth / 2 + element.transform.position.x + rotatedCenterX, + cy: canvasHeight / 2 + element.transform.position.y + rotatedCenterY, + width: measuredWidth * element.transform.scale, + height: measuredHeight * element.transform.scale, + rotation: element.transform.rotate, + }; } const width = measuredWidth * element.transform.scale; |
