Skip to content

Commit b5af72d

Browse files
committed
(wip) vaev-engine: rework, better commit msg later haha
1 parent 7f49a38 commit b5af72d

File tree

8 files changed

+293
-181
lines changed

8 files changed

+293
-181
lines changed

src/vaev-engine/layout/block.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module;
22

3-
#include <karm-math/au.h>
43
#include <karm-core/macros.h>
4+
#include <karm-math/au.h>
55

66
export module Vaev.Engine:layout.block;
77

@@ -122,6 +122,31 @@ Output fragmentEmptyBox(Tree& tree, Input input) {
122122
}
123123
}
124124

125+
void _populateChildSpecifiedSizes(Tree& tree, Box& child, Input& childInput, Au horizontalMargins, Opt<Au> blockInlineSize) {
126+
if (childInput.intrinsic == IntrinsicSize::AUTO or child.style->display != Display::INLINE) {
127+
if (child.style->sizing->width.is<Keywords::Auto>()) {
128+
// https://www.w3.org/TR/css-tables-3/#layout-principles
129+
// Unlike other block-level boxes, tables do not fill their containing block by default.
130+
// When their width computes to auto, they behave as if they had fit-content specified instead.
131+
// This is different from most block-level boxes, which behave as if they had stretch instead.
132+
if (child.style->display == Display::TABLE_BOX) {
133+
// Do nothing. 'fit-content' is kinda intrinsic size, when we don't populate knownSize.
134+
} else if (blockInlineSize) {
135+
// When the inline size is not known, we cannot enforce it to the child. (?)
136+
childInput.knownSize.width = blockInlineSize.unwrap() - horizontalMargins;
137+
}
138+
} else {
139+
childInput.knownSize.width = computeSpecifiedSize(
140+
tree, child, child.style->sizing->width, childInput.containingBlock, true
141+
);
142+
}
143+
144+
childInput.knownSize.height = computeSpecifiedSize(
145+
tree, child, child.style->sizing->height, childInput.containingBlock, false
146+
);
147+
}
148+
}
149+
125150
// https://www.w3.org/TR/CSS22/visuren.html#normal-flow
126151
struct BlockFormatingContext : FormatingContext {
127152
Au _computeCapmin(Tree& tree, Box& box, Input input, Au inlineSize) {
@@ -157,11 +182,6 @@ struct BlockFormatingContext : FormatingContext {
157182
return fragmentEmptyBox(tree, input);
158183
}
159184

160-
// NOTE: Our parent has no clue about our width but wants us to commit,
161-
// we need to compute it first
162-
if (input.fragment and not input.knownSize.width)
163-
inlineSize = run(tree, box, input.withFragment(nullptr), startAt, stopAt).width();
164-
165185
Breakpoint currentBreakpoint;
166186
BaselinePositionsSet firstBaselineSet, lastBaselineSet;
167187

@@ -195,36 +215,34 @@ struct BlockFormatingContext : FormatingContext {
195215
.pendingVerticalSizes = input.pendingVerticalSizes,
196216
};
197217

198-
auto margin = computeMargins(tree, c, childInput);
199-
200-
Opt<Au> childInlineSize = NONE;
201-
if (c.style->sizing->width.is<Keywords::Auto>()) {
202-
childInlineSize = inlineSize - margin.horizontal();
203-
}
218+
UsedSpacings usedSpacings{
219+
.padding = computePaddings(tree, c, childInput.containingBlock),
220+
.borders = computeBorders(tree, c),
221+
.margin = computeMargins(tree, c, childInput)
222+
};
204223

205224
if (not impliesRemovingFromFlow(c.style->position)) {
206225
// TODO: collapsed margins for sibling elements
207-
blockSize += max(margin.top, lastMarginBottom) - lastMarginBottom;
208-
if (input.fragment or input.knownSize.x)
209-
childInput.knownSize.width = childInlineSize;
226+
blockSize += max(usedSpacings.margin.top, lastMarginBottom) - lastMarginBottom;
210227
}
211228

212-
childInput.position = input.position + Vec2Au{margin.start, blockSize};
229+
childInput.position = input.position + Vec2Au{usedSpacings.margin.start, blockSize};
213230

214231
// HACK: Table Box mostly behaves like a block box, let's compute its capmin
215232
// and avoid duplicating the layout code
216233
if (c.style->display == Display::Internal::TABLE_BOX) {
217234
childInput.capmin = _computeCapmin(tree, box, input, inlineSize);
218235
}
219236

220-
auto output = layout(
221-
tree,
222-
c,
223-
childInput
224-
);
237+
_populateChildSpecifiedSizes(tree, c, childInput, usedSpacings.margin.horizontal(), input.knownSize.x);
238+
239+
auto output = input.fragment
240+
? layoutBorderBox(tree, c, childInput, *input.fragment, usedSpacings)
241+
: layoutBorderBox(tree, c, childInput, usedSpacings);
242+
225243
if (not impliesRemovingFromFlow(c.style->position)) {
226-
blockSize += output.size.y + margin.bottom;
227-
lastMarginBottom = margin.bottom;
244+
blockSize += output.size.y + usedSpacings.margin.bottom;
245+
lastMarginBottom = usedSpacings.margin.bottom;
228246
}
229247

230248
maybeProcessChildBreakpoint(
@@ -252,11 +270,14 @@ struct BlockFormatingContext : FormatingContext {
252270
blockWasCompletelyLaidOut = output.completelyLaidOut and i + 1 == box.children().len();
253271
}
254272

255-
inlineSize = max(inlineSize, output.size.x + margin.horizontal());
273+
inlineSize = max(inlineSize, output.size.x + usedSpacings.margin.horizontal());
256274
}
257275

258276
return {
259-
.size = Vec2Au{inlineSize, blockSize},
277+
.size = Vec2Au{
278+
input.knownSize.x.unwrapOr(inlineSize),
279+
input.knownSize.y.unwrapOr(blockSize)
280+
},
260281
.completelyLaidOut = blockWasCompletelyLaidOut,
261282
.breakpoint = currentBreakpoint,
262283
.firstBaselineSet = firstBaselineSet,

src/vaev-engine/layout/flex.cpp

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ struct FlexItem {
134134
FlexProps flexItemProps;
135135
FlexAxis fa;
136136

137-
// these 2 sizes do NOT account margins
137+
Math::Insets<Au> borders;
138+
Math::Insets<Au> padding;
138139
Vec2Au usedSize;
139140
Math::Insets<Opt<Au>> margin;
140141

@@ -152,19 +153,22 @@ struct FlexItem {
152153
// InsetsAu borders;
153154

154155
FlexItem(Tree& tree, Box& box, bool isRowOriented, Vec2Au containingBlock)
155-
: box(&box), flexItemProps(*box.style->flex), fa(isRowOriented) {
156+
: box(&box), flexItemProps(*box.style->flex), fa(isRowOriented),
157+
borders(computeBorders(tree, box)), padding(computePaddings(tree, box, containingBlock)) {
156158
// FIXME: check if really needed
157159
speculateValues(tree, Input{.containingBlock = containingBlock});
158160
// TODO: not always we will need min/max content sizes,
159161
// this can be lazy computed for performance gains
160162
computeContentSizes(tree, containingBlock);
161163
}
162164

163-
void commit(MutCursor<Frag> frag) {
164-
frag->metrics.margin.top = margin.top.unwrapOr(speculativeMargin.top);
165-
frag->metrics.margin.start = margin.start.unwrapOr(speculativeMargin.start);
166-
frag->metrics.margin.end = margin.end.unwrapOr(speculativeMargin.end);
167-
frag->metrics.margin.bottom = margin.bottom.unwrapOr(speculativeMargin.bottom);
165+
InsetsAu resolvedMargin() {
166+
return {
167+
margin.top.unwrapOr(speculativeMargin.top),
168+
margin.end.unwrapOr(speculativeMargin.end),
169+
margin.bottom.unwrapOr(speculativeMargin.bottom),
170+
margin.start.unwrapOr(speculativeMargin.start),
171+
};
168172
}
169173

170174
void computeContentSizes(Tree& tree, Vec2Au containingBlock) {
@@ -227,12 +231,26 @@ struct FlexItem {
227231
}
228232

229233
void speculateValues(Tree& t, Input input) {
230-
speculativeSize = layout(t, *box, input).size;
231234
speculativeMargin = computeMargins(
232235
t,
233236
*box,
234237
input
235238
);
239+
240+
// FIXME: whats up with intrinsic sizing here?
241+
if (input.intrinsic == IntrinsicSize::AUTO or box->style->display != Display::INLINE) {
242+
if (not input.knownSize.width)
243+
input.knownSize.width = computeSpecifiedSize(
244+
t, *box, box->style->sizing->width, input.containingBlock, true
245+
);
246+
247+
if (not input.knownSize.height)
248+
input.knownSize.height = computeSpecifiedSize(
249+
t, *box, box->style->sizing->height, input.containingBlock, false
250+
);
251+
}
252+
253+
speculativeSize = layoutBorderBox(t, *box, input, UsedSpacings{.padding = padding, .borders = borders}).size;
236254
}
237255

238256
// https://www.w3.org/TR/css-flexbox-1/#valdef-flex-basis-auto
@@ -1428,17 +1446,23 @@ struct FlexFormatingContext : FormatingContext {
14281446
for (auto& flexItem : flexLine.items) {
14291447
flexItem.position = flexItem.position + flexLine.position + input.position;
14301448

1431-
auto out = layout(
1432-
tree,
1433-
*flexItem.box,
1434-
{
1435-
.fragment = input.fragment,
1436-
.knownSize = {flexItem.usedSize.x, flexItem.usedSize.y},
1437-
.position = flexItem.position,
1438-
.availableSpace = availableSpace,
1439-
}
1440-
);
1441-
flexItem.commit(input.fragment);
1449+
UsedSpacings usedSpacings{
1450+
.padding = std::move(flexItem.padding),
1451+
.borders = std::move(flexItem.borders),
1452+
.margin = flexItem.resolvedMargin(),
1453+
};
1454+
1455+
Input childInput{
1456+
.fragment = input.fragment,
1457+
.knownSize = {flexItem.usedSize.x, flexItem.usedSize.y},
1458+
.position = flexItem.position,
1459+
.availableSpace = availableSpace,
1460+
};
1461+
1462+
if (input.fragment)
1463+
layoutBorderBox(tree, *flexItem.box, childInput, *input.fragment, usedSpacings);
1464+
else
1465+
layoutBorderBox(tree, *flexItem.box, childInput, usedSpacings);
14421466
}
14431467
}
14441468
}

src/vaev-engine/layout/inline.cpp

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,32 @@ struct InlineFormatingContext : FormatingContext {
5656

5757
auto& atomicBox = *inlineBox.atomicBoxes[boxStrutCell.id];
5858

59+
// FIXME: Intrinsic sizing for inline boxes is not implemented yet
60+
Input childInput{
61+
.availableSpace = {inlineSize, input.availableSpace.y},
62+
.containingBlock = {
63+
input.knownSize.x.unwrapOr(0_au),
64+
input.knownSize.y.unwrapOr(0_au)
65+
},
66+
};
67+
68+
childInput.knownSize.width = computeSpecifiedSize(
69+
tree, atomicBox, atomicBox.style->sizing->width, childInput.containingBlock, true
70+
);
71+
72+
childInput.knownSize.height = computeSpecifiedSize(
73+
tree, atomicBox, atomicBox.style->sizing->height, childInput.containingBlock, false
74+
);
75+
5976
// NOTE: We set the same availableSpace to child inline boxes since line wrapping is possible i.e. in the
6077
// worst case, they will take up the whole availableSpace, and a line break will be done right before them
61-
auto atomicBoxOutput = layout(
78+
auto atomicBoxOutput = layoutBorderBox(
6279
tree,
6380
atomicBox,
64-
Input{
65-
.knownSize = {NONE, NONE},
66-
.availableSpace = {inlineSize, input.availableSpace.y},
67-
.containingBlock = {
68-
input.knownSize.x.unwrapOr(0_au),
69-
input.knownSize.y.unwrapOr(0_au)
70-
},
81+
childInput,
82+
UsedSpacings{
83+
.padding = computePaddings(tree, atomicBox, childInput.containingBlock),
84+
.borders = computeBorders(tree, atomicBox),
7185
}
7286
);
7387

@@ -100,19 +114,26 @@ struct InlineFormatingContext : FormatingContext {
100114
};
101115
}
102116

103-
layout(
104-
tree,
105-
atomicBox,
106-
Input{
107-
.fragment = input.fragment,
108-
.knownSize = knownSize,
109-
.position = input.position + positionInProse,
110-
.containingBlock = {
111-
input.knownSize.x.unwrapOr(0_au),
112-
input.knownSize.y.unwrapOr(0_au)
113-
},
114-
}
115-
);
117+
// TODO: How should pending vertical sizes for fragmentation work here?
118+
Input childInput{
119+
.fragment = input.fragment,
120+
.knownSize = knownSize,
121+
.position = input.position + positionInProse,
122+
.containingBlock = {
123+
input.knownSize.x.unwrapOr(0_au),
124+
input.knownSize.y.unwrapOr(0_au)
125+
},
126+
};
127+
128+
UsedSpacings usedSpacings{
129+
.padding = computePaddings(tree, atomicBox, childInput.containingBlock),
130+
.borders = computeBorders(tree, atomicBox),
131+
};
132+
133+
if (input.fragment)
134+
layoutBorderBox(tree, atomicBox, childInput, *input.fragment, usedSpacings);
135+
else
136+
layoutBorderBox(tree, atomicBox, childInput, usedSpacings);
116137
}
117138

118139
if (tree.fc.allowBreak() and not tree.fc.acceptsFit(
@@ -128,7 +149,7 @@ struct InlineFormatingContext : FormatingContext {
128149
}
129150

130151
return {
131-
.size = size,
152+
.size = {input.knownSize.x.unwrapOr(size.x), input.knownSize.y.unwrapOr(size.y)},
132153
.completelyLaidOut = true,
133154
.firstBaselineSet = firstBaselineSet,
134155
.lastBaselineSet = lastBaselineSet,

0 commit comments

Comments
 (0)