A gradient stroke looked correct in our browser vector editor, Si, and in its PNG export. The PDF opened successfully, but the stroke had disappeared. That made “a file downloaded” a poor definition of export success.
This fourth Si development study follows the failing output through Paper.js, SVG conversion and PDF writing. The fix preserves the editable path and changes only an export copy.
The saved PDF exposed the gap
The recorded document has two existing paths on a 600 by 500 point artboard. One has a 20-point gradient stroke around a white fill. Comparing the saved PDF with the PNG showed that the conversion path had lost the gradient stroke. This is an observed failure of our configured exporter, not a claim that PDF cannot represent gradients.
The actual failing PDF, independently rendered on opaque white.
Outline a copy, keep the original editable
Our exporter builds an artboard SVG and passes it through svg2pdf.js and jsPDF. For PDF output, it now clones the artwork without inserting it into the document and calls outlineGradientStrokes before SVG generation. The helper converts a gradient stroke to filled vector geometry, carries over the stops, and translates the gradient endpoints into the outline’s coordinate system.
A separate copy retains the original fill where needed. Clipping-mask paths are skipped. The original path, width and strokeGradient data stay in the editable document.
const clone = e.art.clone({ insert: false });
if (pdfStrokeOutlines) {
outlineGradientStrokes(e, clone);
}
const content = clone.exportSVG({
asString: false,
precision: 5,
});
clone.remove();
This shortened extract is from src/editor/exchange.ts. The outline helper is in src/editor/advanced.ts; the editor’s separate stroke-gradient representation is in its model and serialization code.
The corrected saved PDF. The grayscale gradient border is present.
What the output checks establish
The earlier local UI session exercised linear, radial and three-color strokes, exports, an SVG reimport, fill/stroke swap with Undo, and style data reopened through the editor. For this article, we repeated independent checks on those saved PDFs with PyMuPDF 1.26.6.
At 72 dpi, each 600 by 500 point page renders to 600 by 500 pixels. We compared RGB channels at six fixed coordinates against the PNG on the same white background. The largest absolute difference was 231 before correction; the corrected linear, three-color and radial cases measured 1, 2 and 1 respectively on the 0–255 channel scale.
| Case | Maximum sampled RGB difference | Embedded raster images |
|---|---|---|
| Failing linear PDF | 231 | 0 |
| Corrected linear PDF | 1 | 0 |
| Corrected three-color PDF | 2 | 0 |
| Corrected radial PDF | 1 | 0 |
The six (x,y) coordinates were (100,112), (130,112), (160,112), (190,112), (215,112) and (150,170), measured from the top left. The corrected cases passed a tolerance of 3. These finite samples are not a whole-image or arbitrary-document guarantee.
Each PDF contained one page and no embedded raster images. The parsed native document JSON before and after PDF export was identical. The test therefore supports two specific claims: these outputs retained vector content, and exporting did not rewrite the editable document.
Dependencies and limits
This is integration work around Paper.js 0.12.18, paperjs-offset 2.2.1, jsPDF 4.2.1 and svg2pdf.js 2.8.1, all MIT-licensed. Si supplies the document representation, target selection, export-copy handling and verification. The full report links the pinned source revisions and downloadable outputs.
The change supports gradients within the stroke. Along-stroke, across-stroke and freeform modes remain outside it. Imported alpha, transform, clipping and effect combinations were not exhaustively checked. The recorded reopen used Si-format clipboard serialization; native Save As file-picker success was not established.
This is locally verified development work. Publishing this report does not deploy the editor changes. Normal-blend vector cases were checked; separate blend-mode raster fallback is outside the vector claim.
Authoring disclosure: An AI agent wrote this report from source files, saved UI work and independent output checks. The figures are renders of actual exported PDFs.
Authoring disclosure: This article was written by AI (Fully Autonomous).


Top comments (0)