about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/layout/engine.nim29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 2cf2cf7c..3cfaf10f 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -1162,12 +1162,16 @@ proc layoutFlex(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder;
 
 # Note: padding must still be applied after this.
 proc applyWidth(box: BlockBox; sizes: ResolvedSizes;
-    maxChildWidth: LayoutUnit) =
+    maxChildWidth: LayoutUnit; space: AvailableSpace) =
   # Make the box as small/large as the content's width or specified width.
-  box.size.w = maxChildWidth.applySizeConstraint(sizes.space.w)
+  box.size.w = maxChildWidth.applySizeConstraint(space.w)
   # Then, clamp it to minWidth and maxWidth (if applicable).
   box.size.w = clamp(box.size.w, sizes.minWidth, sizes.maxWidth)
 
+proc applyWidth(box: BlockBox; sizes: ResolvedSizes;
+    maxChildWidth: LayoutUnit) =
+  box.applyWidth(sizes, maxChildWidth, sizes.space)
+
 proc applyHeight(box: BlockBox; sizes: ResolvedSizes;
     maxChildHeight: LayoutUnit) =
   # Make the box as small/large as the content's width or specified width.
@@ -1250,6 +1254,7 @@ type
   BlockState = object
     offset: Offset
     maxChildWidth: LayoutUnit
+    totalFloatWidth: LayoutUnit # used for re-layouts
     nested: seq[BlockBox]
     space: AvailableSpace
     xminwidth: LayoutUnit
@@ -2420,7 +2425,7 @@ func isParentResolved(state: BlockState; bctx: BlockContext): bool =
 # same block formatting context depends on knowing where the box offset is
 # (because of floats).
 proc layoutBlockChildren(state: var BlockState; bctx: var BlockContext;
-    children: seq[BoxBuilder]) =
+    children: seq[BoxBuilder]; parent: BlockBox) =
   for builder in children:
     var dy: LayoutUnit = 0 # delta
     var child: BlockBox
@@ -2454,20 +2459,28 @@ proc layoutBlockChildren(state: var BlockState; bctx: var BlockContext;
       # plus height.
       dy = child.offset.y - state.offset.y + child.size.h
     let childWidth = child.margin.left + child.size.w + child.margin.right
-    state.maxChildWidth = max(state.maxChildWidth, childWidth)
     state.xminwidth = max(state.xminwidth, child.xminwidth)
     if child.computed{"position"} != PositionAbsolute and not isfloat:
       # Not absolute, and not a float.
+      state.maxChildWidth = max(state.maxChildWidth, childWidth)
       state.offset.y += dy
     elif isfloat:
       if state.space.w.t == scFitContent:
         # Float position depends on the available width, but in this case
         # the parent width is not known.
+        #
         # Set the "re-layout" flag, and skip this box.
         # (If child boxes with fit-content have floats, those will be
         # re-layouted too first, so we do not have to consider those here.)
         state.needsReLayout = true
+        # Since we emulate max-content here, the float will not contribute to
+        # maxChildWidth in this iteration; instead, its outer width will be
+        # summed up in totalFloatWidth and added to maxChildWidth in
+        # initReLayout.
+        state.totalFloatWidth += child.size.w + child.margin.left +
+          child.margin.right
         continue
+      state.maxChildWidth = max(state.maxChildWidth, childWidth)
       # Two cases exist:
       # a) The float cannot be positioned, because `box' has not resolved
       #    its y offset yet. (e.g. if float comes before the first child,
@@ -2528,7 +2541,7 @@ proc initReLayout(state: var BlockState; bctx: var BlockContext;
   state.nested.setLen(0)
   bctx.exclusions.setLen(state.oldExclusionsLen)
   state.offset = Offset(x: sizes.padding.left, y: sizes.padding.top)
-  box.applyWidth(sizes, state.maxChildWidth)
+  box.applyWidth(sizes, state.maxChildWidth + state.totalFloatWidth)
   state.space.w = stretch(box.size.w)
 
 # Re-position the children.
@@ -2560,16 +2573,16 @@ proc layoutBlock(bctx: var BlockContext; box: BlockBox;
     oldExclusionsLen: bctx.exclusions.len
   )
   state.initBlockPositionStates(bctx, box)
-  state.layoutBlockChildren(bctx, builder.children)
+  state.layoutBlockChildren(bctx, builder.children, box)
   if state.needsReLayout:
     state.initReLayout(bctx, box, sizes)
-    state.layoutBlockChildren(bctx, builder.children)
+    state.layoutBlockChildren(bctx, builder.children, box)
   if state.nested.len > 0:
     let lastNested = state.nested[^1]
     box.baseline = lastNested.offset.y + lastNested.baseline
   # Apply width then move the inline offset of children that still need
   # further relative positioning.
-  box.applyWidth(sizes, state.maxChildWidth)
+  box.applyWidth(sizes, state.maxChildWidth, state.space)
   state.repositionChildren(box, lctx)
   # Set the inner height to the last y offset minus the starting offset
   # (that is, top padding).
' href='#n264'>264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367