html2canvas-pro 2.4.4 → 2.5.0
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/README.md +115 -13
- package/dist/html2canvas-pro.cjs +3246 -1601
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +3246 -1601
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +3242 -1597
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +5 -5
- package/dist/types/core/cache-storage.d.ts +4 -1
- package/dist/types/core/context.d.ts +10 -1
- package/dist/types/core/render-element.d.ts +11 -0
- package/dist/types/core/util.d.ts +6 -0
- package/dist/types/css/index.d.ts +77 -46
- package/dist/types/css/parse.d.ts +15 -0
- package/dist/types/css/property-descriptors/accent-color.d.ts +5 -0
- package/dist/types/css/property-descriptors/backdrop-filter.d.ts +9 -0
- package/dist/types/css/property-descriptors/background-blend-mode.d.ts +16 -16
- package/dist/types/css/property-descriptors/border-image-width.d.ts +36 -0
- package/dist/types/css/property-descriptors/clip-path.d.ts +16 -2
- package/dist/types/css/property-descriptors/isolation.d.ts +6 -0
- package/dist/types/css/property-descriptors/mask.d.ts +25 -0
- package/dist/types/css/property-descriptors/mix-blend-mode.d.ts +16 -16
- package/dist/types/css/property-descriptors/outline.d.ts +15 -0
- package/dist/types/css/property-descriptors/text-emphasis.d.ts +22 -0
- package/dist/types/css/property-descriptors/text-shadow.d.ts +1 -1
- package/dist/types/css/property-descriptors/webkit-box-reflect.d.ts +19 -0
- package/dist/types/css/property-descriptors/webkit-text-fill-color.d.ts +9 -0
- package/dist/types/css/syntax/token-constants.d.ts +1 -1
- package/dist/types/css/types/color-math.d.ts +7 -1
- package/dist/types/css/types/color-spaces/a98.d.ts +2 -1
- package/dist/types/css/types/color-spaces/p3.d.ts +5 -4
- package/dist/types/css/types/color-spaces/pro-photo.d.ts +5 -4
- package/dist/types/css/types/color-spaces/rec2020.d.ts +5 -4
- package/dist/types/css/types/color-spaces/srgb.d.ts +5 -4
- package/dist/types/css/types/color-utilities.d.ts +11 -11
- package/dist/types/css/types/color.d.ts +1 -0
- package/dist/types/css/types/functions/conic-gradient.d.ts +11 -0
- package/dist/types/css/types/functions/image-set.d.ts +11 -0
- package/dist/types/css/types/functions/repeating-radial-gradient.d.ts +8 -0
- package/dist/types/css/types/image.d.ts +15 -2
- package/dist/types/css/types/safe-eval.d.ts +0 -6
- package/dist/types/dom/copy-css-styles.d.ts +8 -0
- package/dist/types/dom/document-cloner.d.ts +3 -13
- package/dist/types/dom/iframe-mount.d.ts +37 -0
- package/dist/types/dom/pseudo-content.d.ts +33 -0
- package/dist/types/dom/replaced-elements/iframe-element-container.d.ts +2 -2
- package/dist/types/options.d.ts +8 -2
- package/dist/types/render/canvas/background-renderer.d.ts +19 -0
- package/dist/types/render/canvas/border-image-renderer.d.ts +50 -1
- package/dist/types/render/canvas/box-shadow-geometry.d.ts +3 -0
- package/dist/types/render/canvas/box-shadow-painter.d.ts +13 -0
- package/dist/types/render/canvas/box-shadow-transform.d.ts +16 -0
- package/dist/types/render/canvas/canvas-renderer.d.ts +21 -15
- package/dist/types/render/canvas/mask-renderer.d.ts +36 -0
- package/dist/types/render/canvas/text-clip-renderer.d.ts +36 -0
- package/dist/types/render/canvas/text-renderer.d.ts +22 -0
- package/dist/types/render/stacking-context.d.ts +4 -1
- package/package.json +39 -40
- package/dist/lib/config.js +0 -49
- package/dist/lib/core/abort-helper.js +0 -20
- package/dist/lib/core/background-parser.js +0 -41
- package/dist/lib/core/bitwise.js +0 -5
- package/dist/lib/core/cache-storage.js +0 -283
- package/dist/lib/core/config-assembler.js +0 -88
- package/dist/lib/core/constants.js +0 -25
- package/dist/lib/core/context.js +0 -19
- package/dist/lib/core/debugger.js +0 -27
- package/dist/lib/core/features.js +0 -190
- package/dist/lib/core/logger.js +0 -56
- package/dist/lib/core/lru-map.js +0 -66
- package/dist/lib/core/origin-checker.js +0 -53
- package/dist/lib/core/performance-monitor.js +0 -185
- package/dist/lib/core/render-element.js +0 -131
- package/dist/lib/core/util.js +0 -4
- package/dist/lib/core/validator.js +0 -500
- package/dist/lib/css/grouped/background-styles.js +0 -36
- package/dist/lib/css/grouped/border-styles.js +0 -75
- package/dist/lib/css/grouped/font-styles.js +0 -93
- package/dist/lib/css/grouped/layout-styles.js +0 -127
- package/dist/lib/css/index.js +0 -339
- package/dist/lib/css/layout/bounds.js +0 -52
- package/dist/lib/css/layout/text.js +0 -133
- package/dist/lib/css/property-descriptor.js +0 -2
- package/dist/lib/css/property-descriptors/background-blend-mode.js +0 -41
- package/dist/lib/css/property-descriptors/background-clip.js +0 -25
- package/dist/lib/css/property-descriptors/background-color.js +0 -10
- package/dist/lib/css/property-descriptors/background-image.js +0 -24
- package/dist/lib/css/property-descriptors/background-origin.js +0 -23
- package/dist/lib/css/property-descriptors/background-position.js +0 -19
- package/dist/lib/css/property-descriptors/background-repeat.js +0 -33
- package/dist/lib/css/property-descriptors/background-size.js +0 -23
- package/dist/lib/css/property-descriptors/border-color.js +0 -14
- package/dist/lib/css/property-descriptors/border-image-repeat.js +0 -42
- package/dist/lib/css/property-descriptors/border-image-slice.js +0 -45
- package/dist/lib/css/property-descriptors/border-image-source.js +0 -22
- package/dist/lib/css/property-descriptors/border-radius.js +0 -15
- package/dist/lib/css/property-descriptors/border-style.js +0 -26
- package/dist/lib/css/property-descriptors/border-width.js +0 -20
- package/dist/lib/css/property-descriptors/box-decoration-break.js +0 -18
- package/dist/lib/css/property-descriptors/box-shadow.js +0 -54
- package/dist/lib/css/property-descriptors/clip-path.js +0 -189
- package/dist/lib/css/property-descriptors/color.js +0 -10
- package/dist/lib/css/property-descriptors/content.js +0 -19
- package/dist/lib/css/property-descriptors/counter-increment.js +0 -35
- package/dist/lib/css/property-descriptors/counter-reset.js +0 -18
- package/dist/lib/css/property-descriptors/direction.js +0 -18
- package/dist/lib/css/property-descriptors/display.js +0 -81
- package/dist/lib/css/property-descriptors/duration.js +0 -14
- package/dist/lib/css/property-descriptors/filter.js +0 -86
- package/dist/lib/css/property-descriptors/float.js +0 -22
- package/dist/lib/css/property-descriptors/font-family.js +0 -47
- package/dist/lib/css/property-descriptors/font-size.js +0 -10
- package/dist/lib/css/property-descriptors/font-style.js +0 -20
- package/dist/lib/css/property-descriptors/font-variant-ligatures.js +0 -34
- package/dist/lib/css/property-descriptors/font-variant.js +0 -13
- package/dist/lib/css/property-descriptors/font-weight.js +0 -25
- package/dist/lib/css/property-descriptors/image-rendering.js +0 -33
- package/dist/lib/css/property-descriptors/letter-spacing.js +0 -21
- package/dist/lib/css/property-descriptors/line-break.js +0 -23
- package/dist/lib/css/property-descriptors/line-height.js +0 -24
- package/dist/lib/css/property-descriptors/list-style-image.js +0 -17
- package/dist/lib/css/property-descriptors/list-style-position.js +0 -18
- package/dist/lib/css/property-descriptors/list-style-type.js +0 -122
- package/dist/lib/css/property-descriptors/margin.js +0 -13
- package/dist/lib/css/property-descriptors/mix-blend-mode.js +0 -31
- package/dist/lib/css/property-descriptors/object-fit.js +0 -28
- package/dist/lib/css/property-descriptors/object-position.js +0 -42
- package/dist/lib/css/property-descriptors/opacity.js +0 -16
- package/dist/lib/css/property-descriptors/overflow-wrap.js +0 -18
- package/dist/lib/css/property-descriptors/overflow.js +0 -27
- package/dist/lib/css/property-descriptors/padding.js +0 -14
- package/dist/lib/css/property-descriptors/paint-order.js +0 -33
- package/dist/lib/css/property-descriptors/position.js +0 -22
- package/dist/lib/css/property-descriptors/quotes.js +0 -41
- package/dist/lib/css/property-descriptors/rotate.js +0 -27
- package/dist/lib/css/property-descriptors/text-align.js +0 -21
- package/dist/lib/css/property-descriptors/text-decoration-color.js +0 -10
- package/dist/lib/css/property-descriptors/text-decoration-line.js +0 -28
- package/dist/lib/css/property-descriptors/text-decoration-style.js +0 -24
- package/dist/lib/css/property-descriptors/text-decoration-thickness.js +0 -26
- package/dist/lib/css/property-descriptors/text-overflow.js +0 -18
- package/dist/lib/css/property-descriptors/text-shadow.js +0 -46
- package/dist/lib/css/property-descriptors/text-transform.js +0 -20
- package/dist/lib/css/property-descriptors/text-underline-offset.js +0 -23
- package/dist/lib/css/property-descriptors/transform-origin.js +0 -24
- package/dist/lib/css/property-descriptors/transform.js +0 -57
- package/dist/lib/css/property-descriptors/visibility.js +0 -20
- package/dist/lib/css/property-descriptors/webkit-line-clamp.js +0 -26
- package/dist/lib/css/property-descriptors/webkit-text-stroke-color.js +0 -10
- package/dist/lib/css/property-descriptors/webkit-text-stroke-width.js +0 -16
- package/dist/lib/css/property-descriptors/white-space.js +0 -32
- package/dist/lib/css/property-descriptors/word-break.js +0 -26
- package/dist/lib/css/property-descriptors/writing-mode.js +0 -28
- package/dist/lib/css/property-descriptors/z-index.js +0 -19
- package/dist/lib/css/property-descriptors/zoom.js +0 -18
- package/dist/lib/css/syntax/parser.js +0 -141
- package/dist/lib/css/syntax/token-constants.js +0 -214
- package/dist/lib/css/syntax/token-singletons.js +0 -36
- package/dist/lib/css/syntax/token-types.js +0 -10
- package/dist/lib/css/syntax/tokenizer.js +0 -502
- package/dist/lib/css/type-descriptor.js +0 -2
- package/dist/lib/css/types/angle.js +0 -80
- package/dist/lib/css/types/color-math.js +0 -25
- package/dist/lib/css/types/color-spaces/a98.js +0 -78
- package/dist/lib/css/types/color-spaces/p3.js +0 -86
- package/dist/lib/css/types/color-spaces/pro-photo.js +0 -83
- package/dist/lib/css/types/color-spaces/rec2020.js +0 -85
- package/dist/lib/css/types/color-spaces/srgb.js +0 -79
- package/dist/lib/css/types/color-utilities.js +0 -342
- package/dist/lib/css/types/color.js +0 -400
- package/dist/lib/css/types/functions/-prefix-linear-gradient.js +0 -32
- package/dist/lib/css/types/functions/-prefix-radial-gradient.js +0 -83
- package/dist/lib/css/types/functions/-webkit-gradient.js +0 -59
- package/dist/lib/css/types/functions/counter.js +0 -367
- package/dist/lib/css/types/functions/gradient.js +0 -163
- package/dist/lib/css/types/functions/linear-gradient.js +0 -27
- package/dist/lib/css/types/functions/radial-gradient.js +0 -90
- package/dist/lib/css/types/functions/repeating-linear-gradient.js +0 -9
- package/dist/lib/css/types/image.js +0 -62
- package/dist/lib/css/types/index.js +0 -2
- package/dist/lib/css/types/length-percentage.js +0 -197
- package/dist/lib/css/types/length.js +0 -5
- package/dist/lib/css/types/safe-eval.js +0 -80
- package/dist/lib/css/types/time.js +0 -17
- package/dist/lib/dom/document-cloner.js +0 -618
- package/dist/lib/dom/dom-normalizer.js +0 -115
- package/dist/lib/dom/element-container.js +0 -71
- package/dist/lib/dom/elements/li-element-container.js +0 -11
- package/dist/lib/dom/elements/ol-element-container.js +0 -12
- package/dist/lib/dom/elements/select-element-container.js +0 -12
- package/dist/lib/dom/elements/textarea-element-container.js +0 -11
- package/dist/lib/dom/node-parser.js +0 -125
- package/dist/lib/dom/node-type-guards.js +0 -81
- package/dist/lib/dom/replaced-elements/canvas-element-container.js +0 -13
- package/dist/lib/dom/replaced-elements/iframe-element-container.js +0 -38
- package/dist/lib/dom/replaced-elements/image-element-container.js +0 -14
- package/dist/lib/dom/replaced-elements/index.js +0 -2
- package/dist/lib/dom/replaced-elements/input-element-container.js +0 -89
- package/dist/lib/dom/replaced-elements/svg-element-container.js +0 -57
- package/dist/lib/dom/slot-cloner.js +0 -176
- package/dist/lib/dom/text-container.js +0 -35
- package/dist/lib/index.js +0 -49
- package/dist/lib/options.js +0 -2
- package/dist/lib/render/background.js +0 -188
- package/dist/lib/render/bezier-curve.js +0 -34
- package/dist/lib/render/border.js +0 -104
- package/dist/lib/render/bound-curves.js +0 -188
- package/dist/lib/render/box-sizing.js +0 -20
- package/dist/lib/render/canvas/background-renderer.js +0 -338
- package/dist/lib/render/canvas/border-image-renderer.js +0 -153
- package/dist/lib/render/canvas/border-renderer.js +0 -184
- package/dist/lib/render/canvas/canvas-path.js +0 -25
- package/dist/lib/render/canvas/canvas-renderer.js +0 -633
- package/dist/lib/render/canvas/content-renderer.js +0 -270
- package/dist/lib/render/canvas/effects-renderer.js +0 -171
- package/dist/lib/render/canvas/filter-surface.js +0 -270
- package/dist/lib/render/canvas/font-utils.js +0 -46
- package/dist/lib/render/canvas/foreignobject-renderer.js +0 -38
- package/dist/lib/render/canvas/surface-bounds.js +0 -64
- package/dist/lib/render/canvas/text/text-decoration-renderer.js +0 -99
- package/dist/lib/render/canvas/text-renderer.js +0 -486
- package/dist/lib/render/effects.js +0 -231
- package/dist/lib/render/font-metrics.js +0 -53
- package/dist/lib/render/object-fit.js +0 -91
- package/dist/lib/render/path.js +0 -26
- package/dist/lib/render/renderer-interface.js +0 -2
- package/dist/lib/render/stacking-context.js +0 -341
- package/dist/lib/render/vector.js +0 -16
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.releaseSurface = exports.FilterSurfaceError = void 0;
|
|
4
|
-
exports.parseSimpleFilter = parseSimpleFilter;
|
|
5
|
-
exports.filterOutset = filterOutset;
|
|
6
|
-
exports.supportsNativeFilters = supportsNativeFilters;
|
|
7
|
-
exports.renderFilterSurface = renderFilterSurface;
|
|
8
|
-
exports.renderSvgFilterSurface = renderSvgFilterSurface;
|
|
9
|
-
const effects_1 = require("../effects");
|
|
10
|
-
const abort_helper_1 = require("../../core/abort-helper");
|
|
11
|
-
// Only errors in the optional surface path are eligible for legacy fallback.
|
|
12
|
-
class FilterSurfaceError extends Error {
|
|
13
|
-
}
|
|
14
|
-
exports.FilterSurfaceError = FilterSurfaceError;
|
|
15
|
-
const releaseSurface = (canvas) => {
|
|
16
|
-
canvas.width = canvas.height = 0;
|
|
17
|
-
};
|
|
18
|
-
exports.releaseSurface = releaseSurface;
|
|
19
|
-
// This first renderer integration handles computed blur followed by one shadow.
|
|
20
|
-
// Unsupported chains retain the existing renderer until general filter support lands.
|
|
21
|
-
function parseSimpleFilter(value) {
|
|
22
|
-
if (!value || value === 'none')
|
|
23
|
-
return { blur: 0 };
|
|
24
|
-
const effect = new effects_1.FilterEffect(value);
|
|
25
|
-
const shadows = value.match(/drop-shadow\(/g) || [];
|
|
26
|
-
if (shadows.length > 1 || (shadows.length === 1 && !effect.shadow))
|
|
27
|
-
return null;
|
|
28
|
-
const blur = effect.safeFilterString.match(/^blur\((\d+(?:\.\d+)?)px\)$/);
|
|
29
|
-
if (effect.safeFilterString && !blur)
|
|
30
|
-
return null;
|
|
31
|
-
if (blur && shadows.length && value.indexOf('blur(') > value.indexOf('drop-shadow('))
|
|
32
|
-
return null;
|
|
33
|
-
return {
|
|
34
|
-
blur: blur ? Number(blur[1]) : 0,
|
|
35
|
-
shadow: effect.shadow
|
|
36
|
-
? {
|
|
37
|
-
x: effect.shadow.offsetX,
|
|
38
|
-
y: effect.shadow.offsetY,
|
|
39
|
-
blur: effect.shadow.blur,
|
|
40
|
-
color: effect.shadow.color
|
|
41
|
-
}
|
|
42
|
-
: undefined
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function filterOutset(filter) {
|
|
46
|
-
return Math.ceil(3 * (filter.blur + (filter.shadow?.blur ?? 0)) +
|
|
47
|
-
Math.max(Math.abs(filter.shadow?.x ?? 0), Math.abs(filter.shadow?.y ?? 0)));
|
|
48
|
-
}
|
|
49
|
-
function canvasLike(source) {
|
|
50
|
-
const canvas = document.createElement('canvas');
|
|
51
|
-
canvas.width = source.width;
|
|
52
|
-
canvas.height = source.height;
|
|
53
|
-
return canvas;
|
|
54
|
-
}
|
|
55
|
-
const decodeSurface = (image, signal) => new Promise((resolve, reject) => {
|
|
56
|
-
const finish = (error) => {
|
|
57
|
-
clearTimeout(timer);
|
|
58
|
-
signal?.removeEventListener('abort', abort);
|
|
59
|
-
if (error)
|
|
60
|
-
reject(error);
|
|
61
|
-
else
|
|
62
|
-
resolve();
|
|
63
|
-
};
|
|
64
|
-
const abort = () => finish(new DOMException('The operation was aborted.', 'AbortError'));
|
|
65
|
-
const timer = setTimeout(() => finish(new FilterSurfaceError('Filter surface image decode timed out')), 10000);
|
|
66
|
-
signal?.addEventListener('abort', abort, { once: true });
|
|
67
|
-
if (signal?.aborted)
|
|
68
|
-
abort();
|
|
69
|
-
else
|
|
70
|
-
image.decode().then(() => finish(), () => finish(new FilterSurfaceError('Filter surface image decode failed')));
|
|
71
|
-
});
|
|
72
|
-
// Cache only a capability result, never raster storage. Separate Documents may use
|
|
73
|
-
// different Canvas implementations (including embedded webviews and test realms).
|
|
74
|
-
const canvasFilterSupport = new WeakMap();
|
|
75
|
-
function supportsNativeFilters(owner = document) {
|
|
76
|
-
const cached = canvasFilterSupport.get(owner);
|
|
77
|
-
if (cached !== undefined)
|
|
78
|
-
return cached;
|
|
79
|
-
const source = owner.createElement('canvas');
|
|
80
|
-
const target = owner.createElement('canvas');
|
|
81
|
-
let supported = false;
|
|
82
|
-
try {
|
|
83
|
-
source.width = source.height = target.width = target.height = 32;
|
|
84
|
-
const input = source.getContext('2d');
|
|
85
|
-
const context = target.getContext('2d');
|
|
86
|
-
// Check before assignment: on older WebKit assigning filter creates an
|
|
87
|
-
// expando property, not a working implementation.
|
|
88
|
-
if (input && context && 'filter' in context) {
|
|
89
|
-
input.fillStyle = '#fff';
|
|
90
|
-
input.fillRect(8, 8, 8, 8);
|
|
91
|
-
context.filter = 'blur(2px)';
|
|
92
|
-
context.drawImage(source, 0, 0);
|
|
93
|
-
const blurred = context.getImageData(6, 12, 1, 1).data[3] > 0;
|
|
94
|
-
context.clearRect(0, 0, 32, 32);
|
|
95
|
-
context.filter = 'drop-shadow(12px 0px 0px rgba(255, 0, 0, 0.5))';
|
|
96
|
-
context.drawImage(source, 0, 0);
|
|
97
|
-
const shadow = context.getImageData(24, 12, 1, 1).data;
|
|
98
|
-
supported = blurred && shadow[0] > 240 && shadow[1] < 10 && shadow[3] >= 126 && shadow[3] <= 129;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// Readback can itself be unavailable. Be conservative and retain SVG.
|
|
103
|
-
}
|
|
104
|
-
finally {
|
|
105
|
-
(0, exports.releaseSurface)(source);
|
|
106
|
-
(0, exports.releaseSurface)(target);
|
|
107
|
-
}
|
|
108
|
-
canvasFilterSupport.set(owner, supported);
|
|
109
|
-
return supported;
|
|
110
|
-
}
|
|
111
|
-
function tryNativeFilterSurface(source, { blur, shadow }, opacity, scale, signal) {
|
|
112
|
-
let filtered;
|
|
113
|
-
let output;
|
|
114
|
-
let complete = false;
|
|
115
|
-
try {
|
|
116
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
117
|
-
filtered = canvasLike(source);
|
|
118
|
-
const context = filtered.getContext('2d');
|
|
119
|
-
if (!context || !('filter' in context))
|
|
120
|
-
return null;
|
|
121
|
-
const functions = [];
|
|
122
|
-
if (blur)
|
|
123
|
-
functions.push(`blur(${blur * scale}px)`);
|
|
124
|
-
if (shadow)
|
|
125
|
-
functions.push(`drop-shadow(${shadow.x * scale}px ${shadow.y * scale}px ${shadow.blur * scale}px ${shadow.color})`);
|
|
126
|
-
context.filter = functions.join(' ');
|
|
127
|
-
if (context.filter === 'none')
|
|
128
|
-
return null;
|
|
129
|
-
// Canvas applies globalAlpha before filtering. Filter the complete layer
|
|
130
|
-
// at alpha 1, then composite opacity separately, including its shadow.
|
|
131
|
-
context.drawImage(source, 0, 0);
|
|
132
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
133
|
-
output = canvasLike(source);
|
|
134
|
-
const composite = output.getContext('2d');
|
|
135
|
-
if (!composite)
|
|
136
|
-
return null;
|
|
137
|
-
composite.globalAlpha = opacity;
|
|
138
|
-
composite.drawImage(filtered, 0, 0);
|
|
139
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
140
|
-
complete = true;
|
|
141
|
-
return output;
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
// A native allocation/draw failure may still succeed through SVG, but
|
|
145
|
-
// cancellation must never silently degrade to a successful fallback.
|
|
146
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
finally {
|
|
150
|
-
if (filtered)
|
|
151
|
-
(0, exports.releaseSurface)(filtered);
|
|
152
|
-
if (output && !complete)
|
|
153
|
-
(0, exports.releaseSurface)(output);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Backend selection is internal; the public html2canvas options are unchanged.
|
|
157
|
-
async function renderFilterSurface(source, filter, opacity, scale, signal) {
|
|
158
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
159
|
-
if ((filter.blur || filter.shadow) && supportsNativeFilters()) {
|
|
160
|
-
const output = tryNativeFilterSurface(source, filter, opacity, scale, signal);
|
|
161
|
-
if (output)
|
|
162
|
-
return output;
|
|
163
|
-
}
|
|
164
|
-
return renderSvgFilterSurface(source, filter, opacity, scale, signal);
|
|
165
|
-
}
|
|
166
|
-
// Explicit SVG entry is internal and allows independent fallback benchmarks/tests.
|
|
167
|
-
// No foreignObject or external image is used.
|
|
168
|
-
async function renderSvgFilterSurface(source, { blur, shadow }, opacity, scale, signal) {
|
|
169
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
170
|
-
if (!blur && !shadow) {
|
|
171
|
-
const output = canvasLike(source);
|
|
172
|
-
const context = output.getContext('2d');
|
|
173
|
-
if (!context) {
|
|
174
|
-
(0, exports.releaseSurface)(output);
|
|
175
|
-
throw new FilterSurfaceError('Filter surface canvas is unavailable');
|
|
176
|
-
}
|
|
177
|
-
context.globalAlpha = opacity;
|
|
178
|
-
try {
|
|
179
|
-
context.drawImage(source, 0, 0);
|
|
180
|
-
return output;
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
(0, exports.releaseSurface)(output);
|
|
184
|
-
throw new FilterSurfaceError('Filter surface image cannot be drawn');
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
const namespace = 'http://www.w3.org/2000/svg';
|
|
188
|
-
const element = (tag, attributes = {}) => {
|
|
189
|
-
const node = document.createElementNS(namespace, tag);
|
|
190
|
-
Object.entries(attributes).forEach(([key, value]) => node.setAttribute(key, String(value)));
|
|
191
|
-
return node;
|
|
192
|
-
};
|
|
193
|
-
const svg = element('svg', {
|
|
194
|
-
width: source.width,
|
|
195
|
-
height: source.height,
|
|
196
|
-
viewBox: `0 0 ${source.width} ${source.height}`
|
|
197
|
-
});
|
|
198
|
-
const defs = element('defs');
|
|
199
|
-
const filter = element('filter', {
|
|
200
|
-
id: 'composited-filter',
|
|
201
|
-
filterUnits: 'userSpaceOnUse',
|
|
202
|
-
x: 0,
|
|
203
|
-
y: 0,
|
|
204
|
-
width: source.width,
|
|
205
|
-
height: source.height,
|
|
206
|
-
'color-interpolation-filters': 'sRGB'
|
|
207
|
-
});
|
|
208
|
-
if (blur) {
|
|
209
|
-
filter.appendChild(element('feGaussianBlur', { stdDeviation: blur * scale, result: 'blurred-source' }));
|
|
210
|
-
}
|
|
211
|
-
if (shadow) {
|
|
212
|
-
// Explicit primitives avoid the narrower feDropShadow blur observed in WebKit.
|
|
213
|
-
filter.appendChild(element('feGaussianBlur', {
|
|
214
|
-
in: blur ? 'blurred-source' : 'SourceAlpha',
|
|
215
|
-
stdDeviation: shadow.blur * scale
|
|
216
|
-
}));
|
|
217
|
-
filter.appendChild(element('feOffset', { dx: shadow.x * scale, dy: shadow.y * scale, result: 'offset-shadow' }));
|
|
218
|
-
filter.appendChild(element('feFlood', { 'flood-color': shadow.color }));
|
|
219
|
-
filter.appendChild(element('feComposite', { in2: 'offset-shadow', operator: 'in' }));
|
|
220
|
-
const merge = element('feMerge');
|
|
221
|
-
merge.appendChild(element('feMergeNode'));
|
|
222
|
-
merge.appendChild(element('feMergeNode', { in: blur ? 'blurred-source' : 'SourceGraphic' }));
|
|
223
|
-
filter.appendChild(merge);
|
|
224
|
-
}
|
|
225
|
-
defs.appendChild(filter);
|
|
226
|
-
svg.appendChild(defs);
|
|
227
|
-
let sourceUrl;
|
|
228
|
-
try {
|
|
229
|
-
sourceUrl = source.toDataURL('image/png');
|
|
230
|
-
if (sourceUrl === 'data:,')
|
|
231
|
-
throw new Error('Canvas size is unsupported');
|
|
232
|
-
}
|
|
233
|
-
catch {
|
|
234
|
-
// allowTaint may intentionally produce an unreadable canvas. Keep that
|
|
235
|
-
// API behavior by letting the caller render the subtree on the old path.
|
|
236
|
-
throw new FilterSurfaceError('Filter surface pixels cannot be serialized');
|
|
237
|
-
}
|
|
238
|
-
svg.appendChild(element('image', {
|
|
239
|
-
width: source.width,
|
|
240
|
-
height: source.height,
|
|
241
|
-
href: sourceUrl,
|
|
242
|
-
filter: 'url(#composited-filter)'
|
|
243
|
-
}));
|
|
244
|
-
const image = new Image();
|
|
245
|
-
let output;
|
|
246
|
-
try {
|
|
247
|
-
image.src = `data:image/svg+xml,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
|
|
248
|
-
await decodeSurface(image, signal);
|
|
249
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
250
|
-
output = canvasLike(source);
|
|
251
|
-
const context = output.getContext('2d');
|
|
252
|
-
if (!context)
|
|
253
|
-
throw new FilterSurfaceError('Filter surface canvas is unavailable');
|
|
254
|
-
context.globalAlpha = opacity;
|
|
255
|
-
context.drawImage(image, 0, 0);
|
|
256
|
-
return output;
|
|
257
|
-
}
|
|
258
|
-
catch (error) {
|
|
259
|
-
if (output)
|
|
260
|
-
(0, exports.releaseSurface)(output);
|
|
261
|
-
if (signal?.aborted)
|
|
262
|
-
(0, abort_helper_1.throwIfAborted)(signal);
|
|
263
|
-
throw error instanceof FilterSurfaceError
|
|
264
|
-
? error
|
|
265
|
-
: new FilterSurfaceError('Filter surface image cannot be drawn');
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
image.removeAttribute('src');
|
|
269
|
-
}
|
|
270
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Font measurement utility
|
|
4
|
-
*
|
|
5
|
-
* Provides Canvas API-based font measurement that works correctly with webfonts
|
|
6
|
-
* (which may not be loaded in the original document) and system fonts.
|
|
7
|
-
*
|
|
8
|
-
* Fallback chain:
|
|
9
|
-
* 1. fontBoundingBoxAscent — font-level metric (Chrome 99+, FF 116+, Safari 17.4+)
|
|
10
|
-
* 2. actualBoundingBoxAscent — glyph-level metric (widely supported)
|
|
11
|
-
* 3. fallback value — coarse CSS fallback
|
|
12
|
-
*/
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.measureBaseline = exports.measureFontMetrics = void 0;
|
|
15
|
-
const SAMPLE_TEXT = 'Mg'; // characters with both ascender and descender
|
|
16
|
-
const isValidMetric = (value) => value !== undefined && !Number.isNaN(value);
|
|
17
|
-
/**
|
|
18
|
-
* Measure the baseline ascent and full font box for the currently set font.
|
|
19
|
-
*/
|
|
20
|
-
const measureFontMetrics = (ctx, fallback) => {
|
|
21
|
-
const tm = ctx.measureText(SAMPLE_TEXT);
|
|
22
|
-
const fontMetrics = tm;
|
|
23
|
-
const baseline = isValidMetric(fontMetrics.fontBoundingBoxAscent)
|
|
24
|
-
? fontMetrics.fontBoundingBoxAscent
|
|
25
|
-
: isValidMetric(tm.actualBoundingBoxAscent)
|
|
26
|
-
? tm.actualBoundingBoxAscent
|
|
27
|
-
: fallback;
|
|
28
|
-
const height = isValidMetric(fontMetrics.fontBoundingBoxAscent) && isValidMetric(fontMetrics.fontBoundingBoxDescent)
|
|
29
|
-
? fontMetrics.fontBoundingBoxAscent + fontMetrics.fontBoundingBoxDescent
|
|
30
|
-
: isValidMetric(tm.actualBoundingBoxAscent) && isValidMetric(tm.actualBoundingBoxDescent)
|
|
31
|
-
? tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
|
|
32
|
-
: fallback;
|
|
33
|
-
return { baseline, height };
|
|
34
|
-
};
|
|
35
|
-
exports.measureFontMetrics = measureFontMetrics;
|
|
36
|
-
/**
|
|
37
|
-
* Measure the baseline ascent for the currently set font.
|
|
38
|
-
*
|
|
39
|
-
* @param ctx - Canvas 2D rendering context with ctx.font already set
|
|
40
|
-
* @param fallback - Fallback value when no metrics are available (e.g. fontSize.number)
|
|
41
|
-
* @returns The distance from the text baseline to the top of the bounding box
|
|
42
|
-
*/
|
|
43
|
-
const measureBaseline = (ctx, fallback) => {
|
|
44
|
-
return (0, exports.measureFontMetrics)(ctx, fallback).baseline;
|
|
45
|
-
};
|
|
46
|
-
exports.measureBaseline = measureBaseline;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ForeignObjectRenderer = void 0;
|
|
4
|
-
const features_1 = require("../../core/features");
|
|
5
|
-
const color_utilities_1 = require("../../css/types/color-utilities");
|
|
6
|
-
class ForeignObjectRenderer {
|
|
7
|
-
constructor(context, options) {
|
|
8
|
-
this.context = context;
|
|
9
|
-
this.options = options;
|
|
10
|
-
this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
|
|
11
|
-
const ctx = this.canvas.getContext('2d');
|
|
12
|
-
if (!ctx) {
|
|
13
|
-
throw new Error('Failed to get 2D rendering context from canvas');
|
|
14
|
-
}
|
|
15
|
-
this.ctx = ctx;
|
|
16
|
-
this.canvas.width = Math.floor(options.width * options.scale);
|
|
17
|
-
this.canvas.height = Math.floor(options.height * options.scale);
|
|
18
|
-
this.canvas.style.width = `${options.width}px`;
|
|
19
|
-
this.canvas.style.height = `${options.height}px`;
|
|
20
|
-
this.ctx.scale(this.options.scale, this.options.scale);
|
|
21
|
-
this.ctx.translate(-options.x, -options.y);
|
|
22
|
-
this.context.logger.debug(`EXPERIMENTAL ForeignObject renderer initialized (${options.width}x${options.height} at ${options.x},${options.y}) with scale ${options.scale}`);
|
|
23
|
-
}
|
|
24
|
-
async render(element) {
|
|
25
|
-
if (this.options.signal?.aborted) {
|
|
26
|
-
throw new DOMException('The operation was aborted.', 'AbortError');
|
|
27
|
-
}
|
|
28
|
-
const svg = (0, features_1.createForeignObjectSVG)(this.options.width * this.options.scale, this.options.height * this.options.scale, this.options.scale, this.options.scale, element);
|
|
29
|
-
const img = await (0, features_1.loadSerializedSVG)(svg);
|
|
30
|
-
if (this.options.backgroundColor) {
|
|
31
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(this.options.backgroundColor);
|
|
32
|
-
this.ctx.fillRect(0, 0, this.options.width * this.options.scale, this.options.height * this.options.scale);
|
|
33
|
-
}
|
|
34
|
-
this.ctx.drawImage(img, -this.options.x * this.options.scale, -this.options.y * this.options.scale);
|
|
35
|
-
return this.canvas;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
exports.ForeignObjectRenderer = ForeignObjectRenderer;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_SURFACE_SIDE = exports.MAX_SURFACE_PIXELS = void 0;
|
|
4
|
-
exports.reserveSurface = reserveSurface;
|
|
5
|
-
exports.surfaceBounds = surfaceBounds;
|
|
6
|
-
exports.cropSurface = cropSurface;
|
|
7
|
-
const bounds_1 = require("../../css/layout/bounds");
|
|
8
|
-
const length_percentage_1 = require("../../css/types/length-percentage");
|
|
9
|
-
const filter_surface_1 = require("./filter-surface");
|
|
10
|
-
// Budget backing stores across all active nested surfaces in one capture.
|
|
11
|
-
// Reserve source, filtered output and decoded SVG/PNG rasters conservatively.
|
|
12
|
-
// Browser encoder/decoder overhead and the caller's output canvas are separate.
|
|
13
|
-
exports.MAX_SURFACE_PIXELS = 16 * 1024 * 1024;
|
|
14
|
-
exports.MAX_SURFACE_SIDE = 8192;
|
|
15
|
-
function reserveSurface(budget, width, height) {
|
|
16
|
-
const pixels = width * height * 4;
|
|
17
|
-
if (!Number.isFinite(pixels) ||
|
|
18
|
-
width <= 0 ||
|
|
19
|
-
height <= 0 ||
|
|
20
|
-
width > exports.MAX_SURFACE_SIDE ||
|
|
21
|
-
height > exports.MAX_SURFACE_SIDE ||
|
|
22
|
-
budget.pixels + pixels > exports.MAX_SURFACE_PIXELS)
|
|
23
|
-
return 0;
|
|
24
|
-
budget.pixels += pixels;
|
|
25
|
-
return pixels;
|
|
26
|
-
}
|
|
27
|
-
const expand = (b, margin) => b.add(-margin, -margin, margin * 2, margin * 2);
|
|
28
|
-
const union = (a, b) => new bounds_1.Bounds(Math.min(a.left, b.left), Math.min(a.top, b.top), Math.max(a.left + a.width, b.left + b.width) - Math.min(a.left, b.left), Math.max(a.top + a.height, b.top + b.height) - Math.min(a.top, b.top));
|
|
29
|
-
// Conservative paint bounds for the untransformed subtree supported by this path.
|
|
30
|
-
// Include overflow descendants, text ink padding, box/text shadows and nested filters.
|
|
31
|
-
function surfaceBounds(container) {
|
|
32
|
-
const styles = container.styles;
|
|
33
|
-
let bounds = container.bounds;
|
|
34
|
-
for (const shadow of styles.boxShadow) {
|
|
35
|
-
if (!shadow.inset) {
|
|
36
|
-
const spread = Math.max(0, shadow.spread.number) + 3 * shadow.blur.number;
|
|
37
|
-
bounds = union(bounds, expand(container.bounds.add(shadow.offsetX.number, shadow.offsetY.number, 0, 0), spread));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
for (const text of container.textNodes) {
|
|
41
|
-
for (const part of text.textBounds) {
|
|
42
|
-
const ink = expand(part.bounds, 2 * (0, length_percentage_1.getAbsoluteValue)(styles.fontSize, container.bounds.height) + styles.webkitTextStrokeWidth);
|
|
43
|
-
bounds = union(bounds, ink);
|
|
44
|
-
for (const shadow of styles.textShadow) {
|
|
45
|
-
bounds = union(bounds, expand(ink.add(shadow.offsetX.number, shadow.offsetY.number, 0, 0), 3 * shadow.blur.number));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
for (const child of container.elements) {
|
|
50
|
-
if (child.styles.isVisible())
|
|
51
|
-
bounds = union(bounds, surfaceBounds(child));
|
|
52
|
-
}
|
|
53
|
-
const filter = (0, filter_surface_1.parseSimpleFilter)(styles.filter);
|
|
54
|
-
return expand(bounds, filter ? (0, filter_surface_1.filterOutset)(filter) : 0);
|
|
55
|
-
}
|
|
56
|
-
function cropSurface(bounds, viewport, margin, scale) {
|
|
57
|
-
// Pixels just outside the destination still contribute through blur/shadow.
|
|
58
|
-
const area = expand(viewport, margin);
|
|
59
|
-
const left = Math.floor(Math.max(bounds.left, area.left) * scale) / scale;
|
|
60
|
-
const top = Math.floor(Math.max(bounds.top, area.top) * scale) / scale;
|
|
61
|
-
const right = Math.ceil(Math.min(bounds.left + bounds.width, area.left + area.width) * scale) / scale;
|
|
62
|
-
const bottom = Math.ceil(Math.min(bounds.top + bounds.height, area.top + area.height) * scale) / scale;
|
|
63
|
-
return new bounds_1.Bounds(left, top, Math.max(0, right - left), Math.max(0, bottom - top));
|
|
64
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TextDecorationRenderer = void 0;
|
|
4
|
-
const color_utilities_1 = require("../../../css/types/color-utilities");
|
|
5
|
-
class TextDecorationRenderer {
|
|
6
|
-
constructor(ctx) {
|
|
7
|
-
this.ctx = ctx;
|
|
8
|
-
}
|
|
9
|
-
render(bounds, styles) {
|
|
10
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.textDecorationColor || styles.color);
|
|
11
|
-
let thickness = 1;
|
|
12
|
-
if (typeof styles.textDecorationThickness === 'number') {
|
|
13
|
-
thickness = styles.textDecorationThickness;
|
|
14
|
-
}
|
|
15
|
-
else if (styles.textDecorationThickness === 'from-font') {
|
|
16
|
-
thickness = Math.max(1, Math.floor(styles.fontSize.number * 0.05));
|
|
17
|
-
}
|
|
18
|
-
let underlineOffset = 0;
|
|
19
|
-
if (typeof styles.textUnderlineOffset === 'number') {
|
|
20
|
-
underlineOffset = styles.textUnderlineOffset;
|
|
21
|
-
}
|
|
22
|
-
const decorationStyle = styles.textDecorationStyle;
|
|
23
|
-
styles.textDecorationLine.forEach((line) => {
|
|
24
|
-
let y = 0;
|
|
25
|
-
switch (line) {
|
|
26
|
-
case 1 /* TEXT_DECORATION_LINE.UNDERLINE */:
|
|
27
|
-
y = bounds.top + bounds.height - thickness + underlineOffset;
|
|
28
|
-
break;
|
|
29
|
-
case 2 /* TEXT_DECORATION_LINE.OVERLINE */:
|
|
30
|
-
y = bounds.top;
|
|
31
|
-
break;
|
|
32
|
-
case 3 /* TEXT_DECORATION_LINE.LINE_THROUGH */:
|
|
33
|
-
y = bounds.top + (bounds.height / 2 - thickness / 2);
|
|
34
|
-
break;
|
|
35
|
-
default:
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
this.draw(bounds.left, y, bounds.width, thickness, decorationStyle);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
draw(x, y, width, thickness, style) {
|
|
42
|
-
switch (style) {
|
|
43
|
-
case 0 /* TEXT_DECORATION_STYLE.SOLID */:
|
|
44
|
-
this.ctx.fillRect(x, y, width, thickness);
|
|
45
|
-
break;
|
|
46
|
-
case 1 /* TEXT_DECORATION_STYLE.DOUBLE */: {
|
|
47
|
-
const gap = Math.max(1, thickness);
|
|
48
|
-
this.ctx.fillRect(x, y, width, thickness);
|
|
49
|
-
this.ctx.fillRect(x, y + thickness + gap, width, thickness);
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
case 2 /* TEXT_DECORATION_STYLE.DOTTED */:
|
|
53
|
-
this.drawPattern(x, y, width, thickness, [thickness, thickness * 2]);
|
|
54
|
-
break;
|
|
55
|
-
case 3 /* TEXT_DECORATION_STYLE.DASHED */:
|
|
56
|
-
this.drawPattern(x, y, width, thickness, [thickness * 3, thickness * 2]);
|
|
57
|
-
break;
|
|
58
|
-
case 4 /* TEXT_DECORATION_STYLE.WAVY */:
|
|
59
|
-
this.drawWavy(x, y, width, thickness);
|
|
60
|
-
break;
|
|
61
|
-
default:
|
|
62
|
-
this.ctx.fillRect(x, y, width, thickness);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
drawPattern(x, y, width, thickness, dash) {
|
|
66
|
-
this.ctx.save();
|
|
67
|
-
this.ctx.beginPath();
|
|
68
|
-
this.ctx.setLineDash(dash);
|
|
69
|
-
this.ctx.lineWidth = thickness;
|
|
70
|
-
this.ctx.strokeStyle = this.ctx.fillStyle;
|
|
71
|
-
this.ctx.moveTo(x, y + thickness / 2);
|
|
72
|
-
this.ctx.lineTo(x + width, y + thickness / 2);
|
|
73
|
-
this.ctx.stroke();
|
|
74
|
-
this.ctx.restore();
|
|
75
|
-
}
|
|
76
|
-
drawWavy(x, y, width, thickness) {
|
|
77
|
-
this.ctx.save();
|
|
78
|
-
this.ctx.beginPath();
|
|
79
|
-
this.ctx.lineWidth = thickness;
|
|
80
|
-
this.ctx.strokeStyle = this.ctx.fillStyle;
|
|
81
|
-
const amplitude = thickness * 2;
|
|
82
|
-
const wavelength = thickness * 4;
|
|
83
|
-
let currentX = x;
|
|
84
|
-
this.ctx.moveTo(currentX, y + thickness / 2);
|
|
85
|
-
while (currentX < x + width) {
|
|
86
|
-
const nextX = Math.min(currentX + wavelength / 2, x + width);
|
|
87
|
-
this.ctx.quadraticCurveTo(currentX + wavelength / 4, y + thickness / 2 - amplitude, nextX, y + thickness / 2);
|
|
88
|
-
currentX = nextX;
|
|
89
|
-
if (currentX < x + width) {
|
|
90
|
-
const nextX2 = Math.min(currentX + wavelength / 2, x + width);
|
|
91
|
-
this.ctx.quadraticCurveTo(currentX + wavelength / 4, y + thickness / 2 + amplitude, nextX2, y + thickness / 2);
|
|
92
|
-
currentX = nextX2;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
this.ctx.stroke();
|
|
96
|
-
this.ctx.restore();
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
exports.TextDecorationRenderer = TextDecorationRenderer;
|