fix: Text-only measurements off by a pixel
This commit is contained in:
parent
208285b7ba
commit
4d6d6cf129
@ -621,8 +621,6 @@ const measureMarkup = (
|
|||||||
container.appendChild(span);
|
container.appendChild(span);
|
||||||
// Baseline is important for positioning text on canvas
|
// Baseline is important for positioning text on canvas
|
||||||
const baseline = span.offsetTop + span.offsetHeight;
|
const baseline = span.offsetTop + span.offsetHeight;
|
||||||
const width = container.offsetWidth + 1;
|
|
||||||
const height = container.offsetHeight;
|
|
||||||
|
|
||||||
const containerRect = container.getBoundingClientRect();
|
const containerRect = container.getBoundingClientRect();
|
||||||
// Compute for each SVG or Text child node of line (the last
|
// 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 });
|
childMetrics.push({ x: 0, y: 0, width: 0, height: 0 });
|
||||||
}
|
}
|
||||||
document.body.removeChild(container);
|
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 };
|
return { width, height, baseline, childMetrics };
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -735,10 +739,14 @@ const getMetrics = (
|
|||||||
imageHeight += height;
|
imageHeight += height;
|
||||||
}
|
}
|
||||||
const lastLineMetrics = lineMetrics[lineMetrics.length - 1];
|
const lastLineMetrics = lineMetrics[lineMetrics.length - 1];
|
||||||
|
const imageBaseline = Math.max(
|
||||||
|
0,
|
||||||
|
imageHeight - lastLineMetrics.height + lastLineMetrics.baseline - 1,
|
||||||
|
);
|
||||||
const imageMetrics = {
|
const imageMetrics = {
|
||||||
width: imageWidth,
|
width: imageWidth,
|
||||||
height: imageHeight,
|
height: imageHeight,
|
||||||
baseline: imageHeight - lastLineMetrics.height + lastLineMetrics.baseline,
|
baseline: imageBaseline,
|
||||||
};
|
};
|
||||||
const metrics = { markupMetrics, lineMetrics, imageMetrics };
|
const metrics = { markupMetrics, lineMetrics, imageMetrics };
|
||||||
if (isMathJaxLoaded) {
|
if (isMathJaxLoaded) {
|
||||||
@ -778,17 +786,17 @@ const renderMath = (
|
|||||||
);
|
);
|
||||||
const width = parentWidth ?? metrics.imageMetrics.width;
|
const width = parentWidth ?? metrics.imageMetrics.width;
|
||||||
|
|
||||||
let y = 0;
|
let y = -1;
|
||||||
for (let index = 0; index < markup.length; index++) {
|
for (let index = 0; index < markup.length; index++) {
|
||||||
const lineMetrics = metrics.lineMetrics[index];
|
const lineMetrics = metrics.lineMetrics[index];
|
||||||
const lineMarkupMetrics = metrics.markupMetrics[index];
|
const lineMarkupMetrics = metrics.markupMetrics[index];
|
||||||
const rtl = isRTL(mathLines[index]);
|
const rtl = isRTL(mathLines[index]);
|
||||||
const x =
|
const x =
|
||||||
textAlign === "right"
|
textAlign === "right"
|
||||||
? width - lineMetrics.width
|
? width - lineMetrics.width + 1
|
||||||
: textAlign === "left"
|
: textAlign === "left"
|
||||||
? 0
|
? 0
|
||||||
: (width - lineMetrics.width) / 2;
|
: (width - lineMetrics.width + 1) / 2;
|
||||||
// Drop any empty strings from this line to match childMetrics
|
// Drop any empty strings from this line to match childMetrics
|
||||||
const content = markup[index].filter((value) => value !== "");
|
const content = markup[index].filter((value) => value !== "");
|
||||||
for (let i = 0; i < content.length; i += 1) {
|
for (let i = 0; i < content.length; i += 1) {
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user