feat(drawing): improve drawing-object fidelity for picture fills, connectors, charts, and anchored media (SD-2998 and SD-2996)#3779
Open
luccas-harbour wants to merge 30 commits into
Conversation
…d images The table indent is already applied to the cell x offset, so subtracting it again shifted column-relative anchored images left by the indent amount.
Replace the local computePhysicalAnchorX helper with the shared resolveAnchoredGraphicX from @superdoc/contracts, and apply X normalization to all page-relative fragments rather than only those with a page-relative horizontal anchor. Column-relative drawings in headers and footers now resolve their X against the physical page margins, fixing media placed at the wrong horizontal position.
Add support for horizontal (bar-direction) bar charts in the DOM chart renderer, including category labels, in-bar percentage data labels, gap width, value-axis ticks/gridlines, and axis deletion. - Parse c:gapWidth, c:dLbls (showVal/numFmt/dLblPos), axis c:delete, and c:majorGridlines from chart XML, merging series-level data labels over chart-level ones per field - Extend ChartModel/ChartSeriesData/ChartAxisConfig contracts with gapWidth, dataLabels, deleted, and majorGridlines - Add a dedicated horizontal bar layout and renderers, reversing category order for top-down display and formatting percentage labels - Account for the new elements in the SVG element-budget estimate
…ends Render the chart-area outline from c:spPr (honoring a:noFill to disable it), gate value-axis gridlines behind the OOXML majorGridlines flag instead of always drawing them, and lay out right-positioned legends as a column beside bar charts that reserve right-edge space. Thread per-chart padding through the bar layout so the right legend gets dedicated room, and align gridline color with the axis color.
Drop the connector re-export barrel in shared/svg-utils.js and have ShapeGroupView, VectorShapeView, and the svg-utils test import connector helpers directly from @superdoc/preset-geometry/connectors.
normalizeFragmentsForRegion was rewriting column-relative X whenever the vertical anchor was page-relative, conflating the two independent OOXML axes. Switch the gate to the horizontal anchor (hRelativeFrom === 'page') so column-relative X stays content-local and the painter applies the physical page margin exactly once. Update tests to cover both axes independently.
bead74d to
0c8ce93
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bead74d2d7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Summary
This branch is a broad fidelity pass on DrawingML objects so they render against their parent surface (page, column, table, header/footer) the way Word does. It adds support for picture-filled vector shapes, real connector geometry, horizontal bar charts with data labels, and corrects the positioning of page-relative anchored media in headers/footers and column-anchored images inside tables. Along the way it consolidates the line-end/marker and connector rendering logic into a single shared module so the three shape renderers (DomPainter,
VectorShapeView,ShapeGroupView) stop duplicating it.Picture fills for vector shapes
DrawingML shapes can carry an image fill (
a:blipFill) instead of a solid/gradient color. Previously these rendered as a flat#ccccccplaceholder.PictureFilltype in@superdoc/contracts({ type: 'picture', src, rId?, extension? }) added to theFillColorunion.vector-shape-helpers.js) now resolvesa:blipFill→r:embedrelationship → media target path, returning aPictureFillfor both standalone shapes and shape-group children.extractFillColortakes converterparamsto do the relationship lookup.src(media path → data URI) for vector shapes, textbox shapes, and shape-group vector children, mirroring how image runs are hydrated.normalizeFillColor/isPictureFillrecognize the new shape.<pattern>/<image>clipped to the shape geometry (with a CSSbackground-imagefallback path in DomPainter). SharedcreatePictureFillPatternhelper added insvg-utils.js.Connector shapes
packages/preset-geometry/connectors.js(+.d.ts) provides bent/curved connector path geometry (bentConnector2-5,curvedConnector2-5),isConnectorPresetShape, non-scaling-stroke helpers, and the canonical line-end marker/shape builders.VectorShapeView, andShapeGroupViewnow import connector geometry and line-end rendering from this module instead of each carrying their own copy. The per-classcreateLineEndMarker/createLineEndShapeimplementations are deleted.vector-effect: non-scaling-strokeand a stretched/preserveAspectRatio="none"viewBox so strokes stay uniform when the shape box is non-square. Non-connector preset SVGs get their viewBox expanded by half the stroke width so centered strokes aren't clipped (container overflow switched fromhiddentovisible).line,straightConnector1) are now centered on the thin axis instead of drawn corner-to-corner.head→marker-start,tail→marker-end).Charts
barDirection === 'bar') are now rendered with their own layout: category labels on the value axis, value ticks/gridlines along the bottom, gap-width-aware bar sizing, and category ordering that respects axis orientation.c:dLbls) are parsed at both chart and series level (merged, withc:deletehonored) and painted for vertical and horizontal bars, withoutEnd/inEnd/inBase/center placement and percentage/number formatting fromc:numFmt.gapWidth, axisdeletedandmajorGridlinesflags,chartAreaBorder(chart-space outline), and a right-side legend layout. Gridlines are only drawn when the source declares major gridlines; the SVG element-budget estimate accounts for the new elements.versionSignaturenow hashes the fullchartDataandfillColorobjects (via a newvalueVersionhelper) and includes chart geometry rotation/flips, so chart and fill changes actually bust the cache.Anchored media positioning
resolveAnchoredGraphicX. Horizontal and vertical anchors are treated independently (each branch re-checks its own axis), and column-relative X is left content-local so the painter adds the page margin exactly once. Painter comments updated to match.tableIndentparameter threaded throughrenderTableFragment→renderTableRow→renderTableCell. Column (ST_RelFromH) anchors already encodewp:posOffsetrelative to the column, so subtractingtblIndin addition to the cell's local x shifted table images left. Now only the cell's local x is subtracted.Shared media-target normalization
Extracted the duplicated
normalizeTargetPath(relationship target →word/media/...media key) into a singlehelpers/media-target-path.js, now used by the watermark importer, image-node encoder, and vector-shape helpers.Tests
New/expanded unit coverage for connectors, picture-fill hydration and rendering, horizontal bar charts and data labels, header/footer X normalization, table-indent removal, media-target-path, and the
versionSignatureobject hashing.