@effing/canvas 0.24.7 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -261,6 +261,12 @@ import { GlobalFonts } from "@napi-rs/canvas";
261
261
 
262
262
  // src/jsx/font-metrics.ts
263
263
  import { inflateSync } from "zlib";
264
+ function fontMetricsToPx(metrics, fontSize) {
265
+ return {
266
+ ascent: metrics.ascender / metrics.unitsPerEm * fontSize,
267
+ descent: -metrics.descender / metrics.unitsPerEm * fontSize
268
+ };
269
+ }
264
270
  var WOFF_SIGNATURE = 2001684038;
265
271
  function readWoffTable(view, entry) {
266
272
  const compressed = entry.compLength < entry.origLength;
@@ -474,8 +480,9 @@ function measureTrimMetrics(fontSize, fontFamily, fontWeight, fontStyle, lineHei
474
480
  let fontAscent;
475
481
  let fontDescent;
476
482
  if (fontMetrics) {
477
- fontAscent = fontMetrics.ascender / fontMetrics.unitsPerEm * fontSize;
478
- fontDescent = -fontMetrics.descender / fontMetrics.unitsPerEm * fontSize;
483
+ const px = fontMetricsToPx(fontMetrics, fontSize);
484
+ fontAscent = px.ascent;
485
+ fontDescent = px.descent;
479
486
  } else {
480
487
  fontAscent = refMetrics.fontBoundingBoxAscent ?? refMetrics.actualBoundingBoxAscent ?? fontSize * 0.8;
481
488
  fontDescent = refMetrics.fontBoundingBoxDescent ?? refMetrics.actualBoundingBoxDescent ?? fontSize * 0.2;
@@ -699,7 +706,8 @@ function layoutText(text, style, maxWidth, ctx, emojiEnabled) {
699
706
  let totalHeight = 0;
700
707
  let maxLineWidth = 0;
701
708
  const isAutoLineHeight = style.lineHeight === void 0 || style.lineHeight === "normal";
702
- let lastMetrics;
709
+ const fontPx = fontMetrics ? fontMetricsToPx(fontMetrics, fontSize) : null;
710
+ let lastPositioningDescent;
703
711
  for (let i = 0; i < lines.length; i++) {
704
712
  const line = lines[i];
705
713
  const lineWidth = measure(line);
@@ -717,14 +725,16 @@ function layoutText(text, style, maxWidth, ctx, emojiEnabled) {
717
725
  fontStyle,
718
726
  ctx
719
727
  );
720
- lastMetrics = metrics;
721
- const contentHeight = metrics.ascent + metrics.descent;
722
- let effectiveAscent = metrics.ascent;
723
- let effectiveDescent = metrics.descent;
728
+ const positioningAscent = fontPx?.ascent ?? metrics.ascent;
729
+ const positioningDescent = fontPx?.descent ?? metrics.descent;
730
+ lastPositioningDescent = positioningDescent;
731
+ const contentHeight = positioningAscent + positioningDescent;
732
+ let effectiveAscent = positioningAscent;
733
+ let effectiveDescent = positioningDescent;
724
734
  if (isAutoLineHeight && contentHeight > lineHeightPx) {
725
735
  const scale = lineHeightPx / contentHeight;
726
- effectiveAscent = metrics.ascent * scale;
727
- effectiveDescent = metrics.descent * scale;
736
+ effectiveAscent = positioningAscent * scale;
737
+ effectiveDescent = positioningDescent * scale;
728
738
  }
729
739
  const baselineY = totalHeight + (lineHeightPx + effectiveAscent - effectiveDescent) / 2;
730
740
  segments.push({
@@ -748,9 +758,9 @@ function layoutText(text, style, maxWidth, ctx, emojiEnabled) {
748
758
  totalHeight += lineHeightPx;
749
759
  maxLineWidth = Math.max(maxLineWidth, lineWidth);
750
760
  }
751
- if (isAutoLineHeight && lastMetrics && segments.length > 0) {
761
+ if (isAutoLineHeight && lastPositioningDescent !== void 0 && segments.length > 0) {
752
762
  const lastSeg = segments[segments.length - 1];
753
- const descentOverflow = lastSeg.y + lastMetrics.descent - totalHeight;
763
+ const descentOverflow = lastSeg.y + lastPositioningDescent - totalHeight;
754
764
  if (descentOverflow > 0) {
755
765
  totalHeight += descentOverflow;
756
766
  }
@@ -788,8 +798,8 @@ function layoutText(text, style, maxWidth, ctx, emojiEnabled) {
788
798
  function resolveLineHeight(lineHeight, fontSize, canvasMetrics, fontMetrics) {
789
799
  if (lineHeight === void 0 || lineHeight === "normal") {
790
800
  if (fontMetrics) {
791
- const { ascender, descender, unitsPerEm } = fontMetrics;
792
- return (ascender - descender) / unitsPerEm * fontSize;
801
+ const px = fontMetricsToPx(fontMetrics, fontSize);
802
+ return px.ascent + px.descent;
793
803
  }
794
804
  return canvasMetrics ? canvasMetrics.ascent + canvasMetrics.descent : fontSize * 1.2;
795
805
  }
@@ -1207,9 +1217,6 @@ function resolveBoxValue(v, referenceWidth) {
1207
1217
  function drawRect(ctx, x, y, width, height, style) {
1208
1218
  const borderRadius = getBorderRadiusFromStyle(style, width, height);
1209
1219
  const hasRoundedCorners = hasRadius(borderRadius);
1210
- if (style.boxShadow) {
1211
- drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);
1212
- }
1213
1220
  if (style.backgroundColor) {
1214
1221
  ctx.fillStyle = style.backgroundColor;
1215
1222
  if (hasRoundedCorners) {
@@ -2831,12 +2838,15 @@ async function drawNodeCore(ctx, node, parentX, parentY, offsetX, offsetY, debug
2831
2838
  style.transformOrigin
2832
2839
  );
2833
2840
  }
2841
+ const borderRadius = getBorderRadiusFromStyle(style, width, height);
2842
+ if (style.boxShadow) {
2843
+ drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);
2844
+ }
2834
2845
  const isClipped = style.overflow === "hidden" || style.overflowX === "hidden" || style.overflowY === "hidden";
2835
2846
  if (isClipped) {
2836
- const borderRadius = getBorderRadiusFromStyle(style, width, height);
2837
2847
  applyClip(ctx, x, y, width, height, borderRadius);
2838
2848
  }
2839
- if (style.backgroundColor || style.borderTopWidth || style.borderRightWidth || style.borderBottomWidth || style.borderLeftWidth || style.boxShadow) {
2849
+ if (style.backgroundColor || style.borderTopWidth || style.borderRightWidth || style.borderBottomWidth || style.borderLeftWidth) {
2840
2850
  drawRect(ctx, x, y, width, height, style);
2841
2851
  }
2842
2852
  if (style.backgroundImage) {
@@ -2846,7 +2856,6 @@ async function drawNodeCore(ctx, node, parentX, parentY, offsetX, offsetY, debug
2846
2856
  const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);
2847
2857
  if (gradient) {
2848
2858
  ctx.fillStyle = gradient;
2849
- const borderRadius = getBorderRadiusFromStyle(style, width, height);
2850
2859
  if (hasRadius(borderRadius)) {
2851
2860
  ctx.beginPath();
2852
2861
  roundedRect(
@@ -2867,7 +2876,6 @@ async function drawNodeCore(ctx, node, parentX, parentY, offsetX, offsetY, debug
2867
2876
  } else {
2868
2877
  const urlMatch = layer.match(/url\(["']?(.*?)["']?\)/);
2869
2878
  if (urlMatch) {
2870
- const borderRadius = getBorderRadiusFromStyle(style, width, height);
2871
2879
  if (hasRadius(borderRadius)) {
2872
2880
  applyClip(ctx, x, y, width, height, borderRadius);
2873
2881
  }
@@ -2968,7 +2976,6 @@ async function drawNodeCore(ctx, node, parentX, parentY, offsetX, offsetY, debug
2968
2976
  const imgW = width - paddingLeft - paddingRight - borderLeftW - borderRightW;
2969
2977
  const imgH = height - paddingTop - paddingBottom - borderTopW - borderBottomW;
2970
2978
  if (!isClipped) {
2971
- const borderRadius = getBorderRadiusFromStyle(style, width, height);
2972
2979
  if (hasRadius(borderRadius)) {
2973
2980
  applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);
2974
2981
  }