You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The motivation is to have one array represent the entire layout tree
rather than parent boxes storing children arrays. I started down this
rabbit hole in December after I realized text-align: justify needs to
bsearch inline content to reapply spacing after wrapping and reshaping.
It is a much more memory-efficient layout: up to 3% less memory is used
in CellEngine. I learned this technique from Chrome:
> The flat list is created for each inline formatting context in the
> order of a depth-first search of its inline layout subtree. Each entry
> in the list is a tuple of (object, number of descendants)
https://developer.chrome.com/docs/chromium/renderingng-data-structures#inline_fragment_items
For dropflow, it makes more sense to store the last descendant's index
instead of the number of descendants, since we maintain a parent stack
during iteration. The index of the box itself doesn't necessarily need
to be stored - usually you have the index during iteration - but I found
passing it around to be cumbersome, and it makes for a much better .id!
This refactor also includes a much more efficient strategy for handling
mixed block and inline content, documented in the comment. Generating
boxes was deeply affected due to the new way of storing trees.
Whitespace collapsing was also deeply affected since it can remove tree
nodes. It now happens in the generate phase, which is now called
flow.layout instead of flow.generate, and the old flow.layout is now
called flow.reflow. I want to use "layout" as a noun from now on, and
"reflow" for the verb, which is about what Firefox does. The new Layout
class will eventually store flat arrays of items and fragments, not just
the tree nodes.
Reflow is faster, mainly due to the removal of whitespace collapsing.
The new memory layout had slightly disappointing results, although it
did lead to fewer CPU cache misses, but the speedup was nothing to
remark about, except in perf-2 where it's a solid 2-3% faster. Painting
also got faster.
@@ -185,12 +185,12 @@ Then, you can either render the DOM into a canvas using its size as the viewport
185
185
186
186
1.[Render DOM to canvas](#render-dom-to-canvas)
187
187
188
-
Or, you can use the lower-level functions to retain the layout, in case you want to re-layout at a different size, choose not to paint (for example if the layout isn't visible) or get intrinsics:
188
+
Or, you can use the lower-level functions to retain the layout, in case you want to reflow at a different size, choose not to paint (for example if the layout isn't visible) or get intrinsics:
189
189
190
190
1.[Load dependent resources](#load)
191
-
2.[Generate a tree of layout boxes from the DOM](#generate)
192
-
3.[Layout the box tree](#layout)
193
-
4.[Paint the box tree to a target like canvas](#paint)
191
+
2.[Create a layout for the DOM](#layout)
192
+
3.[Reflow the layout](#layout)
193
+
4.[Paint the layout to a target like HTML5 canvas](#paint)
194
194
195
195
## Fonts
196
196
@@ -378,7 +378,7 @@ Parses HTML. If you don't specify a root `<html>` element, content will be wrapp
Holdontothereturnvaluesoyoucanlayitoutmanytimesindifferentsizes, paintitordon't paint it if it'soff-screen, orgetintrinsicstobuildahigher-levellogicallayout (forexample, spreadsheetcolumnorrowsizeevenifthecontentisoffscreen).
437
441
438
-
## Layout
442
+
## Reflowingalayout
439
443
440
-
### `layout`
444
+
### `reflow`
441
445
442
446
```ts
443
-
function layout(root: BlockContainer, width = 640, height = 480);
447
+
function reflow(layout: Layout, width = 640, height = 480);
function paintToSvgElements(root: BlockContainer): string;
488
+
function paintToSvgElements(root: Layout): string;
485
489
```
486
490
487
491
Similarto`paintToSvg`, butdoesn't add `<svg>` or `@font-face` rules. Useful if you'repaintinginsideofanalready-existingSVGelement.
488
492
489
493
### `paintToHtml`
490
494
491
495
```ts
492
-
function paintToHtml(root: BlockContainer): string;
496
+
function paintToHtml(root: Layout): string;
493
497
```
494
498
495
499
PainttoHTML!Yes, thisAPIcanactuallybeusedtogofromHTMLtoHTML. Itgeneratesaflatlistofabunchofabsolutelypositionedelements. Probablydon't use this, but it can be useful in development and is amusing.
@@ -529,8 +533,8 @@ Typically when you use `query`, you'll be getting a `BlockContainer`:
529
533
530
534
```ts
531
535
const dom = parse('<div id="d" style="width: 100px; height: 100px;"></div>');
532
-
const root = flow.generate(dom);
533
-
flow.layout(root, 200, 200);
536
+
const layout = flow.layout(dom);
537
+
flow.reflow(layout, 200, 200);
534
538
const [box] = dom.query('#d')!.boxes as flow.BlockContainer[];
0 commit comments