@pixldocs/canvas-renderer 0.5.19 → 0.5.20
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 +93 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +93 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11844,6 +11844,83 @@ 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 getFabricCanvasFromContainer(container) {
|
|
11866
|
+
const registry2 = window.__fabricCanvasRegistry;
|
|
11867
|
+
if (registry2 instanceof Map) {
|
|
11868
|
+
for (const entry of registry2.values()) {
|
|
11869
|
+
const canvas = (entry == null ? void 0 : entry.canvas) || entry;
|
|
11870
|
+
if (!canvas || typeof canvas.toSVG !== "function") continue;
|
|
11871
|
+
const el = canvas.lowerCanvasEl || canvas.upperCanvasEl;
|
|
11872
|
+
if (el && container.contains(el)) return canvas;
|
|
11873
|
+
}
|
|
11874
|
+
}
|
|
11875
|
+
return null;
|
|
11876
|
+
}
|
|
11877
|
+
function stabilizeFabricTextObjects(fabricInstance) {
|
|
11878
|
+
var _a, _b, _c;
|
|
11879
|
+
if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|
|
11880
|
+
clearFabricCharCache();
|
|
11881
|
+
clearMeasurementCache();
|
|
11882
|
+
const walk = (obj) => {
|
|
11883
|
+
var _a2, _b2, _c2, _d;
|
|
11884
|
+
if (!obj) return;
|
|
11885
|
+
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
11886
|
+
if (children.length) children.forEach(walk);
|
|
11887
|
+
const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (TEXT_TYPES.has(obj.type) || obj.isEditing !== void 0);
|
|
11888
|
+
if (!isTextObject) return;
|
|
11889
|
+
const saved = { width: obj.width, scaleX: obj.scaleX, scaleY: obj.scaleY };
|
|
11890
|
+
const reset = () => {
|
|
11891
|
+
var _a3;
|
|
11892
|
+
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
11893
|
+
obj.__charBounds = [];
|
|
11894
|
+
obj.__lineWidths = [];
|
|
11895
|
+
obj.__lineHeights = [];
|
|
11896
|
+
obj.__graphemeLines = [];
|
|
11897
|
+
obj._textLines = [];
|
|
11898
|
+
obj.textLines = [];
|
|
11899
|
+
obj._styleMap = null;
|
|
11900
|
+
obj.styleMap = null;
|
|
11901
|
+
obj.dirty = true;
|
|
11902
|
+
};
|
|
11903
|
+
reset();
|
|
11904
|
+
obj.initDimensions();
|
|
11905
|
+
if (saved.width != null) {
|
|
11906
|
+
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11907
|
+
reset();
|
|
11908
|
+
obj.initDimensions();
|
|
11909
|
+
(_b2 = obj.set) == null ? void 0 : _b2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11910
|
+
}
|
|
11911
|
+
if (obj.underline || obj.linethrough) {
|
|
11912
|
+
const lineWidths = Array.isArray(obj.__lineWidths) ? obj.__lineWidths : [];
|
|
11913
|
+
obj.__lineWidths = getTextLines(obj).map((line, index) => Math.max(lineWidths[index] || 0, measureLineWidth(obj, line)));
|
|
11914
|
+
}
|
|
11915
|
+
obj.dirty = true;
|
|
11916
|
+
(_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
|
|
11917
|
+
(_d = obj.setCoords) == null ? void 0 : _d.call(obj);
|
|
11918
|
+
};
|
|
11919
|
+
fabricInstance.getObjects().forEach(walk);
|
|
11920
|
+
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
11921
|
+
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
11922
|
+
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
11923
|
+
}
|
|
11847
11924
|
function PixldocsPreview(props) {
|
|
11848
11925
|
const {
|
|
11849
11926
|
pageIndex = 0,
|
|
@@ -11940,6 +12017,13 @@ function PixldocsPreview(props) {
|
|
|
11940
12017
|
() => `${pageIndex}-${fontsReadyVersion}-${stabilizationPass}`,
|
|
11941
12018
|
[pageIndex, fontsReadyVersion, stabilizationPass]
|
|
11942
12019
|
);
|
|
12020
|
+
const previewWrapRef = useCallback((node) => {
|
|
12021
|
+
if (!node || !config) return;
|
|
12022
|
+
requestAnimationFrame(() => {
|
|
12023
|
+
const fabricCanvas = getFabricCanvasFromContainer(node);
|
|
12024
|
+
if (fabricCanvas) stabilizeFabricTextObjects(fabricCanvas);
|
|
12025
|
+
});
|
|
12026
|
+
}, [config, previewKey]);
|
|
11943
12027
|
useEffect(() => {
|
|
11944
12028
|
if (isResolveMode) return;
|
|
11945
12029
|
if (!config) {
|
|
@@ -11970,7 +12054,7 @@ function PixldocsPreview(props) {
|
|
|
11970
12054
|
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
12055
|
}
|
|
11972
12056
|
return /* @__PURE__ */ jsxs("div", { className, style: { ...style, position: "relative" }, children: [
|
|
11973
|
-
/* @__PURE__ */ jsx("div", { style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsx(
|
|
12057
|
+
/* @__PURE__ */ jsx("div", { ref: previewWrapRef, style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsx(
|
|
11974
12058
|
PreviewCanvas,
|
|
11975
12059
|
{
|
|
11976
12060
|
config,
|
|
@@ -12702,16 +12786,7 @@ class PixldocsRenderer {
|
|
|
12702
12786
|
* using the global __fabricCanvasRegistry (set by PageCanvas).
|
|
12703
12787
|
*/
|
|
12704
12788
|
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;
|
|
12789
|
+
return getFabricCanvasFromContainer(container);
|
|
12715
12790
|
}
|
|
12716
12791
|
async waitForStableTextMetrics(container, config) {
|
|
12717
12792
|
if (typeof document !== "undefined") {
|
|
@@ -12725,59 +12800,7 @@ class PixldocsRenderer {
|
|
|
12725
12800
|
clearFabricCharCache();
|
|
12726
12801
|
clearMeasurementCache();
|
|
12727
12802
|
};
|
|
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
|
-
};
|
|
12803
|
+
const reflowTextboxes = () => stabilizeFabricTextObjects(fabricInstance);
|
|
12781
12804
|
clearTextMetricCaches();
|
|
12782
12805
|
await waitForPaint();
|
|
12783
12806
|
reflowTextboxes();
|
|
@@ -14533,6 +14556,12 @@ function convertTextDecorationsToLines(svg) {
|
|
|
14533
14556
|
} else {
|
|
14534
14557
|
textWidth = content.length * fontSize * 0.6;
|
|
14535
14558
|
}
|
|
14559
|
+
if (typeof tspan.getComputedTextLength === "function") {
|
|
14560
|
+
try {
|
|
14561
|
+
textWidth = Math.max(textWidth, tspan.getComputedTextLength());
|
|
14562
|
+
} catch {
|
|
14563
|
+
}
|
|
14564
|
+
}
|
|
14536
14565
|
const underlineY = y + fontSize * 0.15;
|
|
14537
14566
|
const thickness = Math.max(0.5, fontSize * 0.066667);
|
|
14538
14567
|
const line = doc.createElementNS("http://www.w3.org/2000/svg", "line");
|