html2canvas-pro 2.4.4 → 2.4.5

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * html2canvas-pro 2.4.4 <https://yorickshan.github.io/html2canvas-pro/>
2
+ * html2canvas-pro 2.4.5 <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
  */
@@ -10805,6 +10805,220 @@ const canvasTextAlign = (textAlign) => {
10805
10805
  }
10806
10806
  };
10807
10807
  //#endregion
10808
+ //#region src/render/canvas/box-shadow-geometry.ts
10809
+ const shadowRadius = (radius, spread) => {
10810
+ const delta = spread > radius ? spread * (1 + Math.pow(radius / spread - 1, 3)) : spread;
10811
+ return Math.max(0, radius + delta);
10812
+ };
10813
+ const spreadShadowPath = (paths, spread) => {
10814
+ if (spread === 0) return paths;
10815
+ const corners = paths.map((point, index) => {
10816
+ if (!isBezierCurve(point)) return {
10817
+ x: point.x,
10818
+ y: point.y,
10819
+ rx: 0,
10820
+ ry: 0
10821
+ };
10822
+ return {
10823
+ x: index % 2 === 0 ? point.start.x : point.end.x,
10824
+ y: index % 2 === 0 ? point.end.y : point.start.y,
10825
+ rx: Math.abs(point.end.x - point.start.x),
10826
+ ry: Math.abs(point.end.y - point.start.y)
10827
+ };
10828
+ });
10829
+ const width = corners[1].x - corners[0].x + 2 * spread;
10830
+ const height = corners[3].y - corners[0].y + 2 * spread;
10831
+ if (width <= 0 || height <= 0) return [];
10832
+ const radii = corners.map((c) => ({
10833
+ x: shadowRadius(c.rx, spread),
10834
+ y: shadowRadius(c.ry, spread)
10835
+ }));
10836
+ const ratio = (size, sum) => sum > 0 ? size / sum : 1;
10837
+ const factor = Math.min(1, ratio(width, radii[0].x + radii[1].x), ratio(width, radii[3].x + radii[2].x), ratio(height, radii[0].y + radii[3].y), ratio(height, radii[1].y + radii[2].y));
10838
+ return paths.map((point, index) => {
10839
+ const corner = corners[index];
10840
+ const x = corner.x + (index === 1 || index === 2 ? spread : -spread);
10841
+ const y = corner.y + (index >= 2 ? spread : -spread);
10842
+ if (!isBezierCurve(point)) return new Vector(x, y);
10843
+ const rx = radii[index].x * factor;
10844
+ const ry = radii[index].y * factor;
10845
+ if (!rx || !ry) return new Vector(x, y);
10846
+ const sx = rx / corner.rx;
10847
+ const sy = ry / corner.ry;
10848
+ const resize = (v) => new Vector(x + (v.x - corner.x) * sx, y + (v.y - corner.y) * sy);
10849
+ return new BezierCurve(resize(point.start), resize(point.startControl), resize(point.endControl), resize(point.end));
10850
+ });
10851
+ };
10852
+ //#endregion
10853
+ //#region src/render/canvas/box-shadow-transform.ts
10854
+ const shadowSpace = (matrix, width, height) => {
10855
+ const { a, b, c, d, e, f } = matrix;
10856
+ if (![
10857
+ a,
10858
+ b,
10859
+ c,
10860
+ d,
10861
+ e,
10862
+ f,
10863
+ width,
10864
+ height
10865
+ ].every(Number.isFinite)) return null;
10866
+ const determinant = a * d - b * c;
10867
+ if (!Number.isFinite(determinant) || determinant === 0) return null;
10868
+ const inversePoint = (x, y) => ({
10869
+ x: (d * (x - e) - c * (y - f)) / determinant,
10870
+ y: (-b * (x - e) + a * (y - f)) / determinant
10871
+ });
10872
+ const corners = [
10873
+ inversePoint(0, 0),
10874
+ inversePoint(width, 0),
10875
+ inversePoint(width, height),
10876
+ inversePoint(0, height)
10877
+ ];
10878
+ if (!corners.every((point) => Number.isFinite(point.x) && Number.isFinite(point.y))) return null;
10879
+ const left = Math.min(...corners.map((point) => point.x));
10880
+ const top = Math.min(...corners.map((point) => point.y));
10881
+ const right = Math.max(...corners.map((point) => point.x));
10882
+ const bottom = Math.max(...corners.map((point) => point.y));
10883
+ const xx = a * a + b * b;
10884
+ const yy = c * c + d * d;
10885
+ const xy = a * c + b * d;
10886
+ const scale = Math.sqrt((xx + yy + Math.hypot(xx - yy, 2 * xy)) / 2);
10887
+ if (!Number.isFinite(scale) || scale <= 0) return null;
10888
+ const tolerance = 1e-10 * Math.max(xx, yy);
10889
+ return {
10890
+ matrix,
10891
+ viewport: new Bounds(left, top, right - left, bottom - top),
10892
+ scale,
10893
+ uniform: Math.abs(xx - yy) <= tolerance && Math.abs(xy) <= tolerance
10894
+ };
10895
+ };
10896
+ //#endregion
10897
+ //#region src/render/canvas/box-shadow-painter.ts
10898
+ const complement = (ctx, rect, hole) => {
10899
+ ctx.beginPath();
10900
+ ctx.rect(rect.left, rect.top, rect.width, rect.height);
10901
+ if (hole.length) {
10902
+ formatCanvasPath(ctx, hole);
10903
+ ctx.closePath();
10904
+ }
10905
+ };
10906
+ const insetHole = (paint, shadow) => {
10907
+ const spread = shadow.spread.number;
10908
+ const box = paddingBox(paint.container);
10909
+ if (box.width - 2 * spread <= 0 || box.height - 2 * spread <= 0) return [];
10910
+ return spreadShadowPath(calculatePaddingBoxPath(paint.curves), -spread);
10911
+ };
10912
+ const paintShadowSurface = async (ctx, paint, shadow, options, budget, space) => {
10913
+ const padding = paddingBox(paint.container);
10914
+ const blur = shadow.blur.number / 2;
10915
+ const margin = Math.ceil(3 * blur) + 2;
10916
+ const spread = shadow.spread.number;
10917
+ const bounds = cropSurface((shadow.inset ? padding : paint.container.bounds.add(shadow.offsetX.number - spread, shadow.offsetY.number - spread, 2 * spread, 2 * spread)).add(-margin, -margin, 2 * margin, 2 * margin), space.viewport, margin, space.scale);
10918
+ if (!bounds.width || !bounds.height) return true;
10919
+ const width = Math.ceil(bounds.width * space.scale);
10920
+ const height = Math.ceil(bounds.height * space.scale);
10921
+ const reserved = reserveSurface(budget, width, height);
10922
+ if (!reserved) return false;
10923
+ let source;
10924
+ let filtered;
10925
+ try {
10926
+ source = ctx.canvas.ownerDocument.createElement("canvas");
10927
+ source.width = width;
10928
+ source.height = height;
10929
+ const sourceCtx = source.getContext("2d");
10930
+ if (!sourceCtx) return false;
10931
+ sourceCtx.scale(space.scale, space.scale);
10932
+ sourceCtx.translate(-bounds.left, -bounds.top);
10933
+ const path = transformPath(shadow.inset ? insetHole(paint, shadow) : spreadShadowPath(calculateBorderBoxPath(paint.curves), spread), shadow.offsetX.number, shadow.offsetY.number, 0, 0);
10934
+ if (shadow.inset) complement(sourceCtx, bounds, path);
10935
+ else createCanvasPath(sourceCtx, path);
10936
+ sourceCtx.fillStyle = asString(shadow.color);
10937
+ sourceCtx.fill(shadow.inset ? "evenodd" : "nonzero");
10938
+ filtered = await renderFilterSurface(source, { blur }, 1, space.scale, options.signal);
10939
+ ctx.save();
10940
+ try {
10941
+ if (shadow.inset) {
10942
+ createCanvasPath(ctx, calculatePaddingBoxPath(paint.curves));
10943
+ ctx.clip();
10944
+ } else {
10945
+ complement(ctx, space.viewport, calculateBorderBoxPath(paint.curves));
10946
+ ctx.clip("evenodd");
10947
+ }
10948
+ ctx.drawImage(filtered, bounds.left, bounds.top, filtered.width / space.scale, filtered.height / space.scale);
10949
+ } finally {
10950
+ ctx.restore();
10951
+ }
10952
+ return true;
10953
+ } catch (error) {
10954
+ if (!(error instanceof FilterSurfaceError)) throw error;
10955
+ return false;
10956
+ } finally {
10957
+ if (filtered && filtered !== source) releaseSurface(filtered);
10958
+ if (source) releaseSurface(source);
10959
+ budget.pixels -= reserved;
10960
+ }
10961
+ };
10962
+ const paintBoxShadow = async (ctx, paint, shadow, options, budget) => {
10963
+ if (options.signal?.aborted) throw new DOMException("The operation was aborted.", "AbortError");
10964
+ if (isTransparent(shadow.color)) return;
10965
+ const spread = shadow.spread.number;
10966
+ if (!shadow.inset && (paint.container.bounds.width + 2 * spread <= 0 || paint.container.bounds.height + 2 * spread <= 0)) return;
10967
+ const knownTransform = typeof ctx.getTransform === "function";
10968
+ const matrix = knownTransform ? ctx.getTransform() : {
10969
+ a: options.scale,
10970
+ b: 0,
10971
+ c: 0,
10972
+ d: options.scale,
10973
+ e: -options.x * options.scale,
10974
+ f: -options.y * options.scale
10975
+ };
10976
+ const space = shadowSpace(matrix, ctx.canvas.width, ctx.canvas.height);
10977
+ if (!space) return;
10978
+ const { viewport } = space;
10979
+ if (shadow.blur.number > 0 && (shadow.inset || !space.uniform) && await paintShadowSurface(ctx, paint, shadow, options, budget, space)) return;
10980
+ const padding = paddingBox(paint.container);
10981
+ ctx.save();
10982
+ try {
10983
+ if (shadow.inset && shadow.blur.number === 0) {
10984
+ createCanvasPath(ctx, calculatePaddingBoxPath(paint.curves));
10985
+ ctx.clip();
10986
+ complement(ctx, padding, transformPath(insetHole(paint, shadow), shadow.offsetX.number, shadow.offsetY.number, 0, 0));
10987
+ ctx.fillStyle = asString(shadow.color);
10988
+ ctx.fill("evenodd");
10989
+ return;
10990
+ }
10991
+ const margin = Math.ceil(shadow.blur.number * 2 + Math.abs(spread) + Math.abs(shadow.offsetX.number) + Math.abs(shadow.offsetY.number)) + 2;
10992
+ const sourceBounds = shadow.inset ? padding.add(-margin, -margin, 2 * margin, 2 * margin) : paint.container.bounds.add(-spread, -spread, 2 * spread, 2 * spread);
10993
+ const { a, b, c, d, e, f } = matrix;
10994
+ const right = sourceBounds.left + sourceBounds.width;
10995
+ const bottom = sourceBounds.top + sourceBounds.height;
10996
+ const maxX = Math.max(a * sourceBounds.left + c * sourceBounds.top + e, a * right + c * sourceBounds.top + e, a * right + c * bottom + e, a * sourceBounds.left + c * bottom + e);
10997
+ const displacement = Math.max(SHADOW_MASK_OFFSET, maxX + margin * space.scale + 2);
10998
+ if (shadow.inset) {
10999
+ createCanvasPath(ctx, calculatePaddingBoxPath(paint.curves));
11000
+ ctx.clip();
11001
+ } else {
11002
+ complement(ctx, viewport, calculateBorderBoxPath(paint.curves));
11003
+ ctx.clip("evenodd");
11004
+ }
11005
+ if (knownTransform) ctx.setTransform(a, b, c, d, e - displacement, f);
11006
+ else ctx.translate(-displacement / a, 0);
11007
+ if (shadow.inset) complement(ctx, sourceBounds, insetHole(paint, shadow));
11008
+ else createCanvasPath(ctx, spreadShadowPath(calculateBorderBoxPath(paint.curves), spread));
11009
+ if (knownTransform) ctx.setTransform(a, b, c, d, e, f);
11010
+ else ctx.translate(displacement / a, 0);
11011
+ ctx.shadowOffsetX = displacement + a * shadow.offsetX.number + c * shadow.offsetY.number;
11012
+ ctx.shadowOffsetY = b * shadow.offsetX.number + d * shadow.offsetY.number;
11013
+ ctx.shadowBlur = shadow.blur.number * space.scale;
11014
+ ctx.shadowColor = asString(shadow.color);
11015
+ ctx.fillStyle = "rgb(0, 0, 0)";
11016
+ ctx.fill(shadow.inset ? "evenodd" : "nonzero");
11017
+ } finally {
11018
+ ctx.restore();
11019
+ }
11020
+ };
11021
+ //#endregion
10808
11022
  //#region src/render/canvas/canvas-renderer.ts
