@@ -43,6 +43,16 @@ urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn;
4343 text: TypeError
4444</pre>
4545
46+ <!--
47+ TODO
48+ - Fix layout invalidation section.
49+ - Add painting behaviour section.
50+ - Fix examples.
51+ - Add utility functions.
52+ - Define invalid fragment.
53+ - Layout instance on box is incorrect.
54+ -->
55+
4656Introduction {#intro}
4757=====================
4858
@@ -99,6 +109,10 @@ href="https://www.w3.org/TR/CSS2/visuren.html#dis-pos-flo">CSS 2.1 Section 9.7</
99109contain an additional row, with ''inline-layout()'' in the "Specified Value" column and ''layout()''
100110in the "Computed Value" column.
101111
112+ A <a>layout API container</a> has a <dfn>layout instance</dfn> , initially this is set to null. This
113+ is an instance of the author defined layout class (see [[#registering-layout]] ). If the <a>box</a> 's
114+ <a>computed value</a> of 'display' changes, this must be reset to null.
115+
102116Layout API Model and Terminology {#layout-api-model-and-terminology}
103117====================================================================
104118
@@ -117,7 +131,7 @@ Layout Children {#layout-children}
117131
118132<pre class='idl'>
119133interface LayoutChild {
120- FragmentRequestToken doLayout(ConstraintSpace space, ChildBreakToken breakToken);
134+ FragmentRequest doLayout(ConstraintSpace space, ChildBreakToken breakToken);
121135};
122136
123137interface InlineLayoutChild : LayoutChild {
@@ -339,6 +353,9 @@ interface ConstraintSpace {
339353 readonly attribute double percentageInlineSize;
340354 readonly attribute double percentageBlockSize;
341355
356+ readonly attribute boolean inlineOverflow;
357+ readonly attribute boolean blockOverflow;
358+
342359 readonly attribute BlockFragmentationType blockFragmentationType;
343360};
344361
@@ -556,6 +573,19 @@ registerLayout('fragmenting', class {
556573</pre>
557574</div>
558575
576+ Utility Functions {#utility-functions}
577+ --------------------------------------
578+
579+ <pre class='idl'>
580+ partial interface LayoutWorkletGlobalScope {
581+ resolveInlineSize();
582+ resolveBlockSize();
583+
584+ resolveBordersAndPadding();
585+ resolveScrollbarSize();
586+ };
587+ </pre>
588+
559589Layout {#layout}
560590================
561591
@@ -735,7 +765,7 @@ Layout Engine {#layout-engine}
735765------------------------------
736766
737767<pre class="idl">
738- interface FragmentRequestToken {
768+ interface FragmentRequest {
739769 // Has internal slots:
740770 // [[layoutChild]] - The layout child to generate the fragment for.
741771 // [[constraintSpace]] - The constraint space to perform layout in.
@@ -749,10 +779,10 @@ engines.
749779
750780When an author invokes the {{LayoutChild/doLayout()}} method on a {{LayoutChild}} the user-agent
751781doesn't synchronously generate a {{Fragment}} to return to the author's code. Instead it returns a
752- {{FragmentRequestToken }} . This is a completely opaque object to the author but contains internal
753- slots which encapsulates the {{Box /doLayout()}} method call.
782+ {{FragmentRequest }} . This is a completely opaque object to the author but contains internal
783+ slots which encapsulates the {{LayoutChild /doLayout()}} method call.
754784
755- When a {{FragmentRequestToken }} (s) are yielded from a layout generator object the user-agent's
785+ When a {{FragmentRequest }} (s) are yielded from a layout generator object the user-agent's
756786layout engine may run the algorithm asynchronously with other work, and/or on a different thread of
757787execution. When {{Fragment}} (s) have been produced by the engine, the user-agent will 'tick' the
758788generator object with the resulting {{Fragment}} (s).
@@ -775,7 +805,7 @@ class LayoutEngine {
775805 });
776806 }
777807
778- // This function takes a FragmentRequestToken and calls the appropriate layout
808+ // This function takes a FragmentRequest and calls the appropriate layout
779809 // algorithm to generate the a Fragment.
780810 layoutFragment(fragmentRequest) {
781811 const box = fragmentRequest.box;
@@ -806,61 +836,175 @@ class LayoutEngine {
806836</pre>
807837</div>
808838
809- TODO explain parallel layout + {{FragmentRequestToken }} , etc.
839+ TODO explain parallel layout + {{FragmentRequest }} , etc.
810840
811- Performing layout {#performing-layout}
841+ Performing Layout {#performing-layout}
812842--------------------------------------
813843
814844<pre class='idl'>
815- dictionary LayoutResult {
816- double inlineSize;
817- double blockSize;
818- sequence<Fragment> fragments;
819- BreakToken breakToken;
820- double baseline;
845+ // This is the final return value from the author defined layout() method.
846+ dictionary FragmentResultOptions {
847+ double inlineSize = 0;
848+ double blockSize = 0;
849+ double inlineOverflowSize = null;
850+ double blockOverflowSize = null;
851+ sequence<Fragment> childFragments = [];
852+ BreakTokenOptions breakToken = null;
853+ double dominantBaseline = null;
821854};
822855</pre>
823856
824- {{LayoutClass/layout()}} is invoked by the user agent when <a>generate a layout</a> for a <a>box</a> .
857+ When the user agent wants to <dfn>generate a layout API fragment</dfn> of a <a>layout API formatting
858+ context</a> for a given |box|, |constraintSpace|, |children| and an optional |breakToken| it
859+ <em> must</em> run the following steps:
860+
861+ 1. If the <a>layout valid flag</a> for the |box| is <a>layout-valid</a> the user agent
862+ <em> may</em> use a fragment from a previous invocation of this algorithm if the |box|,
863+ |constraintSpace|, |children| and optional |breakToken| are the same. If so it <em> may</em>
864+ abort all these steps and use the cached fragment.
865+
866+ Issue: The above is too limiting wrt. the layout valid flag. Need to separate out the produce
867+ the fragment step, with the cache invalidation.
868+
869+ Note: The user agent for implementation reasons may also continue with all these steps in this
870+ case. It can do this every frame, or multiple times per frame.
871+
872+ 2. Let |layoutFunction| be the <<layout()>> or <<inline-layout()>> for the <a>computed value</a>
873+ of 'display' on the |box|.
874+
875+ 3. Let |name| be the first argument of the |layoutFunction|.
876+
877+ 4. Let |workletGlobalScope| be a {{LayoutWorkletGlobalScope}} from the list of <a>worklet's
878+ WorkletGlobalScopes</a> from the layout {{Worklet}} .
879+
880+ The user agent <em> may</em> also <a>create a WorkletGlobalScope</a> given the layout
881+ {{Worklet}} and use that.
882+
883+ Note: The user agent <em> may</em> use any policy for which {{LayoutWorkletGlobalScope}} to
884+ select or create. It may use a single {{LayoutWorkletGlobalScope}} or multiple and
885+ randomly assign between them.
886+
887+ 5. Let |definition| be the result of looking up |name| on the |workletGlobalScope|'s <a>layout
888+ name to layout definition map</a> .
889+
890+ If |definition| does not exist, let the fragment output be an <a>invalid fragment</a> and
891+ abort all these steps.
892+
893+ 6. Let |layoutInstance| be the result of looking up the <a>layout instance</a> on the |box|. If
894+ |layoutInstance| is null run the following substeps.
895+
896+ 1. If the <a>layout class constructor valid flag</a> on |definition| is false, let the
897+ fragment output be an <a>invalid fragment</a> and abort all these steps.
898+
899+ 2. Let |layoutCtor| be the <a>layout class constructor</a> on |definition|.
900+
901+ 3. Let |layoutInstance| be the result of <a>Construct</a> (|layoutCtor|).
902+
903+ If <a>Construct</a> throws an exception, set the |definition|'s <a>layout class
904+ constructor valid flag</a> to false, let the fragment output be an <a>invalid
905+ fragment</a> and abort all these steps.
906+
907+ 4. Set <a>layout instance</a> on |box| to |layoutInstance|.
908+
909+ Note: <a>Layout instance</a> will be set to null whenever the <a>computed style</a> of
910+ 'display' on |box| changes.
911+
912+ 7. Let |layoutGeneratorFunction| be the result of looking up the <a>layout generator
913+ function</a> .
914+
915+ 8. Let |inputProperties| be the result of looking up |name| on the associated <a>document</a> 's
916+ <a>layout name to input properties map</a> .
917+
918+ 9. Let |styleMap| be a new {{StylePropertyMapReadOnly}} populated with <em> only</em> the
919+ <a>computed value</a> 's for properties listed in |inputProperties|.
920+
921+ 10. Let |layoutGenerator| be the result of <a>Call</a> (|layoutGeneratorFunction|,
922+ |layoutInstance|, «|constraintSpace|, |children|, |styleMap|, |breakToken|»).
923+
924+ 12. Let |childFragmentResults| be «» (the empty list).
925+
926+ 11. Let |nextResult| be the result of calling <a>Invoke</a> (<code> next</code> ,
927+ |layoutGenerator|, |childFragmentResults|).
928+
929+ 12. Perform the following substeps until the result of <a>Get</a> (|nextResult|,
930+ <code> "done"</code> ) is <code> true</code> .
931+
932+ 1. Set |childFragmentResults| be «» (the empty list).
933+
934+ 2. Let |fragmentRequests| be the result of <a>Get</a> (|nextResult|, <code> "value"</code> ).
935+
936+ 3. For each |fragmentRequest| in |fragmentRequests| perform the following substeps:
937+
938+ 1. Let |layoutChild| be result of looking up the internal slot
939+ <code> \[[layoutChild]] </code> on |fragmentRequest|.
940+
941+ 2. Let |childConstraintSpace| be the result of looking up the internal slot
942+ <code> \[[childConstraintSpace]] </code> on |fragmentRequest|.
943+
944+ 3. Let |childBreakToken| be the result of looking up the internal slot
945+ <code> \[[childBreakToken]] </code> on |fragmentRequest|.
946+
947+ 4. Let |childFragmentResult| be the result of invoking <a>generate a fragment</a> with
948+ the arguments |layoutChild|, |childConstraintSpace|, |childBreakToken|.
949+
950+ The user agent <em> may</em> perform this step <a>in parallel</a> .
951+
952+ 5. Append |childFragmentResult| to |childFragmentResults|.
953+
954+ 4. Let |nextResult| be the result of calling <a>Invoke</a> (<code> next</code> ,
955+ |layoutGenerator|, |childFragmentResults|).
956+
957+ 13. Let |fragmentResult| be the result of calling <a>Get</a> (|nextResult|,
958+ <code> "value"</code> ).
959+
960+ 14. Let |fragment| be a <a>fragment</a> with the following properties:
961+
962+ - The <a>border box</a> <a>inline size</a> is set to |fragmentResult|'s
963+ {{FragmentResultOptions/inlineSize}} .
964+
965+ - The <a>border box</a> <a>block size</a> is set to |fragmentRequest|'s
966+ {{FragmentResultOptions/blockSize}} .
967+
968+ - The <a>inline overflow size</a> is set to |fragmentResult|'s
969+ {{FragmentResultOptions/inlineOverflowSize}} if not null, otherwise it is set to
970+ {{FragmentResultOptions/inlineSize}} .
971+
972+ - The <a>block overflow size</a> is set to |fragmentResult|'s
973+ {{FragmentResultOptions/blockOverflowSize}} if not null, otherwise it is set to
974+ {{FragmentResultOptions/blockSize}} .
825975
826- The user agent passes in:
827- - The current children for the <a>box</a> , with only {{LayoutClass/childInputProperties}} on
828- {{Box/styleMap}}
829- - The available space defined by a {{ConstraintSpace}}
830- - The computed style of the <a>box</a> , with only {{LayoutClass/inputProperties}}
831- - The {{BreakToken}} if any, for where the <a>box</a> was last fragmented.
976+ If the |constraintSpace|'s {{ConstraintSpace/inlineOverflow}} is <code> false</code> and
977+ the <a>inline overflow size</a> is greater than the <a>inline size</a> and the <a>computed
978+ value</a> for <a>inline</a> 'overflow' is ''auto'' then set |constraintSpace|'s
979+ {{ConstraintSpace/inlineOverflow}} to <code> true</code> .
832980
833- The author defined code should produce a {{LayoutResult}} .
981+ If the |constraintSpace|'s {{ConstraintSpace/blockOverflow}} is <code> false</code> and the
982+ <a>block overflow size</a> is greater than the <a>block size</a> and the <a>computed
983+ value</a> for <a>block</a> 'overflow' is ''auto'' then set |constraintSpace|'s
984+ {{ConstraintSpace/blockOverflow}} to <code> true</code> .
834985
835- The {{LayoutResult}} consists of:
836- - A {{LayoutResult/minContent}} which represents the fragment's <a>min-content inline-size
837- contribution</a> .
838- - A {{LayoutResult/maxContent}} which represents the fragment's <a>max-content inline-size
839- contribution</a> .
840- - A {{LayoutResult/width}} which represents the fragment's resulting width.
841- - A {{LayoutResult/height}} which represents the fragment's resulting height.
842- - A list of {{LayoutResult/fragments}} which represents the fragment's direct child fragments.
843- - A list of {{LayoutResult/unpositionedFragments}} which represents the fragment's children which
844- should be positioned by a parent fragment.
845- - A {{LayoutResult/breakToken}} which represents where the current layout's box last broke.
846- - A {{LayoutResult/baseline}} which represents the baseline of the fragment.
986+ If either {{ConstraintSpace/inlineOverflow}} or {{ConstraintSpace/blockOverflow}} were set
987+ in the above steps, restart this algorithm with the updated |constraintSpace|.
847988
848- Issue: Write the following into the algorithm.
989+ Note: In a future level of the specification there may be a way to more efficiently abort
990+ a layout given a "scroll trigger line" on the constraint space.
849991
850- If any {{Fragment}} s appear in both the list of {{LayoutResult/fragments}} or the list of
851- {{LayoutResult/unpositionedFragments}} the user agent should throw an error.
992+ - The children fragments of the |fragment| is set from |fragmentResult|'s
993+ {{FragmentResultOptions/childFragments}} . The ordering <em> is</em> important as this is
994+ dictates their paint order (described in [[#layout-api-containers]] ). Their position
995+ relative to the <a>border box</a> of the |fragment| should be based off the author
996+ specified {{Fragment/inlineOffset}} and {{Fragment/blockOffset}} .
852997
853- The user agent should check that a consistent set of {{Fragment}} s generated from a {{LayoutChild}}
854- is returned in either the list of {{LayoutResult/fragments}} or
855- {{LayoutResult/unpositionedFragments}} . (Consistent being that a {{Fragment/breakToken}} from one
856- {{Fragment}} was used to generate another {{Fragment}} in the set).
998+ - The <a>fragmentation break</a> is set to |fragmentResult|'s
999+ {{FragmentResultOptions/breakToken}} .
8571000
858- If any {{Fragment}} s appear more than once, the user agent should throw an error.
1001+ - The <a>dominant baseline</a> is set to |fragmentResult|'s
1002+ {{FragmentResultOptions/dominantBaseline}} if not null, otherwise it is set to:
1003+ - The {{Fragment/dominantBaseline}} of the first child fragment if present.
8591004
860- When the user agent wants to <dfn>generate a layout</dfn> of a <<layout()>> or <<inline-layout()>>
861- for a box it <em> must</em> run the following steps:
1005+ - The {{FragmentResultOptions/blockSize}} of the fragment.
8621006
863- Issue: TODO specify these steps .
1007+ 15. Return |fragment| .
8641008
8651009Examples {#examples}
8661010====================
0 commit comments