Skip to content

fix(svm): read the map mode's unit, and compose the relative one - #790

Merged
andiwand merged 1 commit into
mainfrom
feat/svm-map-mode
Aug 30, 2026
Merged

fix(svm): read the map mode's unit, and compose the relative one#790
andiwand merged 1 commit into
mainfrom
feat/svm-map-mode

Conversation

@andiwand

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Stage 8 of #772, closing its defect 6, stacked on #789#788#787#786
#785#784#779review those first; this branch's base is
feat/svm-fills.

The map mode was taken for its origin and scale and nothing else. Two things
follow from that:

  • The unit was ignored, so a drawing that switches to twips or points came
    out at the wrong size — off by 1.76 for twips.
  • A relative map mode replaced the current one instead of composing with
    it.

MetaMapModeAction::Execute calls OutputDevice::SetMapMode, which replaces
the map mode except where the new unit is MapUnit::MapRelative, and
ImplMapRes::CalcMapResolution says exactly how it composes then:

offset = offset / relative_scale + relative_origin
scale  = relative_scale * scale

The state now holds the resolved mapping — an origin and a scale — rather
than the map mode as read, and the scale carries the unit: the drawing is
measured in the header's unit, so a map mode in another one scales by what the
two are worth. MapPixel and the two font units are device-dependent, and a
metafile has no device, so they resolve at the same 96 dpi a bitmap without a
size of its own is drawn at.

Nothing in the corpus moves

4 of the 1125 harvested metafiles carry a MAPMODE action at all, and the one
relative map mode among them (in odr-public/svm/table-1.svm) composes to
exactly what replacing it produced, because its scale is 1:1. The reference
output does not change and there is no pin bump.

LibreOffice is not the oracle here

Asked to convert a metafile that switches to twips and then to a relative map
mode, LibreOffice's own svg export drops the third rectangle and writes the
second one outside the placement box.
Its metafile player is right; the
exporter is not, so this follows ImplMapRes from source. The one number the
export does agree on is the twips conversion — it writes the rectangle at
1058 wide 884, and so do we.

Verification

4 new tests (44 in the svm suite): a unit switch scales, a relative map mode
composes its origin, a relative map mode multiplies its scale, and a pop
restores the mapping.

@andiwand
andiwand force-pushed the feat/svm-fills branch 2 times, most recently from 1ad4577 to f760ca0 Compare August 30, 2026 18:21
Base automatically changed from feat/svm-fills to main August 30, 2026 18:23
The map mode was taken for its origin and scale and nothing else, so a drawing
that switched to twips or points came out at the wrong size, and a relative map
mode - which composes with the one before it - replaced it instead.

`MetaMapModeAction::Execute` calls `OutputDevice::SetMapMode`, which replaces
the map mode except where the new one's unit is `MapUnit::MapRelative`, and
`ImplMapRes::CalcMapResolution` says exactly how it composes then:

    offset = offset / relative_scale + relative_origin
    scale  = relative_scale * scale

The state now holds the resolved mapping - an origin and a scale - rather than
the map mode as read, and the scale carries the unit: the drawing is measured
in the header's unit, so a map mode in another one scales by what the two are
worth. `MapPixel` and the two font units are device-dependent and a metafile
has no device, so they resolve at the same 96 dpi a bitmap without a size of
its own is drawn at.

Nothing in the corpus moves: 4 of the 1125 metafiles carry a `MAPMODE` action
at all, and the one relative map mode among them composes to what replacing it
produced anyway.

LibreOffice is no oracle here - asked to convert a metafile that switches to
twips and then to a relative map mode, its own svg export drops the third
rectangle and writes the second outside the placement box. Its player is right;
`ImplMapRes` is what this follows, and the twips conversion it does write
(1058, 884) is what we write too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmCr22NW6wPQKiQidk96bq
@andiwand
andiwand merged commit f2c1df7 into main Aug 30, 2026
25 checks passed
@andiwand
andiwand deleted the feat/svm-map-mode branch August 30, 2026 18:31
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.

1 participant