html2canvas-pro 2.3.2 → 2.3.3
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.cjs +98 -10
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +98 -10
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +98 -10
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +3 -3
- package/dist/lib/css/property-descriptors/background-clip.js +2 -0
- package/dist/lib/render/canvas/canvas-renderer.js +123 -9
- package/dist/types/css/property-descriptors/background-clip.d.ts +2 -1
- package/dist/types/render/canvas/canvas-renderer.d.ts +18 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* html2canvas-pro 2.3.
|
|
2
|
+
* html2canvas-pro 2.3.3 <https://yorickshan.github.io/html2canvas-pro/>
|
|
3
3
|
* Copyright (c) 2024-present yorickshan and html2canvas-pro contributors
|
|
4
4
|
* Released under MIT License
|
|
5
5
|
*/
|
|
@@ -3955,6 +3955,7 @@ const backgroundClip = {
|
|
|
3955
3955
|
if (isIdentToken(token)) switch (token.value) {
|
|
3956
3956
|
case "padding-box": return 1;
|
|
3957
3957
|
case "content-box": return 2;
|
|
3958
|
+
case "text": return 3;
|
|
3958
3959
|
}
|
|
3959
3960
|
return 0;
|
|
3960
3961
|
});
|
|
@@ -10521,6 +10522,7 @@ var CanvasRenderer = class CanvasRenderer {
|
|
|
10521
10522
|
this.effectsRenderer.applyEffects(paint.getEffects(2));
|
|
10522
10523
|
const styles = paint.container.styles;
|
|
10523
10524
|
const hasBackground = !isTransparent(styles.backgroundColor) || styles.backgroundImage.length;
|
|
10525
|
+
const hasTextClip = hasTextBackgroundClip(styles);
|
|
10524
10526
|
const borders = [
|
|
10525
10527
|
{
|
|
10526
10528
|
style: styles.borderTopStyle,
|
|
@@ -10543,17 +10545,21 @@ var CanvasRenderer = class CanvasRenderer {
|
|
|
10543
10545
|
width: styles.borderLeftWidth
|
|
10544
10546
|
}
|
|
10545
10547
|
];
|
|
10546
|
-
const
|
|
10548
|
+
const backgroundClipValue = getBackgroundValueForIndex(styles.backgroundClip, 0);
|
|
10549
|
+
const backgroundPaintingArea = calculateBackgroundCurvedPaintingArea(backgroundClipValue, paint.curves);
|
|
10547
10550
|
if (hasBackground || styles.boxShadow.length) {
|
|
10548
|
-
this.
|
|
10549
|
-
|
|
10550
|
-
|
|
10551
|
-
|
|
10552
|
-
this.ctx.
|
|
10553
|
-
|
|
10551
|
+
if (hasTextClip && paint.container.textNodes.length > 0) await this.renderTextClippedBackground(paint);
|
|
10552
|
+
else {
|
|
10553
|
+
this.ctx.save();
|
|
10554
|
+
this.path(backgroundPaintingArea);
|
|
10555
|
+
this.ctx.clip();
|
|
10556
|
+
if (!isTransparent(styles.backgroundColor)) {
|
|
10557
|
+
this.ctx.fillStyle = asString(styles.backgroundColor);
|
|
10558
|
+
this.ctx.fill();
|
|
10559
|
+
}
|
|
10560
|
+
await this.backgroundRenderer.renderBackgroundImage(paint.container);
|
|
10561
|
+
this.ctx.restore();
|
|
10554
10562
|
}
|
|
10555
|
-
await this.backgroundRenderer.renderBackgroundImage(paint.container);
|
|
10556
|
-
this.ctx.restore();
|
|
10557
10563
|
styles.boxShadow.slice(0).reverse().forEach((shadow) => {
|
|
10558
10564
|
this.ctx.save();
|
|
10559
10565
|
const borderBoxArea = calculateBorderBoxPath(paint.curves);
|
|
@@ -10612,6 +10618,82 @@ var CanvasRenderer = class CanvasRenderer {
|
|
|
10612
10618
|
this.effectsRenderer.applyEffects([]);
|
|
10613
10619
|
return this.canvas;
|
|
10614
10620
|
}
|
|
10621
|
+
/**
|
|
10622
|
+
* Render background clipped to text shape using offscreen canvas with destination-in compositing.
|
|
10623
|
+
* This implements background-clip: text support.
|
|
10624
|
+
*
|
|
10625
|
+
* Algorithm:
|
|
10626
|
+
* 1. Draw background (color + images) onto an offscreen canvas
|
|
10627
|
+
* 2. Use destination-in compositing to clip the background to the text glyph shapes
|
|
10628
|
+
* 3. Composite the result back onto the main canvas
|
|
10629
|
+
*
|
|
10630
|
+
* The offscreen canvas uses CSS-pixel dimensions (not device-pixel) because the
|
|
10631
|
+
* background renderer handles scaling internally via BackgroundRenderer options.
|
|
10632
|
+
*/
|
|
10633
|
+
async renderTextClippedBackground(paint) {
|
|
10634
|
+
const container = paint.container;
|
|
10635
|
+
const styles = container.styles;
|
|
10636
|
+
const bounds = container.bounds;
|
|
10637
|
+
if (bounds.width <= 0 || bounds.height <= 0) return;
|
|
10638
|
+
const offscreen = (this.canvas.ownerDocument ?? document).createElement("canvas");
|
|
10639
|
+
const width = Math.ceil(bounds.width);
|
|
10640
|
+
const height = Math.ceil(bounds.height);
|
|
10641
|
+
offscreen.width = width;
|
|
10642
|
+
offscreen.height = height;
|
|
10643
|
+
const offCtx = offscreen.getContext("2d");
|
|
10644
|
+
if (!offCtx) return;
|
|
10645
|
+
const [fontString] = this.textRenderer.createFontStyle(styles);
|
|
10646
|
+
offCtx.font = fontString;
|
|
10647
|
+
offCtx.textBaseline = "alphabetic";
|
|
10648
|
+
offCtx.textAlign = "left";
|
|
10649
|
+
offCtx.direction = styles.direction === 1 ? "rtl" : "ltr";
|
|
10650
|
+
const baseline = measureBaseline(offCtx, styles.fontSize.number);
|
|
10651
|
+
const bgRenderer = new BackgroundRenderer({
|
|
10652
|
+
ctx: offCtx,
|
|
10653
|
+
context: this.context,
|
|
10654
|
+
canvas: offscreen,
|
|
10655
|
+
options: {
|
|
10656
|
+
width,
|
|
10657
|
+
height,
|
|
10658
|
+
scale: 1
|
|
10659
|
+
}
|
|
10660
|
+
});
|
|
10661
|
+
if (!isTransparent(styles.backgroundColor)) {
|
|
10662
|
+
offCtx.fillStyle = asString(styles.backgroundColor);
|
|
10663
|
+
offCtx.fillRect(0, 0, width, height);
|
|
10664
|
+
}
|
|
10665
|
+
offCtx.save();
|
|
10666
|
+
offCtx.translate(-bounds.left, -bounds.top);
|
|
10667
|
+
await bgRenderer.renderBackgroundImage(container);
|
|
10668
|
+
offCtx.restore();
|
|
10669
|
+
offCtx.globalCompositeOperation = "destination-in";
|
|
10670
|
+
offCtx.fillStyle = "#000";
|
|
10671
|
+
const writingMode = styles.writingMode;
|
|
10672
|
+
const letterSpacing = styles.letterSpacing;
|
|
10673
|
+
for (const textNode of container.textNodes) for (const textBound of textNode.textBounds) {
|
|
10674
|
+
const localLeft = textBound.bounds.left - bounds.left;
|
|
10675
|
+
const localTop = textBound.bounds.top - bounds.top + baseline;
|
|
10676
|
+
if (letterSpacing > 0) this.renderTextMaskWithLetterSpacing(offCtx, textBound, letterSpacing, localLeft, localTop, writingMode);
|
|
10677
|
+
else offCtx.fillText(textBound.text, localLeft, localTop);
|
|
10678
|
+
}
|
|
10679
|
+
this.ctx.drawImage(offscreen, bounds.left, bounds.top);
|
|
10680
|
+
}
|
|
10681
|
+
/**
|
|
10682
|
+
* Render text glyphs one-by-one as a mask, applying letter-spacing between characters.
|
|
10683
|
+
* This ensures the mask matches how the text renderer lays out the characters.
|
|
10684
|
+
*/
|
|
10685
|
+
renderTextMaskWithLetterSpacing(ctx, text, letterSpacing, x, y, writingMode) {
|
|
10686
|
+
const letters = segmentGraphemes(text.text);
|
|
10687
|
+
let offset = x;
|
|
10688
|
+
for (const letter of letters) {
|
|
10689
|
+
if (isVerticalWritingMode(writingMode)) {
|
|
10690
|
+
ctx.fillText(text.text, x, y);
|
|
10691
|
+
return;
|
|
10692
|
+
}
|
|
10693
|
+
ctx.fillText(letter, offset, y);
|
|
10694
|
+
offset += ctx.measureText(letter).width + letterSpacing;
|
|
10695
|
+
}
|
|
10696
|
+
}
|
|
10615
10697
|
};
|
|
10616
10698
|
const calculateBackgroundCurvedPaintingArea = (clip, curves) => {
|
|
10617
10699
|
switch (clip) {
|
|
@@ -10620,6 +10702,12 @@ const calculateBackgroundCurvedPaintingArea = (clip, curves) => {
|
|
|
10620
10702
|
default: return calculatePaddingBoxPath(curves);
|
|
10621
10703
|
}
|
|
10622
10704
|
};
|
|
10705
|
+
/**
|
|
10706
|
+
* Check if any background layer uses background-clip: text
|
|
10707
|
+
*/
|
|
10708
|
+
const hasTextBackgroundClip = (styles) => {
|
|
10709
|
+
return styles.backgroundClip.some((clip) => clip === 3);
|
|
10710
|
+
};
|
|
10623
10711
|
//#endregion
|
|
10624
10712
|
//#region src/render/canvas/foreignobject-renderer.ts
|
|
10625
10713
|
var ForeignObjectRenderer = class {
|