@@ -261,6 +261,10 @@ struct BuilderContext {
261261 rootInlineBox ().endInlineBox ();
262262 }
263263
264+ Content& content () {
265+ return _parent.content ;
266+ }
267+
264268 BuilderContext toBlockContext (Box& parent, InlineBox& rootInlineBox) {
265269 return {
266270 From::BLOCK,
@@ -354,19 +358,17 @@ static void _buildText(BuilderContext bc, Gc::Ref<Dom::Text> node, Rc<Style::Spe
354358 }
355359}
356360
357- static void _buildImage (Gc::Ref<Dom::Element> el, InlineBox& rootInlineBox ) {
361+ static void _buildImage (BuilderContext bc, Gc::Ref<Dom::Element> el) {
358362 auto src = el->getAttribute (Html::SRC_ATTR).unwrapOr (" " s);
359363 auto url = Mime::Url::resolveReference (el->baseURI (), Mime::parseUrlOrPath (src))
360364 .unwrapOr (" bundle://vaev-driver/missing.qoi" _url);
361365
362- auto img = Karm::Image::load (url).unwrapOrElse ([] {
366+ bc. content () = Karm::Image::load (url).unwrapOrElse ([] {
363367 return Karm::Image::loadOrFallback (" bundle://vaev-driver/missing.qoi" _url).unwrap ();
364368 });
365-
366- rootInlineBox.add ({el->specifiedValues (), el->computedValues ()->fontFace , img, el});
367369}
368370
369- static void _buildInputProse (Gc::Ref<Dom::Element> el, Box& parent ) {
371+ static void _buildInputProse (BuilderContext bc, Gc::Ref<Dom::Element> el) {
370372 auto font = el->computedValues ()->fontFace ;
371373 Resolver resolver{
372374 .rootFont = Text::Font{font, 16 },
@@ -383,7 +385,7 @@ static void _buildInputProse(Gc::Ref<Dom::Element> el, Box& parent) {
383385 auto prose = makeRc<Text::Prose>(proseStyle, value);
384386
385387 // FIXME: we should guarantee that input has no children (not added before nor to add after)
386- parent .content = InlineBox{prose};
388+ bc .content () = InlineBox{prose};
387389}
388390
389391always_inline static bool isVoidElement (Gc::Ref<Dom::Element> el) {
@@ -392,12 +394,21 @@ always_inline static bool isVoidElement(Gc::Ref<Dom::Element> el) {
392394
393395static void _buildVoidElement (BuilderContext bc, Gc::Ref<Dom::Element> el) {
394396 if (el->tagName == Html::INPUT) {
395- _buildInputProse (el, bc. _parent );
397+ _buildInputProse (bc, el );
396398 } else if (el->tagName == Html::IMG) {
397- _buildImage (*el, bc. rootInlineBox () );
399+ _buildImage (bc, el );
398400 }
399401}
400402
403+ // NOTE: When inlines, <svg> and <img> should not be treated as inline-flow (<span>) and should thus be inside a strut,
404+ // that is, should be inline-block, where we always create a box to wrap around.
405+ // These els are special cases since all other els can take whichever display is set in their style. However, for these
406+ // els, an internal display value will never be valid. This relates to a somewhat "replaced" property from these
407+ // elements, but <img> is replaced whereas <svg> per se is not.
408+ bool _alwaysInlineBlock (Gc::Ref<Dom::Element> el) {
409+ return el->tagName == Html::IMG or el->tagName == Svg::SVG;
410+ }
411+
401412// MARK: Build flow -------------------------------------------------------------------------------
402413
403414static void _buildChildren (BuilderContext bc, Gc::Ref<Dom::Node> parent);
@@ -736,11 +747,11 @@ static void _buildChildDefaultDisplay(BuilderContext bc, Gc::Ref<Dom::Element> c
736747 bc.flushRootInlineBoxIntoAnonymousBox ();
737748 _innerDisplayDispatchCreationOfBlockLevelBox (bc, child, childStyle, display);
738749 } else {
739- if (display == Display::Inside::FLOW) {
750+ // NOTE: <img> and <svg>, for example, should always be treated as inline-block instead of inline-flow (spans)
751+ if (_alwaysInlineBlock (child) or display != Display::Inside::FLOW)
752+ _innerDisplayDispatchCreationOfInlineLevelBox (bc, child, childStyle, display);
753+ else
740754 createAndBuildInlineFlowfromElement (bc, childStyle, child);
741- return ;
742- }
743- _innerDisplayDispatchCreationOfInlineLevelBox (bc, child, childStyle, display);
744755 }
745756}
746757
0 commit comments