10809
11023
  var CanvasRenderer = class CanvasRenderer {
10810
11024
  constructor(context, options, surfaceRoot, surfaceBudget = { pixels: 0 }) {
@@ -11107,27 +11321,7 @@ var CanvasRenderer = class CanvasRenderer {
11107
11321
  await this.renderSurfaceBoxShadow(paint, shadow);
11108
11322
  continue;
11109
11323
  }
11110
- this.ctx.save();
11111
- const borderBoxArea = calculateBorderBoxPath(paint.curves);
11112
- const maskOffset = shadow.inset ? 0 : SHADOW_MASK_OFFSET;
11113
- const shadowPaintingArea = 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));
11114
- if (shadow.inset) {
11115
- this.path(borderBoxArea);
11116
- this.ctx.clip();
11117
- this.mask(shadowPaintingArea);
11118
- } else {
11119
- this.mask(borderBoxArea);
11120
- this.ctx.clip();
11121
- this.path(shadowPaintingArea);
11122
- }
11123
- const shadowScale = this.surfaceRoot ? this.options.scale : 1;
11124
- this.ctx.shadowOffsetX = (shadow.offsetX.number + maskOffset) * shadowScale;
11125
- this.ctx.shadowOffsetY = shadow.offsetY.number * shadowScale;
11126
- this.ctx.shadowColor = asString(shadow.color);
11127
- this.ctx.shadowBlur = shadow.blur.number * shadowScale;
11128
- this.ctx.fillStyle = shadow.inset ? asString(shadow.color) : "rgba(0,0,0,1)";
11129
- this.ctx.fill();
11130
- this.ctx.restore();
11324
+ await paintBoxShadow(this.ctx, paint, shadow, this.options, this.surfaceBudget);
11131
11325
  }
11132
11326
  }
11133
11327
  if (styles.borderImageSource) {