Skip to content

Make damage unions outward-conservative across f32 frame extents #87

Description

@softmarshmallow

Problem

The complete-frame damage seam promises a conservative before+after pixel envelope, but its generic union helper performs endpoint and width arithmetic in f32. Two distinct failures remain possible outside the frame-bounded glyphless stroke projection added by the stroke-width saturation rung:

  1. a mathematically representable union can round inward at the far edge;
  2. two individually representable frame envelopes can have a union wider than f32::MAX, for which the current Option<RectF> / Option<Rectangle> vocabulary has no conservative finite value.

This was found while widening stroke coverage arithmetic. The stroke-specific producer now projects in a wider domain and clips to its finite frame before encoding, but changing the generic public damage contract was deliberately kept out of that capability rung.

Reproductions

Representable union rounds inward

Feed the generic union two RectF values with these exact f32 bit patterns:

  • A: x = 0x90bf0209, w = 0x05000000 (required right edge 0x90bf0208)
  • B: x = 0x0ea445b6, w = 0x03000000 (required right edge 0x0ea445b7)

The current union width is 0x10c94664. Reconstructing x + w yields right edge 0x0ea445b0, seven f32 steps inside B's required edge. A repaint clipped to that envelope can miss changed pixels.

Cross-frame union is not representable

Compile two same-owner, empty-item frame products whose admitted finite bounds are:

  • before: (-2e38, 0, 1e38, 1)
  • after: (1e38, 0, 1e38, 1)

Each far edge is finite, but diff_frame().union_frame.width becomes infinity because the true before+after span is about 4e38.

Required decision

  1. Make every representable union outward-conservative by doing endpoint arithmetic in a wider domain and outward-rounding only at the final encoding.
  2. Give an unrepresentable union an honest typed policy (for example a full/unbounded damage variant), or explicitly constrain the contract to a shared finite frame and enforce that precondition before union.
  3. Add exact bit-pattern regression laws for the inward-rounding case and the far-apart-frame case.
  4. Preserve the existing rule that changed attribution can be nonempty while a genuinely fully clipped envelope is absent; do not overload None to mean an unrepresentable union.

Scope

This is a damage-envelope contract issue, not a stroke painter or Web percentage issue. Do not clamp, split, or erase resolved geometry to make the envelope fit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions