Skip to content

fix(geometry): resolve transform lengths per axis and per font-size - #228

Closed
LeadcodeDev wants to merge 1 commit into
fix/geometry-viewport-unitsfrom
fix/geometry-transform-lengths
Closed

LeadcodeDev wants to merge 1 commit into
fix/geometry-viewport-unitsfrom
fix/geometry-transform-lengths

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Medium, category correctness. Location: crates/rustmotion/src/cli/commands/geometry.rs:477

Impact

apply_transform_chain resolves translate/translateX/translateY lengths through this context. The paint pass resolves the very same functions through LengthContext { ..., parent_size: box_layout.width.max(height), font_size: node.css.font_size_px_or(16.0), ... } and then splits it into per-axis length_ctx_x/length_ctx_y (crates/rustmotion-core/src/engine/paint_pass.rs:229-250, used at :953-962). Two divergences: (a) em — a font-size: 96px text with transform: "translateX(-10em)" is moved -960px by the renderer but only -160px by the validator, so a component at x=200 that renders at x=-760 (fully off-frame) validates clean; (b) percentage translate — the validator uses max(w, h) on both axes, the exact mistake paint_pass.rs:236-242 calls out in a comment ("never max(width, height) on both axes"), which over-estimates on the short axis and produces false positives. Note the --strict-anim path funnels animated transforms through this same function (geometry.rs:1482), so it inherits both errors.

Fix

Build the context from the node's resolved font-size (css.font_size_px_or(16.0)) and resolve the x-component against bbox.w and the y-component against bbox.h, mirroring length_ctx_x/length_ctx_y in paint_pass.rs:243-250.

Evidence the audit read

let ctx = LengthContext {
    viewport_width: viewport.0,
    viewport_height: viewport.1,
    parent_size: bbox.w.max(bbox.h),
    font_size: 16.0,
    root_font_size: 16.0,
};

Stacked on fix/geometry-viewport-units, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-15).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-viewport-units branch from b59cf4f to f94bcad Compare September 21, 2026 23:39
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-transform-lengths branch from e52dc82 to f478e84 Compare September 21, 2026 23:39
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-viewport-units branch from 5d0dc87 to 99491fd Compare September 22, 2026 06:09
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-transform-lengths branch from 9f00928 to 6753586 Compare September 22, 2026 06:09
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-viewport-units branch from 99491fd to c1f4b85 Compare September 22, 2026 08:33
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-transform-lengths branch from 6753586 to de249ff Compare September 22, 2026 08:33
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-viewport-units branch from c1f4b85 to fc20b4c Compare September 22, 2026 08:43
apply_transform_chain resolves translate/translateX/translateY lengths
through this context. The paint pass resolves the very same functions
through LengthContext { ..., parent_size: box_layout.width.max(height),
font_size: node.css.font_size_px_or(16.0), ... } and then splits it into
per-axis length_ctx_x/length_ctx_y (crates/rustmotion-
core/src/engine/paint_pass.rs:229-250, used at :953-962). Two divergences:
(a) em — a font-size: 96px text with transform: "translateX(-10em)" is moved
-960px by the renderer but only -160px by the validator, so a component at
x=200 that renders at x=-760 (fully off-frame) validates clean; (b)
percentage translate — the validator uses max(w, h) on both axes, the exact
mistake paint_pass.rs:236-242 calls out in a comment ("never max(width,
height) on both axes"), which over-estimates on the short axis and produces
false positives. Note the --strict-anim path funnels animated transforms
through this same function (geometry.rs:1482), so it inherits both errors.

Fix: Build the context from the node's resolved font-size
(css.font_size_px_or(16.0)) and resolve the x-component against bbox.w and
the y-component against bbox.h, mirroring length_ctx_x/length_ctx_y in
paint_pass.rs:243-250.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/geometry-transform-lengths branch from de249ff to 59ba406 Compare September 22, 2026 08:43
@LeadcodeDev
LeadcodeDev deleted the branch fix/geometry-viewport-units September 22, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant