@@ -43,6 +43,16 @@ urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn;
43
43
text: TypeError
44
44
</pre>
45
45
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
+
46
56
Introduction {#intro}
47
57
=====================
48
58
@@ -99,6 +109,10 @@ href="https://www.w3.org/TR/CSS2/visuren.html#dis-pos-flo">CSS 2.1 Section 9.7</
99
109
contain an additional row, with ''inline-layout()'' in the "Specified Value" column and ''layout()''
100
110
in the "Computed Value" column.
101
111
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
+
102
116
Layout API Model and Terminology {#layout-api-model-and-terminology}
103
117
====================================================================
104
118
@@ -117,7 +131,7 @@ Layout Children {#layout-children}
117
131
118
132
<pre class='idl'>
119
133
interface LayoutChild {
120
- FragmentRequestToken doLayout(ConstraintSpace space, ChildBreakToken breakToken);
134
+ FragmentRequest doLayout(ConstraintSpace space, ChildBreakToken breakToken);
121
135
};
122
136
123
137
interface InlineLayoutChild : LayoutChild {
@@ -339,6 +353,9 @@ interface ConstraintSpace {
339
353
readonly attribute double percentageInlineSize;
340
354
readonly attribute double percentageBlockSize;
341
355
356
+ readonly attribute boolean inlineOverflow;
357
+ readonly attribute boolean blockOverflow;
358
+
342
359
readonly attribute BlockFragmentationType blockFragmentationType;
343
360
};
344
361
@@ -556,6 +573,19 @@ registerLayout('fragmenting', class {
556
573
</pre>
557
574
</div>
558
575
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
+
559
589
Layout {#layout}
560
590
================
561
591
@@ -735,7 +765,7 @@ Layout Engine {#layout-engine}
735
765
------------------------------
736
766
737
767
<pre class="idl">
738
- interface FragmentRequestToken {
768
+ interface FragmentRequest {
739
769
// Has internal slots:
740
770
// [[layoutChild]] - The layout child to generate the fragment for.
741
771
// [[constraintSpace]] - The constraint space to perform layout in.
@@ -749,10 +779,10 @@ engines.
749
779
750
780
When an author invokes the {{LayoutChild/doLayout()}} method on a {{LayoutChild}} the user-agent
751
781
doesn'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.
754
784
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
756
786
layout engine may run the algorithm asynchronously with other work, and/or on a different thread of
757
787
execution. When {{Fragment}} (s) have been produced by the engine, the user-agent will 'tick' the
758
788
generator object with the resulting {{Fragment}} (s).
@@ -775,7 +805,7 @@ class LayoutEngine {
775
805
});
776
806
}
777
807
778
- // This function takes a FragmentRequestToken and calls the appropriate layout
808
+ // This function takes a FragmentRequest and calls the appropriate layout
779
809
// algorithm to generate the a Fragment.
780
810
layoutFragment(fragmentRequest) {
781
811
const box = fragmentRequest.box;
@@ -806,61 +836,175 @@ class LayoutEngine {
806
836
</pre>
807
837
</div>
808
838
809
- TODO explain parallel layout + {{FragmentRequestToken }} , etc.
839
+ TODO explain parallel layout + {{FragmentRequest }} , etc.
810
840
811
- Performing layout {#performing-layout}
841
+ Performing Layout {#performing-layout}
812
842
--------------------------------------
813
843
814
844
<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;
821
854
};
822
855
</pre>
823
856
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}} .
825
975
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> .
832
980
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> .
834
985
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|.
847
988
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.
849
991
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}} .
852
997
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}} .
857
1000
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.
859
1004
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.
862
1006
863
- Issue: TODO specify these steps .
1007
+ 15. Return |fragment| .
864
1008
865
1009
Examples {#examples}
866
1010
====================
0 commit comments