Skip to content

Extract Lottie text layout module and align rendering with Lottie spec#18333

Merged
VicenteCartas merged 3 commits intoBabylonJS:masterfrom
VicenteCartas:lottie-text-layout
Apr 17, 2026
Merged

Extract Lottie text layout module and align rendering with Lottie spec#18333
VicenteCartas merged 3 commits intoBabylonJS:masterfrom
VicenteCartas:lottie-text-layout

Conversation

@VicenteCartas
Copy link
Copy Markdown
Contributor

Summary

Extracts Lottie text measurement and drawing out of boundingBox.ts and spritePacker.ts into a new textLayout.ts module, and fixes spec-correctness issues in the process. This is a behavior change (bug fix), not a pure refactor, existing Lottie files containing text will render slightly differently, matching the reference renderer.

Spec-correctness fixes

  • Baseline offset from font ascent. Previously derived from the per-glyph metrics.actualBoundingBoxAscent, which caused text to jitter vertically as content changed. Now fontSize × rawFont.ascent / 100, matching the Lottie spec's definition of ascent as a font-level property ("text will be moved down based on this value").
  • Point-text anchor restored to the baseline origin. The old code forced offsetX/Y to 0 and returned width = ceil(metrics.width), which silently shifted glyphs whose side bearings were asymmetric (e.g. italic T). offsetX/Y now reflect actualBoundingBoxLeft/Right so the sprite center matches the authored layer origin.
  • fontKerning = "none" on the measurement/draw context. Lottie applies tracking (tr) as a per-character advance and the reference renderer does not kern; leaving browser kerning on double-applied spacing adjustments.

New capability

  • Paragraph-box text (sz / ps fields on RawTextDocument) with word wrap, long-word breaking, and box-relative justification.

Mechanical changes

  • New helpers: ResolveLottieText, MeasureLottieText, ApplyLottieTextContext, DrawLottieText, BuildCanvasFont.
  • GetTextBoundingBox and SpritePacker._drawText delegate to the new helpers. _drawText drops its unused boundingBox parameter.
  • DrawTrackedText lays glyphs out in a single pass (was O(n²) in measureText calls when tracking was non-zero).

Tests

  • New lottieTextLayout.test.ts (12 tests) covering font resolution, paragraph-box layout, justification, tracking, line-break handling, variable substitution, long-word break, stroke-under / stroke-over-fill ordering, and per-glyph tracked-draw X positions.
  • All 60 lottiePlayer unit tests pass.
  • format:check and eslint pass on changed files.

…Lottie spec

Extracts text measurement and drawing from boundingBox.ts and spritePacker.ts into a new textLayout.ts module, and fixes spec-correctness issues in the process. This is a behavior change (bug fix), not a pure refactor — existing Lottie files containing text will render slightly differently, matching the reference renderer.

Spec-correctness fixes:
- Baseline offset now derived from font ascent (fontSize * rawFont.ascent / 100) instead of per-glyph metrics.actualBoundingBoxAscent. Per the Lottie spec, ascent is a font-level property ("text will be moved down based on this value"); using per-glyph metrics caused text to jitter vertically as content changed.
- Point-text anchor restored to the baseline origin. The old code forced offsetX/Y to 0 and returned width = ceil(metrics.width), which silently shifted glyphs whose side bearings were asymmetric (e.g. italic T). offsetX/Y now reflect actualBoundingBoxLeft/Right so the sprite center matches the authored layer origin.
- fontKerning = "none" on the measurement/draw context. Lottie applies tracking (tr) as a per-character advance and the reference renderer does not kern; leaving browser kerning on double-applied spacing adjustments.

New capability:
- Paragraph-box text (sz / ps fields on RawTextDocument) with word wrap, long-word breaking, and box-relative justification.

Mechanical changes:
- New helpers: ResolveLottieText, MeasureLottieText, ApplyLottieTextContext, DrawLottieText, BuildCanvasFont.
- GetTextBoundingBox and SpritePacker._drawText delegate to the new helpers. _drawText drops its unused boundingBox parameter.
- lottieTextLayout.test.ts: 7 new unit tests covering font resolution, paragraph-box layout, justification, tracking, line-break handling, and variable substitution.

Visual regression coverage is tracked as an Untriaged item on the lottie-fixes task board.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 17, 2026 00:24
@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extracts Lottie text resolution/measurement/drawing into a dedicated textLayout.ts module and updates text atlas packing + bounding-box measurement to be more spec-aligned (baseline handling, point-text anchoring, tracking/kerning behavior, and paragraph-box wrapping).

Changes:

  • Introduces textLayout.ts helpers (ResolveLottieText, MeasureLottieText, ApplyLottieTextContext, DrawLottieText, etc.) and updates text measurement/layout behavior.
  • Refactors GetTextBoundingBox and SpritePacker._drawText to delegate to the new layout module (and adds paragraph-box support).
  • Adds unit tests covering the new layout/draw behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/dev/lottiePlayer/src/parsing/textLayout.ts New shared module for resolving, measuring, and drawing Lottie text (including paragraph box wrapping and tracking).
packages/dev/lottiePlayer/src/maths/boundingBox.ts Routes text bounding-box computation through the new text layout/measurement helpers.
packages/dev/lottiePlayer/src/parsing/spritePacker.ts Updates sprite atlas text drawing to use the new text layout module; removes the unused boundingBox parameter.
packages/dev/lottiePlayer/src/parsing/rawTypes.ts Extends RawTextDocument with sz/ps (paragraph box) fields.
packages/dev/lottiePlayer/test/unit/lottieTextLayout.test.ts Adds focused unit coverage for resolution, layout, wrapping, justification, tracking, and draw ordering.

Comment thread packages/dev/lottiePlayer/src/parsing/spritePacker.ts Outdated
Comment thread packages/dev/lottiePlayer/src/parsing/textLayout.ts Outdated
Comment thread packages/dev/lottiePlayer/src/maths/boundingBox.ts
@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

Snapshot stored with reference name:
refs/pull/18333/merge

Test environment:
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/18333/merge/index.html

To test a playground add it to the URL, for example:

https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/18333/merge/index.html#WGZLGJ#4600

Links to test your changes to core in the published versions of the Babylon tools (does not contain changes you made to the tools themselves):

https://playground.babylonjs.com/?snapshot=refs/pull/18333/merge
https://sandbox.babylonjs.com/?snapshot=refs/pull/18333/merge
https://gui.babylonjs.com/?snapshot=refs/pull/18333/merge
https://nme.babylonjs.com/?snapshot=refs/pull/18333/merge

To test the snapshot in the playground with a playground ID add it after the snapshot query string:

https://playground.babylonjs.com/?snapshot=refs/pull/18333/merge#BCU1XR#0

If you made changes to the sandbox or playground in this PR, additional comments will be generated soon containing links to the dev versions of those tools.

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@VicenteCartas VicenteCartas enabled auto-merge (squash) April 17, 2026 01:15
@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@bjsplat
Copy link
Copy Markdown
Collaborator

bjsplat commented Apr 17, 2026

@VicenteCartas VicenteCartas merged commit f24e65b into BabylonJS:master Apr 17, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants