diff --git a/docs/assets/css-corpus/IRONPRESS-LICENSE.txt b/docs/assets/css-corpus/IRONPRESS-LICENSE.txt new file mode 100644 index 0000000..d669694 --- /dev/null +++ b/docs/assets/css-corpus/IRONPRESS-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Gaston Gouron + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/docs/assets/css-corpus/border-image-diff.png b/docs/assets/css-corpus/border-image-diff.png new file mode 100644 index 0000000..c4e53ee Binary files /dev/null and b/docs/assets/css-corpus/border-image-diff.png differ diff --git a/docs/assets/css-corpus/border-image-fullbleed.png b/docs/assets/css-corpus/border-image-fullbleed.png new file mode 100644 index 0000000..404fd36 Binary files /dev/null and b/docs/assets/css-corpus/border-image-fullbleed.png differ diff --git a/docs/assets/css-corpus/border-image-reference.png b/docs/assets/css-corpus/border-image-reference.png new file mode 100644 index 0000000..2520d96 Binary files /dev/null and b/docs/assets/css-corpus/border-image-reference.png differ diff --git a/docs/assets/css-corpus/source.json b/docs/assets/css-corpus/source.json new file mode 100644 index 0000000..3e1140e --- /dev/null +++ b/docs/assets/css-corpus/source.json @@ -0,0 +1,28 @@ +{ + "invocation_id": "fullbleed-9b0f068e265449c2a9484991523f0c08", + "upstream_commit": "0d1e53b6d8174d0a5059a8696c24e62759381f6d", + "fixture": "backgrounds-borders/border-image-intrinsic-overlap-reset", + "status": "FAIL", + "files": { + "border-image-reference.png": { + "archive_path": "ironpress-evidence/current/refs/backgrounds-borders/border-image-intrinsic-overlap-reset.png", + "bytes": 28496, + "sha256": "0f8b1428ad0a7ec91d648cac854a0d686ebe0dd8bf286193e65727e18e3be385" + }, + "border-image-fullbleed.png": { + "archive_path": "ironpress-evidence/current/out/backgrounds-borders/border-image-intrinsic-overlap-reset.png", + "bytes": 26136, + "sha256": "9a67042575f6537e147c2323db430a14dfcc87b23b4ba004482943366833c6a3" + }, + "border-image-diff.png": { + "archive_path": "ironpress-evidence/current/reports/backgrounds-borders/border-image-intrinsic-overlap-reset.diff.png", + "bytes": 25789, + "sha256": "b948b975185afcb6ea0cc75d42bf1ce0ab99aa4b3a0dbc092ae5945f2c4143f4" + }, + "IRONPRESS-LICENSE.txt": { + "archive_path": "ironpress-evidence/current/IRONPRESS-LICENSE", + "bytes": 1070, + "sha256": "e731e091fab0feefcdc452579b51c7e7dc9072a708586daceddd21b4ac8894b6" + } + } +} diff --git a/docs/css-coverage.md b/docs/css-coverage.md index 2db358c..846bb74 100644 --- a/docs/css-coverage.md +++ b/docs/css-coverage.md @@ -1,5 +1,7 @@ # CSS Coverage and Parity Status +For the published Fullbleed 2.5.14 wheel, see the [complete 1,662-fixture CSS comparison](guides/css-corpus.md), including verdicts, the upstream gate outcome, PDFs, images, and file hashes. The imported reference below preserves earlier version-specific reports. + Reference imported from [v2.5.8](https://github.com/fullbleed-engine/fullbleed-official/blob/f9f1b56f550237c924254ccd7718cc852a06692d/docs/css-coverage.md). Check the installed runtime for your exact version. This document is the canonical statement of validated CSS coverage for Fullbleed's deterministic HTML/CSS-to-PDF engine. diff --git a/docs/guides/css-corpus.md b/docs/guides/css-corpus.md new file mode 100644 index 0000000..888378a --- /dev/null +++ b/docs/guides/css-corpus.md @@ -0,0 +1,195 @@ +--- +title: Fullbleed CSS comparison on the IronPress corpus +description: Inspect a maintainer-run comparison of Fullbleed 2.5.14 against 1,662 pinned independent HTML/CSS fixtures and their committed reference PDFs. +--- +# Inspect the CSS comparison + +This maintainer-run comparison tests the published Fullbleed 2.5.14 Linux wheel +against the independent IronPress corpus at commit +`0d1e53b6d8174d0a5059a8696c24e62759381f6d`. The corpus contains 1,662 HTML/CSS +fixtures and committed reference PDFs: 1,629 Chromium references and 33 +WeasyPrint references. Each fixture identifies its reference renderer; this run uses those pinned PDFs rather than launching current browser +or WeasyPrint versions. + +**The full run completed with 1,616 PASS, 27 FAIL, and 19 REFERENCE-DISPUTED across 1,662 fixtures.** + +| Verdict | Fixtures | +| --- | ---: | +| PASS | 1,616 | +| FAIL | 27 | +| REFERENCE-DISPUTED | 19 | +| Total | 1,662 | + +**The unchanged upstream gate failed (process exit 101).** It records 27 failing fixtures. Its 799 gate entries also include changes relative to the committed IronPress baseline; several entries can refer to the same fixture. All reasons remain in the raw report. + +The upstream gate also checks its committed IronPress raster baseline. A changed +fingerprint can fail that regression check even when the fixture's visibility +verdict is PASS. The run retains this gate result and its reasons alongside the +fixture verdicts; the baseline is not rewritten for this comparison. + +## Read the verdicts + +- **PASS** means the fixture meets the upstream visibility policy. It does not + necessarily mean pixel-identical output. Raw differences remain in the report. +- **FAIL** means the candidate failed the comparator or a rendering check. +- **REFERENCE-DISPUTED** means a visible mismatch against a reference tagged + as disputed by the upstream corpus. These verdicts are not counted as passes. + The reference dispute does not establish that Fullbleed renders the case correctly. + +The corpus marks 20 reference PDFs as disputed. In this run, 19 receive REFERENCE-DISPUTED verdicts and one receives PASS under the unchanged comparator. That PASS does not resolve the reference's standards dispute. The raw JSON retains both the verdict and reference metadata. The passing tagged case is `interactions/interactions-cartesian-effects-x-paged-media`. + +The same Poppler `pdftoppm` 24.08.0 executable rasterizes both sides. The upstream +comparator compares the same coordinates without moving one image to fit the +other. Fixtures, reference PDFs, comparator source, and thresholds are unchanged; +the integration substitutes Fullbleed at the candidate-renderer boundary. + +Of the 1,662 fixtures, **858 have identical candidate and reference page raster fingerprints**. This compares raster dimensions and RGBA hashes, not PDF file bytes. The remaining cases retain their measured differences and individual verdicts in the report. + +## Inspect the evidence + +[Download the complete evidence (50.0 MiB)](https://github.com/fullbleed-engine/fullbleed-official/releases/download/v2.5.14/fullbleed-2.5.14-ironpress-corpus-evidence.zip) · [Structured summary](https://github.com/fullbleed-engine/fullbleed-official/releases/download/v2.5.14/fullbleed-2.5.14-css-corpus-summary.json) · [SHA-256 checksums](https://github.com/fullbleed-engine/fullbleed-official/releases/download/v2.5.14/fullbleed-2.5.14-css-corpus-SHA256SUMS.txt) + +Open `ironpress-evidence/current/reports/index.html` in the downloaded archive. +The unmodified upstream report retains IronPress headings and candidate labels; +**its candidate is Fullbleed in this run**. The archive includes candidate PDFs, +reference and candidate page images, difference images, and the raw JSON report. +The upstream MIT license and font notices are retained. Category pages initially show non-PASS cases; select **show PASS** to inspect passing fixtures too. + +`fullbleed-run.json` identifies the wheel, runner, adapter, patch, dependency lock, +container image, and invocation. `manifest.json` records each exported file's +SHA-256. The wrapper verifies a complete, unique fixture inventory and checks +that the JSON, Markdown, and HTML identify the same invocation and JSON digest. + +### Example of a failing fixture + +`border-image-intrinsic-overlap-reset` fails with a 4.30% above-floor page difference. The repeated border-image patterns differ visibly. These are unmodified page images from the retained report; open an image to inspect it at full size. + +
+ +
+[![Chromium reference for the border-image overlap and sizing fixture](../assets/css-corpus/border-image-reference.png)](../assets/css-corpus/border-image-reference.png) +
Chromium reference
+
+ +
+[![Fullbleed 2.5.14 output for the same border-image fixture](../assets/css-corpus/border-image-fullbleed.png)](../assets/css-corpus/border-image-fullbleed.png) +
Fullbleed 2.5.14
+
+ +
+[![Above-floor difference image highlighting changed border-image patterns](../assets/css-corpus/border-image-diff.png)](../assets/css-corpus/border-image-diff.png) +
Above-floor difference
+
+ +
+ +[Image provenance and hashes](../assets/css-corpus/source.json) | [Upstream MIT license](../assets/css-corpus/IRONPRESS-LICENSE.txt). All failing cases remain in the complete report. + +## Results by category + +These are fixture counts within this corpus, not percentages of the CSS standard. + +| Category | PASS | FAIL | Disputed | +| --- | ---: | ---: | ---: | +| backgrounds-borders | 79 | 3 | 1 | +| backgrounds-gradients | 46 | 0 | 0 | +| block-box-model | 59 | 0 | 0 | +| clip-mask | 52 | 0 | 0 | +| color-opacity | 49 | 0 | 1 | +| effects | 57 | 2 | 1 | +| filters | 46 | 0 | 1 | +| flexbox | 132 | 0 | 0 | +| fonts-advanced | 25 | 1 | 0 | +| generated-content | 33 | 2 | 2 | +| grid | 95 | 1 | 0 | +| images-replaced | 38 | 0 | 0 | +| inline-text | 45 | 4 | 1 | +| interactions | 350 | 10 | 2 | +| lists-counters | 34 | 0 | 1 | +| multicol | 36 | 0 | 0 | +| overflow-clipping | 17 | 0 | 3 | +| paged-media | 82 | 2 | 3 | +| positioning | 22 | 0 | 0 | +| probes | 6 | 0 | 0 | +| selectors-cascade | 60 | 0 | 0 | +| tables | 97 | 1 | 1 | +| text-advanced | 47 | 0 | 2 | +| transforms | 44 | 0 | 0 | +| typography | 23 | 1 | 0 | +| units-values | 42 | 0 | 0 | + +### Failing fixtures + +The raw report retains the diagnostics and images for every failing case. + +- `backgrounds-borders/border-image-fill-axis-repeat` +- `backgrounds-borders/border-image-intrinsic-overlap-reset` +- `backgrounds-borders/border-image-round-horizontal` +- `effects/r2-box-shadow-inset-blur-radius` +- `effects/r2-text-shadow-blur-rgba` +- `fonts-advanced/fonts-advanced-font-synthesis-none` +- `generated-content/generated-content-counters-nested` +- `generated-content/generated-content-no-open-quote-depth` +- `grid/grid-display-contents-fragmentation-text-survival` +- `inline-text/inline-text-decoration-subpoint-geometry` +- `inline-text/inline-text-text-decoration-line-through` +- `inline-text/inline-text-text-decoration-overline` +- `inline-text/inline-text-text-decoration-color` +- `interactions/interactions-grid-fragmentation-svg-background-single-owner` +- `interactions/interactions-cartesian-backgrounds-borders-x-effects` +- `interactions/interactions-cartesian-block-box-model-x-clip-mask` +- `interactions/interactions-cartesian-clip-mask-x-clip-mask` +- `interactions/interactions-cartesian-clip-mask-x-tables` +- `interactions/interactions-cartesian-effects-x-overflow-clipping` +- `interactions/interactions-cartesian-effects-x-page-margins` +- `interactions/interactions-cartesian-filters-x-overflow-clipping` +- `interactions/interactions-cartesian-filters-x-paged-media` +- `interactions/interactions-transforms-x-font-synthesis-matrix` +- `paged-media/paged-footnote-counter-reset` +- `paged-media/paged-string-set-attr-start` +- `tables/tables-cell-generated-before-child` +- `typography/typography-font-weight-bold` + +### Disputed references + +These 19 REFERENCE-DISPUTED verdicts remain separate from the PASS count. The reference metadata is retained for every fixture, including the passing tagged case described above. + +- `background-clip-text-gradient` +- `opacity-text-glyph-group` +- `r2-mix-blend-mode-text-difference` +- `r2-filter-url-feturbulence-displacement` +- `generated-content-first-letter-dropcap` +- `generated-content-string-set-running-header` +- `inline-text-text-decoration-wavy` +- `interactions-cartesian-page-margins-x-paged-media` +- `interactions-cartesian-positioning-x-tables` +- `lists-counters-marker-side-match-parent` +- `overflow-axis-visible-hidden-coercion` +- `overflow-scroll-print-clip` +- `overflow-x-y-separate` +- `footnote-float` +- `paged-footnote-display-compact` +- `paged-footnote-max-height` +- `tables-colspan-max-clamp` +- `text-advanced-text-combine-upright-center` +- `text-advanced-text-combine-upright-digits` + +## Reproduce and evaluate your templates + +Follow the [pinned runner instructions](https://github.com/fullbleed-engine/fullbleed-official/blob/0136a801a4bfe4a0cab5379abdb17fbaa336b4b2/docs/ironpress-parity.md) to use the same corpus and adapter. The [retained workflow run](https://github.com/fullbleed-engine/fullbleed-official/actions/runs/37700802857) records the execution. + +The corpus runner needs Git, Docker, and a compatible Linux wheel. Its container +and external rasterizer are test tools, not dependencies of `pip install +fullbleed`. Cargo dependencies are locked separately for the upstream comparator. +The actual container image is recorded; operating-system packages are not a +byte-identical environment lock. + +A corpus result applies to its exact engine version, fixtures, fonts, references, +and comparison policy. It does not establish support for all CSS, browser +JavaScript, arbitrary web pages, accessibility standards, or PDF conformance. +Test your own templates with representative data and explicit fonts. + +See [CSS coverage](../css-coverage.md) for documented behavior and boundaries, or +the [shared-document renderer comparison](renderer-comparison.md) for PDFs and +timings from three application-style documents. That comparison uses different +versions and inputs; its results should not be combined with this corpus run. diff --git a/docs/guides/renderer-comparison.md b/docs/guides/renderer-comparison.md index c1406cd..c040027 100644 --- a/docs/guides/renderer-comparison.md +++ b/docs/guides/renderer-comparison.md @@ -97,3 +97,5 @@ python3 -m venv .venv The merged revision above contains the same benchmark files as the measured source snapshot. Run on a local Linux filesystem. `--smoke` exercises output qualification with fewer samples; it is not a performance run. Use the [recorded package list](../assets/renderer-comparison/packages.txt) as pip constraints (`-c packages.txt`) to reproduce the measured transitive dependency versions. Change the fixtures and acceptance contract to match your real documents before treating a result as relevant to your application. Fullbleed is a print-document engine. A browser remains relevant when JavaScript or live browser layout is the required behavior. See [Choose a PDF library](comparison.md) for that distinction and [CSS coverage](../css-coverage.md) for Fullbleed's tested surface. Three small fixtures on one host cannot establish a universal speed, memory, or quality ranking. + +For a larger fixture-level comparison, inspect the [Fullbleed 2.5.14 results on the pinned IronPress CSS corpus](css-corpus.md). That run uses different inputs, versions, and comparison rules; evaluate its results separately from these application-document timings. diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index f88601a..26d42e2 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -12,6 +12,13 @@ .md-typeset .facts { padding: .8rem 1rem; border-top: 1px solid #718c8135; border-bottom: 1px solid #718c8135; font-size: .78rem; } .md-typeset .grid.cards > ul > li { border-radius: .4rem; } .md-typeset .gallery img { border: 1px solid #b3c5be; max-height: 23rem; object-fit: contain; object-position: top; } +.md-typeset .corpus-images { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; } +.md-typeset .corpus-images figure { margin: 0; min-width: 0; } +.md-typeset .corpus-images img { display: block; width: 100%; border: 1px solid #718c8140; } +.md-typeset .corpus-images figcaption { font-size: .7rem; } +@media (max-width: 600px) { + .md-typeset .corpus-images { grid-template-columns: 1fr; } +} .md-typeset .md-button { border-radius: .25rem; padding: .55em 1.15em; margin: .25rem .2rem .25rem 0; } .md-typeset .showcase-entry { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 1.7rem; align-items: center; margin: 1.2rem 0 3rem; } .md-typeset .showcase-entry figure { margin: 0; } diff --git a/mkdocs.yml b/mkdocs.yml index ecb8795..c11ada9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -113,6 +113,7 @@ nav: - Evaluate: - Choose a PDF library: guides/comparison.md - Three-renderer comparison: guides/renderer-comparison.md + - CSS corpus evidence: guides/css-corpus.md - PDF file size: guides/pdf-size.md - Performance evidence: guides/performance.md - FAQ: faq.md diff --git a/tools/sync_reference.py b/tools/sync_reference.py index c3f8733..7eeeac4 100644 --- a/tools/sync_reference.py +++ b/tools/sync_reference.py @@ -22,6 +22,12 @@ # Site-only context must survive later imports of the historical report. INTRODUCTIONS = { + "css-coverage.md": ( + "For the published Fullbleed 2.5.14 wheel, see the " + "[complete 1,662-fixture CSS comparison](guides/css-corpus.md), including " + "verdicts, the upstream gate outcome, PDFs, images, and file hashes. " + "The imported reference below preserves earlier version-specific reports." + ), "guides/performance.md": ( "For a current shared-input example, see the " "[Fullbleed 2.5.6, WeasyPrint, and Chromium comparison](renderer-comparison.md). "