Skip to content

Commit

Permalink
base+style: Add calc values (missing recursive calcs).
Browse files Browse the repository at this point in the history
  • Loading branch information
Louciole committed Sep 12, 2024
1 parent 4482a06 commit 312cb8e
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 29 deletions.
71 changes: 71 additions & 0 deletions src/web/vaev-base/calc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once
#include <karm-io/emit.h>
#include <vaev-base/numbers.h>

namespace Vaev {

template <typename T>
struct CalcValue {
enum struct OpCode {
NONE,
ADD,
SUBSTRACT,
MULTIPLY,
DIVIDE,
SIN,
TAN,
COS,

_LEN
};

enum OpType {
FIXED, // a single value
SINGLE, // 1 value + 1 OP
CALC, // 2 values + 1 OP
};

using Leaf = Box<CalcValue<T>>;

using Value = Union<None, T, Leaf, Number>;
OpType type;
Value lhs = NONE;
Value rhs = NONE;
OpCode op = OpCode::NONE;

constexpr CalcValue()
: CalcValue(T{}) {
}

constexpr CalcValue(T value)
: type(OpType::FIXED), lhs(value) {
}

constexpr CalcValue(Value value)
: type(OpType::FIXED), lhs(value) {
}

constexpr CalcValue(Value lhs, OpCode op)
: type(OpType::SINGLE), lhs(lhs), op(op) {
}

constexpr CalcValue(Value lhs, OpCode op, Value rhs)
: type(OpType::CALC), lhs(lhs), rhs(rhs), op(op) {
}

constexpr bool operator==(OpType type2) const {
return type == type2;
}

void repr(Io::Emit &e) const {
if (type == OpType::FIXED) {
e("{}", lhs);
} else if (type == OpType::SINGLE) {
e("{} {}", op, lhs);
} else {
e("{} {} {}", lhs, op, rhs);
}
}
};

} // namespace Vaev
4 changes: 2 additions & 2 deletions src/web/vaev-base/flex.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ struct FlexBasis {
using enum Type;

Type type;
Width width;
Width width = Width::AUTO;

constexpr FlexBasis(Type type)
: type(type) {
}

constexpr FlexBasis(Width width)
FlexBasis(Width width)
: type(Type::WIDTH), width(width) {
}

Expand Down
2 changes: 2 additions & 0 deletions src/web/vaev-base/length.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct Length {

using enum Unit;

using Resolved = Px;

f64 _val = 0;
Unit _unit = Unit::PX;

Expand Down
2 changes: 2 additions & 0 deletions src/web/vaev-base/percent.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct PercentOr {
VALUE,
};

using Resolved = typename T::Resolved;

using enum Type;

Type _type;
Expand Down
5 changes: 3 additions & 2 deletions src/web/vaev-base/sizing.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <karm-io/emit.h>
#include <vaev-base/calc.h>

#include "length.h"
#include "percent.h"
Expand Down Expand Up @@ -29,15 +30,15 @@ struct Size {
using enum Type;

Type type;
PercentOr<Length> value;
CalcValue<PercentOr<Length>> value;

constexpr Size() : type(AUTO), value(Length{}) {
}

constexpr Size(Type type) : type(type), value(Length{}) {
}

constexpr Size(Type type, PercentOr<Length> value) : type(type), value(value) {
Size(CalcValue<PercentOr<Length>> value) : type(LENGTH), value(value) {
}

constexpr Size(Percent value) : type(LENGTH), value(value) {
Expand Down
5 changes: 3 additions & 2 deletions src/web/vaev-base/width.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "length.h"
#include "percent.h"
#include "vaev-base/calc.h"

namespace Vaev {

Expand All @@ -14,13 +15,13 @@ struct Width {
using enum Type;

Type type;
PercentOr<Length> value;
CalcValue<PercentOr<Length>> value;

constexpr Width(Type type)
: type(type) {
}

constexpr Width(PercentOr<Length> percent = {})
Width(CalcValue<PercentOr<Length>> percent = {})
: type(Type::VALUE), value(percent) {
}

Expand Down
58 changes: 58 additions & 0 deletions src/web/vaev-layout/values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,70 @@ Px resolve(Tree &t, Frag &f, Length l) {
}
}

template <typename T>
concept Resolvable = requires {
typename T::Resolved;
};

template <typename T>
using Resolved = Meta::Cond<Resolvable<T>, typename T::Resolved, T>;
static_assert(Resolvable<PercentOr<Length>>);

Px resolve(Tree &t, Frag &f, PercentOr<Length> p, Px relative) {
if (p.resolved())
return resolve(t, f, p.value());
return Px{relative.cast<f64>() * (p.percent().value() / 100.)};
}

template <typename T>
Resolved<T> resolveInfix(typename CalcValue<T>::OpCode op, Resolved<T> lhs, Resolved<T> rhs) {
switch (op) {
case CalcValue<T>::OpCode::ADD:
return lhs + rhs;
case CalcValue<T>::OpCode::SUBSTRACT:
return lhs - rhs;
case CalcValue<T>::OpCode::MULTIPLY:
return lhs * rhs;
case CalcValue<T>::OpCode::DIVIDE:
return lhs / rhs;
default:
return lhs;
}
}

template <typename T>
auto resolve(Tree &t, Frag &f, CalcValue<T> const &p, Px relative) {
if (p.type == CalcValue<T>::OpType::FIXED) {
return resolve(t, f, p.lhs.template unwrap<T>(), relative);
} else if (p.type == CalcValue<T>::OpType::SINGLE) {
// TODO: compute result of funtion here with the resolved value
return resolve(t, f, p.lhs.template unwrap<T>(), relative);
} else if (p.type == CalcValue<T>::OpType::CALC) {
auto resolveUnion = Visitor{
[&](T const &v) {
return resolve<T>(t, f, v, relative);
},
[&](CalcValue<T>::Leaf const &v) {
return resolve<T>(t, f, *v, relative);
},
[&](Number const &v) {
return Math::i24f8{v};
},
[&](None const &) -> Resolved<T>{
panic("invalid value in calc expression");
}
};

return resolveInfix<T>(
p.op,
p.lhs.visit(resolveUnion),
p.rhs.visit(resolveUnion)
);
}

unreachable();
}

Px resolve(Tree &t, Frag &f, Width w, Px relative) {
if (w == Width::Type::AUTO)
return Px{0};
Expand Down
20 changes: 10 additions & 10 deletions src/web/vaev-style/styles.h
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ struct FlexBasisProp {

static constexpr Str name() { return "flex-basis"; }

static constexpr FlexBasis initial() { return Width{Width::AUTO}; }
static FlexBasis initial() { return Width{Width::AUTO}; }

void apply(Computed &c) const {
c.flex.cow().basis = value;
Expand Down Expand Up @@ -998,7 +998,7 @@ struct MarginTopProp {

static Str name() { return "margin-top"; }

static constexpr Width initial() { return Length{}; }
static Width initial() { return Length{}; }

void apply(Computed &c) const {
c.margin.cow().top = value;
Expand All @@ -1015,7 +1015,7 @@ struct MarginRightProp {

static Str name() { return "margin-right"; }

static constexpr Width initial() { return Length{}; }
static Width initial() { return Length{}; }

void apply(Computed &c) const {
c.margin.cow().end = value;
Expand All @@ -1032,7 +1032,7 @@ struct MarginBottomProp {

static constexpr Str name() { return "margin-bottom"; }

static constexpr Width initial() { return Length{}; }
static Width initial() { return Length{}; }

void apply(Computed &c) const {
c.margin.cow().bottom = value;
Expand Down Expand Up @@ -1409,7 +1409,7 @@ struct WidthProp {

static constexpr Str name() { return "width"; }

static constexpr Size initial() { return Size::AUTO; }
static Size initial() { return Size::AUTO; }

void apply(Computed &c) const {
c.sizing.cow().width = value;
Expand All @@ -1428,7 +1428,7 @@ struct HeightProp {

static constexpr Str name() { return "height"; }

static constexpr Size initial() { return Size::AUTO; }
static Size initial() { return Size::AUTO; }

void apply(Computed &c) const {
c.sizing.cow().height = value;
Expand All @@ -1447,7 +1447,7 @@ struct MinWidthProp {

static constexpr Str name() { return "min-width"; }

static constexpr Size initial() { return Size::AUTO; }
static Size initial() { return Size::AUTO; }

void apply(Computed &c) const {
c.sizing.cow().minWidth = value;
Expand All @@ -1466,7 +1466,7 @@ struct MinHeightProp {

static constexpr Str name() { return "min-height"; }

static constexpr Size initial() { return Size::AUTO; }
static Size initial() { return Size::AUTO; }

void apply(Computed &c) const {
c.sizing.cow().minHeight = value;
Expand All @@ -1485,7 +1485,7 @@ struct MaxWidthProp {

static constexpr Str name() { return "max-width"; }

static constexpr Size initial() { return Size::NONE; }
static Size initial() { return Size::NONE; }

void apply(Computed &c) const {
c.sizing.cow().maxWidth = value;
Expand All @@ -1504,7 +1504,7 @@ struct MaxHeightProp {

static constexpr Str name() { return "max-height"; }

static constexpr Size initial() { return Size::NONE; }
static Size initial() { return Size::NONE; }

void apply(Computed &c) const {
c.sizing.cow().maxHeight = value;
Expand Down
19 changes: 6 additions & 13 deletions src/web/vaev-style/values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ Res<Number> ValueParser<Number>::parse(Cursor<Css::Sst> &c) {

if (c.peek() == Css::Token::NUMBER) {
Io::SScan scan = c->token.data;
c.next();
return Ok(try$(Io::atof(scan)));
}

Expand Down Expand Up @@ -817,21 +818,13 @@ Res<Size> ValueParser<Size>::parse(Cursor<Css::Sst> &c) {
return Ok(Size::MIN_CONTENT);
} else if (data == "max-content") {
return Ok(Size::MAX_CONTENT);
} else if (data == "fit-content") {
return Ok(Size::FIT_CONTENT);
}
} else if (c.peek() == Css::Token::PERCENTAGE) {
return Ok(try$(parseValue<Percent>(c)));
} else if (c.peek() == Css::Token::DIMENSION) {
return Ok(try$(parseValue<Length>(c)));
} else if (c.peek() == Css::Sst::FUNC) {
auto const &prefix = c.next().prefix.unwrap();
auto prefixToken = prefix->token;
if (prefixToken.data == "fit-content") {
Cursor<Css::Sst> content = prefix->content;
return Ok(Size{Size::FIT_CONTENT, try$(parseValue<Length>(content))});
}
} else {
return Ok(try$(parseValue<CalcValue<PercentOr<Length>>>(c)));
}

return Error::invalidData("expected size");
unreachable();
}

// MARK: String
Expand Down
Loading

0 comments on commit 312cb8e

Please sign in to comment.