Skip to content

feat(docx): write a barcode as a picture that scans - #736

Merged
DemchaAV merged 1 commit into
2.5-devfrom
feature/docx-barcode
Sep 23, 2026
Merged

DemchaAV merged 1 commit into
2.5-devfrom
feature/docx-barcode

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

The DOCX export dropped a BarcodeNode along with the geometry-only nodes. A receipt, a ticket or a shipping label lost the code a reader scans, and the report showed it as DROPPED.

What changed

  • A barcode is a picture of the symbol (writeBarcode, new DocxBarcodePictures).
    • Matrix. The same ZXing matrix the PDF and PPTX backends draw, through BarcodeMatrices, so the three backends cannot encode one symbol differently.
    • Pixels. One pixel per cell, which gives at least two per point and 200 a side. The two colours are written with their alpha, into a 1-bit indexed PNG.
    • Placement. Written at the node's size. The margin is the space around its paragraph, and its anchor is a bookmark, via blockAnchorOf, so a page reference to it resolves.
  • The PNG is encoded in memory. It goes through ImageWriter on a MemoryCacheImageOutputStream. ImageIO.write to a stream caches through a temp file by default, and that per-barcode cost is the spike the PDF backend's barcodes were measured paying before they became vectors. On the probe, a 90pt QR code is 445 bytes.
  • A barcode drawn in two transparent colours is still written. It holds its space on the page, and an anchor on it needs somewhere to land.
  • The picture's description is the barcode's data (docPr/@descr), for a screen reader.
  • Report. APPROXIMATED, because the data is part of the picture and cannot be edited in Word. The note also says when a link or a transform on the barcode is not carried.
  • graph-compose-render-docx now takes graph-compose-render-pdf at compile scope, as graph-compose-render-pptx does, to reach BarcodeMatrices. It was at runtime scope, and only on the unreleased 2.5 line; 2.4.x declared it at test scope. The v2.5.0 Packaging entry is amended rather than contradicted.
  • Docs. Updated:
    • the capability matrix row and the drawing-nodes paragraph;
    • the recipe's "What is skipped", which also said shapes were skipped silently although the report names each one;
    • troubleshooting.md and ROADMAP.md, which listed barcodes as dropped;
    • render-docx/README.md, the backend's class Javadoc and package-map.md, which said runtime scope;
    • the CHANGELOG.

Verification

In an editor. A 90pt QR code and a 180×45pt Code 128 in a brand colour, each with a top margin, between two paragraphs. Rendered by the engine and converted with LibreOffice, both land at the page's size and position, in their colours.

Tests. ./mvnw -B -ntp test -pl :graph-compose-render-docx → 365 run, 0 failures. New DocxBarcodeTest (11):

  • decoding: a QR code and a Code 128 decode back to their data with ZXing's reader;
  • size and pixels: the picture is 80×80pt; it is exactly the BarcodeMatrices matrix, one pixel a cell, checked cell by cell;
  • colour: the foreground colour is used, and a translucent background keeps its alpha;
  • picture metadata: the description is the data;
  • placement: the anchor is a bookmark, and the margin is w:before;
  • transparency: a transparent barcode still holds its size and its anchor;
  • report: APPROXIMATED with nothing DROPPED, and a link is named as not carried.

Each of these was sabotaged and fails its test:

  • dropping the description;
  • dropping the link note;
  • restoring the transparent early return;
  • dropping the alpha.

Gate. Full reactor gate (clean verify over core, render-pdf/docx/pptx, templates, testing, qa, coverage) → BUILD SUCCESS (qa 1788 green). Examples after install: 93 green; no committed preview moved.

Notes

  • Composed table cells. Inside a composed cell, the engine hands the barcode the cell's inner width and stretches it to that width. The DOCX keeps the node's size.
  • Horizontal padding is not applied, as for images.
  • Page zones. A barcode in a page zone is still skipped, as zones take paragraphs, fields and spacers only.
  • Release smoke is stale. scripts/release-smoke/s8-core-render-docx still states that render-docx declares render-pdf at test scope. That has been stale since build(render-docx): bring the PDF backend so the DOCX module works on its own #722 and is release tooling. Its explicit render-pdf dependency still resolves.

Lane: shared-engine (render-docx) + build (render-docx pom). No public API change.

The export dropped a BarcodeNode with the geometry-only nodes, so a
receipt, a ticket or a shipping label lost the code a reader scans. It is
now a PNG of the same ZXing matrix the PDF and PPTX backends draw,
through BarcodeMatrices: one pixel a cell, in the symbol's two colours
with their alpha, encoded in memory, at the node's size, with its margin
as the space around it, its anchor as a bookmark and its data as the
picture's description. A barcode in two transparent colours still holds
its space. The report calls it APPROXIMATED, since the data is part of
the picture, and names a link or a transform on it as not carried.

To reach BarcodeMatrices, render-docx takes render-pdf at compile scope,
as render-pptx does. The README, class Javadoc, package map, the v2.5.0
Packaging entry, troubleshooting and ROADMAP are brought in line.
@DemchaAV
DemchaAV merged commit d5e5c44 into 2.5-dev Sep 23, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the feature/docx-barcode branch September 23, 2026 21:02
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