diff --git a/server/victory-chart-renderer/tests/__golden__/monthly-spend.png b/server/victory-chart-renderer/tests/__golden__/monthly-spend.png index cfe29a3a1d82..9d3cc7c60184 100644 Binary files a/server/victory-chart-renderer/tests/__golden__/monthly-spend.png and b/server/victory-chart-renderer/tests/__golden__/monthly-spend.png differ diff --git a/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend-truncated-labels.png b/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend-truncated-labels.png index 6469f80c5c77..aaae9f38e08d 100644 Binary files a/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend-truncated-labels.png and b/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend-truncated-labels.png differ diff --git a/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend.png b/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend.png index 1d6324e00606..ddc19d632e90 100644 Binary files a/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend.png and b/server/victory-chart-renderer/tests/__golden__/top-employees-by-spend.png differ diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLabel.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLabel.tsx index 081b442ebc86..a6a597ff09e1 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLabel.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLabel.tsx @@ -5,6 +5,7 @@ import {useChartTypefaces} from '@components/Charts/context/ChartFontsContext'; import getChartSkiaTypeface from '@components/Charts/utils/getChartSkiaTypeface'; import type {LabelItem} from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/types'; import computeTextAnchorPosition from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/computeTextAnchorPosition'; +import getSkiaLineMetrics from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics'; import {getLocalizedVictoryChartLabelText} from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/localizeVictoryChartLabelText'; import resolveChartThemeColor from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/resolveChartThemeColor'; import useTheme from '@hooks/useTheme'; @@ -45,12 +46,11 @@ function VictoryChartLabel({x, y, text, color, fontSize, fontWeight, fontFamily, fontWeight: lineFontWeight, }); const lineFont = typeface && lineFontSize ? Skia.Font(typeface, lineFontSize) : null; - const fontMetrics = lineFont?.getMetrics(); + const {ascent, lineHeight: metricsLineHeight} = getSkiaLineMetrics(lineFont); const lineWidth = lineFont?.getGlyphWidths(lineFont.getGlyphIDs(line)).reduce((totalWidth, width) => totalWidth + width, 0) ?? 0; const customLineHeight = lineLineHeight ? lineLineHeight * (lineFontSize ?? 0) : 0; - const metricsLineHeight = fontMetrics ? -fontMetrics.ascent + fontMetrics.descent + fontMetrics.leading : 0; const lineX = x; - const lineY = acc.y - (fontMetrics?.ascent ?? 0); + const lineY = acc.y + ascent; acc.y += customLineHeight || metricsLineHeight; acc.lines.push({ diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLegend.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLegend.tsx index 81375443875d..6dc481f55353 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLegend.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartLegend.tsx @@ -4,6 +4,7 @@ import React, {Fragment} from 'react'; import {useChartTypefaces} from '@components/Charts/context/ChartFontsContext'; import getChartSkiaTypeface from '@components/Charts/utils/getChartSkiaTypeface'; import type {LegendItem} from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/types'; +import getSkiaLineMetrics from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics'; import resolveChartThemeColor from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/resolveChartThemeColor'; import useTheme from '@hooks/useTheme'; @@ -34,13 +35,13 @@ function VictoryChartLegend({x, y, entries, gutter, symbolSpacer, chartWidth}: V (acc, {text, color, fontSize, fontWeight, fontFamily, fontStyle, symbolColor, symbolSize}) => { const typeface = getChartSkiaTypeface(typefaces, {fontFamily, fontStyle, fontWeight}); const font = typeface && fontSize ? Skia.Font(typeface, fontSize) : null; - const fontMetrics = font?.getMetrics(); - const lineHeight = fontMetrics ? fontMetrics.ascent + fontMetrics.descent + fontMetrics.leading : 0; + const {ascent, descent, lineHeight} = getSkiaLineMetrics(font); + const rowCenterY = y + lineHeight / 2; const symbolX = acc.x; - const symbolY = y; + const symbolY = rowCenterY; acc.x += (symbolSize ?? 0) + (symbolSpacer ?? 0); const textX = acc.x; - const textY = y - lineHeight / 2; + const textY = rowCenterY + (ascent - descent) / 2; acc.x += (font?.getGlyphWidths(font.getGlyphIDs(text)).reduce((totalWidth, width) => totalWidth + width, 0) ?? 0) + (gutter ?? 0); const resolvedColor = resolveChartThemeColor(color, theme); diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics.ts b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics.ts new file mode 100644 index 000000000000..70bbfb41a6f7 --- /dev/null +++ b/src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics.ts @@ -0,0 +1,25 @@ +import type {SkFont} from '@shopify/react-native-skia'; + +type SkiaLineMetrics = { + /** Distance from the baseline up to the glyph tops, as a positive value. */ + ascent: number; + /** Distance from the baseline down to the glyph bottoms, as a positive value. */ + descent: number; + /** Extra spacing requested by the font between consecutive lines. */ + leading: number; + /** Conventional, always non-negative line height (`ascent + descent + leading`). */ + lineHeight: number; +}; + +function getSkiaLineMetrics(font: SkFont | null): SkiaLineMetrics { + const metrics = font?.getMetrics(); + if (!metrics) { + return {ascent: 0, descent: 0, leading: 0, lineHeight: 0}; + } + const ascent = Math.abs(metrics.ascent); + const descent = Math.abs(metrics.descent); + const leading = Math.abs(metrics.leading); + return {ascent, descent, leading, lineHeight: ascent + descent + leading}; +} + +export default getSkiaLineMetrics;