weasyprint 64.1__py3-none-any.whl → 65.0__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 +243 -747
- 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 +390 -571
- weasyprint/layout/float.py +6 -4
- weasyprint/layout/inline.py +23 -27
- weasyprint/layout/page.py +2 -4
- 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.0.dist-info}/METADATA +2 -2
- {weasyprint-64.1.dist-info → weasyprint-65.0.dist-info}/RECORD +32 -32
- {weasyprint-64.1.dist-info → weasyprint-65.0.dist-info}/WHEEL +0 -0
- {weasyprint-64.1.dist-info → weasyprint-65.0.dist-info}/entry_points.txt +0 -0
- {weasyprint-64.1.dist-info → weasyprint-65.0.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,155 @@ 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 = box.replacement
|
|
171
|
+
_, intrinsic_height, intrinsic_ratio = image.get_intrinsic_size(
|
|
172
|
+
box.style['image_resolution'], box.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 = box.replacement
|
|
199
|
+
intrinsic_width, _, intrinsic_ratio = image.get_intrinsic_size(
|
|
200
|
+
box.style['image_resolution'], box.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
|
+
if child.margin_left != 'auto':
|
|
226
|
+
child.main_outer_extra += child.margin_left
|
|
227
|
+
if child.margin_right != 'auto':
|
|
228
|
+
child.main_outer_extra += child.margin_right
|
|
229
|
+
else:
|
|
230
|
+
child.main_outer_extra = (
|
|
231
|
+
child.border_top_width + child.border_bottom_width)
|
|
232
|
+
if child.margin_top != 'auto':
|
|
233
|
+
child.main_outer_extra += child.margin_top
|
|
234
|
+
if child.margin_bottom != 'auto':
|
|
235
|
+
child.main_outer_extra += child.margin_bottom
|
|
228
236
|
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.
|
|
237
|
+
# TODO: 3.B If the flex item has an intrinsic aspect ratio…
|
|
238
|
+
# TODO: 3.C If the used flex basis is 'content'…
|
|
239
|
+
# TODO: 3.D Otherwise, if the used flex basis is 'content'…
|
|
255
240
|
pass
|
|
256
241
|
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()
|
|
242
|
+
# 3.E Otherwise…
|
|
243
|
+
if main == 'width':
|
|
244
|
+
child.flex_base_size = max_content_width(context, child, outer=False)
|
|
245
|
+
child.main_outer_extra = (
|
|
246
|
+
max_content_width(context, child) - child.flex_base_size)
|
|
296
247
|
else:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
248
|
+
new_child = child.copy()
|
|
249
|
+
new_child.width = inf
|
|
250
|
+
new_child = block.block_level_layout(
|
|
251
|
+
context, new_child, bottom_space, child_skip_stack, parent_box,
|
|
252
|
+
page_is_empty, absolute_boxes, fixed_boxes)[0]
|
|
253
|
+
child.flex_base_size = new_child.height
|
|
254
|
+
child.main_outer_extra = new_child.margin_height() - new_child.height
|
|
255
|
+
|
|
256
|
+
if main == 'width':
|
|
257
|
+
position_x += child.flex_base_size + child.main_outer_extra
|
|
258
|
+
else:
|
|
259
|
+
position_y += child.flex_base_size + child.main_outer_extra
|
|
302
260
|
|
|
261
|
+
min_size = getattr(child, f'min_{main}')
|
|
262
|
+
max_size = getattr(child, f'max_{main}')
|
|
303
263
|
child.hypothetical_main_size = max(
|
|
304
|
-
|
|
305
|
-
child.flex_base_size, getattr(child, f'max_{axis}')))
|
|
264
|
+
min_size, min(child.flex_base_size, max_size))
|
|
306
265
|
|
|
307
266
|
# Skip stack is only for the first child.
|
|
308
267
|
child_skip_stack = None
|
|
309
268
|
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
|
|
313
|
-
# are treated as 0.
|
|
314
|
-
# TODO: The whole step has to be fixed.
|
|
315
|
-
if axis == 'width':
|
|
269
|
+
# 4 Determine the main size of the flex container using the rules of the formatting
|
|
270
|
+
# context in which it participates.
|
|
271
|
+
if main == 'width':
|
|
316
272
|
block.block_level_width(box, containing_block)
|
|
317
273
|
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:
|
|
274
|
+
if box.height == 'auto':
|
|
323
275
|
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.
|
|
276
|
+
flex_items = (child for child in children if child.is_flex_item)
|
|
277
|
+
for i, child in enumerate(flex_items):
|
|
278
|
+
box.height += child.hypothetical_main_size + child.main_outer_extra
|
|
279
|
+
if i:
|
|
280
|
+
box.height += main_gap
|
|
281
|
+
box.height = max(box.min_height, min(box.height, box.max_height))
|
|
282
|
+
|
|
283
|
+
# 5 If the flex container is single-line, collect all the flex items into a single
|
|
284
|
+
# flex line.
|
|
340
285
|
flex_lines = []
|
|
341
286
|
line = []
|
|
342
287
|
line_size = 0
|
|
343
|
-
|
|
288
|
+
main_size = getattr(box, main)
|
|
344
289
|
for i, child in enumerate(children, start=skip):
|
|
345
290
|
if not child.is_flex_item:
|
|
346
291
|
continue
|
|
347
|
-
line_size += child.hypothetical_main_size
|
|
348
|
-
if
|
|
292
|
+
line_size += child.hypothetical_main_size + child.main_outer_extra
|
|
293
|
+
if i > skip:
|
|
294
|
+
line_size += main_gap
|
|
295
|
+
if box.style['flex_wrap'] != 'nowrap' and line_size > main_size:
|
|
349
296
|
if line:
|
|
350
297
|
flex_lines.append(FlexLine(line))
|
|
351
298
|
line = [(i, child)]
|
|
352
|
-
line_size = child.hypothetical_main_size
|
|
299
|
+
line_size = child.hypothetical_main_size + child.main_outer_extra
|
|
353
300
|
else:
|
|
354
301
|
line.append((i, child))
|
|
355
302
|
flex_lines.append(FlexLine(line))
|
|
@@ -367,72 +314,58 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
367
314
|
for line in flex_lines:
|
|
368
315
|
line.reverse()
|
|
369
316
|
|
|
370
|
-
#
|
|
371
|
-
|
|
372
|
-
# See https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths.
|
|
373
|
-
available_main_space = getattr(box, axis)
|
|
317
|
+
# 6 Resolve the flexible lengths of all the flex items to find their used main size.
|
|
318
|
+
available_main_space = getattr(box, main)
|
|
374
319
|
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.
|
|
320
|
+
# 9.7.1 Determine the used flex factor.
|
|
379
321
|
hypothetical_main_size = sum(
|
|
380
|
-
child.hypothetical_main_size
|
|
322
|
+
child.hypothetical_main_size + child.main_outer_extra
|
|
323
|
+
for index, child in line)
|
|
381
324
|
if hypothetical_main_size < available_main_space:
|
|
382
325
|
flex_factor_type = 'grow'
|
|
383
326
|
else:
|
|
384
327
|
flex_factor_type = 'shrink'
|
|
385
328
|
|
|
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.
|
|
329
|
+
# 9.7.3 Size inflexible items.
|
|
393
330
|
for index, child in line:
|
|
394
331
|
if flex_factor_type == 'grow':
|
|
395
332
|
child.flex_factor = child.style['flex_grow']
|
|
333
|
+
flex_condition = child.flex_base_size > child.hypothetical_main_size
|
|
396
334
|
else:
|
|
397
335
|
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)):
|
|
336
|
+
flex_condition = child.flex_base_size < child.hypothetical_main_size
|
|
337
|
+
if child.flex_factor == 0 or flex_condition:
|
|
403
338
|
child.target_main_size = child.hypothetical_main_size
|
|
404
339
|
child.frozen = True
|
|
405
340
|
else:
|
|
406
341
|
child.frozen = False
|
|
407
342
|
|
|
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.
|
|
343
|
+
# 9.7.4 Calculate initial free space.
|
|
412
344
|
initial_free_space = available_main_space
|
|
413
|
-
for index, child in line:
|
|
345
|
+
for i, (index, child) in enumerate(line):
|
|
414
346
|
if child.frozen:
|
|
415
|
-
initial_free_space -= child.target_main_size
|
|
347
|
+
initial_free_space -= child.target_main_size + child.main_outer_extra
|
|
416
348
|
else:
|
|
417
|
-
initial_free_space -= child.flex_base_size
|
|
349
|
+
initial_free_space -= child.flex_base_size + child.main_outer_extra
|
|
350
|
+
if i:
|
|
351
|
+
initial_free_space -= main_gap
|
|
418
352
|
|
|
419
|
-
# 9.7.
|
|
420
|
-
# are frozen, free space has been distributed; exit this loop.
|
|
353
|
+
# 9.7.5.a Check for flexible items.
|
|
421
354
|
while not all(child.frozen for index, child in line):
|
|
422
355
|
unfrozen_factor_sum = 0
|
|
423
356
|
remaining_free_space = available_main_space
|
|
424
357
|
|
|
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:
|
|
358
|
+
# 9.7.5.b Calculate the remaining free space.
|
|
359
|
+
for i, (index, child) in enumerate(line):
|
|
431
360
|
if child.frozen:
|
|
432
|
-
remaining_free_space -=
|
|
361
|
+
remaining_free_space -= (
|
|
362
|
+
child.target_main_size + child.main_outer_extra)
|
|
433
363
|
else:
|
|
434
|
-
remaining_free_space -=
|
|
364
|
+
remaining_free_space -= (
|
|
365
|
+
child.flex_base_size + child.main_outer_extra)
|
|
435
366
|
unfrozen_factor_sum += child.flex_factor
|
|
367
|
+
if i:
|
|
368
|
+
remaining_free_space -= main_gap
|
|
436
369
|
|
|
437
370
|
if unfrozen_factor_sum < 1:
|
|
438
371
|
initial_free_space *= unfrozen_factor_sum
|
|
@@ -443,19 +376,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
443
376
|
remaining_free_space = sys.maxsize
|
|
444
377
|
|
|
445
378
|
initial_magnitude = (
|
|
446
|
-
int(log10(initial_free_space)) if initial_free_space > 0
|
|
447
|
-
else -inf)
|
|
379
|
+
int(log10(initial_free_space)) if initial_free_space > 0 else -inf)
|
|
448
380
|
remaining_magnitude = (
|
|
449
|
-
int(log10(remaining_free_space)) if remaining_free_space > 0
|
|
450
|
-
else -inf)
|
|
381
|
+
int(log10(remaining_free_space)) if remaining_free_space > 0 else -inf)
|
|
451
382
|
if initial_magnitude < remaining_magnitude:
|
|
452
383
|
remaining_free_space = initial_free_space
|
|
453
384
|
|
|
454
|
-
# 9.7.
|
|
385
|
+
# 9.7.5.c Distribute free space proportional to the flex factors.
|
|
455
386
|
if remaining_free_space == 0:
|
|
456
|
-
# If the remaining free space is zero: "Do nothing", but we at
|
|
457
|
-
#
|
|
458
|
-
# step.
|
|
387
|
+
# If the remaining free space is zero: "Do nothing", but we at least set
|
|
388
|
+
# the flex_base_size as target_main_size for next step.
|
|
459
389
|
for index, child in line:
|
|
460
390
|
if not child.frozen:
|
|
461
391
|
child.target_main_size = child.flex_base_size
|
|
@@ -471,30 +401,12 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
471
401
|
flex_grow_factors_sum += child.style['flex_grow']
|
|
472
402
|
for index, child in line:
|
|
473
403
|
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."
|
|
404
|
+
# If using the flex grow factor…
|
|
480
405
|
if flex_factor_type == 'grow':
|
|
481
|
-
ratio =
|
|
482
|
-
child.style['flex_grow'] /
|
|
483
|
-
flex_grow_factors_sum)
|
|
406
|
+
ratio = child.style['flex_grow'] / flex_grow_factors_sum
|
|
484
407
|
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."
|
|
408
|
+
child.flex_base_size + remaining_free_space * ratio)
|
|
409
|
+
# If using the flex shrink factor…
|
|
498
410
|
elif flex_factor_type == 'shrink':
|
|
499
411
|
if scaled_flex_shrink_factors_sum == 0:
|
|
500
412
|
child.target_main_size = child.flex_base_size
|
|
@@ -503,24 +415,21 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
503
415
|
child.scaled_flex_shrink_factor /
|
|
504
416
|
scaled_flex_shrink_factors_sum)
|
|
505
417
|
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.
|
|
418
|
+
child.flex_base_size + remaining_free_space * ratio)
|
|
419
|
+
child.target_main_size = min_max(child, child.target_main_size)
|
|
420
|
+
|
|
421
|
+
# 9.7.5.d Fix min/max violations.
|
|
515
422
|
for index, child in line:
|
|
516
423
|
child.adjustment = 0
|
|
517
|
-
if not child.frozen
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
424
|
+
if not child.frozen:
|
|
425
|
+
min_size = getattr(child, f'min_{main}')
|
|
426
|
+
max_size = getattr(child, f'max_{main}')
|
|
427
|
+
min_size = max(min_size , min(child.target_main_size, max_size))
|
|
428
|
+
if child.target_main_size < min_size:
|
|
429
|
+
child.adjustment = min_size - child.target_main_size
|
|
430
|
+
child.target_main_size = min_size
|
|
431
|
+
|
|
432
|
+
# 9.7.5.e Freeze over-flexed items.
|
|
524
433
|
adjustments = sum(child.adjustment for index, child in line)
|
|
525
434
|
for index, child in line:
|
|
526
435
|
# Zero: Freeze all items.
|
|
@@ -533,72 +442,44 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
533
442
|
elif adjustments < 0 and child.adjustment < 0:
|
|
534
443
|
child.frozen = True
|
|
535
444
|
|
|
536
|
-
# 9.7.
|
|
445
|
+
# 9.7.6 Set each item’s used main size to its target main size.
|
|
537
446
|
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
|
|
447
|
+
if main == 'width':
|
|
448
|
+
child.width = child.target_main_size
|
|
547
449
|
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
|
|
450
|
+
child.height = child.target_main_size
|
|
556
451
|
|
|
557
|
-
#
|
|
558
|
-
# TODO: Fix TODO in build.flex_children.
|
|
452
|
+
# 7 Determine the hypothetical cross size of each item.
|
|
559
453
|
# TODO: Handle breaks.
|
|
560
454
|
new_flex_lines = []
|
|
561
455
|
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
456
|
for line in flex_lines:
|
|
566
457
|
new_flex_line = FlexLine()
|
|
567
458
|
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.
|
|
459
|
+
# TODO: Fix this value, see test_flex_item_auto_margin_cross.
|
|
571
460
|
if child.margin_top == 'auto':
|
|
572
461
|
child.margin_top = 0
|
|
573
462
|
if child.margin_bottom == 'auto':
|
|
574
463
|
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
|
-
|
|
464
|
+
# TODO: Find another way than calling block_level_layout_switch.
|
|
465
|
+
new_child = child.copy()
|
|
466
|
+
new_child, _, _, adjoining_margins, _, _ = block.block_level_layout_switch(
|
|
467
|
+
context, new_child, -inf, child_skip_stack, parent_box, page_is_empty,
|
|
468
|
+
absolute_boxes, fixed_boxes, [], discard, None)
|
|
591
469
|
child._baseline = find_in_flow_baseline(new_child) or 0
|
|
592
470
|
if cross == 'height':
|
|
593
471
|
child.height = new_child.height
|
|
594
|
-
# As flex items margins never collapse (with other flex items
|
|
595
|
-
#
|
|
596
|
-
#
|
|
472
|
+
# As flex items margins never collapse (with other flex items or
|
|
473
|
+
# with the flex container), we can add the adjoining margins to the
|
|
474
|
+
# child bottom margin.
|
|
597
475
|
child.margin_bottom += block.collapse_margin(adjoining_margins)
|
|
598
476
|
else:
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
477
|
+
if child.width == 'auto':
|
|
478
|
+
min_width = min_content_width(context, child, outer=False)
|
|
479
|
+
max_width = max_content_width(context, child, outer=False)
|
|
480
|
+
child.width = min(max(min_width, new_child.width), max_width)
|
|
481
|
+
else:
|
|
482
|
+
child.width = new_child.width
|
|
602
483
|
|
|
603
484
|
new_flex_line.append((index, child))
|
|
604
485
|
|
|
@@ -609,33 +490,25 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
609
490
|
new_flex_lines.append(new_flex_line)
|
|
610
491
|
flex_lines = new_flex_lines
|
|
611
492
|
|
|
493
|
+
# 8 Calculate the cross size of each flex line.
|
|
612
494
|
cross_size = getattr(box, cross)
|
|
613
495
|
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.
|
|
496
|
+
# If the flex container is single-line…
|
|
617
497
|
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.
|
|
498
|
+
else:
|
|
499
|
+
# Otherwise, for each flex line…
|
|
500
|
+
# 8.1 Collect all the flex items whose inline-axis is parallel to the main-axis…
|
|
625
501
|
for line in flex_lines:
|
|
626
502
|
collected_items = []
|
|
627
503
|
not_collected_items = []
|
|
628
504
|
for index, child in line:
|
|
629
505
|
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
|
|
506
|
+
collect = (
|
|
507
|
+
box.style['flex_direction'].startswith('row') and
|
|
508
|
+
'baseline' in align_self and
|
|
509
|
+
'auto' not in (child.margin_top, child.margin_bottom))
|
|
510
|
+
(collected_items if collect else not_collected_items).append(child)
|
|
511
|
+
cross_start_distance = cross_end_distance = 0
|
|
639
512
|
for child in collected_items:
|
|
640
513
|
baseline = child._baseline - child.position_y
|
|
641
514
|
cross_start_distance = max(cross_start_distance, baseline)
|
|
@@ -643,8 +516,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
643
516
|
cross_end_distance, child.margin_height() - baseline)
|
|
644
517
|
collected_cross_size = cross_start_distance + cross_end_distance
|
|
645
518
|
non_collected_cross_size = 0
|
|
646
|
-
#
|
|
647
|
-
# find the largest outer hypothetical cross size.
|
|
519
|
+
# 8.2 Find the largest outer hypothetical cross size.
|
|
648
520
|
if not_collected_items:
|
|
649
521
|
non_collected_cross_size = -inf
|
|
650
522
|
for child in not_collected_items:
|
|
@@ -662,15 +534,10 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
662
534
|
child_cross_size += child.margin_right
|
|
663
535
|
non_collected_cross_size = max(
|
|
664
536
|
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.
|
|
537
|
+
# 8.3 Set the used cross-size of the flex line.
|
|
538
|
+
line.cross_size = max(collected_cross_size, non_collected_cross_size)
|
|
539
|
+
|
|
540
|
+
# 8.3 If the flex container is single-line…
|
|
674
541
|
if len(flex_lines) == 1:
|
|
675
542
|
line, = flex_lines
|
|
676
543
|
min_cross_size = getattr(box, f'min_{cross}')
|
|
@@ -679,15 +546,9 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
679
546
|
max_cross_size = getattr(box, f'max_{cross}')
|
|
680
547
|
if max_cross_size == 'auto':
|
|
681
548
|
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.
|
|
549
|
+
line.cross_size = max(min_cross_size, min(line.cross_size, max_cross_size))
|
|
550
|
+
|
|
551
|
+
# 9 Handle 'align-content: stretch'.
|
|
691
552
|
align_content = box.style['align_content']
|
|
692
553
|
if 'normal' in align_content:
|
|
693
554
|
align_content = ('stretch',)
|
|
@@ -702,38 +563,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
702
563
|
else:
|
|
703
564
|
definite_cross_size = box.width
|
|
704
565
|
if definite_cross_size is not None:
|
|
705
|
-
extra_cross_size = definite_cross_size
|
|
706
|
-
|
|
566
|
+
extra_cross_size = definite_cross_size
|
|
567
|
+
extra_cross_size -= sum(line.cross_size for line in flex_lines)
|
|
568
|
+
extra_cross_size -= (len(flex_lines) - 1) * cross_gap
|
|
707
569
|
if extra_cross_size:
|
|
708
570
|
for line in flex_lines:
|
|
709
571
|
line.cross_size += extra_cross_size / len(flex_lines)
|
|
710
572
|
|
|
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.
|
|
573
|
+
# TODO: 10 Collapse 'visibility: collapse' items.
|
|
574
|
+
|
|
575
|
+
# 11 Determine the used cross size of each flex item.
|
|
737
576
|
align_items = box.style['align_items']
|
|
738
577
|
if 'normal' in align_items:
|
|
739
578
|
align_items = ('stretch',)
|
|
@@ -764,12 +603,11 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
764
603
|
child.border_left_width +
|
|
765
604
|
child.border_right_width)
|
|
766
605
|
setattr(child, cross, cross_size)
|
|
767
|
-
# TODO: redo layout?
|
|
768
606
|
# else: Cross size has been set by step 7.
|
|
769
607
|
|
|
770
|
-
#
|
|
771
|
-
|
|
772
|
-
box.content_box_x() if
|
|
608
|
+
# 12 Distribute any remaining free space.
|
|
609
|
+
original_position_main = (
|
|
610
|
+
box.content_box_x() if main == 'width'
|
|
773
611
|
else box.content_box_y())
|
|
774
612
|
justify_content = box.style['justify_content']
|
|
775
613
|
if 'normal' in justify_content:
|
|
@@ -777,13 +615,16 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
777
615
|
if box.style['flex_direction'].endswith('-reverse'):
|
|
778
616
|
if 'flex-start' in justify_content:
|
|
779
617
|
justify_content = ('flex-end',)
|
|
780
|
-
elif
|
|
618
|
+
elif 'flex-end' in justify_content:
|
|
781
619
|
justify_content = ('flex-start',)
|
|
620
|
+
elif 'start' in justify_content:
|
|
621
|
+
justify_content = ('end',)
|
|
622
|
+
elif 'end' in justify_content:
|
|
623
|
+
justify_content = ('start',)
|
|
782
624
|
|
|
783
|
-
# 9.5.12 Distribute any remaining free space. For each flex line:
|
|
784
625
|
for line in flex_lines:
|
|
785
|
-
|
|
786
|
-
if
|
|
626
|
+
position_main = original_position_main
|
|
627
|
+
if main == 'width':
|
|
787
628
|
free_space = box.width
|
|
788
629
|
for index, child in line:
|
|
789
630
|
free_space -= child.border_width()
|
|
@@ -799,13 +640,12 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
799
640
|
free_space -= child.margin_top
|
|
800
641
|
if child.margin_bottom != 'auto':
|
|
801
642
|
free_space -= child.margin_bottom
|
|
643
|
+
free_space -= (len(line) - 1) * main_gap
|
|
802
644
|
|
|
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.
|
|
645
|
+
# 12.1 If the remaining free space is positive…
|
|
806
646
|
margins = 0
|
|
807
647
|
for index, child in line:
|
|
808
|
-
if
|
|
648
|
+
if main == 'width':
|
|
809
649
|
if child.margin_left == 'auto':
|
|
810
650
|
margins += 1
|
|
811
651
|
if child.margin_right == 'auto':
|
|
@@ -818,7 +658,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
818
658
|
if margins:
|
|
819
659
|
free_space /= margins
|
|
820
660
|
for index, child in line:
|
|
821
|
-
if
|
|
661
|
+
if main == 'width':
|
|
822
662
|
if child.margin_left == 'auto':
|
|
823
663
|
child.margin_left = free_space
|
|
824
664
|
if child.margin_right == 'auto':
|
|
@@ -830,68 +670,67 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
830
670
|
child.margin_bottom = free_space
|
|
831
671
|
free_space = 0
|
|
832
672
|
|
|
833
|
-
if box.style['direction'] == 'rtl' and
|
|
673
|
+
if box.style['direction'] == 'rtl' and main == 'width':
|
|
834
674
|
free_space *= -1
|
|
835
675
|
|
|
836
|
-
#
|
|
676
|
+
# 12.2 Align the items along the main-axis per justify-content.
|
|
837
677
|
if {'end', 'flex-end', 'right'} & set(justify_content):
|
|
838
|
-
|
|
678
|
+
position_main += free_space
|
|
839
679
|
elif 'center' in justify_content:
|
|
840
|
-
|
|
680
|
+
position_main += free_space / 2
|
|
841
681
|
elif 'space-around' in justify_content:
|
|
842
|
-
|
|
682
|
+
position_main += free_space / len(line) / 2
|
|
843
683
|
elif 'space-evenly' in justify_content:
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
684
|
+
position_main += free_space / (len(line) + 1)
|
|
685
|
+
|
|
686
|
+
growths = sum(child.style['flex_grow'] for child in children)
|
|
687
|
+
for i, (index, child) in enumerate(line):
|
|
688
|
+
if i:
|
|
689
|
+
position_main += main_gap
|
|
690
|
+
if main == 'width':
|
|
691
|
+
child.position_x = position_main
|
|
692
|
+
if 'stretch' in justify_content and growths:
|
|
693
|
+
child.width += free_space * child.style['flex_grow'] / growths
|
|
851
694
|
else:
|
|
852
|
-
child.position_y =
|
|
853
|
-
|
|
854
|
-
child.margin_width() if
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
position_axis += margin_axis
|
|
695
|
+
child.position_y = position_main
|
|
696
|
+
margin_main = (
|
|
697
|
+
child.margin_width() if main == 'width' else child.margin_height())
|
|
698
|
+
if box.style['direction'] == 'rtl' and main == 'width':
|
|
699
|
+
margin_main *= -1
|
|
700
|
+
position_main += margin_main
|
|
859
701
|
if 'space-around' in justify_content:
|
|
860
|
-
|
|
702
|
+
position_main += free_space / len(line)
|
|
861
703
|
elif 'space-between' in justify_content:
|
|
862
704
|
if len(line) > 1:
|
|
863
|
-
|
|
705
|
+
position_main += free_space / (len(line) - 1)
|
|
864
706
|
elif 'space-evenly' in justify_content:
|
|
865
|
-
|
|
707
|
+
position_main += free_space / (len(line) + 1)
|
|
866
708
|
|
|
867
|
-
#
|
|
868
|
-
# Make sure width/margins are no longer "auto", as we did not do it above
|
|
869
|
-
# in step 9.2.4.
|
|
709
|
+
# 13 Resolve cross-axis auto margins.
|
|
870
710
|
if cross == 'width':
|
|
711
|
+
# Make sure width/margins are no longer "auto", as we did not do it above in
|
|
712
|
+
# step 4.
|
|
871
713
|
block.block_level_width(box, containing_block)
|
|
872
|
-
position_cross = (
|
|
873
|
-
box.content_box_y() if cross == 'height'
|
|
874
|
-
else box.content_box_x())
|
|
714
|
+
position_cross = box.content_box_y() if cross == 'height' else box.content_box_x()
|
|
875
715
|
for line in flex_lines:
|
|
876
716
|
line.lower_baseline = -inf
|
|
877
|
-
# TODO:
|
|
717
|
+
# TODO: Don't duplicate this loop.
|
|
878
718
|
for index, child in line:
|
|
879
719
|
align_self = child.style['align_self']
|
|
880
720
|
if 'auto' in align_self:
|
|
881
721
|
align_self = align_items
|
|
882
|
-
if 'baseline' in align_self and
|
|
722
|
+
if 'baseline' in align_self and main == 'width':
|
|
883
723
|
# TODO: handle vertical text.
|
|
884
724
|
child.baseline = child._baseline - position_cross
|
|
885
725
|
line.lower_baseline = max(line.lower_baseline, child.baseline)
|
|
886
726
|
if line.lower_baseline == -inf:
|
|
887
727
|
line.lower_baseline = line[0][1]._baseline if line else 0
|
|
888
|
-
# 9.6.13 Resolve cross-axis auto margins.
|
|
889
728
|
for index, child in line:
|
|
890
729
|
cross_margins = (
|
|
891
730
|
(child.margin_top, child.margin_bottom) if cross == 'height'
|
|
892
731
|
else (child.margin_left, child.margin_right))
|
|
893
732
|
auto_margins = sum([margin == 'auto' for margin in cross_margins])
|
|
894
|
-
#
|
|
733
|
+
# If a flex item has auto cross-axis margins…
|
|
895
734
|
if auto_margins:
|
|
896
735
|
extra_cross = line.cross_size
|
|
897
736
|
if cross == 'height':
|
|
@@ -907,10 +746,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
907
746
|
if child.margin_right != 'auto':
|
|
908
747
|
extra_cross -= child.margin_right
|
|
909
748
|
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.
|
|
749
|
+
# If its outer cross size is less than the cross size…
|
|
914
750
|
extra_cross /= auto_margins
|
|
915
751
|
if cross == 'height':
|
|
916
752
|
if child.margin_top == 'auto':
|
|
@@ -923,10 +759,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
923
759
|
if child.margin_right == 'auto':
|
|
924
760
|
child.margin_right = extra_cross
|
|
925
761
|
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.
|
|
762
|
+
# Otherwise…
|
|
930
763
|
if cross == 'height':
|
|
931
764
|
if child.margin_top == 'auto':
|
|
932
765
|
child.margin_top = 0
|
|
@@ -936,9 +769,7 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
936
769
|
child.margin_left = 0
|
|
937
770
|
child.margin_right = extra_cross
|
|
938
771
|
else:
|
|
939
|
-
#
|
|
940
|
-
# align-self, if neither of the item’s cross-axis margins are
|
|
941
|
-
# auto.
|
|
772
|
+
# 14 Align all flex items along the cross-axis.
|
|
942
773
|
align_self = child.style['align_self']
|
|
943
774
|
if 'normal' in align_self:
|
|
944
775
|
align_self = ('stretch',)
|
|
@@ -948,24 +779,20 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
948
779
|
setattr(child, position, position_cross)
|
|
949
780
|
if {'end', 'self-end', 'flex-end'} & set(align_self):
|
|
950
781
|
if cross == 'height':
|
|
951
|
-
child.position_y += (
|
|
952
|
-
line.cross_size - child.margin_height())
|
|
782
|
+
child.position_y += line.cross_size - child.margin_height()
|
|
953
783
|
else:
|
|
954
|
-
child.position_x += (
|
|
955
|
-
line.cross_size - child.margin_width())
|
|
784
|
+
child.position_x += line.cross_size - child.margin_width()
|
|
956
785
|
elif 'center' in align_self:
|
|
957
786
|
if cross == 'height':
|
|
958
787
|
child.position_y += (
|
|
959
788
|
line.cross_size - child.margin_height()) / 2
|
|
960
789
|
else:
|
|
961
|
-
child.position_x += (
|
|
962
|
-
line.cross_size - child.margin_width()) / 2
|
|
790
|
+
child.position_x += (line.cross_size - child.margin_width()) / 2
|
|
963
791
|
elif 'baseline' in align_self:
|
|
964
792
|
if cross == 'height':
|
|
965
|
-
child.position_y +=
|
|
966
|
-
line.lower_baseline - child.baseline)
|
|
793
|
+
child.position_y += line.lower_baseline - child.baseline
|
|
967
794
|
else:
|
|
968
|
-
# Handle vertical text.
|
|
795
|
+
# TODO: Handle vertical text.
|
|
969
796
|
pass
|
|
970
797
|
elif 'stretch' in align_self:
|
|
971
798
|
if child.style[cross] == 'auto':
|
|
@@ -976,78 +803,76 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
976
803
|
if child.style['box_sizing'] == 'content-box':
|
|
977
804
|
if cross == 'height':
|
|
978
805
|
margins += (
|
|
979
|
-
child.border_top_width +
|
|
980
|
-
child.border_bottom_width +
|
|
806
|
+
child.border_top_width + child.border_bottom_width +
|
|
981
807
|
child.padding_top + child.padding_bottom)
|
|
982
808
|
else:
|
|
983
809
|
margins += (
|
|
984
|
-
child.border_left_width +
|
|
985
|
-
child.border_right_width +
|
|
810
|
+
child.border_left_width + child.border_right_width +
|
|
986
811
|
child.padding_left + child.padding_right)
|
|
987
|
-
# TODO: Don't set style width, find a way to avoid
|
|
988
|
-
#
|
|
812
|
+
# TODO: Don't set style width, find a way to avoid width
|
|
813
|
+
# re-calculation after 16.
|
|
989
814
|
child.style[cross] = Dimension(line.cross_size - margins, 'px')
|
|
990
815
|
position_cross += line.cross_size
|
|
991
816
|
|
|
992
|
-
#
|
|
817
|
+
# 15 Determine the flex container’s used cross size.
|
|
818
|
+
# TODO: Use the updated algorithm.
|
|
993
819
|
if getattr(box, cross) == 'auto':
|
|
994
|
-
#
|
|
995
|
-
# by the used min and max cross sizes of the flex container.
|
|
820
|
+
# Otherwise, use the sum of the flex lines' cross sizes…
|
|
996
821
|
# TODO: Handle min-max.
|
|
997
822
|
# TODO: What about align-content here?
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
823
|
+
cross_size = sum(line.cross_size for line in flex_lines)
|
|
824
|
+
cross_size += (len(flex_lines) - 1) * cross_gap
|
|
825
|
+
setattr(box, cross, cross_size)
|
|
826
|
+
|
|
827
|
+
if len(flex_lines) > 1:
|
|
828
|
+
# 15 If the cross size property is a definite size, use that…
|
|
829
|
+
extra_cross_size = getattr(box, cross)
|
|
830
|
+
extra_cross_size -= sum(line.cross_size for line in flex_lines)
|
|
831
|
+
extra_cross_size -= (len(flex_lines) - 1) * cross_gap
|
|
832
|
+
# 16 Align all flex lines per align-content.
|
|
833
|
+
cross_translate = 0
|
|
1005
834
|
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)
|
|
835
|
+
for i, line in enumerate(flex_lines):
|
|
836
|
+
flex_items = tuple(child for _, child in line if child.is_flex_item)
|
|
837
|
+
if i:
|
|
838
|
+
cross_translate += cross_gap
|
|
839
|
+
for child in flex_items:
|
|
840
|
+
current_value = getattr(child, direction) + cross_translate
|
|
841
|
+
setattr(child, direction, current_value)
|
|
842
|
+
if extra_cross_size == 0:
|
|
843
|
+
continue
|
|
844
|
+
for child in flex_items:
|
|
845
|
+
if {'flex-end', 'end'} & set(align_content):
|
|
846
|
+
setattr(child, direction, current_value + extra_cross_size)
|
|
847
|
+
elif 'center' in align_content:
|
|
848
|
+
setattr(child, direction, current_value + extra_cross_size / 2)
|
|
1034
849
|
elif 'space-around' in align_content:
|
|
1035
|
-
|
|
850
|
+
setattr(
|
|
851
|
+
child, direction,
|
|
852
|
+
current_value + extra_cross_size / len(flex_lines) / 2)
|
|
1036
853
|
elif 'space-evenly' in align_content:
|
|
1037
|
-
|
|
854
|
+
setattr(
|
|
855
|
+
child, direction,
|
|
856
|
+
current_value + extra_cross_size / (len(flex_lines) + 1))
|
|
857
|
+
if 'space-between' in align_content:
|
|
858
|
+
cross_translate += extra_cross_size / (len(flex_lines) - 1)
|
|
859
|
+
elif 'space-around' in align_content:
|
|
860
|
+
cross_translate += extra_cross_size / len(flex_lines)
|
|
861
|
+
elif 'space-evenly' in align_content:
|
|
862
|
+
cross_translate += extra_cross_size / (len(flex_lines) + 1)
|
|
1038
863
|
|
|
1039
864
|
# Now we are no longer in the flex algorithm.
|
|
1040
|
-
# TODO: Don't use block_box_level_layout_switch.
|
|
1041
865
|
box = box.copy_with_children(
|
|
1042
866
|
[child for child in children if child.is_absolutely_positioned()])
|
|
1043
867
|
child_skip_stack = skip_stack
|
|
1044
868
|
for line in flex_lines:
|
|
1045
869
|
for index, child in line:
|
|
1046
870
|
if child.is_flex_item:
|
|
871
|
+
# TODO: Don't use block_level_layout_switch.
|
|
1047
872
|
new_child, child_resume_at = block.block_level_layout_switch(
|
|
1048
|
-
context, child, bottom_space, child_skip_stack, box,
|
|
1049
|
-
|
|
1050
|
-
|
|
873
|
+
context, child, bottom_space, child_skip_stack, box, page_is_empty,
|
|
874
|
+
absolute_boxes, fixed_boxes, adjoining_margins=[], discard=discard,
|
|
875
|
+
max_lines=None)[:2]
|
|
1051
876
|
if new_child is None:
|
|
1052
877
|
if resume_at:
|
|
1053
878
|
resume_index, = resume_at
|
|
@@ -1079,29 +904,23 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block,
|
|
|
1079
904
|
# New containing block, resolve the layout of the absolute descendants.
|
|
1080
905
|
for absolute_box in absolute_boxes:
|
|
1081
906
|
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
|
|
907
|
+
context, absolute_box, box, fixed_boxes, bottom_space, skip_stack=None)
|
|
1092
908
|
|
|
1093
|
-
#
|
|
1094
|
-
# See https://www.w3.org/TR/css-flexbox-1/#flex-baselines
|
|
1095
|
-
# TODO: Use the real algorithm.
|
|
909
|
+
# TODO: Use real algorithm, see https://www.w3.org/TR/css-flexbox-1/#flex-baselines.
|
|
1096
910
|
if isinstance(box, boxes.InlineFlexBox):
|
|
1097
|
-
if
|
|
911
|
+
if main == 'width': # and main text direction is horizontal
|
|
1098
912
|
box.baseline = flex_lines[0].lower_baseline if flex_lines else 0
|
|
1099
913
|
else:
|
|
1100
|
-
box.
|
|
1101
|
-
|
|
1102
|
-
|
|
914
|
+
for child in box.children:
|
|
915
|
+
if child.is_in_normal_flow():
|
|
916
|
+
box.baseline = find_in_flow_baseline(child) or 0
|
|
917
|
+
break
|
|
918
|
+
else:
|
|
919
|
+
box.baseline = 0
|
|
920
|
+
|
|
921
|
+
box.remove_decoration(start=False, end=resume_at and not discard)
|
|
1103
922
|
|
|
1104
|
-
context.
|
|
923
|
+
context.finish_flex_formatting_context(box)
|
|
1105
924
|
|
|
1106
925
|
# TODO: Check these returned values.
|
|
1107
926
|
return box, resume_at, {'break': 'any', 'page': None}, [], False
|