Skip to content

Commit ef2cc61

Browse files
committed
[css-layout-api] Write very broad layout engine section.
1 parent 5189922 commit ef2cc61

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

css-layout-api/Overview.bs

+76-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Editor: Rossen Atanassov, rossen.atanassov@microsoft.com
1616

1717
<pre class="link-defaults">
1818
spec:css-break-3; type:dfn; text:fragment
19+
spec:css-display-3; type:dfn; text:box
20+
spec:css-display-3; type:value; for:display; text:none
21+
spec:dom; type:dfn; text:element
1922
</pre>
2023

2124
Introduction {#intro}
@@ -43,7 +46,7 @@ Layout Boxes {#layout-boxes}
4346

4447
<pre class='idl'>
4548
interface Box {
46-
readonly attribute ComputedStylePropertyMapReadOnly styleMap;
49+
readonly attribute StylePropertyMapReadOnly styleMap;
4750
FragmentRequestToken doLayout(DerivedConstraintSpace space, ChildBreakToken breakToken);
4851
};
4952
</pre>
@@ -675,6 +678,78 @@ TODO, list all the ways that layout can be invalidated, namely:
675678
Layout Engine {#layout-engine}
676679
==============================
677680

681+
<pre class="idl">
682+
interface FragmentRequestToken {
683+
// Has internal slots:
684+
// [[box]] - The box to generate the fragment for.
685+
// [[constraintSpace]] - The constraint space to perform layout in.
686+
// [[breakToken]] - The break token to resume the layout with.
687+
};
688+
</pre>
689+
690+
The layout method on the author supplied layout class is a generator function instead of a regular
691+
javascript function. This is for user-agents to be able to support asyncronous and parallel layout
692+
engines.
693+
694+
When an author invokes the {{Box/doLayout()}} method on a {{Box}} the user-agent doesn't
695+
synchronously generate a {{Fragment}} to return to the author's code. Instead it returns a
696+
{{FragmentRequestToken}}. This is a completely opaque object to the author but contains internal
697+
slots which encapsulates the {{Box/doLayout()}} method call.
698+
699+
When a {{FragmentRequestToken}}(s) are yielded from a layout generator object the user-agent's
700+
layout engine may run the algorithm asynchronously with other work, and/or on a different thread of
701+
execution. When {{Fragment}}(s) have been produced by the engine, the user-agent will 'tick' the
702+
generator object with the resulting {{Fragment}}(s).
703+
704+
Issue: Write algorithm "<dfn>generate a fragment</dfn>" which encapsulates this.
705+
706+
<div class="example">
707+
An example layout engine written in javascript is shown below.
708+
709+
<pre class="lang-javascript">
710+
class LayoutEngine {
711+
// This function takes the root of the Box-tree, a ConstraintSpace, and a
712+
// BreakToken to (if paginating for printing for example) and generates a
713+
// Fragment.
714+
layoutEntry(rootBox, rootPageConstraintSpace, breakToken) {
715+
return layoutFragment({
716+
box: rootBox,
717+
constraintSpace: rootPageConstraintSpace,
718+
breakToken: breakToken,
719+
});
720+
}
721+
722+
// This function takes a FragmentRequestToken and calls the appropriate layout
723+
// algorithm to generate the a Fragment.
724+
layoutFragment(fragmentRequest) {
725+
const box = fragmentRequest.box;
726+
const algorithm = selectLayoutAlgorithmForBox(box);
727+
const fragmentRequestGenerator = algorithm.layout(
728+
fragmentRequest.constraintSpace,
729+
box.children,
730+
box.styleMap,
731+
fragmentRequest.breakToken);
732+
733+
let nextFragmentRequest = fragmentRequestGenerator.next();
734+
735+
while (!nextFragmentRequest.done) {
736+
// A user-agent may decide to perform layout to generate the fragments in
737+
// parallel on separate threads. This example performs them synchronously
738+
// in order.
739+
let fragments = nextFragmentRequest.value.map(layoutFragment);
740+
741+
// A user-agent may decide to yield for other work (garbage collection for
742+
// example) before resuming this layout work. This example just performs
743+
// layout synchronously without any ability to yield.
744+
nextFragmentRequest = fragmentRequestGenerator.next(fragments);
745+
}
746+
747+
return nextFragmentRequest.value; // Return the final Fragment.
748+
}
749+
}
750+
</pre>
751+
</div>
752+
678753
TODO explain parallel layout + {{FragmentRequestToken}}, etc.
679754

680755
Registering A Layout {#registering-a-layout}

0 commit comments

Comments
 (0)