fix(svm): read the map mode's unit, and compose the relative one - #790
Merged
Conversation
This was referenced Aug 30, 2026
andiwand
force-pushed
the
feat/svm-fills
branch
2 times, most recently
from
August 30, 2026 18:21
1ad4577 to
f760ca0
Compare
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
force-pushed
the
feat/svm-map-mode
branch
from
August 30, 2026 18:29
16bb53a to
5daba1a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Stage 8 of #772, closing its defect 6, stacked on #789 → #788 → #787 → #786 →
#785 → #784 → #779 — review 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:
out at the wrong size — off by 1.76 for twips.
it.
MetaMapModeAction::ExecutecallsOutputDevice::SetMapMode, which replacesthe map mode except where the new unit is
MapUnit::MapRelative, andImplMapRes::CalcMapResolutionsays exactly how it composes then: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.
MapPixeland the two font units are device-dependent, and ametafile 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
MAPMODEaction at all, and the onerelative map mode among them (in
odr-public/svm/table-1.svm) composes toexactly 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
ImplMapResfrom source. The one number theexport 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.