@poe-platform/safe-bash 0.1.764 → 0.1.765
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/image-ast/index.browser.js +66 -22
- package/dist/image-ast/index.js +66 -22
- package/dist/pdf-ast/ast.d.ts +2 -0
- package/dist/pdf-ast/index.js +83 -33
- package/dist/safe-bash/command-chunks/{chunk-B7YLGJRF.js → chunk-DT4MFWV4.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-G3IIEU2N.js → chunk-KO4PXCNL.js} +66 -22
- package/dist/safe-bash/command-chunks/{chunk-RDPJGIQF.js → chunk-SVL6HYQL.js} +1 -1
- package/dist/safe-bash-command-ffmpeg/index.js +4261 -4238
- package/dist/safe-bash-command-imagemagick/index.js +2 -2
- package/dist/safe-bash-command-pandoc/command.js +3 -3
- package/dist/safe-bash-command-pandoc/index.js +3 -3
- package/dist/safe-bash-command-pdfimages/index.js +66 -22
- package/dist/safe-bash-command-pdfinfo/index.js +83 -33
- package/dist/safe-bash-command-pdftk/index.js +66 -22
- package/dist/safe-bash-command-pdftoppm/index.js +83 -33
- package/dist/safe-bash-command-pdftotext/index.js +66 -22
- package/dist/safe-bash-command-qpdf/index.js +66 -22
- package/dist/safe-bash-command-sips/index.js +2 -2
- package/dist/safe-bash-command-soffice/index.js +1 -1
- package/dist/safe-bash-command-ssconvert/index.js +120 -31
- package/dist/safe-bash-command-wkhtmltopdf/index.js +66 -22
- package/package.json +2 -2
- package/third-party/pdf-ast/THIRD_PARTY_NOTICES.md +10 -0
|
@@ -28,8 +28,8 @@ import {
|
|
|
28
28
|
thresholdImage,
|
|
29
29
|
tintImage,
|
|
30
30
|
trimImage
|
|
31
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
32
|
-
import "../safe-bash/command-chunks/chunk-
|
|
31
|
+
} from "../safe-bash/command-chunks/chunk-SVL6HYQL.js";
|
|
32
|
+
import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
|
|
33
33
|
import {
|
|
34
34
|
init_buffer
|
|
35
35
|
} from "../safe-bash/command-chunks/chunk-HX3SHTCE.js";
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
createPandocCommand,
|
|
3
3
|
createPandocCommands,
|
|
4
4
|
pandocCommands
|
|
5
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
5
|
+
} from "../safe-bash/command-chunks/chunk-DT4MFWV4.js";
|
|
6
6
|
import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
|
|
7
7
|
import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
|
|
8
|
-
import "../safe-bash/command-chunks/chunk-
|
|
9
|
-
import "../safe-bash/command-chunks/chunk-
|
|
8
|
+
import "../safe-bash/command-chunks/chunk-SVL6HYQL.js";
|
|
9
|
+
import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
|
|
10
10
|
import "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
|
|
11
11
|
import "../safe-bash/command-chunks/chunk-YGYOVXTO.js";
|
|
12
12
|
import "../safe-bash/command-chunks/chunk-I5GLTNVH.js";
|
|
@@ -21,11 +21,11 @@ import {
|
|
|
21
21
|
readDocument,
|
|
22
22
|
resolveConversionArgs,
|
|
23
23
|
writeDocument
|
|
24
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
24
|
+
} from "../safe-bash/command-chunks/chunk-DT4MFWV4.js";
|
|
25
25
|
import "../safe-bash/command-chunks/chunk-MKQVQMXO.js";
|
|
26
26
|
import "../safe-bash/command-chunks/chunk-RDV7UCYZ.js";
|
|
27
|
-
import "../safe-bash/command-chunks/chunk-
|
|
28
|
-
import "../safe-bash/command-chunks/chunk-
|
|
27
|
+
import "../safe-bash/command-chunks/chunk-SVL6HYQL.js";
|
|
28
|
+
import "../safe-bash/command-chunks/chunk-KO4PXCNL.js";
|
|
29
29
|
import {
|
|
30
30
|
createLuaFilterCapability
|
|
31
31
|
} from "../safe-bash/command-chunks/chunk-Y2KHC6TZ.js";
|
|
@@ -36049,11 +36049,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36049
36049
|
} else if (operator === "d") {
|
|
36050
36050
|
const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
|
|
36051
36051
|
if (arrNode) {
|
|
36052
|
-
const
|
|
36053
|
-
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
|
|
36052
|
+
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
|
|
36054
36053
|
const sum = nums.reduce((a, b) => a + b, 0);
|
|
36055
36054
|
st.dashArray = sum > 0 ? nums : void 0;
|
|
36056
|
-
st.dashPhase = num(1, 0)
|
|
36055
|
+
st.dashPhase = num(1, 0);
|
|
36057
36056
|
} else {
|
|
36058
36057
|
st.dashArray = void 0;
|
|
36059
36058
|
st.dashPhase = void 0;
|
|
@@ -36589,15 +36588,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36589
36588
|
break;
|
|
36590
36589
|
}
|
|
36591
36590
|
const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
|
|
36592
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36593
|
-
const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
|
|
36594
36591
|
emit({ kind: "path", value: {
|
|
36595
36592
|
segments: transformedSegments,
|
|
36596
36593
|
fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
|
|
36597
36594
|
fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
|
|
36598
36595
|
strokeColor: isStroke ? st.strokeColor : void 0,
|
|
36599
36596
|
strokeAlpha: isStroke ? st.strokeAlpha : void 0,
|
|
36600
|
-
strokeWidth:
|
|
36597
|
+
strokeWidth: st.strokeWidth,
|
|
36598
|
+
...isStroke ? { strokeMatrix: [...st.ctm] } : {},
|
|
36601
36599
|
...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
|
|
36602
36600
|
...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
|
|
36603
36601
|
...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
|
|
@@ -36785,14 +36783,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36785
36783
|
if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
|
|
36786
36784
|
const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
|
|
36787
36785
|
const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
|
|
36788
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36789
36786
|
const paint = {
|
|
36790
36787
|
segments: transformedGlyphSegs,
|
|
36791
36788
|
fillColor: isFillGlyph ? st.fillColor : void 0,
|
|
36792
36789
|
fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
|
|
36793
36790
|
strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
|
|
36794
36791
|
strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
|
|
36795
|
-
strokeWidth: isStrokeGlyph ? st.strokeWidth
|
|
36792
|
+
strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
|
|
36793
|
+
...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
|
|
36796
36794
|
fillRule: "nonzero",
|
|
36797
36795
|
...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
|
|
36798
36796
|
...st.clipRect ? { clipRect: [...st.clipRect] } : {}
|
|
@@ -40196,11 +40194,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
|
|
|
40196
40194
|
rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
|
|
40197
40195
|
rgba[idx + 3] = Math.round(outA * 255);
|
|
40198
40196
|
}
|
|
40199
|
-
function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
40197
|
+
function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
|
|
40200
40198
|
const paths = [];
|
|
40201
40199
|
let points = [];
|
|
40202
40200
|
let current = [0, 0];
|
|
40203
|
-
const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
|
|
40204
40201
|
for (const segment of segments) {
|
|
40205
40202
|
if (segment.kind === "move") {
|
|
40206
40203
|
if (points.length) paths.push({ points, closed: false });
|
|
@@ -40239,6 +40236,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
|
40239
40236
|
if (points.length) paths.push({ points, closed: false });
|
|
40240
40237
|
return paths;
|
|
40241
40238
|
}
|
|
40239
|
+
function inverseStrokeMatrix(matrix) {
|
|
40240
|
+
const [a, b, c, d, e, f] = matrix;
|
|
40241
|
+
const det = a * d - b * c;
|
|
40242
|
+
if (!Number.isFinite(det) || det === 0) return void 0;
|
|
40243
|
+
return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
|
|
40244
|
+
}
|
|
40245
|
+
function prepareStroke(path, scale) {
|
|
40246
|
+
const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
|
|
40247
|
+
const [a, b, c, d] = matrix;
|
|
40248
|
+
const area = Math.abs(a * d - b * c) * scale * scale;
|
|
40249
|
+
if (!(area > 0) || !Number.isFinite(area)) return void 0;
|
|
40250
|
+
const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
|
|
40251
|
+
let width = path.strokeWidth || 1;
|
|
40252
|
+
const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
|
|
40253
|
+
const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
|
|
40254
|
+
let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
|
|
40255
|
+
if (scaleX === scaleY) {
|
|
40256
|
+
width *= scaleX;
|
|
40257
|
+
} else {
|
|
40258
|
+
matrix[0] *= scaleX;
|
|
40259
|
+
matrix[1] *= scaleX;
|
|
40260
|
+
matrix[2] *= scaleY;
|
|
40261
|
+
matrix[3] *= scaleY;
|
|
40262
|
+
if (dashArray?.length) {
|
|
40263
|
+
const dashScale = Math.max(scaleX, scaleY);
|
|
40264
|
+
dashArray = dashArray.map((value) => value / dashScale);
|
|
40265
|
+
dashPhase /= dashScale;
|
|
40266
|
+
}
|
|
40267
|
+
}
|
|
40268
|
+
return { matrix, width, dashArray, dashPhase };
|
|
40269
|
+
}
|
|
40270
|
+
function strokeEdges(path, pageHeight, scale) {
|
|
40271
|
+
const stroke = prepareStroke(path, scale);
|
|
40272
|
+
if (!stroke) return [];
|
|
40273
|
+
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
40274
|
+
if (!inverse) return [];
|
|
40275
|
+
const [a, b, c, d, e, f] = stroke.matrix;
|
|
40276
|
+
const strokeScale = scale * Math.hypot(a, b, c, d);
|
|
40277
|
+
const project = (x, y) => [
|
|
40278
|
+
(inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
|
|
40279
|
+
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40280
|
+
];
|
|
40281
|
+
const toScreen = ([x, y]) => [
|
|
40282
|
+
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40283
|
+
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40284
|
+
];
|
|
40285
|
+
const contours = strokeOutlines(
|
|
40286
|
+
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
40287
|
+
stroke.width * strokeScale,
|
|
40288
|
+
path.lineCap ?? 0,
|
|
40289
|
+
path.lineJoin ?? 0,
|
|
40290
|
+
path.miterLimit ?? 10,
|
|
40291
|
+
stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
|
|
40292
|
+
stroke.dashPhase * strokeScale
|
|
40293
|
+
);
|
|
40294
|
+
return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
|
|
40295
|
+
}
|
|
40242
40296
|
function pathsToEdges(paths, closeSubpaths = false) {
|
|
40243
40297
|
const edges = [];
|
|
40244
40298
|
for (const { points, closed } of paths) {
|
|
@@ -40488,19 +40542,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40488
40542
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40489
40543
|
}
|
|
40490
40544
|
if (path.strokeColor) {
|
|
40491
|
-
const rawSw = path.strokeWidth * scale;
|
|
40492
|
-
const sw = Math.max(1, rawSw);
|
|
40545
|
+
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40493
40546
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
40494
|
-
const
|
|
40495
|
-
segmentsToScreenPaths(path.segments, displayList.height, scale),
|
|
40496
|
-
sw,
|
|
40497
|
-
path.lineCap ?? 0,
|
|
40498
|
-
path.lineJoin ?? 0,
|
|
40499
|
-
path.miterLimit ?? 10,
|
|
40500
|
-
path.dashArray?.map((value) => Math.max(0, value * scale)),
|
|
40501
|
-
(path.dashPhase ?? 0) * scale
|
|
40502
|
-
);
|
|
40503
|
-
const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
|
|
40547
|
+
const edges = strokeEdges(path, displayList.height, scale);
|
|
40504
40548
|
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
|
|
40505
40549
|
fillEdgesScanline4x4(
|
|
40506
40550
|
rgba,
|
|
@@ -36243,11 +36243,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36243
36243
|
} else if (operator === "d") {
|
|
36244
36244
|
const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
|
|
36245
36245
|
if (arrNode) {
|
|
36246
|
-
const
|
|
36247
|
-
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
|
|
36246
|
+
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
|
|
36248
36247
|
const sum = nums.reduce((a, b) => a + b, 0);
|
|
36249
36248
|
st.dashArray = sum > 0 ? nums : void 0;
|
|
36250
|
-
st.dashPhase = num(1, 0)
|
|
36249
|
+
st.dashPhase = num(1, 0);
|
|
36251
36250
|
} else {
|
|
36252
36251
|
st.dashArray = void 0;
|
|
36253
36252
|
st.dashPhase = void 0;
|
|
@@ -36783,15 +36782,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36783
36782
|
break;
|
|
36784
36783
|
}
|
|
36785
36784
|
const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
|
|
36786
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36787
|
-
const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
|
|
36788
36785
|
emit({ kind: "path", value: {
|
|
36789
36786
|
segments: transformedSegments,
|
|
36790
36787
|
fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
|
|
36791
36788
|
fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
|
|
36792
36789
|
strokeColor: isStroke ? st.strokeColor : void 0,
|
|
36793
36790
|
strokeAlpha: isStroke ? st.strokeAlpha : void 0,
|
|
36794
|
-
strokeWidth:
|
|
36791
|
+
strokeWidth: st.strokeWidth,
|
|
36792
|
+
...isStroke ? { strokeMatrix: [...st.ctm] } : {},
|
|
36795
36793
|
...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
|
|
36796
36794
|
...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
|
|
36797
36795
|
...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
|
|
@@ -36979,14 +36977,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36979
36977
|
if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
|
|
36980
36978
|
const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
|
|
36981
36979
|
const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
|
|
36982
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36983
36980
|
const paint = {
|
|
36984
36981
|
segments: transformedGlyphSegs,
|
|
36985
36982
|
fillColor: isFillGlyph ? st.fillColor : void 0,
|
|
36986
36983
|
fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
|
|
36987
36984
|
strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
|
|
36988
36985
|
strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
|
|
36989
|
-
strokeWidth: isStrokeGlyph ? st.strokeWidth
|
|
36986
|
+
strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
|
|
36987
|
+
...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
|
|
36990
36988
|
fillRule: "nonzero",
|
|
36991
36989
|
...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
|
|
36992
36990
|
...st.clipRect ? { clipRect: [...st.clipRect] } : {}
|
|
@@ -40632,11 +40630,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
|
|
|
40632
40630
|
rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
|
|
40633
40631
|
rgba[idx + 3] = Math.round(outA * 255);
|
|
40634
40632
|
}
|
|
40635
|
-
function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
40633
|
+
function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
|
|
40636
40634
|
const paths = [];
|
|
40637
40635
|
let points = [];
|
|
40638
40636
|
let current = [0, 0];
|
|
40639
|
-
const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
|
|
40640
40637
|
for (const segment of segments) {
|
|
40641
40638
|
if (segment.kind === "move") {
|
|
40642
40639
|
if (points.length) paths.push({ points, closed: false });
|
|
@@ -40675,6 +40672,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
|
40675
40672
|
if (points.length) paths.push({ points, closed: false });
|
|
40676
40673
|
return paths;
|
|
40677
40674
|
}
|
|
40675
|
+
function inverseStrokeMatrix(matrix) {
|
|
40676
|
+
const [a, b, c, d, e, f] = matrix;
|
|
40677
|
+
const det = a * d - b * c;
|
|
40678
|
+
if (!Number.isFinite(det) || det === 0) return void 0;
|
|
40679
|
+
return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
|
|
40680
|
+
}
|
|
40681
|
+
function prepareStroke(path, scale) {
|
|
40682
|
+
const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
|
|
40683
|
+
const [a, b, c, d] = matrix;
|
|
40684
|
+
const area = Math.abs(a * d - b * c) * scale * scale;
|
|
40685
|
+
if (!(area > 0) || !Number.isFinite(area)) return void 0;
|
|
40686
|
+
const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
|
|
40687
|
+
let width = path.strokeWidth || 1;
|
|
40688
|
+
const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
|
|
40689
|
+
const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
|
|
40690
|
+
let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
|
|
40691
|
+
if (scaleX === scaleY) {
|
|
40692
|
+
width *= scaleX;
|
|
40693
|
+
} else {
|
|
40694
|
+
matrix[0] *= scaleX;
|
|
40695
|
+
matrix[1] *= scaleX;
|
|
40696
|
+
matrix[2] *= scaleY;
|
|
40697
|
+
matrix[3] *= scaleY;
|
|
40698
|
+
if (dashArray?.length) {
|
|
40699
|
+
const dashScale = Math.max(scaleX, scaleY);
|
|
40700
|
+
dashArray = dashArray.map((value) => value / dashScale);
|
|
40701
|
+
dashPhase /= dashScale;
|
|
40702
|
+
}
|
|
40703
|
+
}
|
|
40704
|
+
return { matrix, width, dashArray, dashPhase };
|
|
40705
|
+
}
|
|
40706
|
+
function strokeEdges(path, pageHeight, scale) {
|
|
40707
|
+
const stroke = prepareStroke(path, scale);
|
|
40708
|
+
if (!stroke) return [];
|
|
40709
|
+
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
40710
|
+
if (!inverse) return [];
|
|
40711
|
+
const [a, b, c, d, e, f] = stroke.matrix;
|
|
40712
|
+
const strokeScale = scale * Math.hypot(a, b, c, d);
|
|
40713
|
+
const project = (x, y) => [
|
|
40714
|
+
(inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
|
|
40715
|
+
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40716
|
+
];
|
|
40717
|
+
const toScreen = ([x, y]) => [
|
|
40718
|
+
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40719
|
+
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40720
|
+
];
|
|
40721
|
+
const contours = strokeOutlines(
|
|
40722
|
+
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
40723
|
+
stroke.width * strokeScale,
|
|
40724
|
+
path.lineCap ?? 0,
|
|
40725
|
+
path.lineJoin ?? 0,
|
|
40726
|
+
path.miterLimit ?? 10,
|
|
40727
|
+
stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
|
|
40728
|
+
stroke.dashPhase * strokeScale
|
|
40729
|
+
);
|
|
40730
|
+
return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
|
|
40731
|
+
}
|
|
40678
40732
|
function pathsToEdges(paths, closeSubpaths = false) {
|
|
40679
40733
|
const edges = [];
|
|
40680
40734
|
for (const { points, closed } of paths) {
|
|
@@ -40924,19 +40978,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40924
40978
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40925
40979
|
}
|
|
40926
40980
|
if (path.strokeColor) {
|
|
40927
|
-
const rawSw = path.strokeWidth * scale;
|
|
40928
|
-
const sw = Math.max(1, rawSw);
|
|
40981
|
+
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40929
40982
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
40930
|
-
const
|
|
40931
|
-
segmentsToScreenPaths(path.segments, displayList.height, scale),
|
|
40932
|
-
sw,
|
|
40933
|
-
path.lineCap ?? 0,
|
|
40934
|
-
path.lineJoin ?? 0,
|
|
40935
|
-
path.miterLimit ?? 10,
|
|
40936
|
-
path.dashArray?.map((value) => Math.max(0, value * scale)),
|
|
40937
|
-
(path.dashPhase ?? 0) * scale
|
|
40938
|
-
);
|
|
40939
|
-
const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
|
|
40983
|
+
const edges = strokeEdges(path, displayList.height, scale);
|
|
40940
40984
|
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
|
|
40941
40985
|
fillEdgesScanline4x4(
|
|
40942
40986
|
rgba,
|
|
@@ -41086,17 +41130,19 @@ function svgImage(image, pageHeight) {
|
|
|
41086
41130
|
const [a, b, c, d, e, f] = image.matrix;
|
|
41087
41131
|
return `<image width="1" height="1" preserveAspectRatio="none" transform="matrix(${a} ${-b} ${-c} ${d} ${e + c} ${pageHeight - f - d})" href="data:image/png;base64,${btoa(chunks.join(""))}"/>`;
|
|
41088
41132
|
}
|
|
41089
|
-
function svgPathData(segments, height) {
|
|
41133
|
+
function svgPathData(segments, height, matrix) {
|
|
41090
41134
|
const dParts = [];
|
|
41135
|
+
const point = (x, y) => matrix ? `${matrix[0] * x + matrix[2] * y + matrix[4]} ${height - matrix[1] * x - matrix[3] * y - matrix[5]}` : `${x} ${height - y}`;
|
|
41091
41136
|
for (const seg of segments) {
|
|
41092
41137
|
if (seg.kind === "move") {
|
|
41093
|
-
dParts.push(`M ${seg.x
|
|
41138
|
+
dParts.push(`M ${point(seg.x, seg.y)}`);
|
|
41094
41139
|
} else if (seg.kind === "line") {
|
|
41095
|
-
dParts.push(`L ${seg.x
|
|
41140
|
+
dParts.push(`L ${point(seg.x, seg.y)}`);
|
|
41096
41141
|
} else if (seg.kind === "cubic") {
|
|
41097
|
-
dParts.push(`C ${seg.x1
|
|
41142
|
+
dParts.push(`C ${point(seg.x1, seg.y1)} ${point(seg.x2, seg.y2)} ${point(seg.x, seg.y)}`);
|
|
41098
41143
|
} else if (seg.kind === "rect") {
|
|
41099
|
-
dParts.push(`M ${seg.x} ${
|
|
41144
|
+
if (matrix) dParts.push(`M ${point(seg.x, seg.y)} L ${point(seg.x + seg.width, seg.y)} L ${point(seg.x + seg.width, seg.y + seg.height)} L ${point(seg.x, seg.y + seg.height)} Z`);
|
|
41145
|
+
else dParts.push(`M ${seg.x} ${height - seg.y} h ${seg.width} v ${-seg.height} h ${-seg.width} Z`);
|
|
41100
41146
|
} else if (seg.kind === "close") {
|
|
41101
41147
|
dParts.push("Z");
|
|
41102
41148
|
}
|
|
@@ -41175,21 +41221,25 @@ function renderDisplayListToSvg(displayList, options = {}) {
|
|
|
41175
41221
|
parts.push("</g>");
|
|
41176
41222
|
} else if (operation.kind === "path") {
|
|
41177
41223
|
const p = operation.value;
|
|
41178
|
-
const
|
|
41224
|
+
const prepared = p.strokeColor ? prepareStroke(p, Math.max(scaleX, scaleY)) : void 0;
|
|
41225
|
+
const matrix = prepared && (prepared.matrix[0] !== 1 || prepared.matrix[1] !== 0 || prepared.matrix[2] !== 0 || prepared.matrix[3] !== 1) ? prepared.matrix : void 0;
|
|
41226
|
+
const inverse = matrix ? inverseStrokeMatrix(matrix) : void 0;
|
|
41227
|
+
const pathData = svgPathData(p.segments, inverse ? 0 : displayList.height, inverse);
|
|
41228
|
+
const transformAttr = inverse && matrix ? ` transform="matrix(${matrix[0]} ${-matrix[1]} ${-matrix[2]} ${matrix[3]} ${matrix[4]} ${displayList.height - matrix[5]})"` : "";
|
|
41179
41229
|
if (pathData) {
|
|
41180
41230
|
const fill = p.fillColor ? `rgb(${Math.round(p.fillColor.r * 255)},${Math.round(p.fillColor.g * 255)},${Math.round(p.fillColor.b * 255)})` : "none";
|
|
41181
|
-
const stroke = p.strokeColor ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
|
|
41231
|
+
const stroke = p.strokeColor && prepared ? `rgb(${Math.round(p.strokeColor.r * 255)},${Math.round(p.strokeColor.g * 255)},${Math.round(p.strokeColor.b * 255)})` : "none";
|
|
41182
41232
|
const fillRuleAttr = p.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
|
|
41183
41233
|
const fillOpacityAttr = p.fillAlpha !== void 0 && p.fillAlpha < 1 ? ` fill-opacity="${p.fillAlpha}"` : "";
|
|
41184
41234
|
const strokeOpacityAttr = p.strokeAlpha !== void 0 && p.strokeAlpha < 1 ? ` stroke-opacity="${p.strokeAlpha}"` : "";
|
|
41185
|
-
const strokeWidthAttr = p.strokeWidth <= 0 ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${p.strokeWidth}"`;
|
|
41235
|
+
const strokeWidthAttr = p.strokeWidth <= 0 && !matrix && !p.dashArray?.length ? ` stroke-width="1" vector-effect="non-scaling-stroke"` : ` stroke-width="${prepared?.width ?? p.strokeWidth}"`;
|
|
41186
41236
|
const lineCapAttr = p.lineCap === 1 ? ` stroke-linecap="round"` : p.lineCap === 2 ? ` stroke-linecap="square"` : "";
|
|
41187
41237
|
const lineJoinAttr = p.lineJoin === 1 ? ` stroke-linejoin="round"` : p.lineJoin === 2 ? ` stroke-linejoin="bevel"` : "";
|
|
41188
41238
|
const miterLimitAttr = p.miterLimit !== void 0 && p.miterLimit !== 10 ? ` stroke-miterlimit="${p.miterLimit}"` : "";
|
|
41189
|
-
const dashArrayAttr =
|
|
41190
|
-
const dashOffsetAttr =
|
|
41239
|
+
const dashArrayAttr = prepared?.dashArray?.length ? ` stroke-dasharray="${prepared.dashArray.join(" ")}"` : "";
|
|
41240
|
+
const dashOffsetAttr = prepared?.dashPhase ? ` stroke-dashoffset="${prepared.dashPhase}"` : "";
|
|
41191
41241
|
const labelAttr = original.kind === "glyph" ? ` aria-label="${escapeXmlText(original.value.unicode)}"` : "";
|
|
41192
|
-
parts.push(` <path${labelAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
|
|
41242
|
+
parts.push(` <path${labelAttr}${transformAttr} d="${pathData}" fill="${fill}"${fillRuleAttr}${fillOpacityAttr} stroke="${stroke}"${strokeOpacityAttr}${strokeWidthAttr}${lineCapAttr}${lineJoinAttr}${miterLimitAttr}${dashArrayAttr}${dashOffsetAttr}/>`);
|
|
41193
41243
|
}
|
|
41194
41244
|
} else if (operation.kind === "image") {
|
|
41195
41245
|
parts.push(` ${svgImage(operation.value, displayList.height)}`);
|
|
@@ -35704,11 +35704,10 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
35704
35704
|
} else if (operator === "d") {
|
|
35705
35705
|
const arrNode = ops[0]?.kind === "array" ? ops[0] : void 0;
|
|
35706
35706
|
if (arrNode) {
|
|
35707
|
-
const
|
|
35708
|
-
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value * ctmScale : 0).filter((v) => v >= 0);
|
|
35707
|
+
const nums = arrNode.items.map((it) => it.kind === "number" ? it.value : 0).filter((v) => v >= 0);
|
|
35709
35708
|
const sum = nums.reduce((a, b) => a + b, 0);
|
|
35710
35709
|
st.dashArray = sum > 0 ? nums : void 0;
|
|
35711
|
-
st.dashPhase = num(1, 0)
|
|
35710
|
+
st.dashPhase = num(1, 0);
|
|
35712
35711
|
} else {
|
|
35713
35712
|
st.dashArray = void 0;
|
|
35714
35713
|
st.dashPhase = void 0;
|
|
@@ -36244,15 +36243,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36244
36243
|
break;
|
|
36245
36244
|
}
|
|
36246
36245
|
const fillRule = node.paint.includes("*") ? "evenodd" : "nonzero";
|
|
36247
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36248
|
-
const scaledStrokeWidth = st.strokeWidth === 0 ? 0 : st.strokeWidth * ctmScale;
|
|
36249
36246
|
emit({ kind: "path", value: {
|
|
36250
36247
|
segments: transformedSegments,
|
|
36251
36248
|
fillColor: isFill && !evaluatedFillPattern ? st.fillColor : void 0,
|
|
36252
36249
|
fillAlpha: isFill && !evaluatedFillPattern ? st.fillAlpha : void 0,
|
|
36253
36250
|
strokeColor: isStroke ? st.strokeColor : void 0,
|
|
36254
36251
|
strokeAlpha: isStroke ? st.strokeAlpha : void 0,
|
|
36255
|
-
strokeWidth:
|
|
36252
|
+
strokeWidth: st.strokeWidth,
|
|
36253
|
+
...isStroke ? { strokeMatrix: [...st.ctm] } : {},
|
|
36256
36254
|
...st.lineCap !== 0 ? { lineCap: st.lineCap } : {},
|
|
36257
36255
|
...st.lineJoin !== 0 ? { lineJoin: st.lineJoin } : {},
|
|
36258
36256
|
...st.miterLimit !== 10 ? { miterLimit: st.miterLimit } : {},
|
|
@@ -36440,14 +36438,14 @@ function evaluateContentStreamToDisplayList(params) {
|
|
|
36440
36438
|
if (st.textRenderMode >= 4 && st.textRenderMode <= 7) pendingTextClip.push(...transformedGlyphSegs);
|
|
36441
36439
|
const isFillGlyph = st.textRenderMode === 0 || st.textRenderMode === 2 || st.textRenderMode === 4 || st.textRenderMode === 6;
|
|
36442
36440
|
const isStrokeGlyph = st.textRenderMode === 1 || st.textRenderMode === 2 || st.textRenderMode === 5 || st.textRenderMode === 6;
|
|
36443
|
-
const ctmScale = Math.max(1e-6, Math.hypot(st.ctm[0], st.ctm[1]));
|
|
36444
36441
|
const paint = {
|
|
36445
36442
|
segments: transformedGlyphSegs,
|
|
36446
36443
|
fillColor: isFillGlyph ? st.fillColor : void 0,
|
|
36447
36444
|
fillAlpha: isFillGlyph ? st.fillAlpha : void 0,
|
|
36448
36445
|
strokeColor: isStrokeGlyph ? st.strokeColor : void 0,
|
|
36449
36446
|
strokeAlpha: isStrokeGlyph ? st.strokeAlpha : void 0,
|
|
36450
|
-
strokeWidth: isStrokeGlyph ? st.strokeWidth
|
|
36447
|
+
strokeWidth: isStrokeGlyph ? st.strokeWidth : 0,
|
|
36448
|
+
...isStrokeGlyph ? { strokeMatrix: [...st.ctm] } : {},
|
|
36451
36449
|
fillRule: "nonzero",
|
|
36452
36450
|
...st.blendMode && st.blendMode !== "Normal" ? { blendMode: st.blendMode } : {},
|
|
36453
36451
|
...st.clipRect ? { clipRect: [...st.clipRect] } : {}
|
|
@@ -40261,11 +40259,10 @@ function blendPixel(rgba, width, height, px, py, color, alpha, blendMode, clipMa
|
|
|
40261
40259
|
rgba[idx + 2] = Math.round((effB * a + cbB * dstA * (1 - a)) / outA * 255);
|
|
40262
40260
|
rgba[idx + 3] = Math.round(outA * 255);
|
|
40263
40261
|
}
|
|
40264
|
-
function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
40262
|
+
function segmentsToScreenPaths(segments, pageHeight, scale, toScreen = (x, y) => [x * scale, (pageHeight - y) * scale]) {
|
|
40265
40263
|
const paths = [];
|
|
40266
40264
|
let points = [];
|
|
40267
40265
|
let current = [0, 0];
|
|
40268
|
-
const toScreen = (x, y) => [x * scale, (pageHeight - y) * scale];
|
|
40269
40266
|
for (const segment of segments) {
|
|
40270
40267
|
if (segment.kind === "move") {
|
|
40271
40268
|
if (points.length) paths.push({ points, closed: false });
|
|
@@ -40304,6 +40301,63 @@ function segmentsToScreenPaths(segments, pageHeight, scale) {
|
|
|
40304
40301
|
if (points.length) paths.push({ points, closed: false });
|
|
40305
40302
|
return paths;
|
|
40306
40303
|
}
|
|
40304
|
+
function inverseStrokeMatrix(matrix) {
|
|
40305
|
+
const [a, b, c, d, e, f] = matrix;
|
|
40306
|
+
const det = a * d - b * c;
|
|
40307
|
+
if (!Number.isFinite(det) || det === 0) return void 0;
|
|
40308
|
+
return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
|
|
40309
|
+
}
|
|
40310
|
+
function prepareStroke(path, scale) {
|
|
40311
|
+
const matrix = path.strokeMatrix ? [...path.strokeMatrix] : [1, 0, 0, 1, 0, 0];
|
|
40312
|
+
const [a, b, c, d] = matrix;
|
|
40313
|
+
const area = Math.abs(a * d - b * c) * scale * scale;
|
|
40314
|
+
if (!(area > 0) || !Number.isFinite(area)) return void 0;
|
|
40315
|
+
const normX = Math.hypot(a, b) * scale, normY = Math.hypot(c, d) * scale;
|
|
40316
|
+
let width = path.strokeWidth || 1;
|
|
40317
|
+
const scaleX = path.strokeWidth === 0 ? normY / area : Math.max(1, normY / (width * area));
|
|
40318
|
+
const scaleY = path.strokeWidth === 0 ? normX / area : Math.max(1, normX / (width * area));
|
|
40319
|
+
let dashArray = path.dashArray, dashPhase = path.dashPhase ?? 0;
|
|
40320
|
+
if (scaleX === scaleY) {
|
|
40321
|
+
width *= scaleX;
|
|
40322
|
+
} else {
|
|
40323
|
+
matrix[0] *= scaleX;
|
|
40324
|
+
matrix[1] *= scaleX;
|
|
40325
|
+
matrix[2] *= scaleY;
|
|
40326
|
+
matrix[3] *= scaleY;
|
|
40327
|
+
if (dashArray?.length) {
|
|
40328
|
+
const dashScale = Math.max(scaleX, scaleY);
|
|
40329
|
+
dashArray = dashArray.map((value) => value / dashScale);
|
|
40330
|
+
dashPhase /= dashScale;
|
|
40331
|
+
}
|
|
40332
|
+
}
|
|
40333
|
+
return { matrix, width, dashArray, dashPhase };
|
|
40334
|
+
}
|
|
40335
|
+
function strokeEdges(path, pageHeight, scale) {
|
|
40336
|
+
const stroke = prepareStroke(path, scale);
|
|
40337
|
+
if (!stroke) return [];
|
|
40338
|
+
const inverse = inverseStrokeMatrix(stroke.matrix);
|
|
40339
|
+
if (!inverse) return [];
|
|
40340
|
+
const [a, b, c, d, e, f] = stroke.matrix;
|
|
40341
|
+
const strokeScale = scale * Math.hypot(a, b, c, d);
|
|
40342
|
+
const project = (x, y) => [
|
|
40343
|
+
(inverse[0] * x + inverse[2] * y + inverse[4]) * strokeScale,
|
|
40344
|
+
(inverse[1] * x + inverse[3] * y + inverse[5]) * strokeScale
|
|
40345
|
+
];
|
|
40346
|
+
const toScreen = ([x, y]) => [
|
|
40347
|
+
(a * x / strokeScale + c * y / strokeScale + e) * scale,
|
|
40348
|
+
(pageHeight - b * x / strokeScale - d * y / strokeScale - f) * scale
|
|
40349
|
+
];
|
|
40350
|
+
const contours = strokeOutlines(
|
|
40351
|
+
segmentsToScreenPaths(path.segments, pageHeight, scale, project),
|
|
40352
|
+
stroke.width * strokeScale,
|
|
40353
|
+
path.lineCap ?? 0,
|
|
40354
|
+
path.lineJoin ?? 0,
|
|
40355
|
+
path.miterLimit ?? 10,
|
|
40356
|
+
stroke.dashArray?.map((value) => Math.max(0, value * strokeScale)),
|
|
40357
|
+
stroke.dashPhase * strokeScale
|
|
40358
|
+
);
|
|
40359
|
+
return pathsToEdges(contours.map((points) => ({ points: points.map(toScreen), closed: true })));
|
|
40360
|
+
}
|
|
40307
40361
|
function pathsToEdges(paths, closeSubpaths = false) {
|
|
40308
40362
|
const edges = [];
|
|
40309
40363
|
for (const { points, closed } of paths) {
|
|
@@ -40553,19 +40607,9 @@ function renderDisplayListToBitmap(displayList, options = {}) {
|
|
|
40553
40607
|
fillEdgesScanline4x4(rgba, width, height, edges, path.fillColor, path.fillAlpha ?? 1, path.fillRule ?? "nonzero", clipScreen, original.kind === "glyph" ? aaTxt : aaVec, path.blendMode, clipMask);
|
|
40554
40608
|
}
|
|
40555
40609
|
if (path.strokeColor) {
|
|
40556
|
-
const rawSw = path.strokeWidth * scale;
|
|
40557
|
-
const sw = Math.max(1, rawSw);
|
|
40610
|
+
const rawSw = path.strokeWidth * scale * (path.strokeMatrix ? Math.hypot(path.strokeMatrix[0], path.strokeMatrix[1]) : 1);
|
|
40558
40611
|
const strokeAlpha = options.thinLineMode === "shape" && rawSw < 1 ? (path.strokeAlpha ?? 1) * Math.max(0.25, rawSw) : path.strokeAlpha ?? 1;
|
|
40559
|
-
const
|
|
40560
|
-
segmentsToScreenPaths(path.segments, displayList.height, scale),
|
|
40561
|
-
sw,
|
|
40562
|
-
path.lineCap ?? 0,
|
|
40563
|
-
path.lineJoin ?? 0,
|
|
40564
|
-
path.miterLimit ?? 10,
|
|
40565
|
-
path.dashArray?.map((value) => Math.max(0, value * scale)),
|
|
40566
|
-
(path.dashPhase ?? 0) * scale
|
|
40567
|
-
);
|
|
40568
|
-
const edges = pathsToEdges(contours.map((points) => ({ points, closed: true })));
|
|
40612
|
+
const edges = strokeEdges(path, displayList.height, scale);
|
|
40569
40613
|
const clipScreen = path.clipRect ? [path.clipRect[0] * scale, (displayList.height - path.clipRect[3]) * scale, path.clipRect[2] * scale, (displayList.height - path.clipRect[1]) * scale] : void 0;
|
|
40570
40614
|
fillEdgesScanline4x4(
|
|
40571
40615
|
rgba,
|