weasyprint 64.1__py3-none-any.whl → 65.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weasyprint/__init__.py +2 -1
- weasyprint/css/computed_values.py +1 -1
- weasyprint/css/html5_ph.css +65 -178
- weasyprint/css/html5_ua.css +249 -749
- weasyprint/css/html5_ua_form.css +3 -13
- weasyprint/css/validation/descriptors.py +9 -0
- weasyprint/draw/border.py +4 -4
- weasyprint/draw/text.py +12 -8
- weasyprint/formatting_structure/build.py +17 -17
- weasyprint/images.py +2 -2
- weasyprint/layout/__init__.py +17 -0
- weasyprint/layout/absolute.py +1 -1
- weasyprint/layout/block.py +23 -20
- weasyprint/layout/column.py +2 -3
- weasyprint/layout/flex.py +396 -571
- weasyprint/layout/float.py +6 -4
- weasyprint/layout/inline.py +23 -27
- weasyprint/layout/page.py +22 -18
- weasyprint/layout/percent.py +41 -46
- weasyprint/layout/preferred.py +13 -16
- weasyprint/pdf/fonts.py +22 -23
- weasyprint/stacking.py +2 -2
- weasyprint/svg/__init__.py +6 -3
- weasyprint/text/constants.py +5 -0
- weasyprint/text/ffi.py +12 -0
- weasyprint/text/fonts.py +12 -3
- weasyprint/text/line_break.py +8 -7
- {weasyprint-64.1.dist-info → weasyprint-65.1.dist-info}/METADATA +2 -2
- {weasyprint-64.1.dist-info → weasyprint-65.1.dist-info}/RECORD +32 -32
- {weasyprint-64.1.dist-info → weasyprint-65.1.dist-info}/WHEEL +1 -1
- {weasyprint-64.1.dist-info → weasyprint-65.1.dist-info}/entry_points.txt +0 -0
- {weasyprint-64.1.dist-info → weasyprint-65.1.dist-info}/licenses/LICENSE +0 -0
weasyprint/layout/flex.py
CHANGED
|
@@ -5,126 +5,88 @@ from math import inf, log10
|
|
|
5
5
|
|
|
6
6
|
from ..css.properties import Dimension
|
|
7
7
|
from ..formatting_structure import boxes
|
|
8
|
+
from . import percent
|
|
8
9
|
from .absolute import AbsolutePlaceholder, absolute_layout
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
11
|
-
from .table import find_in_flow_baseline
|
|
10
|
+
from .preferred import max_content_width, min_content_width, min_max
|
|
11
|
+
from .table import find_in_flow_baseline, table_wrapper_width
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class FlexLine(list):
|
|
15
|
-
|
|
15
|
+
"""Flex container line."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
19
|
-
|
|
20
|
-
from . import block
|
|
18
|
+
def flex_layout(context, box, bottom_space, skip_stack, containing_block, page_is_empty,
|
|
19
|
+
absolute_boxes, fixed_boxes, discard):
|
|
20
|
+
from . import block
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
# TODO: merge this with block_container_layout.
|
|
23
|
+
context.create_flex_formatting_context()
|
|
23
24
|
resume_at = None
|
|
24
25
|
|
|
26
|
+
is_start = skip_stack is None
|
|
27
|
+
box.remove_decoration(start=not is_start, end=False)
|
|
28
|
+
|
|
29
|
+
discard |= box.style['continue'] == 'discard'
|
|
30
|
+
draw_bottom_decoration = discard or box.style['box_decoration_break'] == 'clone'
|
|
31
|
+
|
|
32
|
+
row_gap, column_gap = box.style['row_gap'], box.style['column_gap']
|
|
33
|
+
|
|
34
|
+
if draw_bottom_decoration:
|
|
35
|
+
bottom_space += box.padding_bottom + box.border_bottom_width + box.margin_bottom
|
|
36
|
+
|
|
25
37
|
if box.style['position'] == 'relative':
|
|
26
38
|
# New containing block, use a new absolute list
|
|
27
39
|
absolute_boxes = []
|
|
28
40
|
|
|
29
|
-
#
|
|
41
|
+
# References are to: https://www.w3.org/TR/css-flexbox-1/#layout-algorithm.
|
|
42
|
+
|
|
43
|
+
# 1 Initial setup, done in formatting_structure.build.
|
|
30
44
|
|
|
31
|
-
#
|
|
32
|
-
# 9.2. Line length determination.
|
|
45
|
+
# 2 Determine the available main and cross space for the flex items.
|
|
33
46
|
if box.style['flex_direction'].startswith('row'):
|
|
34
|
-
|
|
47
|
+
main, cross = 'width', 'height'
|
|
35
48
|
else:
|
|
36
|
-
|
|
49
|
+
main, cross = 'height', 'width'
|
|
37
50
|
|
|
38
51
|
margin_left = 0 if box.margin_left == 'auto' else box.margin_left
|
|
39
52
|
margin_right = 0 if box.margin_right == 'auto' else box.margin_right
|
|
40
|
-
margin_top = 0 if box.margin_top == 'auto' else box.margin_top
|
|
41
|
-
margin_bottom = 0 if box.margin_bottom == 'auto' else box.margin_bottom
|
|
42
53
|
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
if getattr(box,
|
|
46
|
-
|
|
54
|
+
# Define available main space.
|
|
55
|
+
# TODO: min- and max-content not implemented.
|
|
56
|
+
if getattr(box, main) != 'auto':
|
|
57
|
+
# If that dimension of the flex container’s content box is a definite size…
|
|
58
|
+
available_main_space = getattr(box, main)
|
|
47
59
|
else:
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
# in that dimension is that constraint.
|
|
51
|
-
# TODO: not implemented (at least, not correctly).
|
|
52
|
-
|
|
53
|
-
# 9.2.2 Otherwise, subtract the flex container’s margin,
|
|
54
|
-
# border, and padding from the space available to the flex
|
|
55
|
-
# container in that dimension and use that value. This might
|
|
56
|
-
# result in an infinite value.
|
|
57
|
-
if axis == 'width':
|
|
60
|
+
# Otherwise, subtract the flex container’s margin, border, and padding…
|
|
61
|
+
if main == 'width':
|
|
58
62
|
available_main_space = (
|
|
59
63
|
containing_block.width -
|
|
60
64
|
margin_left - margin_right -
|
|
61
65
|
box.padding_left - box.padding_right -
|
|
62
66
|
box.border_left_width - box.border_right_width)
|
|
63
67
|
else:
|
|
64
|
-
|
|
65
|
-
if containing_block.height != 'auto':
|
|
66
|
-
if isinstance(containing_block.height, Dimension):
|
|
67
|
-
assert containing_block.height.unit == 'px'
|
|
68
|
-
main_space = min(main_space, containing_block.height.value)
|
|
69
|
-
else:
|
|
70
|
-
main_space = min(main_space, containing_block.height)
|
|
71
|
-
available_main_space = (
|
|
72
|
-
main_space -
|
|
73
|
-
margin_top - margin_bottom -
|
|
74
|
-
box.padding_top - box.padding_bottom -
|
|
75
|
-
box.border_top_width - box.border_bottom_width)
|
|
68
|
+
available_main_space = inf
|
|
76
69
|
|
|
77
|
-
# Same as above for available cross space
|
|
70
|
+
# Same as above for available cross space.
|
|
71
|
+
# TODO: min- and max-content not implemented.
|
|
78
72
|
if getattr(box, cross) != 'auto':
|
|
79
73
|
available_cross_space = getattr(box, cross)
|
|
80
74
|
else:
|
|
81
|
-
|
|
82
|
-
# correctly).
|
|
83
|
-
if cross == 'height':
|
|
84
|
-
main_space = (
|
|
85
|
-
context.page_bottom - bottom_space - box.content_box_y())
|
|
86
|
-
if containing_block.height != 'auto':
|
|
87
|
-
if isinstance(containing_block.height, Dimension):
|
|
88
|
-
assert containing_block.height.unit == 'px'
|
|
89
|
-
main_space = min(main_space, containing_block.height.value)
|
|
90
|
-
else:
|
|
91
|
-
main_space = min(main_space, containing_block.height)
|
|
92
|
-
available_cross_space = (
|
|
93
|
-
main_space -
|
|
94
|
-
margin_top - margin_bottom -
|
|
95
|
-
box.padding_top - box.padding_bottom -
|
|
96
|
-
box.border_top_width - box.border_bottom_width)
|
|
97
|
-
else:
|
|
75
|
+
if cross == 'width':
|
|
98
76
|
available_cross_space = (
|
|
99
77
|
containing_block.width -
|
|
100
78
|
margin_left - margin_right -
|
|
101
79
|
box.padding_left - box.padding_right -
|
|
102
80
|
box.border_left_width - box.border_right_width)
|
|
81
|
+
else:
|
|
82
|
+
available_cross_space = inf
|
|
103
83
|
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
resolve_percentages(parent_box, containing_block)
|
|
110
|
-
# We remove auto margins from parent_box (which is a throwaway) only but
|
|
111
|
-
# keep them on box itself. They will get computed later, once we have done
|
|
112
|
-
# some layout.
|
|
113
|
-
if parent_box.margin_top == 'auto':
|
|
114
|
-
parent_box.margin_top = 0
|
|
115
|
-
if parent_box.margin_bottom == 'auto':
|
|
116
|
-
parent_box.margin_bottom = 0
|
|
117
|
-
if parent_box.margin_left == 'auto':
|
|
118
|
-
parent_box.margin_left = 0
|
|
119
|
-
if parent_box.margin_right == 'auto':
|
|
120
|
-
parent_box.margin_right = 0
|
|
121
|
-
if isinstance(parent_box, boxes.FlexBox):
|
|
122
|
-
block.block_level_width(parent_box, containing_block)
|
|
123
|
-
else:
|
|
124
|
-
parent_box.width = preferred.flex_max_content_width(
|
|
125
|
-
context, parent_box)
|
|
84
|
+
# 3 Determine the flex base size and hypothetical main size of each item.
|
|
85
|
+
parent_box = box.copy()
|
|
86
|
+
percent.resolve_percentages(parent_box, containing_block)
|
|
87
|
+
block.block_level_width(parent_box, containing_block)
|
|
88
|
+
children = sorted(box.children, key=lambda item: item.style['order'])
|
|
126
89
|
original_skip_stack = skip_stack
|
|
127
|
-
children = sorted(children, key=lambda item: item.style['order'])
|
|
128
90
|
if skip_stack is not None:
|
|
129
91
|
(skip, skip_stack), = skip_stack.items()
|
|
130
92
|
if box.style['flex_direction'].endswith('-reverse'):
|
|
@@ -133,16 +95,46 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
133
95
|
children = children[skip:]
|
|
134
96
|
skip_stack = skip_stack
|
|
135
97
|
else:
|
|
136
|
-
skip = 0
|
|
137
|
-
skip_stack = None
|
|
98
|
+
skip, skip_stack = 0, None
|
|
138
99
|
child_skip_stack = skip_stack
|
|
139
100
|
|
|
101
|
+
if row_gap == 'normal':
|
|
102
|
+
row_gap = 0
|
|
103
|
+
elif row_gap.unit == '%':
|
|
104
|
+
if box.height == 'auto':
|
|
105
|
+
row_gap = 0
|
|
106
|
+
else:
|
|
107
|
+
row_gap = row_gap.value / 100 * box.height
|
|
108
|
+
else:
|
|
109
|
+
row_gap = row_gap.value
|
|
110
|
+
if column_gap == 'normal':
|
|
111
|
+
column_gap = 0
|
|
112
|
+
elif column_gap.unit == '%':
|
|
113
|
+
if box.width == 'auto':
|
|
114
|
+
column_gap = 0
|
|
115
|
+
else:
|
|
116
|
+
column_gap = column_gap.value / 100 * box.width
|
|
117
|
+
else:
|
|
118
|
+
column_gap = column_gap.value
|
|
119
|
+
if main == 'width':
|
|
120
|
+
main_gap, cross_gap = column_gap, row_gap
|
|
121
|
+
else:
|
|
122
|
+
main_gap, cross_gap = row_gap, column_gap
|
|
123
|
+
|
|
124
|
+
position_x = (
|
|
125
|
+
parent_box.position_x + parent_box.border_left_width + parent_box.padding_left)
|
|
126
|
+
if parent_box.margin_left != 'auto':
|
|
127
|
+
position_x += parent_box.margin_left
|
|
128
|
+
position_y = (
|
|
129
|
+
parent_box.position_y + parent_box.border_top_width + parent_box.padding_top)
|
|
130
|
+
if parent_box.margin_top != 'auto':
|
|
131
|
+
position_y += parent_box.margin_top
|
|
140
132
|
for index, child in enumerate(children):
|
|
141
133
|
if not child.is_flex_item:
|
|
142
134
|
# Absolute child layout: create placeholder.
|
|
143
135
|
if child.is_absolutely_positioned():
|
|
144
|
-
child.position_x =
|
|
145
|
-
child.position_y =
|
|
136
|
+
child.position_x = position_x
|
|
137
|
+
child.position_y = position_y
|
|
146
138
|
new_child = placeholder = AbsolutePlaceholder(child)
|
|
147
139
|
placeholder.index = index
|
|
148
140
|
children[index] = placeholder
|
|
@@ -156,200 +148,161 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
156
148
|
context.running_elements[running_name][page].append(child)
|
|
157
149
|
continue
|
|
158
150
|
# See https://www.w3.org/TR/css-flexbox-1/#min-size-auto.
|
|
159
|
-
if
|
|
160
|
-
|
|
151
|
+
if main == 'width':
|
|
152
|
+
child_containing_block = (available_main_space, parent_box.height)
|
|
161
153
|
else:
|
|
162
|
-
|
|
163
|
-
resolve_percentages(child,
|
|
164
|
-
child.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
new_child = child.copy()
|
|
154
|
+
child_containing_block = (parent_box.width, available_main_space)
|
|
155
|
+
percent.resolve_percentages(child, child_containing_block)
|
|
156
|
+
if child.is_table_wrapper:
|
|
157
|
+
table_wrapper_width(context, child, child_containing_block)
|
|
158
|
+
child.position_x = position_x
|
|
159
|
+
child.position_y = position_y
|
|
160
|
+
if child.style['min_width'] == 'auto':
|
|
161
|
+
specified_size = child.width
|
|
162
|
+
new_child = child.copy()
|
|
172
163
|
new_child.style = child.style.copy()
|
|
173
164
|
new_child.style['width'] = 'auto'
|
|
174
165
|
new_child.style['min_width'] = Dimension(0, 'px')
|
|
175
166
|
new_child.style['max_width'] = Dimension(inf, 'px')
|
|
176
167
|
content_size = min_content_width(context, new_child, outer=False)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
168
|
+
transferred_size = None
|
|
169
|
+
if isinstance(child, boxes.ReplacedBox):
|
|
170
|
+
image = child.replacement
|
|
171
|
+
_, intrinsic_height, intrinsic_ratio = image.get_intrinsic_size(
|
|
172
|
+
child.style['image_resolution'], child.style['font_size'])
|
|
173
|
+
if intrinsic_ratio and intrinsic_height:
|
|
174
|
+
transferred_size = intrinsic_height * intrinsic_ratio
|
|
175
|
+
if specified_size != 'auto':
|
|
176
|
+
child.min_width = min(specified_size, content_size)
|
|
177
|
+
elif transferred_size is not None:
|
|
178
|
+
child.min_width = min(transferred_size, content_size)
|
|
183
179
|
else:
|
|
184
|
-
|
|
180
|
+
child.min_width = content_size
|
|
181
|
+
if child.style['min_height'] == 'auto':
|
|
182
|
+
# TODO: avoid calling block_level_layout, write min_content_height instead.
|
|
183
|
+
specified_size = child.height
|
|
184
|
+
new_child = child.copy()
|
|
185
185
|
new_child.style = child.style.copy()
|
|
186
|
+
if new_child.style['width'] == 'auto':
|
|
187
|
+
new_child_width = max_content_width(context, new_child)
|
|
188
|
+
new_child.style['width'] = Dimension(new_child_width, 'px')
|
|
186
189
|
new_child.style['height'] = 'auto'
|
|
187
190
|
new_child.style['min_height'] = Dimension(0, 'px')
|
|
188
191
|
new_child.style['max_height'] = Dimension(inf, 'px')
|
|
189
192
|
new_child = block.block_level_layout(
|
|
190
|
-
context, new_child,
|
|
193
|
+
context, new_child, bottom_space, child_skip_stack, parent_box,
|
|
191
194
|
page_is_empty)[0]
|
|
192
|
-
content_size = new_child.height
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
content_size = new_child.height if new_child else 0
|
|
196
|
+
transferred_size = None
|
|
197
|
+
if isinstance(child, boxes.ReplacedBox):
|
|
198
|
+
image = child.replacement
|
|
199
|
+
intrinsic_width, _, intrinsic_ratio = image.get_intrinsic_size(
|
|
200
|
+
child.style['image_resolution'], child.style['font_size'])
|
|
201
|
+
if intrinsic_ratio and intrinsic_width:
|
|
202
|
+
transferred_size = intrinsic_width / intrinsic_ratio
|
|
203
|
+
if specified_size != 'auto':
|
|
204
|
+
child.min_height = min(specified_size, content_size)
|
|
205
|
+
elif transferred_size is not None:
|
|
206
|
+
child.min_height = min(transferred_size, content_size)
|
|
207
|
+
else:
|
|
208
|
+
child.min_height = content_size
|
|
196
209
|
|
|
197
210
|
if child.style['flex_basis'] == 'content':
|
|
198
|
-
flex_basis =
|
|
211
|
+
flex_basis = 'content'
|
|
199
212
|
else:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
# See https://www.w3.org/TR/css-flexbox-1/#propdef-flex-basis.
|
|
206
|
-
resolve_one_percentage(child, axis, available_main_space)
|
|
207
|
-
if flex_basis == 'auto':
|
|
208
|
-
if child.style[axis] == 'auto':
|
|
209
|
-
flex_basis = 'content'
|
|
210
|
-
else:
|
|
211
|
-
if axis == 'width':
|
|
212
|
-
flex_basis = child.border_width()
|
|
213
|
-
if child.margin_left != 'auto':
|
|
214
|
-
flex_basis += child.margin_left
|
|
215
|
-
if child.margin_right != 'auto':
|
|
216
|
-
flex_basis += child.margin_right
|
|
217
|
-
else:
|
|
218
|
-
flex_basis = child.border_height()
|
|
219
|
-
if child.margin_top != 'auto':
|
|
220
|
-
flex_basis += child.margin_top
|
|
221
|
-
if child.margin_bottom != 'auto':
|
|
222
|
-
flex_basis += child.margin_bottom
|
|
213
|
+
flex_basis = percent.percentage(
|
|
214
|
+
child.style['flex_basis'], available_main_space)
|
|
215
|
+
if flex_basis == 'auto':
|
|
216
|
+
if (flex_basis := getattr(child, main)) == 'auto':
|
|
217
|
+
flex_basis = 'content'
|
|
223
218
|
|
|
224
|
-
#
|
|
225
|
-
# base size.
|
|
219
|
+
# 3.A If the item has a definite used flex basis…
|
|
226
220
|
if flex_basis != 'content':
|
|
227
221
|
child.flex_base_size = flex_basis
|
|
222
|
+
if main == 'width':
|
|
223
|
+
child.main_outer_extra = (
|
|
224
|
+
child.border_left_width + child.border_right_width +
|
|
225
|
+
child.padding_left + child.padding_right)
|
|
226
|
+
if child.margin_left != 'auto':
|
|
227
|
+
child.main_outer_extra += child.margin_left
|
|
228
|
+
if child.margin_right != 'auto':
|
|
229
|
+
child.main_outer_extra += child.margin_right
|
|
230
|
+
else:
|
|
231
|
+
child.main_outer_extra = (
|
|
232
|
+
child.border_top_width + child.border_bottom_width +
|
|
233
|
+
child.padding_top + child.padding_bottom)
|
|
234
|
+
if child.margin_top != 'auto':
|
|
235
|
+
child.main_outer_extra += child.margin_top
|
|
236
|
+
if child.margin_bottom != 'auto':
|
|
237
|
+
child.main_outer_extra += child.margin_bottom
|
|
228
238
|
elif False:
|
|
229
|
-
# TODO:
|
|
230
|
-
# used flex basis
|
|
231
|
-
#
|
|
232
|
-
# flex item’s intrinsic aspect ratio.
|
|
233
|
-
pass
|
|
234
|
-
elif False:
|
|
235
|
-
# TODO: 9.2.3.C If the used flex basis is 'content' or depends on
|
|
236
|
-
# its available space, and the flex container is being sized under
|
|
237
|
-
# a 'min-content' or 'max-content' constraint (e.g. when performing
|
|
238
|
-
# automatic table layout [CSS21]), size the item under that
|
|
239
|
-
# constraint. The flex base size is the item’s resulting main size.
|
|
240
|
-
pass
|
|
241
|
-
elif False:
|
|
242
|
-
# TODO: 9.2.3.D Otherwise, if the used flex basis is 'content' or
|
|
243
|
-
# depends on its available space, the available main size is
|
|
244
|
-
# infinite, and the flex item’s inline axis is parallel to the main
|
|
245
|
-
# axis, lay the item out using the rules for a box in an orthogonal
|
|
246
|
-
# flow [CSS3-WRITING-MODES]. The flex base size is the item’s
|
|
247
|
-
# max-content main size. This case occurs, for example, in an
|
|
248
|
-
# English document (horizontal writing mode) containing a column
|
|
249
|
-
# flex container containing a vertical Japanese (vertical writing
|
|
250
|
-
# mode) flex item. We *can* have infinite main size (only for
|
|
251
|
-
# flex-direction: column - see
|
|
252
|
-
# https://www.w3.org/TR/css-flexbox-1/#pagination), but we don't
|
|
253
|
-
# support vertical writing mode (or writing-mode in general) yet,
|
|
254
|
-
# so this isn't relevant.
|
|
239
|
+
# TODO: 3.B If the flex item has an intrinsic aspect ratio…
|
|
240
|
+
# TODO: 3.C If the used flex basis is 'content'…
|
|
241
|
+
# TODO: 3.D Otherwise, if the used flex basis is 'content'…
|
|
255
242
|
pass
|
|
256
243
|
else:
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
# 'auto' and not definite, in this calculation use 'fit-content' as
|
|
263
|
-
# the flex item’s cross size. The flex base size is the item’s
|
|
264
|
-
# resulting main size.
|
|
265
|
-
child.style[axis] = 'max-content'
|
|
266
|
-
|
|
267
|
-
# TODO: Don't set style value, support *-content values instead.
|
|
268
|
-
if child.style[axis] == 'max-content':
|
|
269
|
-
child.style[axis] = 'auto'
|
|
270
|
-
if axis == 'width':
|
|
271
|
-
child.flex_base_size = max_content_width(context, child)
|
|
272
|
-
else:
|
|
273
|
-
if isinstance(child, boxes.ParentBox):
|
|
274
|
-
new_child = child.copy_with_children(child.children)
|
|
275
|
-
else:
|
|
276
|
-
new_child = child.copy()
|
|
277
|
-
new_child.width = inf
|
|
278
|
-
new_child = block.block_level_layout(
|
|
279
|
-
context, new_child, -inf, child_skip_stack, parent_box,
|
|
280
|
-
page_is_empty, absolute_boxes, fixed_boxes)[0]
|
|
281
|
-
child.flex_base_size = new_child.margin_height()
|
|
282
|
-
elif child.style[axis] == 'min-content':
|
|
283
|
-
child.style[axis] = 'auto'
|
|
284
|
-
if axis == 'width':
|
|
285
|
-
child.flex_base_size = min_content_width(context, child)
|
|
286
|
-
else:
|
|
287
|
-
if isinstance(child, boxes.ParentBox):
|
|
288
|
-
new_child = child.copy_with_children(child.children)
|
|
289
|
-
else:
|
|
290
|
-
new_child = child.copy()
|
|
291
|
-
new_child.width = 0
|
|
292
|
-
new_child = block.block_level_layout(
|
|
293
|
-
context, new_child, -inf, child_skip_stack, parent_box,
|
|
294
|
-
page_is_empty, absolute_boxes, fixed_boxes)[0]
|
|
295
|
-
child.flex_base_size = new_child.margin_height()
|
|
244
|
+
# 3.E Otherwise…
|
|
245
|
+
if main == 'width':
|
|
246
|
+
child.flex_base_size = max_content_width(context, child, outer=False)
|
|
247
|
+
child.main_outer_extra = (
|
|
248
|
+
max_content_width(context, child) - child.flex_base_size)
|
|
296
249
|
else:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
250
|
+
new_child = child.copy()
|
|
251
|
+
new_child.width = inf
|
|
252
|
+
new_child = block.block_level_layout(
|
|
253
|
+
context, new_child, bottom_space, child_skip_stack, parent_box,
|
|
254
|
+
page_is_empty, absolute_boxes, fixed_boxes)[0]
|
|
255
|
+
if new_child:
|
|
256
|
+
child.flex_base_size = new_child.height
|
|
257
|
+
child.main_outer_extra = (
|
|
258
|
+
new_child.margin_height() - new_child.height)
|
|
259
|
+
else:
|
|
260
|
+
child.flex_base_size = child.main_outer_extra = 0
|
|
261
|
+
|
|
262
|
+
if main == 'width':
|
|
263
|
+
position_x += child.flex_base_size + child.main_outer_extra
|
|
264
|
+
else:
|
|
265
|
+
position_y += child.flex_base_size + child.main_outer_extra
|
|
302
266
|
|
|
267
|
+
min_size = getattr(child, f'min_{main}')
|
|
268
|
+
max_size = getattr(child, f'max_{main}')
|
|
303
269
|
child.hypothetical_main_size = max(
|
|
304
|
-
|
|
305
|
-
child.flex_base_size, getattr(child, f'max_{axis}')))
|
|
270
|
+
min_size, min(child.flex_base_size, max_size))
|
|
306
271
|
|
|
307
272
|
# Skip stack is only for the first child.
|
|
308
273
|
child_skip_stack = None
|
|
309
274
|
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
|
|
313
|
-
# are treated as 0.
|
|
314
|
-
# TODO: The whole step has to be fixed.
|
|
315
|
-
if axis == 'width':
|
|
275
|
+
# 4 Determine the main size of the flex container using the rules of the formatting
|
|
276
|
+
# context in which it participates.
|
|
277
|
+
if main == 'width':
|
|
316
278
|
block.block_level_width(box, containing_block)
|
|
317
279
|
else:
|
|
318
|
-
if box.
|
|
319
|
-
box.height = box.style['height'].value
|
|
320
|
-
elif box.style['height'] != 'auto' and containing_block.height != 'auto':
|
|
321
|
-
box.height = box.style['height'].value / 100 * containing_block.height
|
|
322
|
-
else:
|
|
280
|
+
if box.height == 'auto':
|
|
323
281
|
box.height = 0
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
resume_at = {index: None}
|
|
334
|
-
children = children[:index + 1]
|
|
335
|
-
break
|
|
336
|
-
box.height += child_height
|
|
337
|
-
|
|
338
|
-
# 9.3.5 If the flex container is single-line, collect all the flex items
|
|
339
|
-
# into a single flex line.
|
|
282
|
+
flex_items = (child for child in children if child.is_flex_item)
|
|
283
|
+
for i, child in enumerate(flex_items):
|
|
284
|
+
box.height += child.hypothetical_main_size + child.main_outer_extra
|
|
285
|
+
if i:
|
|
286
|
+
box.height += main_gap
|
|
287
|
+
box.height = max(box.min_height, min(box.height, box.max_height))
|
|
288
|
+
|
|
289
|
+
# 5 If the flex container is single-line, collect all the flex items into a single
|
|
290
|
+
# flex line.
|
|
340
291
|
flex_lines = []
|
|
341
292
|
line = []
|
|
342
293
|
line_size = 0
|
|
343
|
-
|
|
294
|
+
main_size = getattr(box, main)
|
|
344
295
|
for i, child in enumerate(children, start=skip):
|
|
345
296
|
if not child.is_flex_item:
|
|
346
297
|
continue
|
|
347
|
-
line_size += child.hypothetical_main_size
|
|
348
|
-
if
|
|
298
|
+
line_size += child.hypothetical_main_size + child.main_outer_extra
|
|
299
|
+
if i > skip:
|
|
300
|
+
line_size += main_gap
|
|
301
|
+
if box.style['flex_wrap'] != 'nowrap' and line_size > main_size:
|
|
349
302
|
if line:
|
|
350
303
|
flex_lines.append(FlexLine(line))
|
|
351
304
|
line = [(i, child)]
|
|
352
|
-
line_size = child.hypothetical_main_size
|
|
305
|
+
line_size = child.hypothetical_main_size + child.main_outer_extra
|
|
353
306
|
else:
|
|
354
307
|
line.append((i, child))
|
|
355
308
|
flex_lines.append(FlexLine(line))
|
|
@@ -367,72 +320,58 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
367
320
|
for line in flex_lines:
|
|
368
321
|
line.reverse()
|
|
369
322
|
|
|
370
|
-
#
|
|
371
|
-
|
|
372
|
-
# See https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths.
|
|
373
|
-
available_main_space = getattr(box, axis)
|
|
323
|
+
# 6 Resolve the flexible lengths of all the flex items to find their used main size.
|
|
324
|
+
available_main_space = getattr(box, main)
|
|
374
325
|
for line in flex_lines:
|
|
375
|
-
# 9.7.1 Determine the used flex factor.
|
|
376
|
-
# sizes of all items on the line. If the sum is less than the flex
|
|
377
|
-
# container’s inner main size, use the flex grow factor for the rest of
|
|
378
|
-
# this algorithm; otherwise, use the flex shrink factor.
|
|
326
|
+
# 9.7.1 Determine the used flex factor.
|
|
379
327
|
hypothetical_main_size = sum(
|
|
380
|
-
child.hypothetical_main_size
|
|
328
|
+
child.hypothetical_main_size + child.main_outer_extra
|
|
329
|
+
for index, child in line)
|
|
381
330
|
if hypothetical_main_size < available_main_space:
|
|
382
331
|
flex_factor_type = 'grow'
|
|
383
332
|
else:
|
|
384
333
|
flex_factor_type = 'shrink'
|
|
385
334
|
|
|
386
|
-
# 9.7.
|
|
387
|
-
# its hypothetical main size…
|
|
388
|
-
# - any item that has a flex factor of zero,
|
|
389
|
-
# - if using the flex grow factor: any item that has a flex base size
|
|
390
|
-
# greater than its hypothetical main size,
|
|
391
|
-
# - if using the flex shrink factor: any item that has a flex base
|
|
392
|
-
# size smaller than its hypothetical main size.
|
|
335
|
+
# 9.7.3 Size inflexible items.
|
|
393
336
|
for index, child in line:
|
|
394
337
|
if flex_factor_type == 'grow':
|
|
395
338
|
child.flex_factor = child.style['flex_grow']
|
|
339
|
+
flex_condition = child.flex_base_size > child.hypothetical_main_size
|
|
396
340
|
else:
|
|
397
341
|
child.flex_factor = child.style['flex_shrink']
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
child.flex_base_size > child.hypothetical_main_size) or
|
|
401
|
-
(flex_factor_type == 'shrink' and
|
|
402
|
-
child.flex_base_size < child.hypothetical_main_size)):
|
|
342
|
+
flex_condition = child.flex_base_size < child.hypothetical_main_size
|
|
343
|
+
if child.flex_factor == 0 or flex_condition:
|
|
403
344
|
child.target_main_size = child.hypothetical_main_size
|
|
404
345
|
child.frozen = True
|
|
405
346
|
else:
|
|
406
347
|
child.frozen = False
|
|
407
348
|
|
|
408
|
-
# 9.7.
|
|
409
|
-
# on the line, and subtract this from the flex container’s inner main
|
|
410
|
-
# size. For frozen items, use their outer target main size; for other
|
|
411
|
-
# items, use their outer flex base size.
|
|
349
|
+
# 9.7.4 Calculate initial free space.
|
|
412
350
|
initial_free_space = available_main_space
|
|
413
|
-
for index, child in line:
|
|
351
|
+
for i, (index, child) in enumerate(line):
|
|
414
352
|
if child.frozen:
|
|
415
|
-
initial_free_space -= child.target_main_size
|
|
353
|
+
initial_free_space -= child.target_main_size + child.main_outer_extra
|
|
416
354
|
else:
|
|
417
|
-
initial_free_space -= child.flex_base_size
|
|
355
|
+
initial_free_space -= child.flex_base_size + child.main_outer_extra
|
|
356
|
+
if i:
|
|
357
|
+
initial_free_space -= main_gap
|
|
418
358
|
|
|
419
|
-
# 9.7.
|
|
420
|
-
# are frozen, free space has been distributed; exit this loop.
|
|
359
|
+
# 9.7.5.a Check for flexible items.
|
|
421
360
|
while not all(child.frozen for index, child in line):
|
|
422
361
|
unfrozen_factor_sum = 0
|
|
423
362
|
remaining_free_space = available_main_space
|
|
424
363
|
|
|
425
|
-
# 9.7.
|
|
426
|
-
|
|
427
|
-
# is less than one, multiply the initial free space by this sum. If
|
|
428
|
-
# the magnitude of this value is less than the magnitude of the
|
|
429
|
-
# remaining free space, use this as the remaining free space.
|
|
430
|
-
for index, child in line:
|
|
364
|
+
# 9.7.5.b Calculate the remaining free space.
|
|
365
|
+
for i, (index, child) in enumerate(line):
|
|
431
366
|
if child.frozen:
|
|
432
|
-
remaining_free_space -=
|
|
367
|
+
remaining_free_space -= (
|
|
368
|
+
child.target_main_size + child.main_outer_extra)
|
|
433
369
|
else:
|
|
434
|
-
remaining_free_space -=
|
|
370
|
+
remaining_free_space -= (
|
|
371
|
+
child.flex_base_size + child.main_outer_extra)
|
|
435
372
|
unfrozen_factor_sum += child.flex_factor
|
|
373
|
+
if i:
|
|
374
|
+
remaining_free_space -= main_gap
|
|
436
375
|
|
|
437
376
|
if unfrozen_factor_sum < 1:
|
|
438
377
|
initial_free_space *= unfrozen_factor_sum
|
|
@@ -443,19 +382,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
443
382
|
remaining_free_space = sys.maxsize
|
|
444
383
|
|
|
445
384
|
initial_magnitude = (
|
|
446
|
-
int(log10(initial_free_space)) if initial_free_space > 0
|
|
447
|
-
else -inf)
|
|
385
|
+
int(log10(initial_free_space)) if initial_free_space > 0 else -inf)
|
|
448
386
|
remaining_magnitude = (
|
|
449
|
-
int(log10(remaining_free_space)) if remaining_free_space > 0
|
|
450
|
-
else -inf)
|
|
387
|
+
int(log10(remaining_free_space)) if remaining_free_space > 0 else -inf)
|
|
451
388
|
if initial_magnitude < remaining_magnitude:
|
|
452
389
|
remaining_free_space = initial_free_space
|
|
453
390
|
|
|
454
|
-
# 9.7.
|
|
391
|
+
# 9.7.5.c Distribute free space proportional to the flex factors.
|
|
455
392
|
if remaining_free_space == 0:
|
|
456
|
-
# If the remaining free space is zero: "Do nothing", but we at
|
|
457
|
-
#
|
|
458
|
-
# step.
|
|
393
|
+
# If the remaining free space is zero: "Do nothing", but we at least set
|
|
394
|
+
# the flex_base_size as target_main_size for next step.
|
|
459
395
|
for index, child in line:
|
|
460
396
|
if not child.frozen:
|
|
461
397
|
child.target_main_size = child.flex_base_size
|
|
@@ -471,30 +407,12 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
471
407
|
flex_grow_factors_sum += child.style['flex_grow']
|
|
472
408
|
for index, child in line:
|
|
473
409
|
if not child.frozen:
|
|
474
|
-
# If using the flex grow factor
|
|
475
|
-
# item’s flex grow factor to the sum of the flex grow
|
|
476
|
-
# factors of all unfrozen items on the line. Set the
|
|
477
|
-
# item’s target main size to its flex base size plus a
|
|
478
|
-
# fraction of the remaining free space proportional to
|
|
479
|
-
# the ratio."
|
|
410
|
+
# If using the flex grow factor…
|
|
480
411
|
if flex_factor_type == 'grow':
|
|
481
|
-
ratio =
|
|
482
|
-
child.style['flex_grow'] /
|
|
483
|
-
flex_grow_factors_sum)
|
|
412
|
+
ratio = child.style['flex_grow'] / flex_grow_factors_sum
|
|
484
413
|
child.target_main_size = (
|
|
485
|
-
child.flex_base_size +
|
|
486
|
-
|
|
487
|
-
# If using the flex shrink factor: "For every unfrozen
|
|
488
|
-
# item on the line, multiply its flex shrink factor by
|
|
489
|
-
# its inner flex base size, and note this as its scaled
|
|
490
|
-
# flex shrink factor. Find the ratio of the item’s
|
|
491
|
-
# scaled flex shrink factor to the sum of the scaled
|
|
492
|
-
# flex shrink factors of all unfrozen items on the
|
|
493
|
-
# line. Set the item’s target main size to its flex
|
|
494
|
-
# base size minus a fraction of the absolute value of
|
|
495
|
-
# the remaining free space proportional to the ratio.
|
|
496
|
-
# Note this may result in a negative inner main size;
|
|
497
|
-
# it will be corrected in the next step."
|
|
414
|
+
child.flex_base_size + remaining_free_space * ratio)
|
|
415
|
+
# If using the flex shrink factor…
|
|
498
416
|
elif flex_factor_type == 'shrink':
|
|
499
417
|
if scaled_flex_shrink_factors_sum == 0:
|
|
500
418
|
child.target_main_size = child.flex_base_size
|
|
@@ -503,24 +421,21 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
503
421
|
child.scaled_flex_shrink_factor /
|
|
504
422
|
scaled_flex_shrink_factors_sum)
|
|
505
423
|
child.target_main_size = (
|
|
506
|
-
child.flex_base_size +
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
# 9.7.
|
|
510
|
-
# target main size by its used min and max main sizes and floor its
|
|
511
|
-
# content-box size at zero. If the item’s target main size was made
|
|
512
|
-
# smaller by this, it’s a max violation. If the item’s target main
|
|
513
|
-
# size was made larger by this, it’s a min violation.
|
|
514
|
-
# TODO: First part of this step is useless until 3.E is correct.
|
|
424
|
+
child.flex_base_size + remaining_free_space * ratio)
|
|
425
|
+
child.target_main_size = min_max(child, child.target_main_size)
|
|
426
|
+
|
|
427
|
+
# 9.7.5.d Fix min/max violations.
|
|
515
428
|
for index, child in line:
|
|
516
429
|
child.adjustment = 0
|
|
517
|
-
if not child.frozen
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
430
|
+
if not child.frozen:
|
|
431
|
+
min_size = getattr(child, f'min_{main}')
|
|
432
|
+
max_size = getattr(child, f'max_{main}')
|
|
433
|
+
min_size = max(min_size , min(child.target_main_size, max_size))
|
|
434
|
+
if child.target_main_size < min_size:
|
|
435
|
+
child.adjustment = min_size - child.target_main_size
|
|
436
|
+
child.target_main_size = min_size
|
|
437
|
+
|
|
438
|
+
# 9.7.5.e Freeze over-flexed items.
|
|
524
439
|
adjustments = sum(child.adjustment for index, child in line)
|
|
525
440
|
for index, child in line:
|
|
526
441
|
# Zero: Freeze all items.
|
|
@@ -533,72 +448,44 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
533
448
|
elif adjustments < 0 and child.adjustment < 0:
|
|
534
449
|
child.frozen = True
|
|
535
450
|
|
|
536
|
-
# 9.7.
|
|
451
|
+
# 9.7.6 Set each item’s used main size to its target main size.
|
|
537
452
|
for index, child in line:
|
|
538
|
-
if
|
|
539
|
-
child.width =
|
|
540
|
-
child.target_main_size -
|
|
541
|
-
child.padding_left - child.padding_right -
|
|
542
|
-
child.border_left_width - child.border_right_width)
|
|
543
|
-
if child.margin_left != 'auto':
|
|
544
|
-
child.width -= child.margin_left
|
|
545
|
-
if child.margin_right != 'auto':
|
|
546
|
-
child.width -= child.margin_right
|
|
453
|
+
if main == 'width':
|
|
454
|
+
child.width = child.target_main_size
|
|
547
455
|
else:
|
|
548
|
-
child.height =
|
|
549
|
-
child.target_main_size -
|
|
550
|
-
child.padding_top - child.padding_bottom -
|
|
551
|
-
child.border_top_width - child.border_top_width)
|
|
552
|
-
if child.margin_top != 'auto':
|
|
553
|
-
child.height -= child.margin_top
|
|
554
|
-
if child.margin_bottom != 'auto':
|
|
555
|
-
child.height -= child.margin_bottom
|
|
456
|
+
child.height = child.target_main_size
|
|
556
457
|
|
|
557
|
-
#
|
|
558
|
-
# TODO: Fix TODO in build.flex_children.
|
|
458
|
+
# 7 Determine the hypothetical cross size of each item.
|
|
559
459
|
# TODO: Handle breaks.
|
|
560
460
|
new_flex_lines = []
|
|
561
461
|
child_skip_stack = skip_stack
|
|
562
|
-
# 9.4.7 Determine the hypothetical cross size of each item by performing
|
|
563
|
-
# layout with the used main size and the available space, treating auto as
|
|
564
|
-
# fit-content.
|
|
565
462
|
for line in flex_lines:
|
|
566
463
|
new_flex_line = FlexLine()
|
|
567
464
|
for index, child in line:
|
|
568
|
-
# TODO:
|
|
569
|
-
# TODO: Find another way than calling block_level_layout_switch to
|
|
570
|
-
# get baseline and child.height.
|
|
465
|
+
# TODO: Fix this value, see test_flex_item_auto_margin_cross.
|
|
571
466
|
if child.margin_top == 'auto':
|
|
572
467
|
child.margin_top = 0
|
|
573
468
|
if child.margin_bottom == 'auto':
|
|
574
469
|
child.margin_bottom = 0
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
# TODO: We set the style here above, otherwise used main size will
|
|
581
|
-
# get clobbered by resolve_percentages() somewhere down the line,
|
|
582
|
-
# particularly if the child is itself a flex container. Is this the
|
|
583
|
-
# right approach?
|
|
584
|
-
child_copy.style[axis] = Dimension(getattr(child, axis), 'px')
|
|
585
|
-
new_child, _, _, adjoining_margins, _, _ = (
|
|
586
|
-
block.block_level_layout_switch(
|
|
587
|
-
context, child_copy, -inf, child_skip_stack, parent_box,
|
|
588
|
-
page_is_empty, absolute_boxes, fixed_boxes,
|
|
589
|
-
[], False, None))
|
|
590
|
-
|
|
470
|
+
# TODO: Find another way than calling block_level_layout_switch.
|
|
471
|
+
new_child = child.copy()
|
|
472
|
+
new_child, _, _, adjoining_margins, _, _ = block.block_level_layout_switch(
|
|
473
|
+
context, new_child, -inf, child_skip_stack, parent_box, page_is_empty,
|
|
474
|
+
absolute_boxes, fixed_boxes, [], discard, None)
|
|
591
475
|
child._baseline = find_in_flow_baseline(new_child) or 0
|
|
592
476
|
if cross == 'height':
|
|
593
477
|
child.height = new_child.height
|
|
594
|
-
# As flex items margins never collapse (with other flex items
|
|
595
|
-
#
|
|
596
|
-
#
|
|
478
|
+
# As flex items margins never collapse (with other flex items or
|
|
479
|
+
# with the flex container), we can add the adjoining margins to the
|
|
480
|
+
# child bottom margin.
|
|
597
481
|
child.margin_bottom += block.collapse_margin(adjoining_margins)
|
|
598
482
|
else:
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
483
|
+
if child.width == 'auto':
|
|
484
|
+
min_width = min_content_width(context, child, outer=False)
|
|
485
|
+
max_width = max_content_width(context, child, outer=False)
|
|
486
|
+
child.width = min(max(min_width, new_child.width), max_width)
|
|
487
|
+
else:
|
|
488
|
+
child.width = new_child.width
|
|
602
489
|
|
|
603
490
|
new_flex_line.append((index, child))
|
|
604
491
|
|
|
@@ -609,33 +496,25 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
609
496
|
new_flex_lines.append(new_flex_line)
|
|
610
497
|
flex_lines = new_flex_lines
|
|
611
498
|
|
|
499
|
+
# 8 Calculate the cross size of each flex line.
|
|
612
500
|
cross_size = getattr(box, cross)
|
|
613
501
|
if len(flex_lines) == 1 and cross_size != 'auto':
|
|
614
|
-
#
|
|
615
|
-
# definite cross size, the cross size of the flex line is the
|
|
616
|
-
# flex container’s inner cross size.
|
|
502
|
+
# If the flex container is single-line…
|
|
617
503
|
flex_lines[0].cross_size = cross_size
|
|
618
|
-
else:
|
|
619
|
-
#
|
|
620
|
-
# the
|
|
621
|
-
# margins are both non-auto. Find the largest of the distances between
|
|
622
|
-
# each item’s baseline and its hypothetical outer cross-start edge, and
|
|
623
|
-
# the largest of the distances between each item’s baseline and its
|
|
624
|
-
# hypothetical outer cross-end edge, and sum these two values.
|
|
504
|
+
else:
|
|
505
|
+
# Otherwise, for each flex line…
|
|
506
|
+
# 8.1 Collect all the flex items whose inline-axis is parallel to the main-axis…
|
|
625
507
|
for line in flex_lines:
|
|
626
508
|
collected_items = []
|
|
627
509
|
not_collected_items = []
|
|
628
510
|
for index, child in line:
|
|
629
511
|
align_self = child.style['align_self']
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
not_collected_items.append(child)
|
|
637
|
-
cross_start_distance = 0
|
|
638
|
-
cross_end_distance = 0
|
|
512
|
+
collect = (
|
|
513
|
+
box.style['flex_direction'].startswith('row') and
|
|
514
|
+
'baseline' in align_self and
|
|
515
|
+
'auto' not in (child.margin_top, child.margin_bottom))
|
|
516
|
+
(collected_items if collect else not_collected_items).append(child)
|
|
517
|
+
cross_start_distance = cross_end_distance = 0
|
|
639
518
|
for child in collected_items:
|
|
640
519
|
baseline = child._baseline - child.position_y
|
|
641
520
|
cross_start_distance = max(cross_start_distance, baseline)
|
|
@@ -643,8 +522,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
643
522
|
cross_end_distance, child.margin_height() - baseline)
|
|
644
523
|
collected_cross_size = cross_start_distance + cross_end_distance
|
|
645
524
|
non_collected_cross_size = 0
|
|
646
|
-
#
|
|
647
|
-
# find the largest outer hypothetical cross size.
|
|
525
|
+
# 8.2 Find the largest outer hypothetical cross size.
|
|
648
526
|
if not_collected_items:
|
|
649
527
|
non_collected_cross_size = -inf
|
|
650
528
|
for child in not_collected_items:
|
|
@@ -662,15 +540,10 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
662
540
|
child_cross_size += child.margin_right
|
|
663
541
|
non_collected_cross_size = max(
|
|
664
542
|
child_cross_size, non_collected_cross_size)
|
|
665
|
-
#
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
# 9.4.8.3 If the flex container is single-line, then clamp the line’s
|
|
671
|
-
# cross-size to be within the container’s computed min and max cross sizes.
|
|
672
|
-
# Note that if CSS 2.1’s definition of min/max-width/height applied more
|
|
673
|
-
# generally, this behavior would fall out automatically.
|
|
543
|
+
# 8.3 Set the used cross-size of the flex line.
|
|
544
|
+
line.cross_size = max(collected_cross_size, non_collected_cross_size)
|
|
545
|
+
|
|
546
|
+
# 8.3 If the flex container is single-line…
|
|
674
547
|
if len(flex_lines) == 1:
|
|
675
548
|
line, = flex_lines
|
|
676
549
|
min_cross_size = getattr(box, f'min_{cross}')
|
|
@@ -679,15 +552,9 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
679
552
|
max_cross_size = getattr(box, f'max_{cross}')
|
|
680
553
|
if max_cross_size == 'auto':
|
|
681
554
|
max_cross_size = inf
|
|
682
|
-
line.cross_size = max(
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
# 9.4.9 Handle 'align-content: stretch'. If the flex container has a
|
|
686
|
-
# definite cross size, align-content is stretch, and the sum of the flex
|
|
687
|
-
# lines' cross sizes is less than the flex container’s inner cross size,
|
|
688
|
-
# increase the cross size of each flex line by equal amounts such that the
|
|
689
|
-
# sum of their cross sizes exactly equals the flex container’s inner cross
|
|
690
|
-
# size.
|
|
555
|
+
line.cross_size = max(min_cross_size, min(line.cross_size, max_cross_size))
|
|
556
|
+
|
|
557
|
+
# 9 Handle 'align-content: stretch'.
|
|
691
558
|
align_content = box.style['align_content']
|
|
692
559
|
if 'normal' in align_content:
|
|
693
560
|
align_content = ('stretch',)
|
|
@@ -702,38 +569,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
702
569
|
else:
|
|
703
570
|
definite_cross_size = box.width
|
|
704
571
|
if definite_cross_size is not None:
|
|
705
|
-
extra_cross_size = definite_cross_size
|
|
706
|
-
|
|
572
|
+
extra_cross_size = definite_cross_size
|
|
573
|
+
extra_cross_size -= sum(line.cross_size for line in flex_lines)
|
|
574
|
+
extra_cross_size -= (len(flex_lines) - 1) * cross_gap
|
|
707
575
|
if extra_cross_size:
|
|
708
576
|
for line in flex_lines:
|
|
709
577
|
line.cross_size += extra_cross_size / len(flex_lines)
|
|
710
578
|
|
|
711
|
-
# TODO:
|
|
712
|
-
|
|
713
|
-
#
|
|
714
|
-
#
|
|
715
|
-
# In this second layout round, when collecting items into lines, treat the
|
|
716
|
-
# collapsed items as having zero main size. For the rest of the algorithm
|
|
717
|
-
# following that step, ignore the collapsed items entirely (as if they were
|
|
718
|
-
# display:none) except that after calculating the cross size of the lines,
|
|
719
|
-
# if any line’s cross size is less than the largest strut size among all
|
|
720
|
-
# the collapsed items in the line, set its cross size to that strut size.
|
|
721
|
-
#
|
|
722
|
-
# Skip this step in the second layout round.
|
|
723
|
-
|
|
724
|
-
# Step 11 - 9.4.11 Determine the used cross size of each flex item. If a
|
|
725
|
-
# flex item has align-self: stretch, its computed cross size property is
|
|
726
|
-
# auto, and neither of its cross-axis margins are auto, the used outer
|
|
727
|
-
# cross size is the used cross size of its flex line, clamped according to
|
|
728
|
-
# the item’s used min and max cross sizes. Otherwise, the used cross size
|
|
729
|
-
# is the item’s hypothetical cross size.
|
|
730
|
-
#
|
|
731
|
-
# If the flex item has align-self: stretch, redo layout for its contents,
|
|
732
|
-
# treating this used size as its definite cross size so that
|
|
733
|
-
# percentage-sized children can be resolved.
|
|
734
|
-
#
|
|
735
|
-
# Note that this step does not affect the main size of the flex item, even
|
|
736
|
-
# if it has an intrinsic aspect ratio.
|
|
579
|
+
# TODO: 10 Collapse 'visibility: collapse' items.
|
|
580
|
+
|
|
581
|
+
# 11 Determine the used cross size of each flex item.
|
|
737
582
|
align_items = box.style['align_items']
|
|
738
583
|
if 'normal' in align_items:
|
|
739
584
|
align_items = ('stretch',)
|
|
@@ -764,12 +609,11 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
764
609
|
child.border_left_width +
|
|
765
610
|
child.border_right_width)
|
|
766
611
|
setattr(child, cross, cross_size)
|
|
767
|
-
# TODO: redo layout?
|
|
768
612
|
# else: Cross size has been set by step 7.
|
|
769
613
|
|
|
770
|
-
#
|
|
771
|
-
|
|
772
|
-
box.content_box_x() if
|
|
614
|
+
# 12 Distribute any remaining free space.
|
|
615
|
+
original_position_main = (
|
|
616
|
+
box.content_box_x() if main == 'width'
|
|
773
617
|
else box.content_box_y())
|
|
774
618
|
justify_content = box.style['justify_content']
|
|
775
619
|
if 'normal' in justify_content:
|
|
@@ -777,13 +621,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
777
621
|
if box.style['flex_direction'].endswith('-reverse'):
|
|
778
622
|
if 'flex-start' in justify_content:
|
|
779
623
|
justify_content = ('flex-end',)
|
|
780
|
-
elif
|
|
624
|
+
elif 'flex-end' in justify_content:
|
|
781
625
|
justify_content = ('flex-start',)
|
|
626
|
+
elif 'start' in justify_content:
|
|
627
|
+
justify_content = ('end',)
|
|
628
|
+
elif 'end' in justify_content:
|
|
629
|
+
justify_content = ('start',)
|
|
782
630
|
|
|
783
|
-
# 9.5.12 Distribute any remaining free space. For each flex line:
|
|
784
631
|
for line in flex_lines:
|
|
785
|
-
|
|
786
|
-
if
|
|
632
|
+
position_main = original_position_main
|
|
633
|
+
if main == 'width':
|
|
787
634
|
free_space = box.width
|
|
788
635
|
for index, child in line:
|
|
789
636
|
free_space -= child.border_width()
|
|
@@ -799,13 +646,12 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
799
646
|
free_space -= child.margin_top
|
|
800
647
|
if child.margin_bottom != 'auto':
|
|
801
648
|
free_space -= child.margin_bottom
|
|
649
|
+
free_space -= (len(line) - 1) * main_gap
|
|
802
650
|
|
|
803
|
-
#
|
|
804
|
-
# main-axis margin on this line is auto, distribute the free space
|
|
805
|
-
# equally among these margins. Otherwise, set all auto margins to zero.
|
|
651
|
+
# 12.1 If the remaining free space is positive…
|
|
806
652
|
margins = 0
|
|
807
653
|
for index, child in line:
|
|
808
|
-
if
|
|
654
|
+
if main == 'width':
|
|
809
655
|
if child.margin_left == 'auto':
|
|
810
656
|
margins += 1
|
|
811
657
|
if child.margin_right == 'auto':
|
|
@@ -818,7 +664,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
818
664
|
if margins:
|
|
819
665
|
free_space /= margins
|
|
820
666
|
for index, child in line:
|
|
821
|
-
if
|
|
667
|
+
if main == 'width':
|
|
822
668
|
if child.margin_left == 'auto':
|
|
823
669
|
child.margin_left = free_space
|
|
824
670
|
if child.margin_right == 'auto':
|
|
@@ -830,68 +676,67 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
830
676
|
child.margin_bottom = free_space
|
|
831
677
|
free_space = 0
|
|
832
678
|
|
|
833
|
-
if box.style['direction'] == 'rtl' and
|
|
679
|
+
if box.style['direction'] == 'rtl' and main == 'width':
|
|
834
680
|
free_space *= -1
|
|
835
681
|
|
|
836
|
-
#
|
|
682
|
+
# 12.2 Align the items along the main-axis per justify-content.
|
|
837
683
|
if {'end', 'flex-end', 'right'} & set(justify_content):
|
|
838
|
-
|
|
684
|
+
position_main += free_space
|
|
839
685
|
elif 'center' in justify_content:
|
|
840
|
-
|
|
686
|
+
position_main += free_space / 2
|
|
841
687
|
elif 'space-around' in justify_content:
|
|
842
|
-
|
|
688
|
+
position_main += free_space / len(line) / 2
|
|
843
689
|
elif 'space-evenly' in justify_content:
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
690
|
+
position_main += free_space / (len(line) + 1)
|
|
691
|
+
|
|
692
|
+
growths = sum(child.style['flex_grow'] for child in children)
|
|
693
|
+
for i, (index, child) in enumerate(line):
|
|
694
|
+
if i:
|
|
695
|
+
position_main += main_gap
|
|
696
|
+
if main == 'width':
|
|
697
|
+
child.position_x = position_main
|
|
698
|
+
if 'stretch' in justify_content and growths:
|
|
699
|
+
child.width += free_space * child.style['flex_grow'] / growths
|
|
851
700
|
else:
|
|
852
|
-
child.position_y =
|
|
853
|
-
|
|
854
|
-
child.margin_width() if
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
position_axis += margin_axis
|
|
701
|
+
child.position_y = position_main
|
|
702
|
+
margin_main = (
|
|
703
|
+
child.margin_width() if main == 'width' else child.margin_height())
|
|
704
|
+
if box.style['direction'] == 'rtl' and main == 'width':
|
|
705
|
+
margin_main *= -1
|
|
706
|
+
position_main += margin_main
|
|
859
707
|
if 'space-around' in justify_content:
|
|
860
|
-
|
|
708
|
+
position_main += free_space / len(line)
|
|
861
709
|
elif 'space-between' in justify_content:
|
|
862
710
|
if len(line) > 1:
|
|
863
|
-
|
|
711
|
+
position_main += free_space / (len(line) - 1)
|
|
864
712
|
elif 'space-evenly' in justify_content:
|
|
865
|
-
|
|
713
|
+
position_main += free_space / (len(line) + 1)
|
|
866
714
|
|
|
867
|
-
#
|
|
868
|
-
# Make sure width/margins are no longer "auto", as we did not do it above
|
|
869
|
-
# in step 9.2.4.
|
|
715
|
+
# 13 Resolve cross-axis auto margins.
|
|
870
716
|
if cross == 'width':
|
|
717
|
+
# Make sure width/margins are no longer "auto", as we did not do it above in
|
|
718
|
+
# step 4.
|
|
871
719
|
block.block_level_width(box, containing_block)
|
|
872
|
-
position_cross = (
|
|
873
|
-
box.content_box_y() if cross == 'height'
|
|
874
|
-
else box.content_box_x())
|
|
720
|
+
position_cross = box.content_box_y() if cross == 'height' else box.content_box_x()
|
|
875
721
|
for line in flex_lines:
|
|
876
722
|
line.lower_baseline = -inf
|
|
877
|
-
# TODO:
|
|
723
|
+
# TODO: Don't duplicate this loop.
|
|
878
724
|
for index, child in line:
|
|
879
725
|
align_self = child.style['align_self']
|
|
880
726
|
if 'auto' in align_self:
|
|
881
727
|
align_self = align_items
|
|
882
|
-
if 'baseline' in align_self and
|
|
728
|
+
if 'baseline' in align_self and main == 'width':
|
|
883
729
|
# TODO: handle vertical text.
|
|
884
730
|
child.baseline = child._baseline - position_cross
|
|
885
731
|
line.lower_baseline = max(line.lower_baseline, child.baseline)
|
|
886
732
|
if line.lower_baseline == -inf:
|
|
887
733
|
line.lower_baseline = line[0][1]._baseline if line else 0
|
|
888
|
-
# 9.6.13 Resolve cross-axis auto margins.
|
|
889
734
|
for index, child in line:
|
|
890
735
|
cross_margins = (
|
|
891
736
|
(child.margin_top, child.margin_bottom) if cross == 'height'
|
|
892
737
|
else (child.margin_left, child.margin_right))
|
|
893
738
|
auto_margins = sum([margin == 'auto' for margin in cross_margins])
|
|
894
|
-
#
|
|
739
|
+
# If a flex item has auto cross-axis margins…
|
|
895
740
|
if auto_margins:
|
|
896
741
|
extra_cross = line.cross_size
|
|
897
742
|
if cross == 'height':
|
|
@@ -907,10 +752,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
907
752
|
if child.margin_right != 'auto':
|
|
908
753
|
extra_cross -= child.margin_right
|
|
909
754
|
if extra_cross > 0:
|
|
910
|
-
#
|
|
911
|
-
# margins as zero) is less than the cross size of its flex
|
|
912
|
-
# line, distribute the difference in those sizes equally to
|
|
913
|
-
# the auto margins.
|
|
755
|
+
# If its outer cross size is less than the cross size…
|
|
914
756
|
extra_cross /= auto_margins
|
|
915
757
|
if cross == 'height':
|
|
916
758
|
if child.margin_top == 'auto':
|
|
@@ -923,10 +765,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
923
765
|
if child.margin_right == 'auto':
|
|
924
766
|
child.margin_right = extra_cross
|
|
925
767
|
else:
|
|
926
|
-
#
|
|
927
|
-
# margin (whichever is in the cross axis) is auto, set it
|
|
928
|
-
# to zero. Set the opposite margin so that the outer cross
|
|
929
|
-
# size of the item equals the cross size of its flex line.
|
|
768
|
+
# Otherwise…
|
|
930
769
|
if cross == 'height':
|
|
931
770
|
if child.margin_top == 'auto':
|
|
932
771
|
child.margin_top = 0
|
|
@@ -936,9 +775,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
936
775
|
child.margin_left = 0
|
|
937
776
|
child.margin_right = extra_cross
|
|
938
777
|
else:
|
|
939
|
-
#
|
|
940
|
-
# align-self, if neither of the item’s cross-axis margins are
|
|
941
|
-
# auto.
|
|
778
|
+
# 14 Align all flex items along the cross-axis.
|
|
942
779
|
align_self = child.style['align_self']
|
|
943
780
|
if 'normal' in align_self:
|
|
944
781
|
align_self = ('stretch',)
|
|
@@ -948,24 +785,20 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
948
785
|
setattr(child, position, position_cross)
|
|
949
786
|
if {'end', 'self-end', 'flex-end'} & set(align_self):
|
|
950
787
|
if cross == 'height':
|
|
951
|
-
child.position_y += (
|
|
952
|
-
line.cross_size - child.margin_height())
|
|
788
|
+
child.position_y += line.cross_size - child.margin_height()
|
|
953
789
|
else:
|
|
954
|
-
child.position_x += (
|
|
955
|
-
line.cross_size - child.margin_width())
|
|
790
|
+
child.position_x += line.cross_size - child.margin_width()
|
|
956
791
|
elif 'center' in align_self:
|
|
957
792
|
if cross == 'height':
|
|
958
793
|
child.position_y += (
|
|
959
794
|
line.cross_size - child.margin_height()) / 2
|
|
960
795
|
else:
|
|
961
|
-
child.position_x += (
|
|
962
|
-
line.cross_size - child.margin_width()) / 2
|
|
796
|
+
child.position_x += (line.cross_size - child.margin_width()) / 2
|
|
963
797
|
elif 'baseline' in align_self:
|
|
964
798
|
if cross == 'height':
|
|
965
|
-
child.position_y +=
|
|
966
|
-
line.lower_baseline - child.baseline)
|
|
799
|
+
child.position_y += line.lower_baseline - child.baseline
|
|
967
800
|
else:
|
|
968
|
-
# Handle vertical text.
|
|
801
|
+
# TODO: Handle vertical text.
|
|
969
802
|
pass
|
|
970
803
|
elif 'stretch' in align_self:
|
|
971
804
|
if child.style[cross] == 'auto':
|
|
@@ -976,78 +809,76 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
976
809
|
if child.style['box_sizing'] == 'content-box':
|
|
977
810
|
if cross == 'height':
|
|
978
811
|
margins += (
|
|
979
|
-
child.border_top_width +
|
|
980
|
-
child.border_bottom_width +
|
|
812
|
+
child.border_top_width + child.border_bottom_width +
|
|
981
813
|
child.padding_top + child.padding_bottom)
|
|
982
814
|
else:
|
|
983
815
|
margins += (
|
|
984
|
-
child.border_left_width +
|
|
985
|
-
child.border_right_width +
|
|
816
|
+
child.border_left_width + child.border_right_width +
|
|
986
817
|
child.padding_left + child.padding_right)
|
|
987
|
-
# TODO: Don't set style width, find a way to avoid
|
|
988
|
-
#
|
|
818
|
+
# TODO: Don't set style width, find a way to avoid width
|
|
819
|
+
# re-calculation after 16.
|
|
989
820
|
child.style[cross] = Dimension(line.cross_size - margins, 'px')
|
|
990
821
|
position_cross += line.cross_size
|
|
991
822
|
|
|
992
|
-
#
|
|
823
|
+
# 15 Determine the flex container’s used cross size.
|
|
824
|
+
# TODO: Use the updated algorithm.
|
|
993
825
|
if getattr(box, cross) == 'auto':
|
|
994
|
-
#
|
|
995
|
-
# by the used min and max cross sizes of the flex container.
|
|
826
|
+
# Otherwise, use the sum of the flex lines' cross sizes…
|
|
996
827
|
# TODO: Handle min-max.
|
|
997
828
|
# TODO: What about align-content here?
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
829
|
+
cross_size = sum(line.cross_size for line in flex_lines)
|
|
830
|
+
cross_size += (len(flex_lines) - 1) * cross_gap
|
|
831
|
+
setattr(box, cross, cross_size)
|
|
832
|
+
|
|
833
|
+
if len(flex_lines) > 1:
|
|
834
|
+
# 15 If the cross size property is a definite size, use that…
|
|
835
|
+
extra_cross_size = getattr(box, cross)
|
|
836
|
+
extra_cross_size -= sum(line.cross_size for line in flex_lines)
|
|
837
|
+
extra_cross_size -= (len(flex_lines) - 1) * cross_gap
|
|
838
|
+
# 16 Align all flex lines per align-content.
|
|
839
|
+
cross_translate = 0
|
|
1005
840
|
direction = 'position_y' if cross == 'height' else 'position_x'
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
child, direction,
|
|
1021
|
-
current_value + extra_cross_size / 2)
|
|
1022
|
-
elif 'space-around' in align_content:
|
|
1023
|
-
setattr(
|
|
1024
|
-
child, direction,
|
|
1025
|
-
current_value + extra_cross_size /
|
|
1026
|
-
len(flex_lines) / 2)
|
|
1027
|
-
elif 'space-evenly' in align_content:
|
|
1028
|
-
setattr(
|
|
1029
|
-
child, direction,
|
|
1030
|
-
current_value + extra_cross_size /
|
|
1031
|
-
(len(flex_lines) + 1))
|
|
1032
|
-
if 'space-between' in align_content:
|
|
1033
|
-
cross_translate += extra_cross_size / (len(flex_lines) - 1)
|
|
841
|
+
for i, line in enumerate(flex_lines):
|
|
842
|
+
flex_items = tuple(child for _, child in line if child.is_flex_item)
|
|
843
|
+
if i:
|
|
844
|
+
cross_translate += cross_gap
|
|
845
|
+
for child in flex_items:
|
|
846
|
+
current_value = getattr(child, direction) + cross_translate
|
|
847
|
+
setattr(child, direction, current_value)
|
|
848
|
+
if extra_cross_size == 0:
|
|
849
|
+
continue
|
|
850
|
+
for child in flex_items:
|
|
851
|
+
if {'flex-end', 'end'} & set(align_content):
|
|
852
|
+
setattr(child, direction, current_value + extra_cross_size)
|
|
853
|
+
elif 'center' in align_content:
|
|
854
|
+
setattr(child, direction, current_value + extra_cross_size / 2)
|
|
1034
855
|
elif 'space-around' in align_content:
|
|
1035
|
-
|
|
856
|
+
setattr(
|
|
857
|
+
child, direction,
|
|
858
|
+
current_value + extra_cross_size / len(flex_lines) / 2)
|
|
1036
859
|
elif 'space-evenly' in align_content:
|
|
1037
|
-
|
|
860
|
+
setattr(
|
|
861
|
+
child, direction,
|
|
862
|
+
current_value + extra_cross_size / (len(flex_lines) + 1))
|
|
863
|
+
if 'space-between' in align_content:
|
|
864
|
+
cross_translate += extra_cross_size / (len(flex_lines) - 1)
|
|
865
|
+
elif 'space-around' in align_content:
|
|
866
|
+
cross_translate += extra_cross_size / len(flex_lines)
|
|
867
|
+
elif 'space-evenly' in align_content:
|
|
868
|
+
cross_translate += extra_cross_size / (len(flex_lines) + 1)
|
|
1038
869
|
|
|
1039
870
|
# Now we are no longer in the flex algorithm.
|
|
1040
|
-
# TODO: Don't use block_box_level_layout_switch.
|
|
1041
871
|
box = box.copy_with_children(
|
|
1042
872
|
[child for child in children if child.is_absolutely_positioned()])
|
|
1043
873
|
child_skip_stack = skip_stack
|
|
1044
874
|
for line in flex_lines:
|
|
1045
875
|
for index, child in line:
|
|
1046
876
|
if child.is_flex_item:
|
|
877
|
+
# TODO: Don't use block_level_layout_switch.
|
|
1047
878
|
new_child, child_resume_at = block.block_level_layout_switch(
|
|
1048
|
-
context, child, bottom_space, child_skip_stack, box,
|
|
1049
|
-
|
|
1050
|
-
|
|
879
|
+
context, child, bottom_space, child_skip_stack, box, page_is_empty,
|
|
880
|
+
absolute_boxes, fixed_boxes, adjoining_margins=[], discard=discard,
|
|
881
|
+
max_lines=None)[:2]
|
|
1051
882
|
if new_child is None:
|
|
1052
883
|
if resume_at:
|
|
1053
884
|
resume_index, = resume_at
|
|
@@ -1079,29 +910,23 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
1079
910
|
# New containing block, resolve the layout of the absolute descendants.
|
|
1080
911
|
for absolute_box in absolute_boxes:
|
|
1081
912
|
absolute_layout(
|
|
1082
|
-
context, absolute_box, box, fixed_boxes, bottom_space,
|
|
1083
|
-
skip_stack=None)
|
|
1084
|
-
|
|
1085
|
-
# Set box height.
|
|
1086
|
-
# TODO: This is probably useless because of 9.6.15.
|
|
1087
|
-
if axis == 'width' and box.height == 'auto':
|
|
1088
|
-
if flex_lines:
|
|
1089
|
-
box.height = sum(line.cross_size for line in flex_lines)
|
|
1090
|
-
else:
|
|
1091
|
-
box.height = 0
|
|
913
|
+
context, absolute_box, box, fixed_boxes, bottom_space, skip_stack=None)
|
|
1092
914
|
|
|
1093
|
-
#
|
|
1094
|
-
# See https://www.w3.org/TR/css-flexbox-1/#flex-baselines
|
|
1095
|
-
# TODO: Use the real algorithm.
|
|
915
|
+
# TODO: Use real algorithm, see https://www.w3.org/TR/css-flexbox-1/#flex-baselines.
|
|
1096
916
|
if isinstance(box, boxes.InlineFlexBox):
|
|
1097
|
-
if
|
|
917
|
+
if main == 'width': # and main text direction is horizontal
|
|
1098
918
|
box.baseline = flex_lines[0].lower_baseline if flex_lines else 0
|
|
1099
919
|
else:
|
|
1100
|
-
box.
|
|
1101
|
-
|
|
1102
|
-
|
|
920
|
+
for child in box.children:
|
|
921
|
+
if child.is_in_normal_flow():
|
|
922
|
+
box.baseline = find_in_flow_baseline(child) or 0
|
|
923
|
+
break
|
|
924
|
+
else:
|
|
925
|
+
box.baseline = 0
|
|
926
|
+
|
|
927
|
+
box.remove_decoration(start=False, end=resume_at and not discard)
|
|
1103
928
|
|
|
1104
|
-
context.
|
|
929
|
+
context.finish_flex_formatting_context(box)
|
|
1105
930
|
|
|
1106
931
|
# TODO: Check these returned values.
|
|
1107
932
|
return box, resume_at, {'break': 'any', 'page': None}, [], False
|