Skip to content

Commit a4a6631

Browse files
pauloamedsleepy-monax
authored andcommitted
vaev-layout: Fix double creation of <img> block wrapper by enforcing it being treated as inline-block.
Since we are pushing directly into the wrapper content, a helper was creaeted what lead to some refactoring benefitting from it.
1 parent 4f55f4b commit a4a6631

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

src/vaev-layout/builder.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

389391
always_inline static bool isVoidElement(Gc::Ref<Dom::Element> el) {
@@ -392,12 +394,21 @@ always_inline static bool isVoidElement(Gc::Ref<Dom::Element> el) {
392394

393395
static 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

403414
static 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

Comments
 (0)