html2canvas-pro 2.0.0 → 2.0.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/dist/html2canvas-pro.esm.js +524 -91
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +524 -91
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +5 -5
- package/dist/lib/css/index.js +2 -0
- package/dist/lib/css/index.js.map +1 -1
- package/dist/lib/css/property-descriptors/__tests__/clip-path.test.js +273 -0
- package/dist/lib/css/property-descriptors/__tests__/clip-path.test.js.map +1 -0
- package/dist/lib/css/property-descriptors/clip-path.js +190 -0
- package/dist/lib/css/property-descriptors/clip-path.js.map +1 -0
- package/dist/lib/dom/dom-normalizer.js +57 -21
- package/dist/lib/dom/dom-normalizer.js.map +1 -1
- package/dist/lib/render/canvas/__tests__/text-renderer.test.js +283 -36
- package/dist/lib/render/canvas/__tests__/text-renderer.test.js.map +1 -1
- package/dist/lib/render/canvas/effects-renderer.js +11 -6
- package/dist/lib/render/canvas/effects-renderer.js.map +1 -1
- package/dist/lib/render/canvas/text-renderer.js +131 -64
- package/dist/lib/render/canvas/text-renderer.js.map +1 -1
- package/dist/lib/render/effects.js +17 -1
- package/dist/lib/render/effects.js.map +1 -1
- package/dist/lib/render/stacking-context.js +131 -0
- package/dist/lib/render/stacking-context.js.map +1 -1
- package/dist/types/css/index.d.ts +2 -0
- package/dist/types/css/property-descriptors/__tests__/clip-path.test.d.ts +1 -0
- package/dist/types/css/property-descriptors/clip-path.d.ts +62 -0
- package/dist/types/dom/dom-normalizer.d.ts +30 -11
- package/dist/types/render/canvas/effects-renderer.d.ts +2 -1
- package/dist/types/render/canvas/text-renderer.d.ts +20 -2
- package/dist/types/render/effects.d.ts +15 -1
- package/package.json +1 -1
|
@@ -9,11 +9,38 @@ exports.DOMNormalizer = void 0;
|
|
|
9
9
|
const node_type_guards_1 = require("./node-type-guards");
|
|
10
10
|
/**
|
|
11
11
|
* Normalize element styles for accurate rendering
|
|
12
|
-
* This includes disabling animations and
|
|
12
|
+
* This includes disabling animations and neutralizing transforms.
|
|
13
13
|
*/
|
|
14
14
|
class DOMNormalizer {
|
|
15
15
|
/**
|
|
16
|
-
* Normalize a single element and return original styles
|
|
16
|
+
* Normalize a single element and return original styles.
|
|
17
|
+
*
|
|
18
|
+
* ## Why we replace transforms with an identity value instead of "none"
|
|
19
|
+
*
|
|
20
|
+
* `getBoundingClientRect()` returns visual (post-transform) coordinates, so we
|
|
21
|
+
* must neutralize any active transform before measuring element bounds.
|
|
22
|
+
*
|
|
23
|
+
* The naive approach of setting `transform: none` (or `rotate: none`) has a
|
|
24
|
+
* critical side-effect: per **CSS Transforms Level 2**, an element whose
|
|
25
|
+
* `transform` is non-none automatically becomes the **containing block** for
|
|
26
|
+
* all of its `position: absolute` *and* `position: fixed` descendants.
|
|
27
|
+
* Setting it to `none` destroys that role, causing children to resolve their
|
|
28
|
+
* percentage dimensions and offsets against an unintended ancestor — which
|
|
29
|
+
* produces completely wrong bounds.
|
|
30
|
+
*
|
|
31
|
+
* Solution: instead of removing the transform, we replace it with a visually
|
|
32
|
+
* inert identity value:
|
|
33
|
+
*
|
|
34
|
+
* - `transform: scale(0.5)` → `transform: translate(0, 0)`
|
|
35
|
+
* - `translate(0, 0)` is an identity transform (no visual change, no layout shift).
|
|
36
|
+
* - `getBoundingClientRect()` returns the same layout-space coordinates as
|
|
37
|
+
* if there were no transform at all.
|
|
38
|
+
* - Because the value is still non-none, the element **remains a containing
|
|
39
|
+
* block** for both `position: absolute` and `position: fixed` descendants.
|
|
40
|
+
*
|
|
41
|
+
* - `rotate: 45deg` → `rotate: 0deg`
|
|
42
|
+
* - `0deg` is the identity rotation; `0deg ≠ none`, so the same containing-
|
|
43
|
+
* block guarantee holds.
|
|
17
44
|
*
|
|
18
45
|
* @param element - Element to normalize
|
|
19
46
|
* @param styles - Parsed CSS styles
|
|
@@ -29,33 +56,43 @@ class DOMNormalizer {
|
|
|
29
56
|
originalStyles.animationDuration = element.style.animationDuration;
|
|
30
57
|
element.style.animationDuration = '0s';
|
|
31
58
|
}
|
|
32
|
-
//
|
|
33
|
-
// getBoundingClientRect
|
|
59
|
+
// Replace the actual transform with an identity translate so that:
|
|
60
|
+
// 1. getBoundingClientRect() returns layout-space (unscaled/unrotated) coords.
|
|
61
|
+
// 2. The element still satisfies "transform != none" and therefore keeps
|
|
62
|
+
// its role as a containing block for position:absolute / position:fixed
|
|
63
|
+
// descendants (CSS Transforms Level 2 §2.3).
|
|
34
64
|
if (styles.transform !== null) {
|
|
35
65
|
originalStyles.transform = element.style.transform;
|
|
36
|
-
element.style.transform = '
|
|
66
|
+
element.style.transform = 'translate(0, 0)';
|
|
37
67
|
}
|
|
38
|
-
//
|
|
68
|
+
// Same rationale for the standalone `rotate` property.
|
|
69
|
+
// `rotate: 0deg` is an identity rotation with no visual effect.
|
|
70
|
+
//
|
|
71
|
+
// However, individual transform properties (`rotate`, `translate`, `scale`)
|
|
72
|
+
// are part of CSS Transforms Level 2 and their containing-block guarantee
|
|
73
|
+
// is not uniformly implemented across all browsers. To be safe, if `rotate`
|
|
74
|
+
// is the only transform-like property active on this element, we also set
|
|
75
|
+
// `transform: translate(0, 0)` so that the containing-block role is reliably
|
|
76
|
+
// preserved via the well-supported `transform` property.
|
|
39
77
|
if (styles.rotate !== null) {
|
|
40
78
|
originalStyles.rotate = element.style.rotate;
|
|
41
|
-
element.style.rotate = '
|
|
79
|
+
element.style.rotate = '0deg';
|
|
80
|
+
// Individual transform properties (`rotate`, `translate`, `scale`) are
|
|
81
|
+
// CSS Transforms Level 2 and their containing-block guarantee is not
|
|
82
|
+
// uniformly implemented in all browsers. If `transform` was not already
|
|
83
|
+
// set to translate(0,0) in the block above (i.e. this element has
|
|
84
|
+
// `rotate` but no `transform`), we set it now so the containing-block
|
|
85
|
+
// role is reliably established via the widely-supported `transform`
|
|
86
|
+
// property – independently of browser support for individual props.
|
|
87
|
+
if (originalStyles.transform === undefined) {
|
|
88
|
+
originalStyles.transform = element.style.transform;
|
|
89
|
+
element.style.transform = 'translate(0, 0)';
|
|
90
|
+
}
|
|
42
91
|
}
|
|
43
92
|
return originalStyles;
|
|
44
93
|
}
|
|
45
94
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* @param element - Element to normalize
|
|
49
|
-
* @param styles - Parsed CSS styles
|
|
50
|
-
* @returns Original styles map for restoration
|
|
51
|
-
*/
|
|
52
|
-
static normalizeTree(element, styles) {
|
|
53
|
-
return this.normalizeElement(element, styles);
|
|
54
|
-
// Could add recursive normalization here if needed
|
|
55
|
-
// For now, only normalize the element itself
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Restore element styles after rendering
|
|
95
|
+
* Restore element styles after rendering.
|
|
59
96
|
*
|
|
60
97
|
* @param element - Element to restore
|
|
61
98
|
* @param originalStyles - Original styles to restore
|
|
@@ -64,7 +101,6 @@ class DOMNormalizer {
|
|
|
64
101
|
if (!(0, node_type_guards_1.isHTMLElementNode)(element)) {
|
|
65
102
|
return;
|
|
66
103
|
}
|
|
67
|
-
// Restore each property that was saved
|
|
68
104
|
if (originalStyles.animationDuration !== undefined) {
|
|
69
105
|
element.style.animationDuration = originalStyles.animationDuration;
|
|
70
106
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-normalizer.js","sourceRoot":"","sources":["../../../src/dom/dom-normalizer.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAGH,yDAAuD;AAWvD;;;GAGG;AACH,MAAa,aAAa;IACtB
|
|
1
|
+
{"version":3,"file":"dom-normalizer.js","sourceRoot":"","sources":["../../../src/dom/dom-normalizer.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAGH,yDAAuD;AAWvD;;;GAGG;AACH,MAAa,aAAa;IACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAgB,EAAE,MAA4B;QAClE,MAAM,cAAc,GAAmB,EAAE,CAAC;QAE1C,IAAI,CAAC,IAAA,oCAAiB,EAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,6CAA6C;QAC7C,IAAI,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;YAC5D,cAAc,CAAC,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC3C,CAAC;QAED,mEAAmE;QACnE,iFAAiF;QACjF,2EAA2E;QAC3E,6EAA6E;QAC7E,kDAAkD;QAClD,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5B,cAAc,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,iBAAiB,CAAC;QAChD,CAAC;QAED,uDAAuD;QACvD,gEAAgE;QAChE,EAAE;QACF,4EAA4E;QAC5E,0EAA0E;QAC1E,4EAA4E;QAC5E,0EAA0E;QAC1E,6EAA6E;QAC7E,yDAAyD;QACzD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACzB,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;YAE9B,uEAAuE;YACvE,qEAAqE;YACrE,wEAAwE;YACxE,kEAAkE;YAClE,sEAAsE;YACtE,oEAAoE;YACpE,oEAAoE;YACpE,IAAI,cAAc,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACzC,cAAc,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;gBACnD,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,iBAAiB,CAAC;YAChD,CAAC;QACL,CAAC;QAED,OAAO,cAAc,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,cAAc,CAAC,OAAgB,EAAE,cAA8B;QAClE,IAAI,CAAC,IAAA,oCAAiB,EAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO;QACX,CAAC;QAED,IAAI,cAAc,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACjD,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,cAAc,CAAC,iBAAiB,CAAC;QACvE,CAAC;QAED,IAAI,cAAc,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC;QACvD,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QACjD,CAAC;IACL,CAAC;CACJ;AA9GD,sCA8GC"}
|
|
@@ -4,41 +4,44 @@ const assert_1 = require("assert");
|
|
|
4
4
|
const text_renderer_1 = require("../text-renderer");
|
|
5
5
|
const context_1 = require("../../../core/context");
|
|
6
6
|
const bounds_1 = require("../../../css/layout/bounds");
|
|
7
|
+
const text_1 = require("../../../css/layout/text");
|
|
7
8
|
const config_1 = require("../../../config");
|
|
9
|
+
const createMockContext = () => {
|
|
10
|
+
const mockWindow = {
|
|
11
|
+
document: {
|
|
12
|
+
createElement: (_name) => {
|
|
13
|
+
let _href = '';
|
|
14
|
+
return {
|
|
15
|
+
set href(value) {
|
|
16
|
+
_href = value;
|
|
17
|
+
},
|
|
18
|
+
get href() {
|
|
19
|
+
return _href;
|
|
20
|
+
},
|
|
21
|
+
get protocol() {
|
|
22
|
+
return 'http:';
|
|
23
|
+
},
|
|
24
|
+
get hostname() {
|
|
25
|
+
return 'localhost';
|
|
26
|
+
},
|
|
27
|
+
get port() {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
location: { href: 'http://localhost/' }
|
|
34
|
+
};
|
|
35
|
+
const config = new config_1.Html2CanvasConfig({ window: mockWindow });
|
|
36
|
+
return new context_1.Context({
|
|
37
|
+
logging: false,
|
|
38
|
+
imageTimeout: 15000,
|
|
39
|
+
useCORS: false,
|
|
40
|
+
allowTaint: false
|
|
41
|
+
}, new bounds_1.Bounds(0, 0, 800, 600), config);
|
|
42
|
+
};
|
|
8
43
|
describe('TextRenderer', () => {
|
|
9
44
|
it('should be instantiated', () => {
|
|
10
|
-
const mockWindow = {
|
|
11
|
-
document: {
|
|
12
|
-
createElement: (_name) => {
|
|
13
|
-
let _href = '';
|
|
14
|
-
return {
|
|
15
|
-
set href(value) {
|
|
16
|
-
_href = value;
|
|
17
|
-
},
|
|
18
|
-
get href() {
|
|
19
|
-
return _href;
|
|
20
|
-
},
|
|
21
|
-
get protocol() {
|
|
22
|
-
return 'http:';
|
|
23
|
-
},
|
|
24
|
-
get hostname() {
|
|
25
|
-
return 'localhost';
|
|
26
|
-
},
|
|
27
|
-
get port() {
|
|
28
|
-
return '';
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
location: { href: 'http://localhost/' }
|
|
34
|
-
};
|
|
35
|
-
const config = new config_1.Html2CanvasConfig({ window: mockWindow });
|
|
36
|
-
const context = new context_1.Context({
|
|
37
|
-
logging: false,
|
|
38
|
-
imageTimeout: 15000,
|
|
39
|
-
useCORS: false,
|
|
40
|
-
allowTaint: false
|
|
41
|
-
}, new bounds_1.Bounds(0, 0, 800, 600), config);
|
|
42
45
|
const ctx = {
|
|
43
46
|
fillStyle: '',
|
|
44
47
|
font: '',
|
|
@@ -47,10 +50,8 @@ describe('TextRenderer', () => {
|
|
|
47
50
|
};
|
|
48
51
|
const deps = {
|
|
49
52
|
ctx,
|
|
50
|
-
context,
|
|
51
|
-
options: {
|
|
52
|
-
scale: 1
|
|
53
|
-
}
|
|
53
|
+
context: createMockContext(),
|
|
54
|
+
options: { scale: 1 }
|
|
54
55
|
};
|
|
55
56
|
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
56
57
|
(0, assert_1.ok)(renderer);
|
|
@@ -60,4 +61,250 @@ describe('TextRenderer', () => {
|
|
|
60
61
|
(0, assert_1.strictEqual)(typeof renderer.createFontStyle, 'function');
|
|
61
62
|
});
|
|
62
63
|
});
|
|
64
|
+
describe('hasCJKCharacters', () => {
|
|
65
|
+
it('should return true for Chinese characters', () => {
|
|
66
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('快照'), true);
|
|
67
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('截图'), true);
|
|
68
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('中文'), true);
|
|
69
|
+
});
|
|
70
|
+
it('should return true for Japanese characters', () => {
|
|
71
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('ひらがな'), true); // Hiragana
|
|
72
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('カタカナ'), true); // Katakana
|
|
73
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('漢字'), true); // Kanji
|
|
74
|
+
});
|
|
75
|
+
it('should return true for Korean characters', () => {
|
|
76
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('한글'), true);
|
|
77
|
+
});
|
|
78
|
+
it('should return true for CJK punctuation and symbols', () => {
|
|
79
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('。'), true); // CJK full stop (U+3002)
|
|
80
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('、'), true); // CJK comma (U+3001)
|
|
81
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('「」'), true); // CJK brackets
|
|
82
|
+
});
|
|
83
|
+
it('should return true for fullwidth characters (U+FF01–U+FFEF)', () => {
|
|
84
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('!'), true); // Fullwidth ! (U+FF01, range start)
|
|
85
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('A'), true); // Fullwidth A (U+FF21)
|
|
86
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('1'), true); // Fullwidth 1 (U+FF11)
|
|
87
|
+
});
|
|
88
|
+
it('should return false for Latin characters', () => {
|
|
89
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('Hello'), false);
|
|
90
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('SOS'), false);
|
|
91
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('abc123'), false);
|
|
92
|
+
});
|
|
93
|
+
it('should return false for empty string', () => {
|
|
94
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)(''), false);
|
|
95
|
+
});
|
|
96
|
+
it('should return true for mixed text containing CJK', () => {
|
|
97
|
+
(0, assert_1.strictEqual)((0, text_renderer_1.hasCJKCharacters)('SOS 快照'), true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('renderTextWithLetterSpacing', () => {
|
|
101
|
+
it('should apply letterSpacing to each character x position (Issue #73 Bug1)', () => {
|
|
102
|
+
const fillCalls = [];
|
|
103
|
+
const measureResults = { A: 10, B: 12, C: 8 };
|
|
104
|
+
const ctx = {
|
|
105
|
+
fillStyle: '',
|
|
106
|
+
font: '',
|
|
107
|
+
textBaseline: 'alphabetic',
|
|
108
|
+
fillText(text, x, y) {
|
|
109
|
+
fillCalls.push({ text, x, y });
|
|
110
|
+
},
|
|
111
|
+
measureText(text) {
|
|
112
|
+
return { width: measureResults[text] ?? 10 };
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const deps = {
|
|
116
|
+
ctx,
|
|
117
|
+
context: createMockContext(),
|
|
118
|
+
options: { scale: 1 }
|
|
119
|
+
};
|
|
120
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
121
|
+
const bounds = new bounds_1.Bounds(100, 50, 200, 25);
|
|
122
|
+
const text = new text_1.TextBounds('ABC', bounds);
|
|
123
|
+
const letterSpacing = 5;
|
|
124
|
+
const baseline = 20;
|
|
125
|
+
renderer.renderTextWithLetterSpacing(text, letterSpacing, baseline);
|
|
126
|
+
// Verify letter spacing is added between characters
|
|
127
|
+
// A: x=100, B: x=100+10+5=115, C: x=115+12+5=132
|
|
128
|
+
(0, assert_1.strictEqual)(fillCalls.length, 3);
|
|
129
|
+
(0, assert_1.strictEqual)(fillCalls[0].text, 'A');
|
|
130
|
+
(0, assert_1.strictEqual)(fillCalls[0].x, 100);
|
|
131
|
+
(0, assert_1.strictEqual)(fillCalls[1].text, 'B');
|
|
132
|
+
(0, assert_1.strictEqual)(fillCalls[1].x, 115); // 100 + measureText('A').width(10) + letterSpacing(5)
|
|
133
|
+
(0, assert_1.strictEqual)(fillCalls[2].text, 'C');
|
|
134
|
+
(0, assert_1.strictEqual)(fillCalls[2].x, 132); // 115 + measureText('B').width(12) + letterSpacing(5)
|
|
135
|
+
// Verify y position uses baseline
|
|
136
|
+
fillCalls.forEach((call) => {
|
|
137
|
+
(0, assert_1.strictEqual)(call.y, bounds.top + baseline); // 50 + 20 = 70
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
it('should use ideographic baseline for CJK characters (Issue #73 Bug2)', () => {
|
|
141
|
+
const baselineChanges = [];
|
|
142
|
+
let currentBaseline = 'alphabetic';
|
|
143
|
+
const ctx = {
|
|
144
|
+
fillStyle: '',
|
|
145
|
+
font: '',
|
|
146
|
+
get textBaseline() {
|
|
147
|
+
return currentBaseline;
|
|
148
|
+
},
|
|
149
|
+
set textBaseline(value) {
|
|
150
|
+
currentBaseline = value;
|
|
151
|
+
baselineChanges.push(value);
|
|
152
|
+
},
|
|
153
|
+
fillText(_text, _x, _y) { },
|
|
154
|
+
measureText(_text) {
|
|
155
|
+
return { width: 25 };
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const deps = {
|
|
159
|
+
ctx,
|
|
160
|
+
context: createMockContext(),
|
|
161
|
+
options: { scale: 1 }
|
|
162
|
+
};
|
|
163
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
164
|
+
const bounds = new bounds_1.Bounds(0, 0, 100, 25);
|
|
165
|
+
const text = new text_1.TextBounds('快照', bounds);
|
|
166
|
+
renderer.renderTextWithLetterSpacing(text, 10, 20);
|
|
167
|
+
// Should have switched to ideographic for each CJK char and restored
|
|
168
|
+
// Pattern: [ideographic, alphabetic, ideographic, alphabetic]
|
|
169
|
+
(0, assert_1.ok)(baselineChanges.includes('ideographic'), 'should switch to ideographic baseline for CJK');
|
|
170
|
+
// Should restore alphabetic after each CJK char
|
|
171
|
+
const ideographicIdx = baselineChanges.indexOf('ideographic');
|
|
172
|
+
(0, assert_1.strictEqual)(baselineChanges[ideographicIdx + 1], 'alphabetic');
|
|
173
|
+
});
|
|
174
|
+
it('should not change textBaseline for non-CJK characters', () => {
|
|
175
|
+
const baselineChanges = [];
|
|
176
|
+
let currentBaseline = 'alphabetic';
|
|
177
|
+
const ctx = {
|
|
178
|
+
fillStyle: '',
|
|
179
|
+
font: '',
|
|
180
|
+
get textBaseline() {
|
|
181
|
+
return currentBaseline;
|
|
182
|
+
},
|
|
183
|
+
set textBaseline(value) {
|
|
184
|
+
currentBaseline = value;
|
|
185
|
+
baselineChanges.push(value);
|
|
186
|
+
},
|
|
187
|
+
fillText(_text, _x, _y) { },
|
|
188
|
+
measureText(_text) {
|
|
189
|
+
return { width: 10 };
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const deps = {
|
|
193
|
+
ctx,
|
|
194
|
+
context: createMockContext(),
|
|
195
|
+
options: { scale: 1 }
|
|
196
|
+
};
|
|
197
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
198
|
+
const bounds = new bounds_1.Bounds(0, 0, 100, 25);
|
|
199
|
+
const text = new text_1.TextBounds('ABC', bounds);
|
|
200
|
+
renderer.renderTextWithLetterSpacing(text, 5, 20);
|
|
201
|
+
// Should not switch to ideographic for Latin characters
|
|
202
|
+
(0, assert_1.ok)(!baselineChanges.includes('ideographic'), 'should not switch to ideographic for Latin text');
|
|
203
|
+
});
|
|
204
|
+
it('should render whole string in one call when letterSpacing is 0', () => {
|
|
205
|
+
const fillCalls = [];
|
|
206
|
+
const ctx = {
|
|
207
|
+
fillStyle: '',
|
|
208
|
+
font: '',
|
|
209
|
+
textBaseline: 'alphabetic',
|
|
210
|
+
fillText(text, x, y) {
|
|
211
|
+
fillCalls.push({ text, x, y });
|
|
212
|
+
},
|
|
213
|
+
measureText(_text) {
|
|
214
|
+
return { width: 30 };
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
const deps = {
|
|
218
|
+
ctx,
|
|
219
|
+
context: createMockContext(),
|
|
220
|
+
options: { scale: 1 }
|
|
221
|
+
};
|
|
222
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
223
|
+
const bounds = new bounds_1.Bounds(10, 20, 100, 25);
|
|
224
|
+
const text = new text_1.TextBounds('Hello', bounds);
|
|
225
|
+
renderer.renderTextWithLetterSpacing(text, 0, 22);
|
|
226
|
+
(0, assert_1.deepStrictEqual)(fillCalls, [{ text: 'Hello', x: 10, y: 42 }]);
|
|
227
|
+
});
|
|
228
|
+
it('should handle negative letterSpacing correctly', () => {
|
|
229
|
+
const fillCalls = [];
|
|
230
|
+
const ctx = {
|
|
231
|
+
fillStyle: '',
|
|
232
|
+
font: '',
|
|
233
|
+
textBaseline: 'alphabetic',
|
|
234
|
+
fillText(text, x, _y) {
|
|
235
|
+
fillCalls.push({ text, x });
|
|
236
|
+
},
|
|
237
|
+
measureText(_text) {
|
|
238
|
+
return { width: 10 };
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const deps = {
|
|
242
|
+
ctx,
|
|
243
|
+
context: createMockContext(),
|
|
244
|
+
options: { scale: 1 }
|
|
245
|
+
};
|
|
246
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
247
|
+
const bounds = new bounds_1.Bounds(100, 0, 50, 20);
|
|
248
|
+
const text = new text_1.TextBounds('AB', bounds);
|
|
249
|
+
renderer.renderTextWithLetterSpacing(text, -3, 15);
|
|
250
|
+
// A: x=100, B: x=100 + 10 + (-3) = 107
|
|
251
|
+
(0, assert_1.strictEqual)(fillCalls[0].x, 100);
|
|
252
|
+
(0, assert_1.strictEqual)(fillCalls[1].x, 107);
|
|
253
|
+
});
|
|
254
|
+
it('should handle mixed CJK and Latin text with correct baseline per character', () => {
|
|
255
|
+
const baselineAtRender = {};
|
|
256
|
+
let currentBaseline = 'alphabetic';
|
|
257
|
+
const ctx = {
|
|
258
|
+
fillStyle: '',
|
|
259
|
+
font: '',
|
|
260
|
+
get textBaseline() {
|
|
261
|
+
return currentBaseline;
|
|
262
|
+
},
|
|
263
|
+
set textBaseline(value) {
|
|
264
|
+
currentBaseline = value;
|
|
265
|
+
},
|
|
266
|
+
fillText(text, _x, _y) {
|
|
267
|
+
baselineAtRender[text] = currentBaseline;
|
|
268
|
+
},
|
|
269
|
+
measureText(_text) {
|
|
270
|
+
return { width: 12 };
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const deps = {
|
|
274
|
+
ctx,
|
|
275
|
+
context: createMockContext(),
|
|
276
|
+
options: { scale: 1 }
|
|
277
|
+
};
|
|
278
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
279
|
+
const bounds = new bounds_1.Bounds(0, 0, 200, 25);
|
|
280
|
+
// Mixed: Latin 'A', CJK '快', Latin 'B'
|
|
281
|
+
const text = new text_1.TextBounds('A快B', bounds);
|
|
282
|
+
renderer.renderTextWithLetterSpacing(text, 5, 20);
|
|
283
|
+
(0, assert_1.strictEqual)(baselineAtRender['A'], 'alphabetic', 'Latin char should use alphabetic baseline');
|
|
284
|
+
(0, assert_1.strictEqual)(baselineAtRender['快'], 'ideographic', 'CJK char should use ideographic baseline');
|
|
285
|
+
(0, assert_1.strictEqual)(baselineAtRender['B'], 'alphabetic', 'Latin char after CJK should restore alphabetic baseline');
|
|
286
|
+
});
|
|
287
|
+
it('should handle empty string without errors', () => {
|
|
288
|
+
const ctx = {
|
|
289
|
+
fillStyle: '',
|
|
290
|
+
font: '',
|
|
291
|
+
textBaseline: 'alphabetic',
|
|
292
|
+
fillText(_text, _x, _y) { },
|
|
293
|
+
measureText(_text) {
|
|
294
|
+
return { width: 0 };
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
const deps = {
|
|
298
|
+
ctx,
|
|
299
|
+
context: createMockContext(),
|
|
300
|
+
options: { scale: 1 }
|
|
301
|
+
};
|
|
302
|
+
const renderer = new text_renderer_1.TextRenderer(deps);
|
|
303
|
+
const bounds = new bounds_1.Bounds(0, 0, 100, 25);
|
|
304
|
+
const text = new text_1.TextBounds('', bounds);
|
|
305
|
+
// Should not throw
|
|
306
|
+
renderer.renderTextWithLetterSpacing(text, 5, 20);
|
|
307
|
+
renderer.renderTextWithLetterSpacing(text, 0, 20);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
63
310
|
//# sourceMappingURL=text-renderer.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-renderer.test.js","sourceRoot":"","sources":["../../../../../src/render/canvas/__tests__/text-renderer.test.ts"],"names":[],"mappings":";;AAAA,mCAAyC;AACzC,oDAA0E;AAC1E,mDAAgD;AAChD,uDAAoD;AACpD,4CAAoD;AAEpD,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,UAAU,GAAG;YACf,QAAQ,EAAE;gBACN,aAAa,EAAE,CAAC,KAAa,EAAE,EAAE;oBAC7B,IAAI,KAAK,GAAG,EAAE,CAAC;oBACf,OAAO;wBACH,IAAI,IAAI,CAAC,KAAa;4BAClB,KAAK,GAAG,KAAK,CAAC;wBAClB,CAAC;wBACD,IAAI,IAAI;4BACJ,OAAO,KAAK,CAAC;wBACjB,CAAC;wBACD,IAAI,QAAQ;4BACR,OAAO,OAAO,CAAC;wBACnB,CAAC;wBACD,IAAI,QAAQ;4BACR,OAAO,WAAW,CAAC;wBACvB,CAAC;wBACD,IAAI,IAAI;4BACJ,OAAO,EAAE,CAAC;wBACd,CAAC;qBACJ,CAAC;gBACN,CAAC;aACJ;YACD,QAAQ,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE;SACrB,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,0BAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,iBAAO,CACvB;YACI,OAAO,EAAE,KAAK;YACd,YAAY,EAAE,KAAK;YACnB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,KAAK;SACpB,EACD,IAAI,eAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAC1B,MAAM,CACT,CAAC;QAEF,MAAM,GAAG,GAAG;YACR,SAAS,EAAE,EAAE;YACb,IAAI,EAAE,EAAE;YACR,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;YACd,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;SACmB,CAAC;QAEzC,MAAM,IAAI,GAA6B;YACnC,GAAG;YACH,OAAO;YACP,OAAO,EAAE;gBACL,KAAK,EAAE,CAAC;aACX;SACJ,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,4BAAY,CAAC,IAAI,CAAC,CAAC;QACxC,IAAA,WAAE,EAAC,QAAQ,CAAC,CAAC;QAEb,4BAA4B;QAC5B,IAAA,oBAAW,EAAC,OAAO,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACxD,IAAA,oBAAW,EAAC,OAAO,QAAQ,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC;QACrE,IAAA,oBAAW,EAAC,OAAO,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"text-renderer.test.js","sourceRoot":"","sources":["../../../../../src/render/canvas/__tests__/text-renderer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Handles rendering effects including:
|
|
6
6
|
* - Opacity effects
|
|
7
7
|
* - Transform effects (matrix transformations)
|
|
8
|
-
* - Clip effects (clipping
|
|
8
|
+
* - Clip effects (overflow / border-radius clipping via Path[])
|
|
9
|
+
* - Clip-path effects (CSS clip-path shapes: inset, circle, ellipse, polygon, path)
|
|
9
10
|
*/
|
|
10
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
12
|
exports.EffectsRenderer = void 0;
|
|
@@ -43,21 +44,25 @@ class EffectsRenderer {
|
|
|
43
44
|
*/
|
|
44
45
|
applyEffect(effect) {
|
|
45
46
|
this.ctx.save();
|
|
46
|
-
// Apply opacity effect
|
|
47
47
|
if ((0, effects_1.isOpacityEffect)(effect)) {
|
|
48
|
+
// Opacity: multiply into the current global alpha for nested transparency.
|
|
48
49
|
this.ctx.globalAlpha = effect.opacity;
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
else if ((0, effects_1.isTransformEffect)(effect)) {
|
|
52
|
+
// Transform: translate to origin, apply matrix, translate back.
|
|
52
53
|
this.ctx.translate(effect.offsetX, effect.offsetY);
|
|
53
54
|
this.ctx.transform(effect.matrix[0], effect.matrix[1], effect.matrix[2], effect.matrix[3], effect.matrix[4], effect.matrix[5]);
|
|
54
55
|
this.ctx.translate(-effect.offsetX, -effect.offsetY);
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
else if ((0, effects_1.isClipEffect)(effect)) {
|
|
58
|
+
// Clip (overflow / border-radius): build path via callback then clip.
|
|
58
59
|
this.pathCallback.path(effect.path);
|
|
59
60
|
this.ctx.clip();
|
|
60
61
|
}
|
|
62
|
+
else if ((0, effects_1.isClipPathEffect)(effect)) {
|
|
63
|
+
// Clip-path: delegate shape drawing (beginPath … clip()) to the effect.
|
|
64
|
+
effect.applyClip(this.ctx);
|
|
65
|
+
}
|
|
61
66
|
this.activeEffects.push(effect);
|
|
62
67
|
}
|
|
63
68
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effects-renderer.js","sourceRoot":"","sources":["../../../../src/render/canvas/effects-renderer.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"effects-renderer.js","sourceRoot":"","sources":["../../../../src/render/canvas/effects-renderer.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,wCAAgH;AAiBhH;;;;;GAKG;AACH,MAAa,eAAe;IAKxB,YAAY,IAAiC,EAAE,YAAiC;QAF/D,kBAAa,GAAqB,EAAE,CAAC;QAGlD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,OAAyB;QAClC,6BAA6B;QAC7B,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;QACrB,CAAC;QAED,oBAAoB;QACpB,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,MAAsB;QAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAEhB,IAAI,IAAA,yBAAe,EAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,2EAA2E;YAC3E,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC;QAC1C,CAAC;aAAM,IAAI,IAAA,2BAAiB,EAAC,MAAM,CAAC,EAAE,CAAC;YACnC,gEAAgE;YAChE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,GAAG,CAAC,SAAS,CACd,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CACnB,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,IAAA,sBAAY,EAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,sEAAsE;YACtE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;aAAM,IAAI,IAAA,0BAAgB,EAAC,MAAM,CAAC,EAAE,CAAC;YAClC,wEAAwE;YACxE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,SAAS;QACL,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,oBAAoB;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,CAAC;CACJ;AAvFD,0CAuFC"}
|