@pixldocs/canvas-renderer 0.5.19 → 0.5.21
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 +99 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +99 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11844,6 +11844,89 @@ async function ensureFontsForResolvedConfig(config) {
|
|
|
11844
11844
|
});
|
|
11845
11845
|
}
|
|
11846
11846
|
}
|
|
11847
|
+
const TEXT_TYPES = /* @__PURE__ */ new Set(["textbox", "text", "i-text"]);
|
|
11848
|
+
function getTextLines(obj) {
|
|
11849
|
+
const lines = Array.isArray(obj.textLines) && obj.textLines.length ? obj.textLines : String(obj.text || "").split("\n");
|
|
11850
|
+
return lines.map((line) => Array.isArray(line) ? line.join("") : String(line ?? ""));
|
|
11851
|
+
}
|
|
11852
|
+
function measureLineWidth(obj, line) {
|
|
11853
|
+
if (typeof document === "undefined") return 0;
|
|
11854
|
+
const canvas = document.createElement("canvas");
|
|
11855
|
+
const ctx = canvas.getContext("2d");
|
|
11856
|
+
if (!ctx) return 0;
|
|
11857
|
+
const fontStyle = obj.fontStyle || "normal";
|
|
11858
|
+
const fontWeight = obj.fontWeight || 400;
|
|
11859
|
+
const fontSize = obj.fontSize || 16;
|
|
11860
|
+
const fontFamily = obj.fontFamily || "sans-serif";
|
|
11861
|
+
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
11862
|
+
const charSpacing = Number(obj.charSpacing || 0) / 1e3 * fontSize;
|
|
11863
|
+
return ctx.measureText(line).width + Math.max(0, line.length - 1) * charSpacing;
|
|
11864
|
+
}
|
|
11865
|
+
function getDecorationPadding(obj) {
|
|
11866
|
+
var _a;
|
|
11867
|
+
const strokeWidth = Number(obj.strokeWidth || 0);
|
|
11868
|
+
const shadowBlur = Number(((_a = obj.shadow) == null ? void 0 : _a.blur) || 0);
|
|
11869
|
+
return Math.max(0, strokeWidth) + Math.max(0, shadowBlur * 0.25);
|
|
11870
|
+
}
|
|
11871
|
+
function getFabricCanvasFromContainer(container) {
|
|
11872
|
+
const registry2 = window.__fabricCanvasRegistry;
|
|
11873
|
+
if (registry2 instanceof Map) {
|
|
11874
|
+
for (const entry of registry2.values()) {
|
|
11875
|
+
const canvas = (entry == null ? void 0 : entry.canvas) || entry;
|
|
11876
|
+
if (!canvas || typeof canvas.toSVG !== "function") continue;
|
|
11877
|
+
const el = canvas.lowerCanvasEl || canvas.upperCanvasEl;
|
|
11878
|
+
if (el && container.contains(el)) return canvas;
|
|
11879
|
+
}
|
|
11880
|
+
}
|
|
11881
|
+
return null;
|
|
11882
|
+
}
|
|
11883
|
+
function stabilizeFabricTextObjects(fabricInstance) {
|
|
11884
|
+
var _a, _b, _c;
|
|
11885
|
+
if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|
|
11886
|
+
clearFabricCharCache();
|
|
11887
|
+
clearMeasurementCache();
|
|
11888
|
+
const walk = (obj) => {
|
|
11889
|
+
var _a2, _b2, _c2, _d;
|
|
11890
|
+
if (!obj) return;
|
|
11891
|
+
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
11892
|
+
if (children.length) children.forEach(walk);
|
|
11893
|
+
const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (TEXT_TYPES.has(obj.type) || obj.isEditing !== void 0);
|
|
11894
|
+
if (!isTextObject) return;
|
|
11895
|
+
const saved = { width: obj.width, scaleX: obj.scaleX, scaleY: obj.scaleY };
|
|
11896
|
+
const reset = () => {
|
|
11897
|
+
var _a3;
|
|
11898
|
+
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
11899
|
+
obj.__charBounds = [];
|
|
11900
|
+
obj.__lineWidths = [];
|
|
11901
|
+
obj.__lineHeights = [];
|
|
11902
|
+
obj.__graphemeLines = [];
|
|
11903
|
+
obj._textLines = [];
|
|
11904
|
+
obj.textLines = [];
|
|
11905
|
+
obj._styleMap = null;
|
|
11906
|
+
obj.styleMap = null;
|
|
11907
|
+
obj.dirty = true;
|
|
11908
|
+
};
|
|
11909
|
+
reset();
|
|
11910
|
+
obj.initDimensions();
|
|
11911
|
+
if (saved.width != null) {
|
|
11912
|
+
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11913
|
+
reset();
|
|
11914
|
+
obj.initDimensions();
|
|
11915
|
+
(_b2 = obj.set) == null ? void 0 : _b2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11916
|
+
}
|
|
11917
|
+
if (obj.underline || obj.linethrough) {
|
|
11918
|
+
const decorationPadding = getDecorationPadding(obj);
|
|
11919
|
+
obj.__lineWidths = getTextLines(obj).map((line) => Math.max(0, measureLineWidth(obj, line) + decorationPadding));
|
|
11920
|
+
}
|
|
11921
|
+
obj.dirty = true;
|
|
11922
|
+
(_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
|
|
11923
|
+
(_d = obj.setCoords) == null ? void 0 : _d.call(obj);
|
|
11924
|
+
};
|
|
11925
|
+
fabricInstance.getObjects().forEach(walk);
|
|
11926
|
+
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
11927
|
+
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
11928
|
+
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
11929
|
+
}
|
|
11847
11930
|
function PixldocsPreview(props) {
|
|
11848
11931
|
const {
|
|
11849
11932
|
pageIndex = 0,
|
|
@@ -11940,6 +12023,13 @@ function PixldocsPreview(props) {
|
|
|
11940
12023
|
() => `${pageIndex}-${fontsReadyVersion}-${stabilizationPass}`,
|
|
11941
12024
|
[pageIndex, fontsReadyVersion, stabilizationPass]
|
|
11942
12025
|
);
|
|
12026
|
+
const previewWrapRef = useCallback((node) => {
|
|
12027
|
+
if (!node || !config) return;
|
|
12028
|
+
requestAnimationFrame(() => {
|
|
12029
|
+
const fabricCanvas = getFabricCanvasFromContainer(node);
|
|
12030
|
+
if (fabricCanvas) stabilizeFabricTextObjects(fabricCanvas);
|
|
12031
|
+
});
|
|
12032
|
+
}, [config, previewKey]);
|
|
11943
12033
|
useEffect(() => {
|
|
11944
12034
|
if (isResolveMode) return;
|
|
11945
12035
|
if (!config) {
|
|
@@ -11970,7 +12060,7 @@ function PixldocsPreview(props) {
|
|
|
11970
12060
|
return /* @__PURE__ */ jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
|
|
11971
12061
|
}
|
|
11972
12062
|
return /* @__PURE__ */ jsxs("div", { className, style: { ...style, position: "relative" }, children: [
|
|
11973
|
-
/* @__PURE__ */ jsx("div", { style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsx(
|
|
12063
|
+
/* @__PURE__ */ jsx("div", { ref: previewWrapRef, style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsx(
|
|
11974
12064
|
PreviewCanvas,
|
|
11975
12065
|
{
|
|
11976
12066
|
config,
|
|
@@ -12537,7 +12627,6 @@ class PixldocsRenderer {
|
|
|
12537
12627
|
pageIndex,
|
|
12538
12628
|
zoom: pixelRatio,
|
|
12539
12629
|
absoluteZoom: true,
|
|
12540
|
-
skipFontReadyWait: true,
|
|
12541
12630
|
onReady
|
|
12542
12631
|
})
|
|
12543
12632
|
);
|
|
@@ -12641,7 +12730,6 @@ class PixldocsRenderer {
|
|
|
12641
12730
|
zoom: 1,
|
|
12642
12731
|
// 1:1 — no UI scaling for SVG capture
|
|
12643
12732
|
absoluteZoom: true,
|
|
12644
|
-
skipFontReadyWait: true,
|
|
12645
12733
|
onReady
|
|
12646
12734
|
})
|
|
12647
12735
|
);
|
|
@@ -12702,16 +12790,7 @@ class PixldocsRenderer {
|
|
|
12702
12790
|
* using the global __fabricCanvasRegistry (set by PageCanvas).
|
|
12703
12791
|
*/
|
|
12704
12792
|
getFabricCanvasFromContainer(container) {
|
|
12705
|
-
|
|
12706
|
-
if (registry2 instanceof Map) {
|
|
12707
|
-
for (const entry of registry2.values()) {
|
|
12708
|
-
const canvas = (entry == null ? void 0 : entry.canvas) || entry;
|
|
12709
|
-
if (!canvas || typeof canvas.toSVG !== "function") continue;
|
|
12710
|
-
const el = canvas.lowerCanvasEl || canvas.upperCanvasEl;
|
|
12711
|
-
if (el && container.contains(el)) return canvas;
|
|
12712
|
-
}
|
|
12713
|
-
}
|
|
12714
|
-
return null;
|
|
12793
|
+
return getFabricCanvasFromContainer(container);
|
|
12715
12794
|
}
|
|
12716
12795
|
async waitForStableTextMetrics(container, config) {
|
|
12717
12796
|
if (typeof document !== "undefined") {
|
|
@@ -12725,59 +12804,7 @@ class PixldocsRenderer {
|
|
|
12725
12804
|
clearFabricCharCache();
|
|
12726
12805
|
clearMeasurementCache();
|
|
12727
12806
|
};
|
|
12728
|
-
const reflowTextboxes = () =>
|
|
12729
|
-
var _a, _b, _c;
|
|
12730
|
-
const walk = (obj) => {
|
|
12731
|
-
var _a2, _b2, _c2, _d;
|
|
12732
|
-
if (!obj) return;
|
|
12733
|
-
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
12734
|
-
if (children.length) children.forEach(walk);
|
|
12735
|
-
const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (obj.type === "textbox" || obj.type === "text" || obj.type === "i-text" || obj.isEditing !== void 0);
|
|
12736
|
-
if (isTextObject) {
|
|
12737
|
-
const saved = {
|
|
12738
|
-
width: obj.width,
|
|
12739
|
-
scaleX: obj.scaleX,
|
|
12740
|
-
scaleY: obj.scaleY
|
|
12741
|
-
};
|
|
12742
|
-
const resetTextboxLayoutInternals = () => {
|
|
12743
|
-
var _a3;
|
|
12744
|
-
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
12745
|
-
obj.__charBounds = [];
|
|
12746
|
-
obj.__lineWidths = [];
|
|
12747
|
-
obj.__lineHeights = [];
|
|
12748
|
-
obj.__graphemeLines = [];
|
|
12749
|
-
obj._textLines = [];
|
|
12750
|
-
obj.textLines = [];
|
|
12751
|
-
obj._styleMap = null;
|
|
12752
|
-
obj.styleMap = null;
|
|
12753
|
-
obj.dirty = true;
|
|
12754
|
-
};
|
|
12755
|
-
resetTextboxLayoutInternals();
|
|
12756
|
-
obj.initDimensions();
|
|
12757
|
-
if (saved.width != null) {
|
|
12758
|
-
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, {
|
|
12759
|
-
width: saved.width,
|
|
12760
|
-
scaleX: saved.scaleX,
|
|
12761
|
-
scaleY: saved.scaleY
|
|
12762
|
-
});
|
|
12763
|
-
resetTextboxLayoutInternals();
|
|
12764
|
-
obj.initDimensions();
|
|
12765
|
-
}
|
|
12766
|
-
(_b2 = obj.set) == null ? void 0 : _b2.call(obj, {
|
|
12767
|
-
width: saved.width,
|
|
12768
|
-
scaleX: saved.scaleX,
|
|
12769
|
-
scaleY: saved.scaleY,
|
|
12770
|
-
dirty: true
|
|
12771
|
-
});
|
|
12772
|
-
(_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
|
|
12773
|
-
(_d = obj.setCoords) == null ? void 0 : _d.call(obj);
|
|
12774
|
-
}
|
|
12775
|
-
};
|
|
12776
|
-
fabricInstance.getObjects().forEach(walk);
|
|
12777
|
-
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
12778
|
-
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
12779
|
-
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
12780
|
-
};
|
|
12807
|
+
const reflowTextboxes = () => stabilizeFabricTextObjects(fabricInstance);
|
|
12781
12808
|
clearTextMetricCaches();
|
|
12782
12809
|
await waitForPaint();
|
|
12783
12810
|
reflowTextboxes();
|
|
@@ -14533,6 +14560,12 @@ function convertTextDecorationsToLines(svg) {
|
|
|
14533
14560
|
} else {
|
|
14534
14561
|
textWidth = content.length * fontSize * 0.6;
|
|
14535
14562
|
}
|
|
14563
|
+
if (typeof tspan.getComputedTextLength === "function") {
|
|
14564
|
+
try {
|
|
14565
|
+
textWidth = Math.max(textWidth, tspan.getComputedTextLength());
|
|
14566
|
+
} catch {
|
|
14567
|
+
}
|
|
14568
|
+
}
|
|
14536
14569
|
const underlineY = y + fontSize * 0.15;
|
|
14537
14570
|
const thickness = Math.max(0.5, fontSize * 0.066667);
|
|
14538
14571
|
const line = doc.createElementNS("http://www.w3.org/2000/svg", "line");
|