html2canvas-pro 1.5.13 → 1.6.1
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/.eslintrc.old +27 -0
- package/README.md +20 -0
- package/dist/html2canvas-pro.esm.js +2616 -3010
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +2616 -3010
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +6 -2
- package/dist/lib/__tests__/index.js +57 -122
- package/dist/lib/__tests__/index.js.map +1 -1
- package/dist/lib/core/__mocks__/cache-storage.js +2 -5
- package/dist/lib/core/__mocks__/cache-storage.js.map +1 -1
- package/dist/lib/core/__mocks__/context.js +7 -10
- package/dist/lib/core/__mocks__/context.js.map +1 -1
- package/dist/lib/core/__mocks__/logger.js +9 -17
- package/dist/lib/core/__mocks__/logger.js.map +1 -1
- package/dist/lib/core/__tests__/cache-storage.js +153 -351
- package/dist/lib/core/__tests__/cache-storage.js.map +1 -1
- package/dist/lib/core/__tests__/logger.js +12 -13
- package/dist/lib/core/__tests__/logger.js.map +1 -1
- package/dist/lib/core/bitwise.js +1 -1
- package/dist/lib/core/bitwise.js.map +1 -1
- package/dist/lib/core/cache-storage.js +92 -155
- package/dist/lib/core/cache-storage.js.map +1 -1
- package/dist/lib/core/context.js +8 -10
- package/dist/lib/core/context.js.map +1 -1
- package/dist/lib/core/debugger.js +5 -5
- package/dist/lib/core/debugger.js.map +1 -1
- package/dist/lib/core/features.js +65 -68
- package/dist/lib/core/features.js.map +1 -1
- package/dist/lib/core/logger.js +21 -56
- package/dist/lib/core/logger.js.map +1 -1
- package/dist/lib/css/index.js +98 -103
- package/dist/lib/css/index.js.map +1 -1
- package/dist/lib/css/layout/__mocks__/bounds.js +1 -1
- package/dist/lib/css/layout/__mocks__/bounds.js.map +1 -1
- package/dist/lib/css/layout/bounds.js +30 -19
- package/dist/lib/css/layout/bounds.js.map +1 -1
- package/dist/lib/css/layout/text.js +50 -58
- package/dist/lib/css/layout/text.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/background-tests.js +24 -29
- package/dist/lib/css/property-descriptors/__tests__/background-tests.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/font-family.js +14 -20
- package/dist/lib/css/property-descriptors/__tests__/font-family.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/paint-order.js +61 -83
- package/dist/lib/css/property-descriptors/__tests__/paint-order.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/text-shadow.js +75 -87
- package/dist/lib/css/property-descriptors/__tests__/text-shadow.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/transform-tests.js +9 -13
- package/dist/lib/css/property-descriptors/__tests__/transform-tests.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-clip.js +3 -3
- package/dist/lib/css/property-descriptors/background-clip.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-color.js +1 -1
- package/dist/lib/css/property-descriptors/background-image.js +6 -6
- package/dist/lib/css/property-descriptors/background-image.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-origin.js +3 -3
- package/dist/lib/css/property-descriptors/background-origin.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-position.js +17 -4
- package/dist/lib/css/property-descriptors/background-position.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-repeat.js +7 -9
- package/dist/lib/css/property-descriptors/background-repeat.js.map +1 -1
- package/dist/lib/css/property-descriptors/background-size.js +5 -7
- package/dist/lib/css/property-descriptors/background-size.js.map +1 -1
- package/dist/lib/css/property-descriptors/border-color.js +3 -3
- package/dist/lib/css/property-descriptors/border-color.js.map +1 -1
- package/dist/lib/css/property-descriptors/border-radius.js +5 -7
- package/dist/lib/css/property-descriptors/border-radius.js.map +1 -1
- package/dist/lib/css/property-descriptors/border-style.js +4 -4
- package/dist/lib/css/property-descriptors/border-style.js.map +1 -1
- package/dist/lib/css/property-descriptors/border-width.js +5 -5
- package/dist/lib/css/property-descriptors/border-width.js.map +1 -1
- package/dist/lib/css/property-descriptors/box-shadow.js +10 -10
- package/dist/lib/css/property-descriptors/box-shadow.js.map +1 -1
- package/dist/lib/css/property-descriptors/color.js +1 -1
- package/dist/lib/css/property-descriptors/content.js +2 -2
- package/dist/lib/css/property-descriptors/content.js.map +1 -1
- package/dist/lib/css/property-descriptors/counter-increment.js +10 -10
- package/dist/lib/css/property-descriptors/counter-increment.js.map +1 -1
- package/dist/lib/css/property-descriptors/counter-reset.js +9 -9
- package/dist/lib/css/property-descriptors/counter-reset.js.map +1 -1
- package/dist/lib/css/property-descriptors/direction.js +1 -1
- package/dist/lib/css/property-descriptors/direction.js.map +1 -1
- package/dist/lib/css/property-descriptors/display.js +4 -4
- package/dist/lib/css/property-descriptors/display.js.map +1 -1
- package/dist/lib/css/property-descriptors/duration.js +4 -4
- package/dist/lib/css/property-descriptors/duration.js.map +1 -1
- package/dist/lib/css/property-descriptors/float.js +1 -1
- package/dist/lib/css/property-descriptors/float.js.map +1 -1
- package/dist/lib/css/property-descriptors/font-family.js +6 -6
- package/dist/lib/css/property-descriptors/font-family.js.map +1 -1
- package/dist/lib/css/property-descriptors/font-size.js +1 -1
- package/dist/lib/css/property-descriptors/font-style.js +1 -1
- package/dist/lib/css/property-descriptors/font-style.js.map +1 -1
- package/dist/lib/css/property-descriptors/font-variant.js +3 -3
- package/dist/lib/css/property-descriptors/font-variant.js.map +1 -1
- package/dist/lib/css/property-descriptors/font-weight.js +2 -2
- package/dist/lib/css/property-descriptors/font-weight.js.map +1 -1
- package/dist/lib/css/property-descriptors/letter-spacing.js +1 -1
- package/dist/lib/css/property-descriptors/letter-spacing.js.map +1 -1
- package/dist/lib/css/property-descriptors/line-break.js +1 -1
- package/dist/lib/css/property-descriptors/line-break.js.map +1 -1
- package/dist/lib/css/property-descriptors/line-height.js +3 -3
- package/dist/lib/css/property-descriptors/line-height.js.map +1 -1
- package/dist/lib/css/property-descriptors/list-style-image.js +2 -2
- package/dist/lib/css/property-descriptors/list-style-image.js.map +1 -1
- package/dist/lib/css/property-descriptors/list-style-position.js +1 -1
- package/dist/lib/css/property-descriptors/list-style-position.js.map +1 -1
- package/dist/lib/css/property-descriptors/list-style-type.js +1 -1
- package/dist/lib/css/property-descriptors/list-style-type.js.map +1 -1
- package/dist/lib/css/property-descriptors/margin.js +3 -3
- package/dist/lib/css/property-descriptors/margin.js.map +1 -1
- package/dist/lib/css/property-descriptors/object-fit.js +4 -4
- package/dist/lib/css/property-descriptors/object-fit.js.map +1 -1
- package/dist/lib/css/property-descriptors/opacity.js +2 -2
- package/dist/lib/css/property-descriptors/opacity.js.map +1 -1
- package/dist/lib/css/property-descriptors/overflow-wrap.js +1 -1
- package/dist/lib/css/property-descriptors/overflow-wrap.js.map +1 -1
- package/dist/lib/css/property-descriptors/overflow.js +3 -3
- package/dist/lib/css/property-descriptors/overflow.js.map +1 -1
- package/dist/lib/css/property-descriptors/padding.js +3 -3
- package/dist/lib/css/property-descriptors/padding.js.map +1 -1
- package/dist/lib/css/property-descriptors/paint-order.js +6 -6
- package/dist/lib/css/property-descriptors/paint-order.js.map +1 -1
- package/dist/lib/css/property-descriptors/position.js +1 -1
- package/dist/lib/css/property-descriptors/position.js.map +1 -1
- package/dist/lib/css/property-descriptors/quotes.js +11 -11
- package/dist/lib/css/property-descriptors/quotes.js.map +1 -1
- package/dist/lib/css/property-descriptors/rotate.js +3 -3
- package/dist/lib/css/property-descriptors/rotate.js.map +1 -1
- package/dist/lib/css/property-descriptors/text-align.js +1 -1
- package/dist/lib/css/property-descriptors/text-align.js.map +1 -1
- package/dist/lib/css/property-descriptors/text-decoration-color.js +1 -1
- package/dist/lib/css/property-descriptors/text-decoration-line.js +4 -4
- package/dist/lib/css/property-descriptors/text-decoration-line.js.map +1 -1
- package/dist/lib/css/property-descriptors/text-shadow.js +10 -10
- package/dist/lib/css/property-descriptors/text-shadow.js.map +1 -1
- package/dist/lib/css/property-descriptors/text-transform.js +1 -1
- package/dist/lib/css/property-descriptors/text-transform.js.map +1 -1
- package/dist/lib/css/property-descriptors/transform-origin.js +6 -6
- package/dist/lib/css/property-descriptors/transform-origin.js.map +1 -1
- package/dist/lib/css/property-descriptors/transform.js +15 -15
- package/dist/lib/css/property-descriptors/transform.js.map +1 -1
- package/dist/lib/css/property-descriptors/visibility.js +1 -1
- package/dist/lib/css/property-descriptors/visibility.js.map +1 -1
- package/dist/lib/css/property-descriptors/webkit-text-stroke-color.js +1 -1
- package/dist/lib/css/property-descriptors/webkit-text-stroke-width.js +3 -3
- package/dist/lib/css/property-descriptors/webkit-text-stroke-width.js.map +1 -1
- package/dist/lib/css/property-descriptors/word-break.js +1 -1
- package/dist/lib/css/property-descriptors/word-break.js.map +1 -1
- package/dist/lib/css/property-descriptors/z-index.js +3 -3
- package/dist/lib/css/property-descriptors/z-index.js.map +1 -1
- package/dist/lib/css/syntax/__tests__/tokernizer-tests.js +17 -25
- package/dist/lib/css/syntax/__tests__/tokernizer-tests.js.map +1 -1
- package/dist/lib/css/syntax/parser.js +50 -55
- package/dist/lib/css/syntax/parser.js.map +1 -1
- package/dist/lib/css/syntax/tokenizer.js +205 -214
- package/dist/lib/css/syntax/tokenizer.js.map +1 -1
- package/dist/lib/css/types/__tests__/color-tests.js +103 -167
- package/dist/lib/css/types/__tests__/color-tests.js.map +1 -1
- package/dist/lib/css/types/__tests__/image-tests.js +192 -217
- package/dist/lib/css/types/__tests__/image-tests.js.map +1 -1
- package/dist/lib/css/types/angle.js +13 -13
- package/dist/lib/css/types/angle.js.map +1 -1
- package/dist/lib/css/types/color-spaces/a98.js +18 -22
- package/dist/lib/css/types/color-spaces/a98.js.map +1 -1
- package/dist/lib/css/types/color-spaces/p3.js +17 -22
- package/dist/lib/css/types/color-spaces/p3.js.map +1 -1
- package/dist/lib/css/types/color-spaces/pro-photo.js +17 -21
- package/dist/lib/css/types/color-spaces/pro-photo.js.map +1 -1
- package/dist/lib/css/types/color-spaces/rec2020.js +15 -19
- package/dist/lib/css/types/color-spaces/rec2020.js.map +1 -1
- package/dist/lib/css/types/color-spaces/srgb.js +17 -23
- package/dist/lib/css/types/color-spaces/srgb.js.map +1 -1
- package/dist/lib/css/types/color-utilities.js +80 -103
- package/dist/lib/css/types/color-utilities.js.map +1 -1
- package/dist/lib/css/types/color.js +72 -66
- package/dist/lib/css/types/color.js.map +1 -1
- package/dist/lib/css/types/functions/-prefix-linear-gradient.js +11 -11
- package/dist/lib/css/types/functions/-prefix-linear-gradient.js.map +1 -1
- package/dist/lib/css/types/functions/-prefix-radial-gradient.js +16 -16
- package/dist/lib/css/types/functions/-prefix-radial-gradient.js.map +1 -1
- package/dist/lib/css/types/functions/-webkit-gradient.js +26 -26
- package/dist/lib/css/types/functions/-webkit-gradient.js.map +1 -1
- package/dist/lib/css/types/functions/__tests__/radial-gradient.js +57 -65
- package/dist/lib/css/types/functions/__tests__/radial-gradient.js.map +1 -1
- package/dist/lib/css/types/functions/counter.js +59 -65
- package/dist/lib/css/types/functions/counter.js.map +1 -1
- package/dist/lib/css/types/functions/gradient.js +51 -52
- package/dist/lib/css/types/functions/gradient.js.map +1 -1
- package/dist/lib/css/types/functions/linear-gradient.js +10 -10
- package/dist/lib/css/types/functions/linear-gradient.js.map +1 -1
- package/dist/lib/css/types/functions/radial-gradient.js +17 -17
- package/dist/lib/css/types/functions/radial-gradient.js.map +1 -1
- package/dist/lib/css/types/image.js +14 -14
- package/dist/lib/css/types/image.js.map +1 -1
- package/dist/lib/css/types/length-percentage.js +94 -12
- package/dist/lib/css/types/length-percentage.js.map +1 -1
- package/dist/lib/css/types/length.js +1 -3
- package/dist/lib/css/types/length.js.map +1 -1
- package/dist/lib/css/types/time.js +2 -2
- package/dist/lib/css/types/time.js.map +1 -1
- package/dist/lib/dom/__mocks__/document-cloner.js +7 -8
- package/dist/lib/dom/__mocks__/document-cloner.js.map +1 -1
- package/dist/lib/dom/document-cloner.js +195 -219
- package/dist/lib/dom/document-cloner.js.map +1 -1
- package/dist/lib/dom/element-container.js +8 -9
- package/dist/lib/dom/element-container.js.map +1 -1
- package/dist/lib/dom/elements/li-element-container.js +6 -24
- package/dist/lib/dom/elements/li-element-container.js.map +1 -1
- package/dist/lib/dom/elements/ol-element-container.js +7 -25
- package/dist/lib/dom/elements/ol-element-container.js.map +1 -1
- package/dist/lib/dom/elements/select-element-container.js +7 -25
- package/dist/lib/dom/elements/select-element-container.js.map +1 -1
- package/dist/lib/dom/elements/textarea-element-container.js +6 -24
- package/dist/lib/dom/elements/textarea-element-container.js.map +1 -1
- package/dist/lib/dom/node-parser.js +54 -45
- package/dist/lib/dom/node-parser.js.map +1 -1
- package/dist/lib/dom/replaced-elements/canvas-element-container.js +8 -26
- package/dist/lib/dom/replaced-elements/canvas-element-container.js.map +1 -1
- package/dist/lib/dom/replaced-elements/iframe-element-container.js +17 -35
- package/dist/lib/dom/replaced-elements/iframe-element-container.js.map +1 -1
- package/dist/lib/dom/replaced-elements/image-element-container.js +9 -27
- package/dist/lib/dom/replaced-elements/image-element-container.js.map +1 -1
- package/dist/lib/dom/replaced-elements/input-element-container.js +47 -59
- package/dist/lib/dom/replaced-elements/input-element-container.js.map +1 -1
- package/dist/lib/dom/replaced-elements/svg-element-container.js +14 -32
- package/dist/lib/dom/replaced-elements/svg-element-container.js.map +1 -1
- package/dist/lib/dom/text-container.js +7 -8
- package/dist/lib/dom/text-container.js.map +1 -1
- package/dist/lib/index.js +99 -156
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/invariant.js +1 -1
- package/dist/lib/invariant.js.map +1 -1
- package/dist/lib/render/background.js +44 -47
- package/dist/lib/render/background.js.map +1 -1
- package/dist/lib/render/bezier-curve.js +18 -19
- package/dist/lib/render/bezier-curve.js.map +1 -1
- package/dist/lib/render/border.js +9 -9
- package/dist/lib/render/border.js.map +1 -1
- package/dist/lib/render/bound-curves.js +35 -36
- package/dist/lib/render/bound-curves.js.map +1 -1
- package/dist/lib/render/box-sizing.js +11 -11
- package/dist/lib/render/box-sizing.js.map +1 -1
- package/dist/lib/render/canvas/canvas-renderer.js +642 -915
- package/dist/lib/render/canvas/canvas-renderer.js.map +1 -1
- package/dist/lib/render/canvas/foreignobject-renderer.js +35 -101
- package/dist/lib/render/canvas/foreignobject-renderer.js.map +1 -1
- package/dist/lib/render/effects.js +12 -17
- package/dist/lib/render/effects.js.map +1 -1
- package/dist/lib/render/font-metrics.js +17 -18
- package/dist/lib/render/font-metrics.js.map +1 -1
- package/dist/lib/render/path.js +4 -4
- package/dist/lib/render/path.js.map +1 -1
- package/dist/lib/render/renderer.js +3 -4
- package/dist/lib/render/renderer.js.map +1 -1
- package/dist/lib/render/stacking-context.js +71 -70
- package/dist/lib/render/stacking-context.js.map +1 -1
- package/dist/lib/render/vector.js +6 -7
- package/dist/lib/render/vector.js.map +1 -1
- package/dist/types/css/types/length-percentage.d.ts +11 -1
- package/dist/types/dom/replaced-elements/input-element-container.d.ts +2 -0
- package/eslint.config.js +35 -0
- package/jest.config.cjs +5 -0
- package/karma.conf.cjs +295 -0
- package/package.json +19 -15
- package/test-punctuation.html +0 -77
|
@@ -1,114 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
27
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
28
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
29
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
|
-
function step(op) {
|
|
31
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
33
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
|
-
switch (op[0]) {
|
|
36
|
-
case 0: case 1: t = op; break;
|
|
37
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
38
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
39
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
40
|
-
default:
|
|
41
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
42
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
43
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
44
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
45
|
-
if (t[2]) _.ops.pop();
|
|
46
|
-
_.trys.pop(); continue;
|
|
47
|
-
}
|
|
48
|
-
op = body.call(thisArg, _);
|
|
49
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
50
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
3
|
exports.CanvasRenderer = void 0;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
_this.ctx = _this.canvas.getContext('2d');
|
|
4
|
+
const stacking_context_1 = require("../stacking-context");
|
|
5
|
+
const color_utilities_1 = require("../../css/types/color-utilities");
|
|
6
|
+
const path_1 = require("../path");
|
|
7
|
+
const bound_curves_1 = require("../bound-curves");
|
|
8
|
+
const bezier_curve_1 = require("../bezier-curve");
|
|
9
|
+
const vector_1 = require("../vector");
|
|
10
|
+
const image_1 = require("../../css/types/image");
|
|
11
|
+
const border_1 = require("../border");
|
|
12
|
+
const background_1 = require("../background");
|
|
13
|
+
const parser_1 = require("../../css/syntax/parser");
|
|
14
|
+
const text_1 = require("../../css/layout/text");
|
|
15
|
+
const image_element_container_1 = require("../../dom/replaced-elements/image-element-container");
|
|
16
|
+
const box_sizing_1 = require("../box-sizing");
|
|
17
|
+
const canvas_element_container_1 = require("../../dom/replaced-elements/canvas-element-container");
|
|
18
|
+
const svg_element_container_1 = require("../../dom/replaced-elements/svg-element-container");
|
|
19
|
+
const effects_1 = require("../effects");
|
|
20
|
+
const bitwise_1 = require("../../core/bitwise");
|
|
21
|
+
const gradient_1 = require("../../css/types/functions/gradient");
|
|
22
|
+
const length_percentage_1 = require("../../css/types/length-percentage");
|
|
23
|
+
const font_metrics_1 = require("../font-metrics");
|
|
24
|
+
const bounds_1 = require("../../css/layout/bounds");
|
|
25
|
+
const line_height_1 = require("../../css/property-descriptors/line-height");
|
|
26
|
+
const input_element_container_1 = require("../../dom/replaced-elements/input-element-container");
|
|
27
|
+
const textarea_element_container_1 = require("../../dom/elements/textarea-element-container");
|
|
28
|
+
const select_element_container_1 = require("../../dom/elements/select-element-container");
|
|
29
|
+
const iframe_element_container_1 = require("../../dom/replaced-elements/iframe-element-container");
|
|
30
|
+
const renderer_1 = require("../renderer");
|
|
31
|
+
const MASK_OFFSET = 10000;
|
|
32
|
+
class CanvasRenderer extends renderer_1.Renderer {
|
|
33
|
+
constructor(context, options) {
|
|
34
|
+
super(context, options);
|
|
35
|
+
this._activeEffects = [];
|
|
36
|
+
this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
|
|
37
|
+
this.ctx = this.canvas.getContext('2d');
|
|
90
38
|
if (!options.canvas) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
39
|
+
this.canvas.width = Math.floor(options.width * options.scale);
|
|
40
|
+
this.canvas.height = Math.floor(options.height * options.scale);
|
|
41
|
+
this.canvas.style.width = `${options.width}px`;
|
|
42
|
+
this.canvas.style.height = `${options.height}px`;
|
|
95
43
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return _this;
|
|
44
|
+
this.fontMetrics = new font_metrics_1.FontMetrics(document);
|
|
45
|
+
this.ctx.scale(this.options.scale, this.options.scale);
|
|
46
|
+
this.ctx.translate(-options.x, -options.y);
|
|
47
|
+
this.ctx.textBaseline = 'bottom';
|
|
48
|
+
this._activeEffects = [];
|
|
49
|
+
this.context.logger.debug(`Canvas renderer initialized (${options.width}x${options.height}) with scale ${options.scale}`);
|
|
103
50
|
}
|
|
104
|
-
|
|
105
|
-
var _this = this;
|
|
51
|
+
applyEffects(effects) {
|
|
106
52
|
while (this._activeEffects.length) {
|
|
107
53
|
this.popEffect();
|
|
108
54
|
}
|
|
109
|
-
effects.forEach(
|
|
110
|
-
}
|
|
111
|
-
|
|
55
|
+
effects.forEach((effect) => this.applyEffect(effect));
|
|
56
|
+
}
|
|
57
|
+
applyEffect(effect) {
|
|
112
58
|
this.ctx.save();
|
|
113
59
|
if ((0, effects_1.isOpacityEffect)(effect)) {
|
|
114
60
|
this.ctx.globalAlpha = effect.opacity;
|
|
@@ -123,169 +69,143 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
123
69
|
this.ctx.clip();
|
|
124
70
|
}
|
|
125
71
|
this._activeEffects.push(effect);
|
|
126
|
-
}
|
|
127
|
-
|
|
72
|
+
}
|
|
73
|
+
popEffect() {
|
|
128
74
|
this._activeEffects.pop();
|
|
129
75
|
this.ctx.restore();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
};
|
|
148
|
-
CanvasRenderer.prototype.renderNode = function (paint) {
|
|
149
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
150
|
-
return __generator(this, function (_a) {
|
|
151
|
-
switch (_a.label) {
|
|
152
|
-
case 0:
|
|
153
|
-
if ((0, bitwise_1.contains)(paint.container.flags, 16 /* FLAGS.DEBUG_RENDER */)) {
|
|
154
|
-
debugger;
|
|
155
|
-
}
|
|
156
|
-
if (!paint.container.styles.isVisible()) return [3 /*break*/, 3];
|
|
157
|
-
return [4 /*yield*/, this.renderNodeBackgroundAndBorders(paint)];
|
|
158
|
-
case 1:
|
|
159
|
-
_a.sent();
|
|
160
|
-
return [4 /*yield*/, this.renderNodeContent(paint)];
|
|
161
|
-
case 2:
|
|
162
|
-
_a.sent();
|
|
163
|
-
_a.label = 3;
|
|
164
|
-
case 3: return [2 /*return*/];
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
};
|
|
169
|
-
CanvasRenderer.prototype.renderTextWithLetterSpacing = function (text, letterSpacing, baseline) {
|
|
170
|
-
var _this = this;
|
|
76
|
+
}
|
|
77
|
+
async renderStack(stack) {
|
|
78
|
+
const styles = stack.element.container.styles;
|
|
79
|
+
if (styles.isVisible()) {
|
|
80
|
+
await this.renderStackContent(stack);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async renderNode(paint) {
|
|
84
|
+
if ((0, bitwise_1.contains)(paint.container.flags, 16 /* FLAGS.DEBUG_RENDER */)) {
|
|
85
|
+
debugger;
|
|
86
|
+
}
|
|
87
|
+
if (paint.container.styles.isVisible()) {
|
|
88
|
+
await this.renderNodeBackgroundAndBorders(paint);
|
|
89
|
+
await this.renderNodeContent(paint);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
renderTextWithLetterSpacing(text, letterSpacing, baseline) {
|
|
171
93
|
if (letterSpacing === 0) {
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
this.ctx.textBaseline = 'ideographic';
|
|
176
|
-
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + baseline);
|
|
180
|
-
}
|
|
94
|
+
// Use alphabetic baseline for consistent text positioning across browsers
|
|
95
|
+
// Issue #129: text.bounds.top + text.bounds.height causes text to render too low
|
|
96
|
+
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + baseline);
|
|
181
97
|
}
|
|
182
98
|
else {
|
|
183
|
-
|
|
184
|
-
letters.reduce(
|
|
185
|
-
|
|
186
|
-
return left +
|
|
99
|
+
const letters = (0, text_1.segmentGraphemes)(text.text);
|
|
100
|
+
letters.reduce((left, letter) => {
|
|
101
|
+
this.ctx.fillText(letter, left, text.bounds.top + baseline);
|
|
102
|
+
return left + this.ctx.measureText(letter).width;
|
|
187
103
|
}, text.bounds.left);
|
|
188
104
|
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
.filter(
|
|
105
|
+
}
|
|
106
|
+
createFontStyle(styles) {
|
|
107
|
+
const fontVariant = styles.fontVariant
|
|
108
|
+
.filter((variant) => variant === 'normal' || variant === 'small-caps')
|
|
193
109
|
.join('');
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
?
|
|
197
|
-
:
|
|
110
|
+
const fontFamily = fixIOSSystemFonts(styles.fontFamily).join(', ');
|
|
111
|
+
const fontSize = (0, parser_1.isDimensionToken)(styles.fontSize)
|
|
112
|
+
? `${styles.fontSize.number}${styles.fontSize.unit}`
|
|
113
|
+
: `${styles.fontSize.number}px`;
|
|
198
114
|
return [
|
|
199
115
|
[styles.fontStyle, fontVariant, styles.fontWeight, fontSize, fontFamily].join(' '),
|
|
200
116
|
fontFamily,
|
|
201
117
|
fontSize
|
|
202
118
|
];
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
break;
|
|
250
|
-
case 3 /* TEXT_DECORATION_LINE.LINE_THROUGH */:
|
|
251
|
-
_this.ctx.fillRect(text.bounds.left, text.bounds.top + (text.bounds.height / 2 - decorationLineHeight_1 / 2), text.bounds.width, decorationLineHeight_1);
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
break;
|
|
257
|
-
case 1 /* PAINT_ORDER_LAYER.STROKE */:
|
|
258
|
-
if (styles.webkitTextStrokeWidth && text.text.trim().length) {
|
|
259
|
-
_this.ctx.strokeStyle = (0, color_utilities_1.asString)(styles.webkitTextStrokeColor);
|
|
260
|
-
_this.ctx.lineWidth = styles.webkitTextStrokeWidth;
|
|
261
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
262
|
-
_this.ctx.lineJoin = !!window.chrome ? 'miter' : 'round';
|
|
263
|
-
_this.ctx.strokeText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
|
|
119
|
+
}
|
|
120
|
+
async renderTextNode(text, styles) {
|
|
121
|
+
const [font] = this.createFontStyle(styles);
|
|
122
|
+
this.ctx.font = font;
|
|
123
|
+
this.ctx.direction = styles.direction === 1 /* DIRECTION.RTL */ ? 'rtl' : 'ltr';
|
|
124
|
+
this.ctx.textAlign = 'left';
|
|
125
|
+
this.ctx.textBaseline = 'alphabetic';
|
|
126
|
+
const paintOrder = styles.paintOrder;
|
|
127
|
+
text.textBounds.forEach((text) => {
|
|
128
|
+
paintOrder.forEach((paintOrderLayer) => {
|
|
129
|
+
switch (paintOrderLayer) {
|
|
130
|
+
case 0 /* PAINT_ORDER_LAYER.FILL */:
|
|
131
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.color);
|
|
132
|
+
this.renderTextWithLetterSpacing(text, styles.letterSpacing, styles.fontSize.number);
|
|
133
|
+
const textShadows = styles.textShadow;
|
|
134
|
+
if (textShadows.length && text.text.trim().length) {
|
|
135
|
+
textShadows
|
|
136
|
+
.slice(0)
|
|
137
|
+
.reverse()
|
|
138
|
+
.forEach((textShadow) => {
|
|
139
|
+
this.ctx.shadowColor = (0, color_utilities_1.asString)(textShadow.color);
|
|
140
|
+
this.ctx.shadowOffsetX = textShadow.offsetX.number * this.options.scale;
|
|
141
|
+
this.ctx.shadowOffsetY = textShadow.offsetY.number * this.options.scale;
|
|
142
|
+
this.ctx.shadowBlur = textShadow.blur.number;
|
|
143
|
+
this.renderTextWithLetterSpacing(text, styles.letterSpacing, styles.fontSize.number);
|
|
144
|
+
});
|
|
145
|
+
this.ctx.shadowColor = '';
|
|
146
|
+
this.ctx.shadowOffsetX = 0;
|
|
147
|
+
this.ctx.shadowOffsetY = 0;
|
|
148
|
+
this.ctx.shadowBlur = 0;
|
|
149
|
+
}
|
|
150
|
+
if (styles.textDecorationLine.length) {
|
|
151
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.textDecorationColor || styles.color);
|
|
152
|
+
const decorationLineHeight = 1;
|
|
153
|
+
styles.textDecorationLine.forEach((textDecorationLine) => {
|
|
154
|
+
// Fix the issue where textDecorationLine exhibits x-axis positioning errors on high-resolution devices due to varying devicePixelRatio, corrected by using relative values of element heights.
|
|
155
|
+
switch (textDecorationLine) {
|
|
156
|
+
case 1 /* TEXT_DECORATION_LINE.UNDERLINE */:
|
|
157
|
+
this.ctx.fillRect(text.bounds.left, text.bounds.top + text.bounds.height - decorationLineHeight, text.bounds.width, decorationLineHeight);
|
|
158
|
+
break;
|
|
159
|
+
case 2 /* TEXT_DECORATION_LINE.OVERLINE */:
|
|
160
|
+
this.ctx.fillRect(text.bounds.left, text.bounds.top, text.bounds.width, decorationLineHeight);
|
|
161
|
+
break;
|
|
162
|
+
case 3 /* TEXT_DECORATION_LINE.LINE_THROUGH */:
|
|
163
|
+
this.ctx.fillRect(text.bounds.left, text.bounds.top + (text.bounds.height / 2 - decorationLineHeight / 2), text.bounds.width, decorationLineHeight);
|
|
164
|
+
break;
|
|
264
165
|
}
|
|
265
|
-
|
|
266
|
-
_this.ctx.lineWidth = 0;
|
|
267
|
-
_this.ctx.lineJoin = 'miter';
|
|
268
|
-
break;
|
|
166
|
+
});
|
|
269
167
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
168
|
+
break;
|
|
169
|
+
case 1 /* PAINT_ORDER_LAYER.STROKE */:
|
|
170
|
+
if (styles.webkitTextStrokeWidth && text.text.trim().length) {
|
|
171
|
+
this.ctx.strokeStyle = (0, color_utilities_1.asString)(styles.webkitTextStrokeColor);
|
|
172
|
+
this.ctx.lineWidth = styles.webkitTextStrokeWidth;
|
|
173
|
+
this.ctx.lineJoin = !!window.chrome ? 'miter' : 'round';
|
|
174
|
+
// Issue #110: Use baseline (fontSize) for consistent positioning with fill
|
|
175
|
+
// Previously used text.bounds.height which caused stroke to render too low
|
|
176
|
+
const baseline = styles.fontSize.number;
|
|
177
|
+
if (styles.letterSpacing === 0) {
|
|
178
|
+
this.ctx.strokeText(text.text, text.bounds.left, text.bounds.top + baseline);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const letters = (0, text_1.segmentGraphemes)(text.text);
|
|
182
|
+
letters.reduce((left, letter) => {
|
|
183
|
+
this.ctx.strokeText(letter, left, text.bounds.top + baseline);
|
|
184
|
+
return left + this.ctx.measureText(letter).width;
|
|
185
|
+
}, text.bounds.left);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.ctx.strokeStyle = '';
|
|
189
|
+
this.ctx.lineWidth = 0;
|
|
190
|
+
this.ctx.lineJoin = 'miter';
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
273
193
|
});
|
|
274
194
|
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
195
|
+
}
|
|
196
|
+
renderReplacedElement(container, curves, image) {
|
|
197
|
+
const intrinsicWidth = image.naturalWidth || container.intrinsicWidth;
|
|
198
|
+
const intrinsicHeight = image.naturalHeight || container.intrinsicHeight;
|
|
279
199
|
if (image && intrinsicWidth > 0 && intrinsicHeight > 0) {
|
|
280
|
-
|
|
281
|
-
|
|
200
|
+
const box = (0, box_sizing_1.contentBox)(container);
|
|
201
|
+
const path = (0, bound_curves_1.calculatePaddingBoxPath)(curves);
|
|
282
202
|
this.path(path);
|
|
283
203
|
this.ctx.save();
|
|
284
204
|
this.ctx.clip();
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
205
|
+
let sx = 0, sy = 0, sw = intrinsicWidth, sh = intrinsicHeight, dx = box.left, dy = box.top, dw = box.width, dh = box.height;
|
|
206
|
+
const { objectFit } = container.styles;
|
|
207
|
+
const boxRatio = dw / dh;
|
|
208
|
+
const imgRatio = sw / sh;
|
|
289
209
|
if (objectFit === 2 /* OBJECT_FIT.CONTAIN */) {
|
|
290
210
|
if (imgRatio > boxRatio) {
|
|
291
211
|
dh = dw / imgRatio;
|
|
@@ -325,8 +245,8 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
325
245
|
}
|
|
326
246
|
}
|
|
327
247
|
else if (objectFit === 16 /* OBJECT_FIT.SCALE_DOWN */) {
|
|
328
|
-
|
|
329
|
-
|
|
248
|
+
const containW = imgRatio > boxRatio ? dw : dh * imgRatio;
|
|
249
|
+
const noneW = sw > dw ? sw : dw;
|
|
330
250
|
if (containW < noneW) {
|
|
331
251
|
if (imgRatio > boxRatio) {
|
|
332
252
|
dh = dw / imgRatio;
|
|
@@ -359,718 +279,525 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
359
279
|
this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
360
280
|
this.ctx.restore();
|
|
361
281
|
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
if (container instanceof canvas_element_container_1.CanvasElementContainer) {
|
|
401
|
-
this.renderReplacedElement(container, curves, container.canvas);
|
|
402
|
-
}
|
|
403
|
-
if (!(container instanceof svg_element_container_1.SVGElementContainer)) return [3 /*break*/, 12];
|
|
404
|
-
_c.label = 9;
|
|
405
|
-
case 9:
|
|
406
|
-
_c.trys.push([9, 11, , 12]);
|
|
407
|
-
return [4 /*yield*/, this.context.cache.match(container.svg)];
|
|
408
|
-
case 10:
|
|
409
|
-
image = _c.sent();
|
|
410
|
-
this.renderReplacedElement(container, curves, image);
|
|
411
|
-
return [3 /*break*/, 12];
|
|
412
|
-
case 11:
|
|
413
|
-
e_2 = _c.sent();
|
|
414
|
-
this.context.logger.error("Error loading svg ".concat(container.svg.substring(0, 255)));
|
|
415
|
-
return [3 /*break*/, 12];
|
|
416
|
-
case 12:
|
|
417
|
-
if (!(container instanceof iframe_element_container_1.IFrameElementContainer && container.tree)) return [3 /*break*/, 14];
|
|
418
|
-
iframeRenderer = new CanvasRenderer(this.context, {
|
|
419
|
-
scale: this.options.scale,
|
|
420
|
-
backgroundColor: container.backgroundColor,
|
|
421
|
-
x: 0,
|
|
422
|
-
y: 0,
|
|
423
|
-
width: container.width,
|
|
424
|
-
height: container.height
|
|
425
|
-
});
|
|
426
|
-
return [4 /*yield*/, iframeRenderer.render(container.tree)];
|
|
427
|
-
case 13:
|
|
428
|
-
canvas = _c.sent();
|
|
429
|
-
if (container.width && container.height) {
|
|
430
|
-
this.ctx.drawImage(canvas, 0, 0, container.width, container.height, container.bounds.left, container.bounds.top, container.bounds.width, container.bounds.height);
|
|
431
|
-
}
|
|
432
|
-
_c.label = 14;
|
|
433
|
-
case 14:
|
|
434
|
-
if (container instanceof input_element_container_1.InputElementContainer) {
|
|
435
|
-
size = Math.min(container.bounds.width, container.bounds.height);
|
|
436
|
-
if (container.type === input_element_container_1.CHECKBOX) {
|
|
437
|
-
if (container.checked) {
|
|
438
|
-
this.ctx.save();
|
|
439
|
-
this.path([
|
|
440
|
-
new vector_1.Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79),
|
|
441
|
-
new vector_1.Vector(container.bounds.left + size * 0.16, container.bounds.top + size * 0.5549),
|
|
442
|
-
new vector_1.Vector(container.bounds.left + size * 0.27347, container.bounds.top + size * 0.44071),
|
|
443
|
-
new vector_1.Vector(container.bounds.left + size * 0.39694, container.bounds.top + size * 0.5649),
|
|
444
|
-
new vector_1.Vector(container.bounds.left + size * 0.72983, container.bounds.top + size * 0.23),
|
|
445
|
-
new vector_1.Vector(container.bounds.left + size * 0.84, container.bounds.top + size * 0.34085),
|
|
446
|
-
new vector_1.Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79)
|
|
447
|
-
]);
|
|
448
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(input_element_container_1.INPUT_COLOR);
|
|
449
|
-
this.ctx.fill();
|
|
450
|
-
this.ctx.restore();
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
else if (container.type === input_element_container_1.RADIO) {
|
|
454
|
-
if (container.checked) {
|
|
455
|
-
this.ctx.save();
|
|
456
|
-
this.ctx.beginPath();
|
|
457
|
-
this.ctx.arc(container.bounds.left + size / 2, container.bounds.top + size / 2, size / 4, 0, Math.PI * 2, true);
|
|
458
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(input_element_container_1.INPUT_COLOR);
|
|
459
|
-
this.ctx.fill();
|
|
460
|
-
this.ctx.restore();
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
if (isTextInputElement(container) && container.value.length) {
|
|
465
|
-
_b = this.createFontStyle(styles), font = _b[0], fontFamily = _b[1], fontSize = _b[2];
|
|
466
|
-
baseline = this.fontMetrics.getMetrics(fontFamily, fontSize).baseline;
|
|
467
|
-
this.ctx.font = font;
|
|
468
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.color);
|
|
469
|
-
this.ctx.textBaseline = 'alphabetic';
|
|
470
|
-
this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
|
|
471
|
-
bounds = (0, box_sizing_1.contentBox)(container);
|
|
472
|
-
x = 0;
|
|
473
|
-
switch (container.styles.textAlign) {
|
|
474
|
-
case 1 /* TEXT_ALIGN.CENTER */:
|
|
475
|
-
x += bounds.width / 2;
|
|
476
|
-
break;
|
|
477
|
-
case 2 /* TEXT_ALIGN.RIGHT */:
|
|
478
|
-
x += bounds.width;
|
|
479
|
-
break;
|
|
480
|
-
}
|
|
481
|
-
textBounds = bounds.add(x, 0, 0, -bounds.height / 2 + 1);
|
|
482
|
-
this.ctx.save();
|
|
483
|
-
this.path([
|
|
484
|
-
new vector_1.Vector(bounds.left, bounds.top),
|
|
485
|
-
new vector_1.Vector(bounds.left + bounds.width, bounds.top),
|
|
486
|
-
new vector_1.Vector(bounds.left + bounds.width, bounds.top + bounds.height),
|
|
487
|
-
new vector_1.Vector(bounds.left, bounds.top + bounds.height)
|
|
488
|
-
]);
|
|
489
|
-
this.ctx.clip();
|
|
490
|
-
this.renderTextWithLetterSpacing(new text_1.TextBounds(container.value, textBounds), styles.letterSpacing, baseline);
|
|
491
|
-
this.ctx.restore();
|
|
492
|
-
this.ctx.textBaseline = 'alphabetic';
|
|
493
|
-
this.ctx.textAlign = 'left';
|
|
494
|
-
}
|
|
495
|
-
if (!(0, bitwise_1.contains)(container.styles.display, 2048 /* DISPLAY.LIST_ITEM */)) return [3 /*break*/, 20];
|
|
496
|
-
if (!(container.styles.listStyleImage !== null)) return [3 /*break*/, 19];
|
|
497
|
-
img = container.styles.listStyleImage;
|
|
498
|
-
if (!(img.type === 0 /* CSSImageType.URL */)) return [3 /*break*/, 18];
|
|
499
|
-
image = void 0;
|
|
500
|
-
url = img.url;
|
|
501
|
-
_c.label = 15;
|
|
502
|
-
case 15:
|
|
503
|
-
_c.trys.push([15, 17, , 18]);
|
|
504
|
-
return [4 /*yield*/, this.context.cache.match(url)];
|
|
505
|
-
case 16:
|
|
506
|
-
image = _c.sent();
|
|
507
|
-
this.ctx.drawImage(image, container.bounds.left - (image.width + 10), container.bounds.top);
|
|
508
|
-
return [3 /*break*/, 18];
|
|
509
|
-
case 17:
|
|
510
|
-
e_3 = _c.sent();
|
|
511
|
-
this.context.logger.error("Error loading list-style-image ".concat(url));
|
|
512
|
-
return [3 /*break*/, 18];
|
|
513
|
-
case 18: return [3 /*break*/, 20];
|
|
514
|
-
case 19:
|
|
515
|
-
if (paint.listValue && container.styles.listStyleType !== -1 /* LIST_STYLE_TYPE.NONE */) {
|
|
516
|
-
font = this.createFontStyle(styles)[0];
|
|
517
|
-
this.ctx.font = font;
|
|
518
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.color);
|
|
519
|
-
this.ctx.textBaseline = 'middle';
|
|
520
|
-
this.ctx.textAlign = 'right';
|
|
521
|
-
bounds = new bounds_1.Bounds(container.bounds.left, container.bounds.top + (0, length_percentage_1.getAbsoluteValue)(container.styles.paddingTop, container.bounds.width), container.bounds.width, (0, line_height_1.computeLineHeight)(styles.lineHeight, styles.fontSize.number) / 2 + 1);
|
|
522
|
-
this.renderTextWithLetterSpacing(new text_1.TextBounds(paint.listValue, bounds), styles.letterSpacing, (0, line_height_1.computeLineHeight)(styles.lineHeight, styles.fontSize.number) / 2 + 2);
|
|
523
|
-
this.ctx.textBaseline = 'bottom';
|
|
524
|
-
this.ctx.textAlign = 'left';
|
|
525
|
-
}
|
|
526
|
-
_c.label = 20;
|
|
527
|
-
case 20: return [2 /*return*/];
|
|
528
|
-
}
|
|
282
|
+
}
|
|
283
|
+
async renderNodeContent(paint) {
|
|
284
|
+
this.applyEffects(paint.getEffects(4 /* EffectTarget.CONTENT */));
|
|
285
|
+
const container = paint.container;
|
|
286
|
+
const curves = paint.curves;
|
|
287
|
+
const styles = container.styles;
|
|
288
|
+
for (const child of container.textNodes) {
|
|
289
|
+
await this.renderTextNode(child, styles);
|
|
290
|
+
}
|
|
291
|
+
if (container instanceof image_element_container_1.ImageElementContainer) {
|
|
292
|
+
try {
|
|
293
|
+
const image = await this.context.cache.match(container.src);
|
|
294
|
+
this.renderReplacedElement(container, curves, image);
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
this.context.logger.error(`Error loading image ${container.src}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (container instanceof canvas_element_container_1.CanvasElementContainer) {
|
|
301
|
+
this.renderReplacedElement(container, curves, container.canvas);
|
|
302
|
+
}
|
|
303
|
+
if (container instanceof svg_element_container_1.SVGElementContainer) {
|
|
304
|
+
try {
|
|
305
|
+
const image = await this.context.cache.match(container.svg);
|
|
306
|
+
this.renderReplacedElement(container, curves, image);
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
this.context.logger.error(`Error loading svg ${container.svg.substring(0, 255)}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (container instanceof iframe_element_container_1.IFrameElementContainer && container.tree) {
|
|
313
|
+
const iframeRenderer = new CanvasRenderer(this.context, {
|
|
314
|
+
scale: this.options.scale,
|
|
315
|
+
backgroundColor: container.backgroundColor,
|
|
316
|
+
x: 0,
|
|
317
|
+
y: 0,
|
|
318
|
+
width: container.width,
|
|
319
|
+
height: container.height
|
|
529
320
|
});
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
child = _a[_i];
|
|
553
|
-
return [4 /*yield*/, this.renderStack(child)];
|
|
554
|
-
case 3:
|
|
555
|
-
_p.sent();
|
|
556
|
-
_p.label = 4;
|
|
557
|
-
case 4:
|
|
558
|
-
_i++;
|
|
559
|
-
return [3 /*break*/, 2];
|
|
560
|
-
case 5:
|
|
561
|
-
// 3. For all its in-flow, non-positioned, block-level descendants in tree order:
|
|
562
|
-
return [4 /*yield*/, this.renderNodeContent(stack.element)];
|
|
563
|
-
case 6:
|
|
564
|
-
// 3. For all its in-flow, non-positioned, block-level descendants in tree order:
|
|
565
|
-
_p.sent();
|
|
566
|
-
_b = 0, _c = stack.nonInlineLevel;
|
|
567
|
-
_p.label = 7;
|
|
568
|
-
case 7:
|
|
569
|
-
if (!(_b < _c.length)) return [3 /*break*/, 10];
|
|
570
|
-
child = _c[_b];
|
|
571
|
-
return [4 /*yield*/, this.renderNode(child)];
|
|
572
|
-
case 8:
|
|
573
|
-
_p.sent();
|
|
574
|
-
_p.label = 9;
|
|
575
|
-
case 9:
|
|
576
|
-
_b++;
|
|
577
|
-
return [3 /*break*/, 7];
|
|
578
|
-
case 10:
|
|
579
|
-
_d = 0, _e = stack.nonPositionedFloats;
|
|
580
|
-
_p.label = 11;
|
|
581
|
-
case 11:
|
|
582
|
-
if (!(_d < _e.length)) return [3 /*break*/, 14];
|
|
583
|
-
child = _e[_d];
|
|
584
|
-
return [4 /*yield*/, this.renderStack(child)];
|
|
585
|
-
case 12:
|
|
586
|
-
_p.sent();
|
|
587
|
-
_p.label = 13;
|
|
588
|
-
case 13:
|
|
589
|
-
_d++;
|
|
590
|
-
return [3 /*break*/, 11];
|
|
591
|
-
case 14:
|
|
592
|
-
_f = 0, _g = stack.nonPositionedInlineLevel;
|
|
593
|
-
_p.label = 15;
|
|
594
|
-
case 15:
|
|
595
|
-
if (!(_f < _g.length)) return [3 /*break*/, 18];
|
|
596
|
-
child = _g[_f];
|
|
597
|
-
return [4 /*yield*/, this.renderStack(child)];
|
|
598
|
-
case 16:
|
|
599
|
-
_p.sent();
|
|
600
|
-
_p.label = 17;
|
|
601
|
-
case 17:
|
|
602
|
-
_f++;
|
|
603
|
-
return [3 /*break*/, 15];
|
|
604
|
-
case 18:
|
|
605
|
-
_h = 0, _j = stack.inlineLevel;
|
|
606
|
-
_p.label = 19;
|
|
607
|
-
case 19:
|
|
608
|
-
if (!(_h < _j.length)) return [3 /*break*/, 22];
|
|
609
|
-
child = _j[_h];
|
|
610
|
-
return [4 /*yield*/, this.renderNode(child)];
|
|
611
|
-
case 20:
|
|
612
|
-
_p.sent();
|
|
613
|
-
_p.label = 21;
|
|
614
|
-
case 21:
|
|
615
|
-
_h++;
|
|
616
|
-
return [3 /*break*/, 19];
|
|
617
|
-
case 22:
|
|
618
|
-
_k = 0, _l = stack.zeroOrAutoZIndexOrTransformedOrOpacity;
|
|
619
|
-
_p.label = 23;
|
|
620
|
-
case 23:
|
|
621
|
-
if (!(_k < _l.length)) return [3 /*break*/, 26];
|
|
622
|
-
child = _l[_k];
|
|
623
|
-
return [4 /*yield*/, this.renderStack(child)];
|
|
624
|
-
case 24:
|
|
625
|
-
_p.sent();
|
|
626
|
-
_p.label = 25;
|
|
627
|
-
case 25:
|
|
628
|
-
_k++;
|
|
629
|
-
return [3 /*break*/, 23];
|
|
630
|
-
case 26:
|
|
631
|
-
_m = 0, _o = stack.positiveZIndex;
|
|
632
|
-
_p.label = 27;
|
|
633
|
-
case 27:
|
|
634
|
-
if (!(_m < _o.length)) return [3 /*break*/, 30];
|
|
635
|
-
child = _o[_m];
|
|
636
|
-
return [4 /*yield*/, this.renderStack(child)];
|
|
637
|
-
case 28:
|
|
638
|
-
_p.sent();
|
|
639
|
-
_p.label = 29;
|
|
640
|
-
case 29:
|
|
641
|
-
_m++;
|
|
642
|
-
return [3 /*break*/, 27];
|
|
643
|
-
case 30: return [2 /*return*/];
|
|
321
|
+
const canvas = await iframeRenderer.render(container.tree);
|
|
322
|
+
if (container.width && container.height) {
|
|
323
|
+
this.ctx.drawImage(canvas, 0, 0, container.width, container.height, container.bounds.left, container.bounds.top, container.bounds.width, container.bounds.height);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (container instanceof input_element_container_1.InputElementContainer) {
|
|
327
|
+
const size = Math.min(container.bounds.width, container.bounds.height);
|
|
328
|
+
if (container.type === input_element_container_1.CHECKBOX) {
|
|
329
|
+
if (container.checked) {
|
|
330
|
+
this.ctx.save();
|
|
331
|
+
this.path([
|
|
332
|
+
new vector_1.Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79),
|
|
333
|
+
new vector_1.Vector(container.bounds.left + size * 0.16, container.bounds.top + size * 0.5549),
|
|
334
|
+
new vector_1.Vector(container.bounds.left + size * 0.27347, container.bounds.top + size * 0.44071),
|
|
335
|
+
new vector_1.Vector(container.bounds.left + size * 0.39694, container.bounds.top + size * 0.5649),
|
|
336
|
+
new vector_1.Vector(container.bounds.left + size * 0.72983, container.bounds.top + size * 0.23),
|
|
337
|
+
new vector_1.Vector(container.bounds.left + size * 0.84, container.bounds.top + size * 0.34085),
|
|
338
|
+
new vector_1.Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79)
|
|
339
|
+
]);
|
|
340
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(input_element_container_1.INPUT_COLOR);
|
|
341
|
+
this.ctx.fill();
|
|
342
|
+
this.ctx.restore();
|
|
644
343
|
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
344
|
+
}
|
|
345
|
+
else if (container.type === input_element_container_1.RADIO) {
|
|
346
|
+
if (container.checked) {
|
|
347
|
+
this.ctx.save();
|
|
348
|
+
this.ctx.beginPath();
|
|
349
|
+
this.ctx.arc(container.bounds.left + size / 2, container.bounds.top + size / 2, size / 4, 0, Math.PI * 2, true);
|
|
350
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(input_element_container_1.INPUT_COLOR);
|
|
351
|
+
this.ctx.fill();
|
|
352
|
+
this.ctx.restore();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (isTextInputElement(container) && container.value.length) {
|
|
357
|
+
const [font, fontFamily, fontSize] = this.createFontStyle(styles);
|
|
358
|
+
const { baseline } = this.fontMetrics.getMetrics(fontFamily, fontSize);
|
|
359
|
+
this.ctx.font = font;
|
|
360
|
+
// Fix for Issue #92: Use placeholder color when rendering placeholder text
|
|
361
|
+
const isPlaceholder = container instanceof input_element_container_1.InputElementContainer && container.isPlaceholder;
|
|
362
|
+
this.ctx.fillStyle = isPlaceholder ? (0, color_utilities_1.asString)(input_element_container_1.PLACEHOLDER_COLOR) : (0, color_utilities_1.asString)(styles.color);
|
|
363
|
+
this.ctx.textBaseline = 'alphabetic';
|
|
364
|
+
this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
|
|
365
|
+
const bounds = (0, box_sizing_1.contentBox)(container);
|
|
366
|
+
let x = 0;
|
|
367
|
+
switch (container.styles.textAlign) {
|
|
368
|
+
case 1 /* TEXT_ALIGN.CENTER */:
|
|
369
|
+
x += bounds.width / 2;
|
|
370
|
+
break;
|
|
371
|
+
case 2 /* TEXT_ALIGN.RIGHT */:
|
|
372
|
+
x += bounds.width;
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
// Fix for Issue #92: Position text vertically centered in single-line input
|
|
376
|
+
// Only apply vertical centering for InputElementContainer, not for textarea or select
|
|
377
|
+
let verticalOffset = 0;
|
|
378
|
+
if (container instanceof input_element_container_1.InputElementContainer) {
|
|
379
|
+
const fontSizeValue = (0, length_percentage_1.getAbsoluteValue)(styles.fontSize, 0);
|
|
380
|
+
verticalOffset = (bounds.height - fontSizeValue) / 2;
|
|
381
|
+
}
|
|
382
|
+
// Create text bounds with horizontal and vertical offsets
|
|
383
|
+
// Height is not modified as it doesn't affect text rendering position
|
|
384
|
+
const textBounds = bounds.add(x, verticalOffset, 0, 0);
|
|
385
|
+
this.ctx.save();
|
|
386
|
+
this.path([
|
|
387
|
+
new vector_1.Vector(bounds.left, bounds.top),
|
|
388
|
+
new vector_1.Vector(bounds.left + bounds.width, bounds.top),
|
|
389
|
+
new vector_1.Vector(bounds.left + bounds.width, bounds.top + bounds.height),
|
|
390
|
+
new vector_1.Vector(bounds.left, bounds.top + bounds.height)
|
|
391
|
+
]);
|
|
392
|
+
this.ctx.clip();
|
|
393
|
+
this.renderTextWithLetterSpacing(new text_1.TextBounds(container.value, textBounds), styles.letterSpacing, baseline);
|
|
394
|
+
this.ctx.restore();
|
|
395
|
+
this.ctx.textBaseline = 'alphabetic';
|
|
396
|
+
this.ctx.textAlign = 'left';
|
|
397
|
+
}
|
|
398
|
+
if ((0, bitwise_1.contains)(container.styles.display, 2048 /* DISPLAY.LIST_ITEM */)) {
|
|
399
|
+
if (container.styles.listStyleImage !== null) {
|
|
400
|
+
const img = container.styles.listStyleImage;
|
|
401
|
+
if (img.type === 0 /* CSSImageType.URL */) {
|
|
402
|
+
let image;
|
|
403
|
+
const url = img.url;
|
|
404
|
+
try {
|
|
405
|
+
image = await this.context.cache.match(url);
|
|
406
|
+
this.ctx.drawImage(image, container.bounds.left - (image.width + 10), container.bounds.top);
|
|
407
|
+
}
|
|
408
|
+
catch (e) {
|
|
409
|
+
this.context.logger.error(`Error loading list-style-image ${url}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else if (paint.listValue && container.styles.listStyleType !== -1 /* LIST_STYLE_TYPE.NONE */) {
|
|
414
|
+
const [font] = this.createFontStyle(styles);
|
|
415
|
+
this.ctx.font = font;
|
|
416
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.color);
|
|
417
|
+
this.ctx.textBaseline = 'middle';
|
|
418
|
+
this.ctx.textAlign = 'right';
|
|
419
|
+
const bounds = new bounds_1.Bounds(container.bounds.left, container.bounds.top + (0, length_percentage_1.getAbsoluteValue)(container.styles.paddingTop, container.bounds.width), container.bounds.width, (0, line_height_1.computeLineHeight)(styles.lineHeight, styles.fontSize.number) / 2 + 1);
|
|
420
|
+
this.renderTextWithLetterSpacing(new text_1.TextBounds(paint.listValue, bounds), styles.letterSpacing, (0, line_height_1.computeLineHeight)(styles.lineHeight, styles.fontSize.number) / 2 + 2);
|
|
421
|
+
this.ctx.textBaseline = 'bottom';
|
|
422
|
+
this.ctx.textAlign = 'left';
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
async renderStackContent(stack) {
|
|
427
|
+
if ((0, bitwise_1.contains)(stack.element.container.flags, 16 /* FLAGS.DEBUG_RENDER */)) {
|
|
428
|
+
debugger;
|
|
429
|
+
}
|
|
430
|
+
// https://www.w3.org/TR/css-position-3/#painting-order
|
|
431
|
+
// 1. the background and borders of the element forming the stacking context.
|
|
432
|
+
await this.renderNodeBackgroundAndBorders(stack.element);
|
|
433
|
+
// 2. the child stacking contexts with negative stack levels (most negative first).
|
|
434
|
+
for (const child of stack.negativeZIndex) {
|
|
435
|
+
await this.renderStack(child);
|
|
436
|
+
}
|
|
437
|
+
// 3. For all its in-flow, non-positioned, block-level descendants in tree order:
|
|
438
|
+
await this.renderNodeContent(stack.element);
|
|
439
|
+
for (const child of stack.nonInlineLevel) {
|
|
440
|
+
await this.renderNode(child);
|
|
441
|
+
}
|
|
442
|
+
// 4. All non-positioned floating descendants, in tree order. For each one of these,
|
|
443
|
+
// treat the element as if it created a new stacking context, but any positioned descendants and descendants
|
|
444
|
+
// which actually create a new stacking context should be considered part of the parent stacking context,
|
|
445
|
+
// not this new one.
|
|
446
|
+
for (const child of stack.nonPositionedFloats) {
|
|
447
|
+
await this.renderStack(child);
|
|
448
|
+
}
|
|
449
|
+
// 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
|
|
450
|
+
for (const child of stack.nonPositionedInlineLevel) {
|
|
451
|
+
await this.renderStack(child);
|
|
452
|
+
}
|
|
453
|
+
for (const child of stack.inlineLevel) {
|
|
454
|
+
await this.renderNode(child);
|
|
455
|
+
}
|
|
456
|
+
// 6. All positioned, opacity or transform descendants, in tree order that fall into the following categories:
|
|
457
|
+
// All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
|
|
458
|
+
// For those with 'z-index: auto', treat the element as if it created a new stacking context,
|
|
459
|
+
// but any positioned descendants and descendants which actually create a new stacking context should be
|
|
460
|
+
// considered part of the parent stacking context, not this new one. For those with 'z-index: 0',
|
|
461
|
+
// treat the stacking context generated atomically.
|
|
462
|
+
//
|
|
463
|
+
// All opacity descendants with opacity less than 1
|
|
464
|
+
//
|
|
465
|
+
// All transform descendants with transform other than none
|
|
466
|
+
for (const child of stack.zeroOrAutoZIndexOrTransformedOrOpacity) {
|
|
467
|
+
await this.renderStack(child);
|
|
468
|
+
}
|
|
469
|
+
// 7. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index
|
|
470
|
+
// order (smallest first) then tree order.
|
|
471
|
+
for (const child of stack.positiveZIndex) {
|
|
472
|
+
await this.renderStack(child);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
mask(paths) {
|
|
649
476
|
this.ctx.beginPath();
|
|
650
477
|
this.ctx.moveTo(0, 0);
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
478
|
+
// Use logical dimensions (options.width/height) instead of canvas pixel dimensions
|
|
479
|
+
// because context has already been scaled by this.options.scale
|
|
480
|
+
// Fix for Issue #126: Using canvas pixel dimensions causes broken output
|
|
481
|
+
this.ctx.lineTo(this.options.width, 0);
|
|
482
|
+
this.ctx.lineTo(this.options.width, this.options.height);
|
|
483
|
+
this.ctx.lineTo(0, this.options.height);
|
|
654
484
|
this.ctx.lineTo(0, 0);
|
|
655
485
|
this.formatPath(paths.slice(0).reverse());
|
|
656
486
|
this.ctx.closePath();
|
|
657
|
-
}
|
|
658
|
-
|
|
487
|
+
}
|
|
488
|
+
path(paths) {
|
|
659
489
|
this.ctx.beginPath();
|
|
660
490
|
this.formatPath(paths);
|
|
661
491
|
this.ctx.closePath();
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
var start = (0, bezier_curve_1.isBezierCurve)(point) ? point.start : point;
|
|
492
|
+
}
|
|
493
|
+
formatPath(paths) {
|
|
494
|
+
paths.forEach((point, index) => {
|
|
495
|
+
const start = (0, bezier_curve_1.isBezierCurve)(point) ? point.start : point;
|
|
667
496
|
if (index === 0) {
|
|
668
|
-
|
|
497
|
+
this.ctx.moveTo(start.x, start.y);
|
|
669
498
|
}
|
|
670
499
|
else {
|
|
671
|
-
|
|
500
|
+
this.ctx.lineTo(start.x, start.y);
|
|
672
501
|
}
|
|
673
502
|
if ((0, bezier_curve_1.isBezierCurve)(point)) {
|
|
674
|
-
|
|
503
|
+
this.ctx.bezierCurveTo(point.startControl.x, point.startControl.y, point.endControl.x, point.endControl.y, point.end.x, point.end.y);
|
|
675
504
|
}
|
|
676
505
|
});
|
|
677
|
-
}
|
|
678
|
-
|
|
506
|
+
}
|
|
507
|
+
renderRepeat(path, pattern, offsetX, offsetY) {
|
|
679
508
|
this.path(path);
|
|
680
509
|
this.ctx.fillStyle = pattern;
|
|
681
510
|
this.ctx.translate(offsetX, offsetY);
|
|
682
511
|
this.ctx.fill();
|
|
683
512
|
this.ctx.translate(-offsetX, -offsetY);
|
|
684
|
-
}
|
|
685
|
-
|
|
513
|
+
}
|
|
514
|
+
resizeImage(image, width, height) {
|
|
686
515
|
// https://github.com/niklasvh/html2canvas/pull/2911
|
|
687
516
|
// if (image.width === width && image.height === height) {
|
|
688
517
|
// return image;
|
|
689
518
|
// }
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
var canvas = ownerDocument.createElement('canvas');
|
|
519
|
+
const ownerDocument = this.canvas.ownerDocument ?? document;
|
|
520
|
+
const canvas = ownerDocument.createElement('canvas');
|
|
693
521
|
canvas.width = Math.max(1, width);
|
|
694
522
|
canvas.height = Math.max(1, height);
|
|
695
|
-
|
|
523
|
+
const ctx = canvas.getContext('2d');
|
|
696
524
|
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);
|
|
697
525
|
return canvas;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
case 3:
|
|
722
|
-
e_4 = _h.sent();
|
|
723
|
-
this_1.context.logger.error("Error loading background-image ".concat(url));
|
|
724
|
-
return [3 /*break*/, 4];
|
|
725
|
-
case 4:
|
|
726
|
-
if (image) {
|
|
727
|
-
imageWidth = isNaN(image.width) || image.width === 0 ? 1 : image.width;
|
|
728
|
-
imageHeight = isNaN(image.height) || image.height === 0 ? 1 : image.height;
|
|
729
|
-
_c = (0, background_1.calculateBackgroundRendering)(container, index, [
|
|
730
|
-
imageWidth,
|
|
731
|
-
imageHeight,
|
|
732
|
-
imageWidth / imageHeight
|
|
733
|
-
]), path = _c[0], x = _c[1], y = _c[2], width = _c[3], height = _c[4];
|
|
734
|
-
pattern = this_1.ctx.createPattern(this_1.resizeImage(image, width, height), 'repeat');
|
|
735
|
-
this_1.renderRepeat(path, pattern, x, y);
|
|
736
|
-
}
|
|
737
|
-
return [3 /*break*/, 6];
|
|
738
|
-
case 5:
|
|
739
|
-
if ((0, image_1.isLinearGradient)(backgroundImage)) {
|
|
740
|
-
_d = (0, background_1.calculateBackgroundRendering)(container, index, [null, null, null]), path = _d[0], x = _d[1], y = _d[2], width = _d[3], height = _d[4];
|
|
741
|
-
_e = (0, gradient_1.calculateGradientDirection)(backgroundImage.angle, width, height), lineLength = _e[0], x0 = _e[1], x1 = _e[2], y0 = _e[3], y1 = _e[4];
|
|
742
|
-
canvas = document.createElement('canvas');
|
|
743
|
-
canvas.width = width;
|
|
744
|
-
canvas.height = height;
|
|
745
|
-
ctx = canvas.getContext('2d');
|
|
746
|
-
gradient_2 = ctx.createLinearGradient(x0, y0, x1, y1);
|
|
747
|
-
(0, gradient_1.processColorStops)(backgroundImage.stops, lineLength || 1).forEach(function (colorStop) {
|
|
748
|
-
return gradient_2.addColorStop(colorStop.stop, (0, color_utilities_1.asString)(colorStop.color));
|
|
749
|
-
});
|
|
750
|
-
ctx.fillStyle = gradient_2;
|
|
751
|
-
ctx.fillRect(0, 0, width, height);
|
|
752
|
-
if (width > 0 && height > 0) {
|
|
753
|
-
pattern = this_1.ctx.createPattern(canvas, 'repeat');
|
|
754
|
-
this_1.renderRepeat(path, pattern, x, y);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
else if ((0, image_1.isRadialGradient)(backgroundImage)) {
|
|
758
|
-
_f = (0, background_1.calculateBackgroundRendering)(container, index, [
|
|
759
|
-
null,
|
|
760
|
-
null,
|
|
761
|
-
null
|
|
762
|
-
]), path = _f[0], left = _f[1], top_1 = _f[2], width = _f[3], height = _f[4];
|
|
763
|
-
position = backgroundImage.position.length === 0 ? [length_percentage_1.FIFTY_PERCENT] : backgroundImage.position;
|
|
764
|
-
x = (0, length_percentage_1.getAbsoluteValue)(position[0], width);
|
|
765
|
-
y = (0, length_percentage_1.getAbsoluteValue)(position[position.length - 1], height);
|
|
766
|
-
_g = (0, gradient_1.calculateRadius)(backgroundImage, x, y, width, height), rx = _g[0], ry = _g[1];
|
|
767
|
-
if (rx > 0 && ry > 0) {
|
|
768
|
-
radialGradient_1 = this_1.ctx.createRadialGradient(left + x, top_1 + y, 0, left + x, top_1 + y, rx);
|
|
769
|
-
(0, gradient_1.processColorStops)(backgroundImage.stops, rx * 2).forEach(function (colorStop) {
|
|
770
|
-
return radialGradient_1.addColorStop(colorStop.stop, (0, color_utilities_1.asString)(colorStop.color));
|
|
771
|
-
});
|
|
772
|
-
this_1.path(path);
|
|
773
|
-
this_1.ctx.fillStyle = radialGradient_1;
|
|
774
|
-
if (rx !== ry) {
|
|
775
|
-
midX = container.bounds.left + 0.5 * container.bounds.width;
|
|
776
|
-
midY = container.bounds.top + 0.5 * container.bounds.height;
|
|
777
|
-
f = ry / rx;
|
|
778
|
-
invF = 1 / f;
|
|
779
|
-
this_1.ctx.save();
|
|
780
|
-
this_1.ctx.translate(midX, midY);
|
|
781
|
-
this_1.ctx.transform(1, 0, 0, f, 0, 0);
|
|
782
|
-
this_1.ctx.translate(-midX, -midY);
|
|
783
|
-
this_1.ctx.fillRect(left, invF * (top_1 - midY) + midY, width, height * invF);
|
|
784
|
-
this_1.ctx.restore();
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
this_1.ctx.fill();
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
_h.label = 6;
|
|
792
|
-
case 6:
|
|
793
|
-
index--;
|
|
794
|
-
return [2 /*return*/];
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
};
|
|
798
|
-
this_1 = this;
|
|
799
|
-
_i = 0, _a = container.styles.backgroundImage.slice(0).reverse();
|
|
800
|
-
_b.label = 1;
|
|
801
|
-
case 1:
|
|
802
|
-
if (!(_i < _a.length)) return [3 /*break*/, 4];
|
|
803
|
-
backgroundImage = _a[_i];
|
|
804
|
-
return [5 /*yield**/, _loop_1(backgroundImage)];
|
|
805
|
-
case 2:
|
|
806
|
-
_b.sent();
|
|
807
|
-
_b.label = 3;
|
|
808
|
-
case 3:
|
|
809
|
-
_i++;
|
|
810
|
-
return [3 /*break*/, 1];
|
|
811
|
-
case 4: return [2 /*return*/];
|
|
526
|
+
}
|
|
527
|
+
async renderBackgroundImage(container) {
|
|
528
|
+
let index = container.styles.backgroundImage.length - 1;
|
|
529
|
+
for (const backgroundImage of container.styles.backgroundImage.slice(0).reverse()) {
|
|
530
|
+
if (backgroundImage.type === 0 /* CSSImageType.URL */) {
|
|
531
|
+
let image;
|
|
532
|
+
const url = backgroundImage.url;
|
|
533
|
+
try {
|
|
534
|
+
image = await this.context.cache.match(url);
|
|
535
|
+
}
|
|
536
|
+
catch (e) {
|
|
537
|
+
this.context.logger.error(`Error loading background-image ${url}`);
|
|
538
|
+
}
|
|
539
|
+
if (image) {
|
|
540
|
+
const imageWidth = isNaN(image.width) || image.width === 0 ? 1 : image.width;
|
|
541
|
+
const imageHeight = isNaN(image.height) || image.height === 0 ? 1 : image.height;
|
|
542
|
+
const [path, x, y, width, height] = (0, background_1.calculateBackgroundRendering)(container, index, [
|
|
543
|
+
imageWidth,
|
|
544
|
+
imageHeight,
|
|
545
|
+
imageWidth / imageHeight
|
|
546
|
+
]);
|
|
547
|
+
const pattern = this.ctx.createPattern(this.resizeImage(image, width, height), 'repeat');
|
|
548
|
+
this.renderRepeat(path, pattern, x, y);
|
|
812
549
|
}
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
var outerPaths, innerPaths;
|
|
829
|
-
return __generator(this, function (_a) {
|
|
830
|
-
switch (_a.label) {
|
|
831
|
-
case 0:
|
|
832
|
-
if (!(width < 3)) return [3 /*break*/, 2];
|
|
833
|
-
return [4 /*yield*/, this.renderSolidBorder(color, side, curvePoints)];
|
|
834
|
-
case 1:
|
|
835
|
-
_a.sent();
|
|
836
|
-
return [2 /*return*/];
|
|
837
|
-
case 2:
|
|
838
|
-
outerPaths = (0, border_1.parsePathForBorderDoubleOuter)(curvePoints, side);
|
|
839
|
-
this.path(outerPaths);
|
|
840
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(color);
|
|
841
|
-
this.ctx.fill();
|
|
842
|
-
innerPaths = (0, border_1.parsePathForBorderDoubleInner)(curvePoints, side);
|
|
843
|
-
this.path(innerPaths);
|
|
844
|
-
this.ctx.fill();
|
|
845
|
-
return [2 /*return*/];
|
|
550
|
+
}
|
|
551
|
+
else if ((0, image_1.isLinearGradient)(backgroundImage)) {
|
|
552
|
+
const [path, x, y, width, height] = (0, background_1.calculateBackgroundRendering)(container, index, [null, null, null]);
|
|
553
|
+
const [lineLength, x0, x1, y0, y1] = (0, gradient_1.calculateGradientDirection)(backgroundImage.angle, width, height);
|
|
554
|
+
const canvas = document.createElement('canvas');
|
|
555
|
+
canvas.width = width;
|
|
556
|
+
canvas.height = height;
|
|
557
|
+
const ctx = canvas.getContext('2d');
|
|
558
|
+
const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
|
|
559
|
+
(0, gradient_1.processColorStops)(backgroundImage.stops, lineLength || 1).forEach((colorStop) => gradient.addColorStop(colorStop.stop, (0, color_utilities_1.asString)(colorStop.color)));
|
|
560
|
+
ctx.fillStyle = gradient;
|
|
561
|
+
ctx.fillRect(0, 0, width, height);
|
|
562
|
+
if (width > 0 && height > 0) {
|
|
563
|
+
const pattern = this.ctx.createPattern(canvas, 'repeat');
|
|
564
|
+
this.renderRepeat(path, pattern, x, y);
|
|
846
565
|
}
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
566
|
+
}
|
|
567
|
+
else if ((0, image_1.isRadialGradient)(backgroundImage)) {
|
|
568
|
+
const [path, left, top, width, height] = (0, background_1.calculateBackgroundRendering)(container, index, [
|
|
569
|
+
null,
|
|
570
|
+
null,
|
|
571
|
+
null
|
|
572
|
+
]);
|
|
573
|
+
const position = backgroundImage.position.length === 0 ? [length_percentage_1.FIFTY_PERCENT] : backgroundImage.position;
|
|
574
|
+
const x = (0, length_percentage_1.getAbsoluteValue)(position[0], width);
|
|
575
|
+
const y = (0, length_percentage_1.getAbsoluteValue)(position[position.length - 1], height);
|
|
576
|
+
const [rx, ry] = (0, gradient_1.calculateRadius)(backgroundImage, x, y, width, height);
|
|
577
|
+
if (rx > 0 && ry > 0) {
|
|
578
|
+
const radialGradient = this.ctx.createRadialGradient(left + x, top + y, 0, left + x, top + y, rx);
|
|
579
|
+
(0, gradient_1.processColorStops)(backgroundImage.stops, rx * 2).forEach((colorStop) => radialGradient.addColorStop(colorStop.stop, (0, color_utilities_1.asString)(colorStop.color)));
|
|
580
|
+
this.path(path);
|
|
581
|
+
this.ctx.fillStyle = radialGradient;
|
|
582
|
+
if (rx !== ry) {
|
|
583
|
+
// transforms for elliptical radial gradient
|
|
584
|
+
const midX = container.bounds.left + 0.5 * container.bounds.width;
|
|
585
|
+
const midY = container.bounds.top + 0.5 * container.bounds.height;
|
|
586
|
+
const f = ry / rx;
|
|
587
|
+
const invF = 1 / f;
|
|
868
588
|
this.ctx.save();
|
|
869
|
-
this.
|
|
870
|
-
this.ctx.
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
this.ctx.fill();
|
|
874
|
-
}
|
|
875
|
-
return [4 /*yield*/, this.renderBackgroundImage(paint.container)];
|
|
876
|
-
case 1:
|
|
877
|
-
_a.sent();
|
|
589
|
+
this.ctx.translate(midX, midY);
|
|
590
|
+
this.ctx.transform(1, 0, 0, f, 0, 0);
|
|
591
|
+
this.ctx.translate(-midX, -midY);
|
|
592
|
+
this.ctx.fillRect(left, invF * (top - midY) + midY, width, height * invF);
|
|
878
593
|
this.ctx.restore();
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
_this.ctx.save();
|
|
884
|
-
var borderBoxArea = (0, bound_curves_1.calculateBorderBoxPath)(paint.curves);
|
|
885
|
-
var maskOffset = shadow.inset ? 0 : MASK_OFFSET;
|
|
886
|
-
var shadowPaintingArea = (0, path_1.transformPath)(borderBoxArea, -maskOffset + (shadow.inset ? 1 : -1) * shadow.spread.number, (shadow.inset ? 1 : -1) * shadow.spread.number, shadow.spread.number * (shadow.inset ? -2 : 2), shadow.spread.number * (shadow.inset ? -2 : 2));
|
|
887
|
-
if (shadow.inset) {
|
|
888
|
-
_this.path(borderBoxArea);
|
|
889
|
-
_this.ctx.clip();
|
|
890
|
-
_this.mask(shadowPaintingArea);
|
|
891
|
-
}
|
|
892
|
-
else {
|
|
893
|
-
_this.mask(borderBoxArea);
|
|
894
|
-
_this.ctx.clip();
|
|
895
|
-
_this.path(shadowPaintingArea);
|
|
896
|
-
}
|
|
897
|
-
_this.ctx.shadowOffsetX = shadow.offsetX.number + maskOffset;
|
|
898
|
-
_this.ctx.shadowOffsetY = shadow.offsetY.number;
|
|
899
|
-
_this.ctx.shadowColor = (0, color_utilities_1.asString)(shadow.color);
|
|
900
|
-
_this.ctx.shadowBlur = shadow.blur.number;
|
|
901
|
-
_this.ctx.fillStyle = shadow.inset ? (0, color_utilities_1.asString)(shadow.color) : 'rgba(0,0,0,1)';
|
|
902
|
-
_this.ctx.fill();
|
|
903
|
-
_this.ctx.restore();
|
|
904
|
-
});
|
|
905
|
-
_a.label = 2;
|
|
906
|
-
case 2:
|
|
907
|
-
side = 0;
|
|
908
|
-
_i = 0, borders_1 = borders;
|
|
909
|
-
_a.label = 3;
|
|
910
|
-
case 3:
|
|
911
|
-
if (!(_i < borders_1.length)) return [3 /*break*/, 13];
|
|
912
|
-
border = borders_1[_i];
|
|
913
|
-
if (!(border.style !== 0 /* BORDER_STYLE.NONE */ && !(0, color_utilities_1.isTransparent)(border.color) && border.width > 0)) return [3 /*break*/, 11];
|
|
914
|
-
if (!(border.style === 2 /* BORDER_STYLE.DASHED */)) return [3 /*break*/, 5];
|
|
915
|
-
return [4 /*yield*/, this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 2 /* BORDER_STYLE.DASHED */)];
|
|
916
|
-
case 4:
|
|
917
|
-
_a.sent();
|
|
918
|
-
return [3 /*break*/, 11];
|
|
919
|
-
case 5:
|
|
920
|
-
if (!(border.style === 3 /* BORDER_STYLE.DOTTED */)) return [3 /*break*/, 7];
|
|
921
|
-
return [4 /*yield*/, this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 3 /* BORDER_STYLE.DOTTED */)];
|
|
922
|
-
case 6:
|
|
923
|
-
_a.sent();
|
|
924
|
-
return [3 /*break*/, 11];
|
|
925
|
-
case 7:
|
|
926
|
-
if (!(border.style === 4 /* BORDER_STYLE.DOUBLE */)) return [3 /*break*/, 9];
|
|
927
|
-
return [4 /*yield*/, this.renderDoubleBorder(border.color, border.width, side, paint.curves)];
|
|
928
|
-
case 8:
|
|
929
|
-
_a.sent();
|
|
930
|
-
return [3 /*break*/, 11];
|
|
931
|
-
case 9: return [4 /*yield*/, this.renderSolidBorder(border.color, side, paint.curves)];
|
|
932
|
-
case 10:
|
|
933
|
-
_a.sent();
|
|
934
|
-
_a.label = 11;
|
|
935
|
-
case 11:
|
|
936
|
-
side++;
|
|
937
|
-
_a.label = 12;
|
|
938
|
-
case 12:
|
|
939
|
-
_i++;
|
|
940
|
-
return [3 /*break*/, 3];
|
|
941
|
-
case 13: return [2 /*return*/];
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
this.ctx.fill();
|
|
597
|
+
}
|
|
942
598
|
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
599
|
+
}
|
|
600
|
+
index--;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
async renderSolidBorder(color, side, curvePoints) {
|
|
604
|
+
this.path((0, border_1.parsePathForBorder)(curvePoints, side));
|
|
605
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(color);
|
|
606
|
+
this.ctx.fill();
|
|
607
|
+
}
|
|
608
|
+
async renderDoubleBorder(color, width, side, curvePoints) {
|
|
609
|
+
if (width < 3) {
|
|
610
|
+
await this.renderSolidBorder(color, side, curvePoints);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const outerPaths = (0, border_1.parsePathForBorderDoubleOuter)(curvePoints, side);
|
|
614
|
+
this.path(outerPaths);
|
|
615
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(color);
|
|
616
|
+
this.ctx.fill();
|
|
617
|
+
const innerPaths = (0, border_1.parsePathForBorderDoubleInner)(curvePoints, side);
|
|
618
|
+
this.path(innerPaths);
|
|
619
|
+
this.ctx.fill();
|
|
620
|
+
}
|
|
621
|
+
async renderNodeBackgroundAndBorders(paint) {
|
|
622
|
+
this.applyEffects(paint.getEffects(2 /* EffectTarget.BACKGROUND_BORDERS */));
|
|
623
|
+
const styles = paint.container.styles;
|
|
624
|
+
const hasBackground = !(0, color_utilities_1.isTransparent)(styles.backgroundColor) || styles.backgroundImage.length;
|
|
625
|
+
const borders = [
|
|
626
|
+
{ style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth },
|
|
627
|
+
{ style: styles.borderRightStyle, color: styles.borderRightColor, width: styles.borderRightWidth },
|
|
628
|
+
{ style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth },
|
|
629
|
+
{ style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth }
|
|
630
|
+
];
|
|
631
|
+
const backgroundPaintingArea = calculateBackgroundCurvedPaintingArea((0, background_1.getBackgroundValueForIndex)(styles.backgroundClip, 0), paint.curves);
|
|
632
|
+
if (hasBackground || styles.boxShadow.length) {
|
|
633
|
+
this.ctx.save();
|
|
634
|
+
this.path(backgroundPaintingArea);
|
|
635
|
+
this.ctx.clip();
|
|
636
|
+
if (!(0, color_utilities_1.isTransparent)(styles.backgroundColor)) {
|
|
637
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(styles.backgroundColor);
|
|
638
|
+
this.ctx.fill();
|
|
639
|
+
}
|
|
640
|
+
await this.renderBackgroundImage(paint.container);
|
|
641
|
+
this.ctx.restore();
|
|
642
|
+
styles.boxShadow
|
|
643
|
+
.slice(0)
|
|
644
|
+
.reverse()
|
|
645
|
+
.forEach((shadow) => {
|
|
950
646
|
this.ctx.save();
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
647
|
+
const borderBoxArea = (0, bound_curves_1.calculateBorderBoxPath)(paint.curves);
|
|
648
|
+
const maskOffset = shadow.inset ? 0 : MASK_OFFSET;
|
|
649
|
+
const shadowPaintingArea = (0, path_1.transformPath)(borderBoxArea, -maskOffset + (shadow.inset ? 1 : -1) * shadow.spread.number, (shadow.inset ? 1 : -1) * shadow.spread.number, shadow.spread.number * (shadow.inset ? -2 : 2), shadow.spread.number * (shadow.inset ? -2 : 2));
|
|
650
|
+
if (shadow.inset) {
|
|
651
|
+
this.path(borderBoxArea);
|
|
955
652
|
this.ctx.clip();
|
|
956
|
-
|
|
957
|
-
if ((0, bezier_curve_1.isBezierCurve)(boxPaths[0])) {
|
|
958
|
-
startX = boxPaths[0].start.x;
|
|
959
|
-
startY = boxPaths[0].start.y;
|
|
653
|
+
this.mask(shadowPaintingArea);
|
|
960
654
|
}
|
|
961
655
|
else {
|
|
962
|
-
|
|
963
|
-
|
|
656
|
+
this.mask(borderBoxArea);
|
|
657
|
+
this.ctx.clip();
|
|
658
|
+
this.path(shadowPaintingArea);
|
|
964
659
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
660
|
+
this.ctx.shadowOffsetX = shadow.offsetX.number + maskOffset;
|
|
661
|
+
this.ctx.shadowOffsetY = shadow.offsetY.number;
|
|
662
|
+
this.ctx.shadowColor = (0, color_utilities_1.asString)(shadow.color);
|
|
663
|
+
this.ctx.shadowBlur = shadow.blur.number;
|
|
664
|
+
this.ctx.fillStyle = shadow.inset ? (0, color_utilities_1.asString)(shadow.color) : 'rgba(0,0,0,1)';
|
|
665
|
+
this.ctx.fill();
|
|
666
|
+
this.ctx.restore();
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
let side = 0;
|
|
670
|
+
for (const border of borders) {
|
|
671
|
+
if (border.style !== 0 /* BORDER_STYLE.NONE */ && !(0, color_utilities_1.isTransparent)(border.color) && border.width > 0) {
|
|
672
|
+
if (border.style === 2 /* BORDER_STYLE.DASHED */) {
|
|
673
|
+
await this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 2 /* BORDER_STYLE.DASHED */);
|
|
968
674
|
}
|
|
969
|
-
else {
|
|
970
|
-
|
|
971
|
-
endY = boxPaths[1].y;
|
|
675
|
+
else if (border.style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
676
|
+
await this.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 3 /* BORDER_STYLE.DOTTED */);
|
|
972
677
|
}
|
|
973
|
-
if (
|
|
974
|
-
|
|
678
|
+
else if (border.style === 4 /* BORDER_STYLE.DOUBLE */) {
|
|
679
|
+
await this.renderDoubleBorder(border.color, border.width, side, paint.curves);
|
|
975
680
|
}
|
|
976
681
|
else {
|
|
977
|
-
|
|
682
|
+
await this.renderSolidBorder(border.color, side, paint.curves);
|
|
978
683
|
}
|
|
684
|
+
}
|
|
685
|
+
side++;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
async renderDashedDottedBorder(color, width, side, curvePoints, style) {
|
|
689
|
+
this.ctx.save();
|
|
690
|
+
const strokePaths = (0, border_1.parsePathForBorderStroke)(curvePoints, side);
|
|
691
|
+
const boxPaths = (0, border_1.parsePathForBorder)(curvePoints, side);
|
|
692
|
+
if (style === 2 /* BORDER_STYLE.DASHED */) {
|
|
693
|
+
this.path(boxPaths);
|
|
694
|
+
this.ctx.clip();
|
|
695
|
+
}
|
|
696
|
+
let startX, startY, endX, endY;
|
|
697
|
+
if ((0, bezier_curve_1.isBezierCurve)(boxPaths[0])) {
|
|
698
|
+
startX = boxPaths[0].start.x;
|
|
699
|
+
startY = boxPaths[0].start.y;
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
startX = boxPaths[0].x;
|
|
703
|
+
startY = boxPaths[0].y;
|
|
704
|
+
}
|
|
705
|
+
if ((0, bezier_curve_1.isBezierCurve)(boxPaths[1])) {
|
|
706
|
+
endX = boxPaths[1].end.x;
|
|
707
|
+
endY = boxPaths[1].end.y;
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
endX = boxPaths[1].x;
|
|
711
|
+
endY = boxPaths[1].y;
|
|
712
|
+
}
|
|
713
|
+
let length;
|
|
714
|
+
if (side === 0 || side === 2) {
|
|
715
|
+
length = Math.abs(startX - endX);
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
length = Math.abs(startY - endY);
|
|
719
|
+
}
|
|
720
|
+
this.ctx.beginPath();
|
|
721
|
+
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
722
|
+
this.formatPath(strokePaths);
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
this.formatPath(boxPaths.slice(0, 2));
|
|
726
|
+
}
|
|
727
|
+
let dashLength = width < 3 ? width * 3 : width * 2;
|
|
728
|
+
let spaceLength = width < 3 ? width * 2 : width;
|
|
729
|
+
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
730
|
+
dashLength = width;
|
|
731
|
+
spaceLength = width;
|
|
732
|
+
}
|
|
733
|
+
let useLineDash = true;
|
|
734
|
+
if (length <= dashLength * 2) {
|
|
735
|
+
useLineDash = false;
|
|
736
|
+
}
|
|
737
|
+
else if (length <= dashLength * 2 + spaceLength) {
|
|
738
|
+
const multiplier = length / (2 * dashLength + spaceLength);
|
|
739
|
+
dashLength *= multiplier;
|
|
740
|
+
spaceLength *= multiplier;
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
const numberOfDashes = Math.floor((length + spaceLength) / (dashLength + spaceLength));
|
|
744
|
+
const minSpace = (length - numberOfDashes * dashLength) / (numberOfDashes - 1);
|
|
745
|
+
const maxSpace = (length - (numberOfDashes + 1) * dashLength) / numberOfDashes;
|
|
746
|
+
spaceLength =
|
|
747
|
+
maxSpace <= 0 || Math.abs(spaceLength - minSpace) < Math.abs(spaceLength - maxSpace)
|
|
748
|
+
? minSpace
|
|
749
|
+
: maxSpace;
|
|
750
|
+
}
|
|
751
|
+
if (useLineDash) {
|
|
752
|
+
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
753
|
+
this.ctx.setLineDash([0, dashLength + spaceLength]);
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
this.ctx.setLineDash([dashLength, spaceLength]);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
760
|
+
this.ctx.lineCap = 'round';
|
|
761
|
+
this.ctx.lineWidth = width;
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
this.ctx.lineWidth = width * 2 + 1.1;
|
|
765
|
+
}
|
|
766
|
+
this.ctx.strokeStyle = (0, color_utilities_1.asString)(color);
|
|
767
|
+
this.ctx.stroke();
|
|
768
|
+
this.ctx.setLineDash([]);
|
|
769
|
+
// dashed round edge gap
|
|
770
|
+
if (style === 2 /* BORDER_STYLE.DASHED */) {
|
|
771
|
+
if ((0, bezier_curve_1.isBezierCurve)(boxPaths[0])) {
|
|
772
|
+
const path1 = boxPaths[3];
|
|
773
|
+
const path2 = boxPaths[0];
|
|
979
774
|
this.ctx.beginPath();
|
|
980
|
-
|
|
981
|
-
this.formatPath(strokePaths);
|
|
982
|
-
}
|
|
983
|
-
else {
|
|
984
|
-
this.formatPath(boxPaths.slice(0, 2));
|
|
985
|
-
}
|
|
986
|
-
dashLength = width < 3 ? width * 3 : width * 2;
|
|
987
|
-
spaceLength = width < 3 ? width * 2 : width;
|
|
988
|
-
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
989
|
-
dashLength = width;
|
|
990
|
-
spaceLength = width;
|
|
991
|
-
}
|
|
992
|
-
useLineDash = true;
|
|
993
|
-
if (length <= dashLength * 2) {
|
|
994
|
-
useLineDash = false;
|
|
995
|
-
}
|
|
996
|
-
else if (length <= dashLength * 2 + spaceLength) {
|
|
997
|
-
multiplier = length / (2 * dashLength + spaceLength);
|
|
998
|
-
dashLength *= multiplier;
|
|
999
|
-
spaceLength *= multiplier;
|
|
1000
|
-
}
|
|
1001
|
-
else {
|
|
1002
|
-
numberOfDashes = Math.floor((length + spaceLength) / (dashLength + spaceLength));
|
|
1003
|
-
minSpace = (length - numberOfDashes * dashLength) / (numberOfDashes - 1);
|
|
1004
|
-
maxSpace = (length - (numberOfDashes + 1) * dashLength) / numberOfDashes;
|
|
1005
|
-
spaceLength =
|
|
1006
|
-
maxSpace <= 0 || Math.abs(spaceLength - minSpace) < Math.abs(spaceLength - maxSpace)
|
|
1007
|
-
? minSpace
|
|
1008
|
-
: maxSpace;
|
|
1009
|
-
}
|
|
1010
|
-
if (useLineDash) {
|
|
1011
|
-
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
1012
|
-
this.ctx.setLineDash([0, dashLength + spaceLength]);
|
|
1013
|
-
}
|
|
1014
|
-
else {
|
|
1015
|
-
this.ctx.setLineDash([dashLength, spaceLength]);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
if (style === 3 /* BORDER_STYLE.DOTTED */) {
|
|
1019
|
-
this.ctx.lineCap = 'round';
|
|
1020
|
-
this.ctx.lineWidth = width;
|
|
1021
|
-
}
|
|
1022
|
-
else {
|
|
1023
|
-
this.ctx.lineWidth = width * 2 + 1.1;
|
|
1024
|
-
}
|
|
1025
|
-
this.ctx.strokeStyle = (0, color_utilities_1.asString)(color);
|
|
775
|
+
this.formatPath([new vector_1.Vector(path1.end.x, path1.end.y), new vector_1.Vector(path2.start.x, path2.start.y)]);
|
|
1026
776
|
this.ctx.stroke();
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
};
|
|
1050
|
-
CanvasRenderer.prototype.render = function (element) {
|
|
1051
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
1052
|
-
var stack;
|
|
1053
|
-
return __generator(this, function (_a) {
|
|
1054
|
-
switch (_a.label) {
|
|
1055
|
-
case 0:
|
|
1056
|
-
if (this.options.backgroundColor) {
|
|
1057
|
-
this.ctx.fillStyle = (0, color_utilities_1.asString)(this.options.backgroundColor);
|
|
1058
|
-
this.ctx.fillRect(this.options.x, this.options.y, this.options.width, this.options.height);
|
|
1059
|
-
}
|
|
1060
|
-
stack = (0, stacking_context_1.parseStackingContexts)(element);
|
|
1061
|
-
return [4 /*yield*/, this.renderStack(stack)];
|
|
1062
|
-
case 1:
|
|
1063
|
-
_a.sent();
|
|
1064
|
-
this.applyEffects([]);
|
|
1065
|
-
return [2 /*return*/, this.canvas];
|
|
1066
|
-
}
|
|
1067
|
-
});
|
|
1068
|
-
});
|
|
1069
|
-
};
|
|
1070
|
-
return CanvasRenderer;
|
|
1071
|
-
}(renderer_1.Renderer));
|
|
777
|
+
}
|
|
778
|
+
if ((0, bezier_curve_1.isBezierCurve)(boxPaths[1])) {
|
|
779
|
+
const path1 = boxPaths[1];
|
|
780
|
+
const path2 = boxPaths[2];
|
|
781
|
+
this.ctx.beginPath();
|
|
782
|
+
this.formatPath([new vector_1.Vector(path1.end.x, path1.end.y), new vector_1.Vector(path2.start.x, path2.start.y)]);
|
|
783
|
+
this.ctx.stroke();
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
this.ctx.restore();
|
|
787
|
+
}
|
|
788
|
+
async render(element) {
|
|
789
|
+
if (this.options.backgroundColor) {
|
|
790
|
+
this.ctx.fillStyle = (0, color_utilities_1.asString)(this.options.backgroundColor);
|
|
791
|
+
this.ctx.fillRect(this.options.x, this.options.y, this.options.width, this.options.height);
|
|
792
|
+
}
|
|
793
|
+
const stack = (0, stacking_context_1.parseStackingContexts)(element);
|
|
794
|
+
await this.renderStack(stack);
|
|
795
|
+
this.applyEffects([]);
|
|
796
|
+
return this.canvas;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
1072
799
|
exports.CanvasRenderer = CanvasRenderer;
|
|
1073
|
-
|
|
800
|
+
const isTextInputElement = (container) => {
|
|
1074
801
|
if (container instanceof textarea_element_container_1.TextareaElementContainer) {
|
|
1075
802
|
return true;
|
|
1076
803
|
}
|
|
@@ -1082,7 +809,7 @@ var isTextInputElement = function (container) {
|
|
|
1082
809
|
}
|
|
1083
810
|
return false;
|
|
1084
811
|
};
|
|
1085
|
-
|
|
812
|
+
const calculateBackgroundCurvedPaintingArea = (clip, curves) => {
|
|
1086
813
|
switch (clip) {
|
|
1087
814
|
case 0 /* BACKGROUND_CLIP.BORDER_BOX */:
|
|
1088
815
|
return (0, bound_curves_1.calculateBorderBoxPath)(curves);
|
|
@@ -1093,7 +820,7 @@ var calculateBackgroundCurvedPaintingArea = function (clip, curves) {
|
|
|
1093
820
|
return (0, bound_curves_1.calculatePaddingBoxPath)(curves);
|
|
1094
821
|
}
|
|
1095
822
|
};
|
|
1096
|
-
|
|
823
|
+
const canvasTextAlign = (textAlign) => {
|
|
1097
824
|
switch (textAlign) {
|
|
1098
825
|
case 1 /* TEXT_ALIGN.CENTER */:
|
|
1099
826
|
return 'center';
|
|
@@ -1105,10 +832,10 @@ var canvasTextAlign = function (textAlign) {
|
|
|
1105
832
|
}
|
|
1106
833
|
};
|
|
1107
834
|
// see https://github.com/niklasvh/html2canvas/pull/2645
|
|
1108
|
-
|
|
1109
|
-
|
|
835
|
+
const iOSBrokenFonts = ['-apple-system', 'system-ui'];
|
|
836
|
+
const fixIOSSystemFonts = (fontFamilies) => {
|
|
1110
837
|
return /iPhone OS 15_(0|1)/.test(window.navigator.userAgent)
|
|
1111
|
-
? fontFamilies.filter(
|
|
838
|
+
? fontFamilies.filter((fontFamily) => iOSBrokenFonts.indexOf(fontFamily) === -1)
|
|
1112
839
|
: fontFamilies;
|
|
1113
840
|
};
|
|
1114
841
|
//# sourceMappingURL=canvas-renderer.js.map
|