Repository navigation
fix(docx): name the drawing a panel painted beside it covers - #989
Merged
Merged
Conversation
A panel is written as a shaded cell, and a cell's fill belongs to the text layer, which Word and LibreOffice both paint over everything drawn behind that layer. A drawing standing beside such a panel — on a layer above it, not inside it — is therefore covered wherever the two boxes meet, and a layer stack's z-index does not lift it clear. The export said nothing about it. Measured at 300 dpi in Word 16.0.20527 and LibreOffice 24.2 on the one document of the fidelity corpus that holds the case, an 18pt icon laid over a card's corner: the engine's PDF draws 4308 pixels of the icon's own ink, Word's draws none and LibreOffice's draws none — not one pixel anywhere on the page, the icon's whole box coming back the card's colour in both. With the card unpainted, the one difference, Word draws every pixel the engine does. The export now records each shape it queues behind the text with the box it is drawn in, and each panel whose cell it gives a fill with the box the layout gave it, and names the drawings a panel beside them covers as APPROXIMATED, with the path of the drawing and of the panel. The panels are taken where the fill is written rather than read off the node tree: whether a section, a container or a row that paints becomes a cell with shading is decided as it is written, so a panel bearing borders alone writes no shading and is not named, and a row written as a panel is. Each record carries its section, since a section's pages are counted from its own first and a page's height is its section's, and the pass runs once at the end of the export. A shape is asked for its own place in the stack rather than the flag of the call: a badge holding its initials is handed over already in front with that flag saying otherwise. DocxNeighbourFillGuardTest holds the corpus to the one drawing that is known. It judges by the boxes the layout gave the nodes, not by behindDoc, which is set on drawings the reader sees perfectly well — the same fixture with its panel unpainted keeps its anchor's behindDoc="1" while showing all 3237 pixels of its shape in Word. It computes the overlaps itself and requires the export to name nothing it does not find; what it finds and the export does not is held in a list of its own. It names the four painted panels the layout breaks across pages, which no overlap can be judged against, and treats a note that says a shape was drawn and that it cannot classify as a failure rather than a silence. No document of the corpus changes: the note states what the bytes already were.
…ot named A drawing was named once per path. Each section's paths are built from its own roots, so two sections of one preset give their drawing a single path, and the second section's loss went unnamed. The key is the section and the path, and the note says which section the loss is in, as a document of several sections says of its other notes. Three claims did not hold. A timeline's rail was said to be beyond judging for want of a path, but a rail is drawn under the path its layout pass carries and is judged like any other drawing. A panel composed in an authored table cell is given no box by the layout and so is never recorded, and a cell's paint the table draws itself never passes the queue the drawings are recorded in: both are real edges of what the export sees and neither was written down. The recipe, the capability matrix, the CHANGELOG and the guard now say what is named and what is not, and the javadoc of the pass lists all five. The guard asked that everything the export names be found by its own scan, and called that structural. It is not: the export records a rail, which its note calls a line, and a picture drawn over a badge, neither of which the scan recognises. It now checks each drawing the export names on its own geometry, and holds the ones it cannot place — a rail has no node of the graph to take a box from — apart from a real disagreement.
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.
Why
A panel is written as a shaded cell, and a cell's fill belongs to the text layer. Word and
LibreOffice both paint that layer over everything drawn behind it — including a drawing that
belongs to a neighbour of the panel rather than to the panel itself. So a drawing on a layer
above a painted layer beside it is covered wherever the two boxes meet, and a layer stack's
z-index does not lift it clear. The export said nothing about this at all, while it does name the
case where a drawing stands inside a painted panel.
Measured at 300 dpi in Word 16.0.20527 and LibreOffice 24.2, on the one document of the
71-document fidelity corpus that holds the case — an 18pt icon laid over a card's top right
corner through a layer stack:
The icon is not dimmed or shifted; it is not drawn. With the card unpainted — the one difference
— Word draws every pixel the engine does.
What changed
The export names the loss.
DocxSemanticBackendrecords each shape it queues behind the textwith the box it is drawn in (
rememberDrawnBehind) and each panel whose cell it gives a fill withthe box the layout gave it (
rememberShadedPanel), and at the end of an export names the drawingsa panel standing beside them covers (
nameTheDrawingsAPaintedPanelCovers), asAPPROXIMATED,with the path of the drawing and of the panel. A drawing standing inside the panel is skipped:
that is the export's own case, which already puts such a drawing in front wherever it frames no
text, and has a note of its own.
Three decisions in that are worth their lines:
container or a row that paints becomes a cell with shading is decided as it is written — a
row's paint goes unwritten where its panel cannot hold it, a container's where it is a band's
layer or a stack's column — so the tree cannot be asked. Reading it would also have named a
panel bearing borders alone, which writes no
w:shdat all and covers nothing, and missed apainted row, which reaches the same cell through
writePaintedRow→writePanelPiece.layoutandcanvasHeightareper-section fields, a section's pages are counted from its own first, and the pass runs once at
the end of the export, so each record carries its section — as
PanelOverPagesalready does forthe panels it cuts. Without it the pass would judge every section's drawings against the last
section's panels, in the last section's page frame. One note per drawing per section, too:
each section's paths are built from its own roots, so two sections of one preset give their
drawing a single path, and a note per path would name the first section's loss and hide the
rest. The note says which section it is in.
badge holding its initials is handed to the queue already in front and queued with that flag
saying otherwise, so trusting the flag would have named a badge over a painted neighbour as
hidden under it when the reader sees it plainly. One record per shape, too, rather than one box
round a node's shapes: a box drawn as its top border alone is a line, and a box round it would
be the whole empty rectangle.
A guard over the corpus.
DocxNeighbourFillGuardTestholds the corpus to the one drawing thatis known. It judges by the boxes the layout gave the nodes and not by
behindDoc: that attributeis set on drawings the reader sees perfectly well, and the same fixture with its panel unpainted
keeps its anchor's
behindDoc="1"while showing all 3237 pixels of its shape in Word. Geometryis what decides, so geometry is what it computes.
It fails closed, on positive signals:
must come back lying under some painted panel it does not stand inside. Where it cannot place
the drawing at all — a timeline's rail is drawn under the layout pass's path, which no node of
the graph carries — it says so in a list of its own rather than calling it a disagreement. The
other direction is a real difference rather than an identity, a node's box being able to exceed
its ink, so what the guard finds and the export does not is held in a list too. Both empty
today;
fails here rather than reporting a clean corpus;
silence. Four notes in the export begin that way and only two are a drawing's; an unknown one
would narrow the scan, and a drawing the scan stops seeing is one it can no longer find under
a panel;
be judged against a box that belongs to one page of several, and a change that breaks a fifth
panel across pages is seen here instead of quietly shrinking what is judged;
container, row or shape container as a candidate panel. Reading it narrowly would make the
guard blind where the export sees; reading it broadly can only add candidates, and each lands
in the held list rather than passing unnoticed.
What neither the export nor the guard judges is written out in both, and in the recipe, rather
than left to be discovered — these are the edges of what is checked, not invariants: a panel
composed in an authored table cell, which the layout gives no box of its own; a table cell's own
shading, which belongs to a cell and not to a node; a cell's paint the table draws itself, which
never passes the export's queue; and the second panel over a drawing lying over two, one note
naming one panel.
Verification
./mvnw -B -ntp test -pl :graph-compose-render-docxand./mvnw -B -ntp test -f qa/pom.xml.Eight unit tests in
DocxDrawingUnderANeighboursFillTest: a shape over a painted neighbour isnamed; one over an unpainted neighbour is not; one over a neighbour bearing borders alone is not;
one beside a panel it does not reach is not; one inside a painted panel and behind its text is
not — that fixture first asserts the drawing does go behind the text, so that it reaches the test
of which box holds which rather than passing because the panel put it in front; a badge handed
over already in front is not; across a document of three sections each section's drawing is named
against its own section's panel; and two sections of one preset, whose drawings share a path, are
each named with their section.
Ten sabotages, each breaking one rule and requiring the test that claims it to fail: the overlap
geometry, the test of which box holds which, the shape's own place in the stack, the fill at the
recording point, the section a record is matched within, the note-per-section key, the guard's
note classifier, the guard's own geometry, the ledger, and the list of panels broken across
pages. Each caught on a run of exactly one test, every file byte-identical afterwards against the
copy taken in that same run.
The corpus is unchanged — no document and no part differs, so neither editor is asked to draw
anything differently; the report gains the one note. The full reactor gate passes.