fix: Text-only measurements off by a pixel

This commit is contained in:
Daniel J. Geiger 2023-09-22 10:17:51 -05:00
parent 208285b7ba
commit 4d6d6cf129
2 changed files with 35 additions and 6 deletions

View File

@ -621,8 +621,6 @@ const measureMarkup = (
container.appendChild(span);
// Baseline is important for positioning text on canvas
const baseline = span.offsetTop + span.offsetHeight;
const width = container.offsetWidth + 1;
const height = container.offsetHeight;
const containerRect = container.getBoundingClientRect();
// Compute for each SVG or Text child node of line (the last
@ -673,6 +671,12 @@ const measureMarkup = (
childMetrics.push({ x: 0, y: 0, width: 0, height: 0 });
}
document.body.removeChild(container);
let width = 0;
let height = 0;
childMetrics.forEach((metrics) => (width += metrics.width));
childMetrics.forEach(
(metrics) => (height = Math.max(height, metrics.height)),
);
return { width, height, baseline, childMetrics };
};
@ -735,10 +739,14 @@ const getMetrics = (
imageHeight += height;
}
const lastLineMetrics = lineMetrics[lineMetrics.length - 1];
const imageBaseline = Math.max(
0,
imageHeight - lastLineMetrics.height + lastLineMetrics.baseline - 1,
);
const imageMetrics = {
width: imageWidth,
height: imageHeight,
baseline: imageHeight - lastLineMetrics.height + lastLineMetrics.baseline,
baseline: imageBaseline,
};
const metrics = { markupMetrics, lineMetrics, imageMetrics };
if (isMathJaxLoaded) {
@ -778,17 +786,17 @@ const renderMath = (
);
const width = parentWidth ?? metrics.imageMetrics.width;
let y = 0;
let y = -1;
for (let index = 0; index < markup.length; index++) {
const lineMetrics = metrics.lineMetrics[index];
const lineMarkupMetrics = metrics.markupMetrics[index];
const rtl = isRTL(mathLines[index]);
const x =
textAlign === "right"
? width - lineMetrics.width
? width - lineMetrics.width + 1
: textAlign === "left"
? 0
: (width - lineMetrics.width) / 2;
: (width - lineMetrics.width + 1) / 2;
// Drop any empty strings from this line to match childMetrics
const content = markup[index].filter((value) => value !== "");
for (let i = 0; i < content.length; i += 1) {

View File

@ -0,0 +1,21 @@
import { render } from "../../../../tests/test-utils";
import { API } from "../../../../tests/helpers/api";
import ExcalidrawApp from "../../../";
import { measureTextElement } from "../../../../element/textElement";
import { ensureSubtypesLoaded } from "../../../../subtypes";
describe("mathjax", () => {
it("text-only measurements match", async () => {
await render(<ExcalidrawApp />);
await ensureSubtypesLoaded(["math"]);
const text = "A quick brown fox jumps over the lazy dog.";
const elements = [
API.createElement({ type: "text", id: "A", text, subtype: "math" }),
API.createElement({ type: "text", id: "B", text }),
];
const metrics1 = measureTextElement(elements[0]);
const metrics2 = measureTextElement(elements[1]);
expect(metrics1).toStrictEqual(metrics2);
});
});