Skip to content

Commit

Permalink
web-css: borders draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Louciole committed Jul 24, 2024
1 parent ca99c90 commit 534e2b9
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 59 deletions.
24 changes: 17 additions & 7 deletions src/apps/hideo-browser/res/samples/normal-flow.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@
</head>

<body>
<div class="box red"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box red">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
<div class="box red">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
<div class="box red">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
<div class="box red">coucou</div>
<div class="box green">coucou</div>
<div class="box blue">coucou</div>
</body>

<style>
Expand All @@ -35,4 +45,4 @@
}
</style>

</html>
</html>
3 changes: 2 additions & 1 deletion src/libs/karm-gfx/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ void Path::clear() {
void Path::close() {
evalOp(CLOSE);
}
top void Path::moveTo(Math::Vec2f p, Flags flags) {

void Path::moveTo(Math::Vec2f p, Flags flags) {
evalOp({MOVE_TO, p, flags});
}

Expand Down
6 changes: 3 additions & 3 deletions src/web/vaev-base/background.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ struct BackgroundRepeat {

struct Background {
Color paint;
BackgroundAttachment attachment;
BackgroundPosition position;
BackgroundRepeat repeat;
BackgroundAttachment attachment{};
BackgroundPosition position{};
BackgroundRepeat repeat{};
};

} // namespace Vaev
11 changes: 11 additions & 0 deletions src/web/vaev-driver/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ RenderResult render(Dom::Document const &dom, Style::Media const &media, Vec2Px

auto paintRoot = makeStrong<Paint::Stack>();
layoutRoot->makePaintables(*paintRoot);

// FIXME delete me
layoutRoot->_borderBox.height = Px{500.};
auto child = makeStrong<Paint::Box>();
child->bound.x = Px{300.};
child->bound.y = Px{100.};
child->bound.width = Px{100.};
child->bound.height = Px{100.};
child->backgrounds.pushBack(Background{RED});
paintRoot->add(child);

paintRoot->prepare();

return {layoutRoot, paintRoot};
Expand Down
158 changes: 111 additions & 47 deletions src/web/vaev-paint/borders.h
Original file line number Diff line number Diff line change
@@ -1,101 +1,165 @@
#pragma once

#include <karm-gfx/context.h>
#include <karm-gfx/paint.h>
#include <karm-math/curve.h>
#include <karm-math/radius.h>
#include <vaev-base/borders.h>

#include "karm-gfx/context.h"
#include "vaev-base/borders.h"
#include "karm-logger/logger.h"

namespace Vaev::Paint {

struct BorderPaint {
f64 width;
BorderStyle style;
Gfx::Color fill = Gfx::BLACK;
f64 radiStart, radiEnd; // Right = Top = Start --- Left = Bottom = End
f64 radiStart = 0, radiEnd = 0; // Right = Top = Start --- Left = Bottom = End
};

// https://drafts.csswg.org/css-backgrounds/#borders
struct Borders {
BorderCollapse collapse;

Border top, right, bottom, left;
BorderPaint top, start, bottom, end;

constexpr void all(Border b) {
top = right = bottom = left = b;
constexpr void all(BorderPaint b) {
top = start = bottom = end = b;
}

constexpr void set(BorderEdge edge, Border b) {
constexpr void set(BorderEdge edge, BorderPaint b) {
switch (edge) {
case BorderEdge::ALL:
all(b);
break;
case BorderEdge::TOP:
top = b;
break;
case BorderEdge::RIGHT:
right = b;
case BorderEdge::START:
start = b;
break;
case BorderEdge::BOTTOM:
bottom = b;
break;
case BorderEdge::LEFT:
left = b;
case BorderEdge::END:
end = b;
break;
}
}

void paint(Gfx::Context &ctx, Math::Rectf rect) {
all(Border{8, BorderStyle::SOLID});
all(BorderPaint{
8,
BorderStyle::SOLID,
OLIVE,
8,
8,
});

ctx.begin();
Math::Rectf const outer = Math::Rectf{
{rect.x - right.width, rect.y - top.width},
{rect.width + right.width + left.width, rect.height + top.width + bottom.width}
};
Math::Vec2f const cornerTopStart = {rect.x - start.width, rect.y - top.width};

// precise path, this allow us to paint the borders independantly
if (top.fill == left.fill and left.fill == bottom.fill and bottom.fill == right.fill and top.sty) {
paintEdge(Gfx::Context, , left, top, right)
if (top.fill == start.fill and start.fill == bottom.fill and bottom.fill == end.fill and top.style == bottom.style and bottom.style == start.style and start.style == end.style) {
paintEdge(ctx, cornerTopStart, start, top, end);
return;
}

// fast path, this allow us to paint the border easily if all the borders are the same color/style

Math::Rectf const outer = Math::Rectf{
cornerTopStart,
{rect.width + end.width + start.width, rect.height + top.width + bottom.width}
};

// TODO get correct radius in f
ctx.rect(outer, 0);
ctx.rect(rect, 0);
ctx.fill(top.fill, Gfx::FillRule{Karm::Gfx::FillRule::EVENODD});
}

void paintEdge(Gfx::Context ctx, Math::Vec2f pos, BorderPaint prev, BorderPaint current, BorderPaint next, bool vertical = false, bool positive = true) {
(void)prev;
(void)positive;

(void)next;
(void)vertical;

ctx.moveTo({pos.x + prev.width, pos.y});
ctx.lineTo({pos.x + 108, pos.y});
paintCornerPart(ctx, {pos[0] + 108, pos[1]}, current, next);
ctx.lineTo({pos.x + 108, pos.y + 8});
ctx.lineTo({pos.x, pos.y + 8});
ctx.lineTo({pos.x, pos.y});
ctx.close();
// Math::Rectf const outer = Math::Rectf{
// pos,
// {50, current.width}
// };

// TODO get correct radius in f
// ctx.rect(outer, 0);
// ctx.rect(rect, 0);
// ctx.fill(top.fill, Gfx::FillRule{Karm::Gfx::FillRule::EVENODD});

// if (vertical) {
// ctx.moveTo({pos[0], pos[1] + current.radiStart});
// ctx.lineTo({pos[0], pos[1] + current.radiStart + current.width});
// paintCornerPart(ctx, {pos[0], pos[1] + current.width}, current, next);

// } else {
// ctx.moveTo({pos[0] + current.radiStart, pos[1]});
// ctx.lineTo({pos[0], pos[1] + current.radiStart + current.width});
// paintCornerPart(ctx, {pos[0] + current.width, pos[1]}, current, next);
// }
// ctx.lineTo(pos);
// ctx.cubicTo();
// ctx.lineTo();
// ctx.lineTo();
// ctx.cubicTo();
// ctx.lineTo();
ctx.fill(current.fill);
}

void paintEdge(Gfx::Context ctx, Math::Vec2f pos, Border prev, Border current, Border next, bool vertical = false) {
void paintCornerPart(Gfx::Context ctx, Math::Vec2f pos, BorderPaint start, BorderPaint end) {
Math::Vec2f endPoint = {pos[0] + start.radiEnd, pos[1] + end.radiStart};
logDebug("CRONER : {} {}", pos, endPoint);

if (vertical) {
ctx.moveTo({pos[0], pos[1] + current.radiStart});
ctx.lineTo({pos[0], pos[1] + current.radiStart + current.width});
} else {
ctx.moveTo({pos[0] + current.radiStart, pos[1]});
ctx.lineTo({pos[0], pos[1] + current.radiStart + current.width});
}
f64 cp1 = start.radiEnd - (start.radiEnd * 0.5522847498);
f64 cp2 = end.radiStart - (end.radiStart * 0.5522847498);

Math::Vec2f pointPos = (xsize / ysize) / 2;
Math::Vec2f intersec = evalOp({
Gfx::Path::Code::CUBIC_TO,
{rect.x + rect.width - radius.c - (radius.c * 0.5522847498), rect.y},
{rect.x + rect.width, rect.y + radius.d - (radius.d * 0.5522847498)},
{rect.x + rect.width, rect.y + radius.d},
});
// FIXME control points should probably be linked to proportions
ctx.cubicTo(
{rect.x + rect.width - radius.c - (radius.c * 0.5522847498), rect.y},
{rect.x + rect.width, rect.y + radius.d - (radius.d * 0.5522847498)},
{rect.x + rect.width, rect.y + radius.d}
auto curve = Math::Curvef::cubic(
pos,
{pos.x + cp1, pos.y},
{pos.x, pos.y - cp2},
endPoint
);
ctx.lineTo();
ctx.cubicTo();
ctx.lineTo();
ctx.lineTo();
ctx.cubicTo();
ctx.lineTo();
ctx.fill()
auto [part, _] = splitCubic(curve);

logDebug("CUBIC TO : {} {} {}", part.a, part.b, part.c);
logDebug("CRONER ++ : {} {}", curve.b, curve.c);

// ctx.cubicTo(
// part.b,
// part.c,
// part.d
// );
ctx.cubicTo(curve.b, curve.c, endPoint);
}

// TODO make it split at right point
// TODO make it a method on Curvef
Pair<Math::Curvef> splitCubic(Math::Curvef &og) const {
Math::Vec2f const center = (og.b + og.c) * 0.5;

Math::Vec2f const aP2 = (og.a + og.b) * 0.5;
Math::Vec2f const bP3 = (og.c + og.d) * 0.5;
Math::Vec2f const aP3 = (aP2 + center) * 0.5;
Math::Vec2f const bP2 = (bP3 + center) * 0.5;
Math::Vec2f const m = (aP3 + bP2) * 0.5;

return (Pair<Math::Curvef>{
Math::Curvef::cubic(og.a, aP2, aP3, m),
Math::Curvef::cubic(m, bP2, bP3, og.d)
});
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/web/vaev-paint/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Vaev::Paint {

struct Box : public Node {
RectPx bound;
BorderPaint borders;
Borders borders;
Vec<Background> backgrounds;

void paint(Gfx::Context &ctx) override {
Expand Down

0 comments on commit 534e2b9

Please sign in to comment.