Skip to content

Commit

Permalink
vaev-layout: Improved z-index ordering.
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepy-monax committed Oct 1, 2024
1 parent a28202a commit 197c2f8
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 28 deletions.
24 changes: 12 additions & 12 deletions meta/plugins/reftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ def getInfo(txt):
print(f"{vt100.YELLOW}Skip test{vt100.RESET}")
continue

input_path = TEST_REPORT / f"{temp_file_name}-{num}.xhtml"
input_path = TEST_REPORT / f"{counter}.xhtml"

update_temp_file(input_path, container, rendering)

# generate temporary bmp
img_path = TEST_REPORT / f"{temp_file_name}-{num}.bmp"
img_path = TEST_REPORT / f"{counter}.bmp"

if props.get("size") == "full":
paperMuncher.popen("render", "-sdlpo", img_path, input_path)
Expand All @@ -177,7 +177,7 @@ def getInfo(txt):
paperMuncher.popen(
"print",
"-sdlpo",
TEST_REPORT / f"{temp_file_name}-{num}.pdf",
TEST_REPORT / f"{counter}.pdf",
input_path,
)

Expand Down Expand Up @@ -206,12 +206,12 @@ def getInfo(txt):
if ok:
passed += 1
# img_path.unlink()
print(f"{help}: {vt100.GREEN}Passed{vt100.RESET}")
print(f"{counter}: {help}: {vt100.GREEN}Passed{vt100.RESET}")
else:
failed += 1

print()
print(f"{help}: {vt100.RED}Failed{vt100.RESET}")
print(f"{counter}: {help}: {vt100.RED}Failed{vt100.RESET}")
# generate temporary file for debugging

print(f"file://{input_path}")
Expand All @@ -220,7 +220,7 @@ def getInfo(txt):

