@pixldocs/canvas-renderer 0.5.99 → 0.5.101
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 +96 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +96 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5085,10 +5085,14 @@ function applyTextBackground(obj, cfg) {
|
|
|
5085
5085
|
const blur = Math.max(0, Number(shadow.blur ?? 0));
|
|
5086
5086
|
const shadowColor = String(shadow.color);
|
|
5087
5087
|
const pad = Math.max(16, Math.ceil(blur * 4) + Math.ceil(Math.max(Math.abs(ox), Math.abs(oy))) + 8);
|
|
5088
|
-
const
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5088
|
+
const shadowBounds = unionBounds([
|
|
5089
|
+
...rects,
|
|
5090
|
+
computeTextVisualBounds(this, w, h)
|
|
5091
|
+
]);
|
|
5092
|
+
const bx = shadowBounds.x - pad;
|
|
5093
|
+
const by = shadowBounds.y - pad;
|
|
5094
|
+
const bw = shadowBounds.w + pad * 2;
|
|
5095
|
+
const bh = shadowBounds.h + pad * 2;
|
|
5092
5096
|
const dataAttrs = `data-blur="${blur.toFixed(3)}" data-ox="${ox.toFixed(3)}" data-oy="${oy.toFixed(3)}" data-bx="${bx.toFixed(3)}" data-by="${by.toFixed(3)}" data-bw="${bw.toFixed(3)}" data-bh="${bh.toFixed(3)}" data-color="${escapeXmlAttr(shadowColor)}"`;
|
|
5093
5097
|
const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
|
|
5094
5098
|
if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
|
|
@@ -5150,6 +5154,51 @@ function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
|
|
|
5150
5154
|
parts.push("Z");
|
|
5151
5155
|
return parts.join(" ");
|
|
5152
5156
|
}
|
|
5157
|
+
function unionBounds(bounds) {
|
|
5158
|
+
const valid = bounds.filter((b) => Number.isFinite(b.x) && Number.isFinite(b.y) && b.w > 0 && b.h > 0);
|
|
5159
|
+
if (valid.length === 0) return { x: 0, y: 0, w: 1, h: 1 };
|
|
5160
|
+
const minX = Math.min(...valid.map((b) => b.x));
|
|
5161
|
+
const minY = Math.min(...valid.map((b) => b.y));
|
|
5162
|
+
const maxX = Math.max(...valid.map((b) => b.x + b.w));
|
|
5163
|
+
const maxY = Math.max(...valid.map((b) => b.y + b.h));
|
|
5164
|
+
return { x: minX, y: minY, w: Math.max(1, maxX - minX), h: Math.max(1, maxY - minY) };
|
|
5165
|
+
}
|
|
5166
|
+
function computeTextVisualBounds(obj, w, h) {
|
|
5167
|
+
var _a;
|
|
5168
|
+
const lines = (obj == null ? void 0 : obj._textLines) ?? [];
|
|
5169
|
+
if (!lines || lines.length === 0) return { x: -w / 2, y: -h / 2, w, h };
|
|
5170
|
+
const rects = [];
|
|
5171
|
+
const halfW = w / 2;
|
|
5172
|
+
const halfH = h / 2;
|
|
5173
|
+
const lineHeightRatio = Math.max(0.01, Number((obj == null ? void 0 : obj.lineHeight) ?? 1) || 1);
|
|
5174
|
+
let cursorY = -halfH;
|
|
5175
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5176
|
+
let lineW = 0;
|
|
5177
|
+
let lineLeft = 0;
|
|
5178
|
+
let lineH = 0;
|
|
5179
|
+
try {
|
|
5180
|
+
lineW = obj.getLineWidth(i) || 0;
|
|
5181
|
+
} catch {
|
|
5182
|
+
lineW = 0;
|
|
5183
|
+
}
|
|
5184
|
+
try {
|
|
5185
|
+
lineLeft = ((_a = obj._getLineLeftOffset) == null ? void 0 : _a.call(obj, i)) ?? 0;
|
|
5186
|
+
} catch {
|
|
5187
|
+
lineLeft = 0;
|
|
5188
|
+
}
|
|
5189
|
+
try {
|
|
5190
|
+
lineH = obj.getHeightOfLine(i) || 0;
|
|
5191
|
+
} catch {
|
|
5192
|
+
lineH = 0;
|
|
5193
|
+
}
|
|
5194
|
+
const rawSlotH = i === lines.length - 1 ? lineH / lineHeightRatio : lineH;
|
|
5195
|
+
const usedH = cursorY + halfH;
|
|
5196
|
+
const slotH = Math.max(0, Math.min(rawSlotH, h - usedH));
|
|
5197
|
+
if (lineW > 0 && slotH > 0) rects.push({ x: -halfW + lineLeft, y: cursorY, w: lineW, h: slotH });
|
|
5198
|
+
cursorY += slotH;
|
|
5199
|
+
}
|
|
5200
|
+
return unionBounds(rects.length > 0 ? rects : [{ x: -w / 2, y: -h / 2, w, h }]);
|
|
5201
|
+
}
|
|
5153
5202
|
function computeBgRects(obj, w, h, pT, pR, pB, pL, fit) {
|
|
5154
5203
|
var _a;
|
|
5155
5204
|
if (!fit) {
|
|
@@ -13103,7 +13152,7 @@ function PixldocsPreview(props) {
|
|
|
13103
13152
|
!canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
|
|
13104
13153
|
] });
|
|
13105
13154
|
}
|
|
13106
|
-
const PACKAGE_VERSION = "0.5.
|
|
13155
|
+
const PACKAGE_VERSION = "0.5.101";
|
|
13107
13156
|
const roundParityValue = (value) => {
|
|
13108
13157
|
if (typeof value !== "number") return value;
|
|
13109
13158
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -15233,6 +15282,33 @@ const GRADIENT_ATTRS_LINEAR = ["x1", "y1", "x2", "y2", "gradientUnits", "gradien
|
|
|
15233
15282
|
const GRADIENT_ATTRS_RADIAL = ["cx", "cy", "r", "fx", "fy", "gradientUnits", "gradientTransform", "spreadMethod"];
|
|
15234
15283
|
const URL_GRADIENT_RE = /^\s*url\s*\(\s*(['"]?)([^)]+?)\1\s*\)/i;
|
|
15235
15284
|
const SHADOW_RASTER_ALPHA_COMPENSATION = 0.84;
|
|
15285
|
+
function collectFontSpecsFromMarkup(markup) {
|
|
15286
|
+
const specs = /* @__PURE__ */ new Set();
|
|
15287
|
+
const re = /<(?:text|tspan)\b[^>]*>/gi;
|
|
15288
|
+
let match;
|
|
15289
|
+
while ((match = re.exec(markup)) !== null) {
|
|
15290
|
+
const tag = match[0];
|
|
15291
|
+
const get = (attr) => {
|
|
15292
|
+
const m = tag.match(new RegExp(`\\s${attr}\\s*=\\s*"([^"]*)"`, "i"));
|
|
15293
|
+
if (m) return m[1];
|
|
15294
|
+
const styleM = tag.match(/\sstyle\s*=\s*"([^"]*)"/i);
|
|
15295
|
+
if (styleM) {
|
|
15296
|
+
const sm = styleM[1].match(new RegExp(`${attr}\\s*:\\s*([^;]+)`, "i"));
|
|
15297
|
+
if (sm) return sm[1].trim();
|
|
15298
|
+
}
|
|
15299
|
+
return null;
|
|
15300
|
+
};
|
|
15301
|
+
const family = (get("font-family") || "").split(",")[0].replace(/['"]/g, "").trim();
|
|
15302
|
+
if (!family) continue;
|
|
15303
|
+
const weight = get("font-weight") || "400";
|
|
15304
|
+
const style = get("font-style") || "normal";
|
|
15305
|
+
const size = get("font-size") || "16px";
|
|
15306
|
+
const sizePx = /[a-z%]/i.test(size) ? size : `${size}px`;
|
|
15307
|
+
const famSpec = /\s/.test(family) ? `"${family}"` : family;
|
|
15308
|
+
specs.add(`${style} ${weight} ${sizePx} ${famSpec}`);
|
|
15309
|
+
}
|
|
15310
|
+
return Array.from(specs);
|
|
15311
|
+
}
|
|
15236
15312
|
function parseColor(color) {
|
|
15237
15313
|
if (!color) return null;
|
|
15238
15314
|
const raw = color.trim().toLowerCase();
|
|
@@ -16268,7 +16344,7 @@ async function convertSvgTextDecorationsToLinesString(svgStr) {
|
|
|
16268
16344
|
}
|
|
16269
16345
|
}
|
|
16270
16346
|
async function rasterizeShadowMarkers(svg) {
|
|
16271
|
-
var _a, _b, _c, _d, _e;
|
|
16347
|
+
var _a, _b, _c, _d, _e, _f;
|
|
16272
16348
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
16273
16349
|
const markers = Array.from(svg.querySelectorAll("g.__pdShadowRaster"));
|
|
16274
16350
|
if (markers.length === 0) return;
|
|
@@ -16293,6 +16369,17 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
16293
16369
|
continue;
|
|
16294
16370
|
}
|
|
16295
16371
|
const innerXml = Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
|
|
16372
|
+
try {
|
|
16373
|
+
const fontSpecs = collectFontSpecsFromMarkup(innerXml);
|
|
16374
|
+
if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
|
|
16375
|
+
await Promise.all(
|
|
16376
|
+
fontSpecs.map(
|
|
16377
|
+
(spec) => document.fonts.load(spec).catch(() => void 0)
|
|
16378
|
+
)
|
|
16379
|
+
);
|
|
16380
|
+
}
|
|
16381
|
+
} catch {
|
|
16382
|
+
}
|
|
16296
16383
|
const scale = 2;
|
|
16297
16384
|
const pxW = Math.min(4096, Math.max(8, Math.ceil(bw * scale)));
|
|
16298
16385
|
const pxH = Math.min(4096, Math.max(8, Math.ceil(bh * scale)));
|
|
@@ -16302,7 +16389,7 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
16302
16389
|
const miniSvg = `<svg xmlns="${SVG_NS}" xmlns:xlink="${XLINK_NS}" width="${pxW}" height="${pxH}" viewBox="${bx} ${by} ${bw} ${bh}">${styleBlock}<defs><filter id="${filterId}" filterUnits="userSpaceOnUse" x="${bx}" y="${by}" width="${bw}" height="${bh}" color-interpolation-filters="sRGB"><feOffset dx="${ox}" dy="${oy}" result="offsetShadow" /><feGaussianBlur in="offsetShadow" stdDeviation="${stdDev}" /></filter></defs><g filter="url(#${filterId})">${innerXml}</g></svg>`;
|
|
16303
16390
|
const dataUrl = await rasterSvgToPngDataUrl(miniSvg, pxW, pxH);
|
|
16304
16391
|
if (!dataUrl) {
|
|
16305
|
-
(
|
|
16392
|
+
(_d = marker.parentNode) == null ? void 0 : _d.removeChild(marker);
|
|
16306
16393
|
continue;
|
|
16307
16394
|
}
|
|
16308
16395
|
const img = svg.ownerDocument.createElementNS(SVG_NS, "image");
|
|
@@ -16314,11 +16401,11 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
16314
16401
|
img.setAttribute("preserveAspectRatio", "none");
|
|
16315
16402
|
img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
|
|
16316
16403
|
img.setAttribute("href", dataUrl);
|
|
16317
|
-
(
|
|
16404
|
+
(_e = marker.parentNode) == null ? void 0 : _e.replaceChild(img, marker);
|
|
16318
16405
|
} catch (e) {
|
|
16319
16406
|
console.warn("[pdf-export] rasterizeShadowMarkers failed for one marker:", e);
|
|
16320
16407
|
try {
|
|
16321
|
-
(
|
|
16408
|
+
(_f = marker.parentNode) == null ? void 0 : _f.removeChild(marker);
|
|
16322
16409
|
} catch {
|
|
16323
16410
|
}
|
|
16324
16411
|
}
|