@pixldocs/canvas-renderer 0.3.23 → 0.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +55 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +55 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11038,6 +11038,14 @@ class PixldocsRenderer {
|
|
|
11038
11038
|
});
|
|
11039
11039
|
}
|
|
11040
11040
|
// ─── Internal: capture SVG from a rendered Fabric canvas ───
|
|
11041
|
+
//
|
|
11042
|
+
// APPROACH: Use the SAME PreviewCanvas that renders perfect PNGs, then call
|
|
11043
|
+
// Fabric's toSVG() on that canvas. This guarantees 100% layout parity —
|
|
11044
|
+
// the SVG is a vector snapshot of exactly what's on screen.
|
|
11045
|
+
//
|
|
11046
|
+
// The trick: before calling toSVG(), we temporarily neutralize the viewport
|
|
11047
|
+
// transform and retina scaling so Fabric emits coordinates in logical
|
|
11048
|
+
// document space (e.g. 612x792) instead of inflated pixel space.
|
|
11041
11049
|
captureSvgViaPreviewCanvas(config, pageIndex, canvasWidth, canvasHeight) {
|
|
11042
11050
|
return new Promise(async (resolve, reject) => {
|
|
11043
11051
|
const { PreviewCanvas: PreviewCanvas2 } = await Promise.resolve().then(() => PreviewCanvas$1);
|
|
@@ -11073,17 +11081,25 @@ class PixldocsRenderer {
|
|
|
11073
11081
|
}
|
|
11074
11082
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
11075
11083
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
11076
|
-
const
|
|
11077
|
-
const
|
|
11084
|
+
const prevRetina = fabricInstance.enableRetinaScaling;
|
|
11085
|
+
const prevWidth = fabricInstance.width;
|
|
11086
|
+
const prevHeight = fabricInstance.height;
|
|
11087
|
+
fabricInstance.viewportTransform = [1, 0, 0, 1, 0, 0];
|
|
11088
|
+
fabricInstance.svgViewportTransformation = false;
|
|
11089
|
+
fabricInstance.enableRetinaScaling = false;
|
|
11078
11090
|
fabricInstance.setDimensions(
|
|
11079
11091
|
{ width: canvasWidth, height: canvasHeight },
|
|
11080
11092
|
{ cssOnly: false, backstoreOnly: false }
|
|
11081
11093
|
);
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11094
|
+
const rawSvgString = fabricInstance.toSVG();
|
|
11095
|
+
const svgString = this.normalizeSvgDimensions(
|
|
11096
|
+
rawSvgString,
|
|
11097
|
+
canvasWidth,
|
|
11098
|
+
canvasHeight
|
|
11099
|
+
);
|
|
11100
|
+
fabricInstance.enableRetinaScaling = prevRetina;
|
|
11085
11101
|
fabricInstance.setDimensions(
|
|
11086
|
-
{ width:
|
|
11102
|
+
{ width: prevWidth, height: prevHeight },
|
|
11087
11103
|
{ cssOnly: false, backstoreOnly: false }
|
|
11088
11104
|
);
|
|
11089
11105
|
if (prevVPT) fabricInstance.viewportTransform = prevVPT;
|
|
@@ -11111,7 +11127,7 @@ class PixldocsRenderer {
|
|
|
11111
11127
|
config,
|
|
11112
11128
|
pageIndex,
|
|
11113
11129
|
zoom: 1,
|
|
11114
|
-
// 1:1 — no scaling for SVG capture
|
|
11130
|
+
// 1:1 — no UI scaling for SVG capture
|
|
11115
11131
|
absoluteZoom: true,
|
|
11116
11132
|
onReady
|
|
11117
11133
|
})
|
|
@@ -11126,22 +11142,43 @@ class PixldocsRenderer {
|
|
|
11126
11142
|
* the SVG coordinate system matches the intended page size exactly.
|
|
11127
11143
|
*/
|
|
11128
11144
|
normalizeSvgDimensions(svg, targetWidth, targetHeight) {
|
|
11129
|
-
const widthMatch = svg.match(/<svg[^>]*\bwidth="([^"]+)"/);
|
|
11130
|
-
const heightMatch = svg.match(/<svg[^>]*\bheight="([^"]+)"/);
|
|
11145
|
+
const widthMatch = svg.match(/<svg[^>]*\bwidth="([^"]+)"/i);
|
|
11146
|
+
const heightMatch = svg.match(/<svg[^>]*\bheight="([^"]+)"/i);
|
|
11131
11147
|
const svgWidth = widthMatch ? parseFloat(widthMatch[1]) : targetWidth;
|
|
11132
11148
|
const svgHeight = heightMatch ? parseFloat(heightMatch[1]) : targetHeight;
|
|
11133
|
-
if (Math.abs(svgWidth - targetWidth) < 1 && Math.abs(svgHeight - targetHeight) < 1) {
|
|
11134
|
-
return svg;
|
|
11135
|
-
}
|
|
11136
11149
|
console.log(
|
|
11137
|
-
`[canvas-renderer][svg-normalize]
|
|
11150
|
+
`[canvas-renderer][svg-normalize] root ${svgWidth}x${svgHeight} → page ${targetWidth}x${targetHeight}`
|
|
11138
11151
|
);
|
|
11139
|
-
let normalized = svg
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11152
|
+
let normalized = svg;
|
|
11153
|
+
if (/\bwidth="[^"]*"/i.test(normalized)) {
|
|
11154
|
+
normalized = normalized.replace(/(<svg[^>]*\b)width="[^"]*"/i, `$1width="${targetWidth}"`);
|
|
11155
|
+
} else {
|
|
11156
|
+
normalized = normalized.replace(/<svg\b/i, `<svg width="${targetWidth}"`);
|
|
11157
|
+
}
|
|
11158
|
+
if (/\bheight="[^"]*"/i.test(normalized)) {
|
|
11159
|
+
normalized = normalized.replace(/(<svg[^>]*\b)height="[^"]*"/i, `$1height="${targetHeight}"`);
|
|
11143
11160
|
} else {
|
|
11144
|
-
normalized = normalized.replace(/<svg\b
|
|
11161
|
+
normalized = normalized.replace(/<svg\b/i, `<svg height="${targetHeight}"`);
|
|
11162
|
+
}
|
|
11163
|
+
const viewBox = `0 0 ${targetWidth} ${targetHeight}`;
|
|
11164
|
+
if (/\bviewBox="[^"]*"/i.test(normalized)) {
|
|
11165
|
+
normalized = normalized.replace(/viewBox="[^"]*"/i, `viewBox="${viewBox}"`);
|
|
11166
|
+
} else {
|
|
11167
|
+
normalized = normalized.replace(/<svg\b/i, `<svg viewBox="${viewBox}"`);
|
|
11168
|
+
}
|
|
11169
|
+
if (/\bx="[^"]*"/i.test(normalized)) {
|
|
11170
|
+
normalized = normalized.replace(/(<svg[^>]*\b)x="[^"]*"/i, '$1x="0"');
|
|
11171
|
+
} else {
|
|
11172
|
+
normalized = normalized.replace(/<svg\b/i, '<svg x="0"');
|
|
11173
|
+
}
|
|
11174
|
+
if (/\by="[^"]*"/i.test(normalized)) {
|
|
11175
|
+
normalized = normalized.replace(/(<svg[^>]*\b)y="[^"]*"/i, '$1y="0"');
|
|
11176
|
+
} else {
|
|
11177
|
+
normalized = normalized.replace(/<svg\b/i, '<svg y="0"');
|
|
11178
|
+
}
|
|
11179
|
+
normalized = normalized.replace(/\bpreserveAspectRatio="[^"]*"/i, 'preserveAspectRatio="none"');
|
|
11180
|
+
if (!/\bpreserveAspectRatio="[^"]*"/i.test(normalized)) {
|
|
11181
|
+
normalized = normalized.replace(/<svg\b/i, '<svg preserveAspectRatio="none"');
|
|
11145
11182
|
}
|
|
11146
11183
|
return normalized;
|
|
11147
11184
|
}
|