report += f"""
<div id="case-{counter}" class="test-case {ok and 'passed' or 'failed'}">
<h2>{tag} - {props.get('name')}</h2>
<h2>{counter} - {tag} - {props.get('name')}</h2>
<p>{help}</p>
<div class="outputs">
<div>
Expand All @@ -229,7 +229,7 @@ def getInfo(txt):
</div>
<div>
<img class="actual" src="{TEST_REPORT / f'{temp_file_name}-{num}.bmp'}" />
<img class="actual" src="{TEST_REPORT / f'{counter}.bmp'}" />
<figcaption>Actual</figcaption>
</div>
Expand All @@ -238,7 +238,7 @@ def getInfo(txt):
<figcaption>Rendition</figcaption>
</div>
</div>
<a href="{TEST_REPORT / f'{temp_file_name}-{num}.pdf'}">PDF</a>
<a href="{TEST_REPORT / f'{counter}.pdf'}">PDF</a>
<a href="{expected_image_url}">Expected</a>
<a href="{input_path}">Source</a>
</div>
Expand All @@ -255,6 +255,8 @@ def getInfo(txt):
<style>
body {
font-family: sans-serif;
background-color: #18181b;
color: #fafafa
}
.test-case {
Expand All @@ -263,13 +265,11 @@ def getInfo(txt):
}
.passed {
border: 2px solid #aea;
background-color: #efe;
}
.failed {
border: 2px solid red;
background-color: lightcoral;
border: 2px solid #991b1b;
background-color: #450a0a;
}
.outputs {
Expand Down
1 change: 1 addition & 0 deletions src/vaev-base/insets.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Vaev {
// https://www.w3.org/TR/CSS22/visuren.html#propdef-position
enum struct Position {
STATIC,

RELATIVE,
ABSOLUTE,
FIXED,
Expand Down
4 changes: 4 additions & 0 deletions src/vaev-base/z-index.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ struct ZIndex {

bool operator==(_Auto) const { return auto_; }

bool operator==(isize value) const {
return not auto_ and this->value == value;
}

void repr(Io::Emit &e) const {
if (auto_) {
e("auto");
Expand Down
4 changes: 2 additions & 2 deletions src/vaev-layout/frag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void Frag::add(Frag &&frag) {

void Frag::repr(Io::Emit &e) const {
if (children()) {
e("(flow {} {}", style->display, layout.borderBox());
e("(flow {} {} {}", style->display, style->position, layout.borderBox());
e.indentNewline();
for (auto &c : children()) {
c.repr(e);
Expand All @@ -50,7 +50,7 @@ void Frag::repr(Io::Emit &e) const {
e.deindent();
e(")");
} else {
e("(frag {} {})", style->display, layout.borderBox());
e("(frag {} {} {})", style->display, style->position, layout.borderBox());
}
}

Expand Down
82 changes: 70 additions & 12 deletions src/vaev-layout/paint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,17 @@ static void _paintBackground(Frag &frag, Gfx::Color currentColor, Paint::Stack &
stack.add(makeStrong<Paint::Box>(std::move(paint)));
}

static void _paintInner(Frag &frag, Paint::Stack &stack) {
static void _establishStackingContext(Frag &frag, Paint::Stack &stack);
static void _paintStackingContext(Frag &frag, Paint::Stack &stack);

static void _paintFrag(Frag &frag, Paint::Stack &stack) {
Gfx::Color currentColor = Gfx::BLACK;
currentColor = resolve(frag.style->color, currentColor);

_paintBackground(frag, currentColor, stack);

for (auto &c : frag.children())
paint(c, stack);
if (not frag.layout.borders.zero())
_paintBorders(frag, currentColor, stack);

if (auto run = frag.content.is<Strong<Text::Run>>()) {
Math::Vec2f baseline = {0, frag.font.metrics().ascend};
Expand All @@ -83,22 +86,77 @@ static void _paintInner(Frag &frag, Paint::Stack &stack) {
currentColor
));
}

if (not frag.layout.borders.zero())
_paintBorders(frag, currentColor, stack);
}

void paint(Frag &frag, Paint::Stack &stack) {
if (frag.style->zIndex == ZIndex::AUTO) {
_paintInner(frag, stack);
return;
static void _paintChildren(Frag &frag, Paint::Stack &stack, auto predicate) {
for (auto &c : frag.children()) {
auto &s = *c.style;

auto zIndex = s.zIndex;
if (zIndex != ZIndex::AUTO) {
if (predicate(s))
_establishStackingContext(c, stack);
continue;
}

// NOTE: Positioned elements act as if they establish a stacking context
auto position = s.position;
if (position != Position::STATIC) {
if (predicate(s))
_paintStackingContext(c, stack);
continue;
}

if (predicate(s))
_paintFrag(c, stack);
_paintChildren(c, stack, predicate);
}
}

// Z-index is not auto, we need to create a new stacking context
static void _paintStackingContext(Frag &frag, Paint::Stack &stack) {
// 1. the background and borders of the element forming the stacking context.
_paintFrag(frag, stack);

// 2. the child stacking contexts with negative stack levels (most negative first).
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex.value < 0;
});

// 3. the in-flow, non-inline-level, non-positioned descendants.
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex == ZIndex::AUTO and s.display != Display::INLINE and s.position == Position::STATIC;
});

// 4. the non-positioned floats.
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex == ZIndex::AUTO and s.position == Position::STATIC and s.float_ != Float::NONE;
});

// 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex == ZIndex::AUTO and s.display == Display::INLINE and s.position == Position::STATIC;
});

// 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex.value == 0 and s.position != Position::STATIC;
});

// 7. the child stacking contexts with positive stack levels (least positive first).
_paintChildren(frag, stack, [](Style::Computed const &s) {
return s.zIndex.value > 0;
});
}

static void _establishStackingContext(Frag &frag, Paint::Stack &stack) {
auto innerStack = makeStrong<Paint::Stack>();
innerStack->zIndex = frag.style->zIndex.value;
_paintInner(frag, *innerStack);
_paintStackingContext(frag, *innerStack);
stack.add(std::move(innerStack));
}

void paint(Frag &frag, Paint::Stack &stack) {
_paintStackingContext(frag, stack);
}

} // namespace Vaev::Layout
4 changes: 2 additions & 2 deletions src/vaev-layout/positioned.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ void layoutPositioned(Tree &t, Frag &f, RectPx containingBlock) {
if (f.style->position == Position::RELATIVE)
origin = f.layout.position;

auto top = f.layout.borderBox().top();
auto start = f.layout.borderBox().start();
auto top = f.layout.position.y;
auto start = f.layout.position.x;

auto topOffset = f.style->offsets->top;
if (topOffset != Width::AUTO) {
Expand Down

0 comments on commit 197c2f8

Please sign in to comment.