feat: improve text measurements in bound containers (#6187)

* feat: move to canvas measureText

* calcualte height with better heuristic

* improve heuristic more

* remove vertical offset as its not needed

* lint

* calculate width of individual char and ceil to calculate width and remove adjustment factor

* push the word if equal to max width

* update height when text overflows for vertical alignment top/bottom

* remove the hack of updating height when line mismatch as its not needed

* remove scroll height and calculate the height instead

* remove unused code

* fix

* remove

* use math.ceil for whole width instead of individual chars

* fix tests

* fix

* fix

* redraw text bounding box instead when font loaded to fix alignment as well

* fix

* fix

* fix

* Add a 0.05px extra only for firefox

* Add spec

* stop taking ceil and increase firefox editor width by 0.05px

* Ad 0.05px in safari too

* lint

* lint

* remove baseline from measureFontSizeFromWH

* don't redraw on font load

* lint

* refactor name and signature
This commit is contained in:
Aakansha Doshi 2023-02-23 16:33:10 +05:30 committed by GitHub
parent 39b96cb011
commit 9659254fd6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 142 additions and 349 deletions

View file

@ -5,7 +5,6 @@ import {
getContainerCoords,
getMaxContainerWidth,
getMaxContainerHeight,
measureText,
wrapText,
} from "./textElement";
import { FontString } from "./types";
@ -73,6 +72,13 @@ up`,
width: 250,
res: "Hello whats up",
},
{
desc: "should push the word if its equal to max width",
width: 60,
res: `Hello
whats
up`,
},
].forEach((data) => {
it(`should ${data.desc}`, () => {
const res = wrapText(text, font, data.width - BOUND_TEXT_PADDING * 2);
@ -80,6 +86,7 @@ up`,
});
});
});
describe("When text contain new lines", () => {
const text = `Hello
whats up`;
@ -170,38 +177,6 @@ break it now`,
});
describe("Test measureText", () => {
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
const text = "Hello World";
it("should add correct attributes when maxWidth is passed", () => {
const maxWidth = 200 - BOUND_TEXT_PADDING * 2;
const res = measureText(text, font, maxWidth);
expect(res.container).toMatchInlineSnapshot(`
<div
style="position: absolute; white-space: pre-wrap; font: Emoji 20px 20px; min-height: 1em; max-width: 191px; overflow: hidden; word-break: break-word; line-height: 0px;"
>
<span
style="display: inline-block; overflow: hidden; width: 1px; height: 1px;"
/>
</div>
`);
});
it("should add correct attributes when maxWidth is not passed", () => {
const res = measureText(text, font);
expect(res.container).toMatchInlineSnapshot(`
<div
style="position: absolute; white-space: pre; font: Emoji 20px 20px; min-height: 1em;"
>
<span
style="display: inline-block; overflow: hidden; width: 1px; height: 1px;"
/>
</div>
`);
});
describe("Test getContainerCoords", () => {
const params = { width: 200, height: 100, x: 10, y: 20 };