Skip to content

Commit

Permalink
karm-gfx: Implemented box shadows.
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepy-monax committed Apr 2, 2024
1 parent ce895c6 commit b3d5bf6
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 90 deletions.
24 changes: 15 additions & 9 deletions src/apps/hideo-shell/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,27 +168,33 @@ Ui::Child tablet(State const &state) {

Ui::Child appStack(State const &state) {
Ui::Children apps;
usize index = 0;
for (auto &s : state.surfaces) {
usize index = state.surfaces.len() - 1;
for (auto &s : iterRev(state.surfaces)) {
apps.pushBack(
Ui::empty() |
scafold(Scafold{
.icon = s.entry.icon.icon,
.title = s.entry.name,
.body = slot$(Ui::empty()),
}) |
Ui::box({
.borderRadius = 8,
.borderRadius = 6,
.borderWidth = 1,
.borderPaint = Ui::GRAY800,
.backgroundPaint = Ui::GRAY950,
.backgroundPaint = Gfx::GRAY950,
.shadowStyle = Gfx::BoxShadow::elevated(index ? 4 : 16),
}) |
Ui::dragRegion() |
Ui::placed(s.bound) |
Ui::intent([=](Ui::Node &n, Sys::Event &e) {
if (auto *m = e.is<Ui::DragEvent>(Sys::Propagation::UP)) {
logInfo("{}", m->delta);
e.accept();
Model::bubble<MoveApp>(n, {index, m->delta});
} else if (auto *c = e.is<Events::RequestExitEvent>(Sys::Propagation::UP)) {
e.accept();
Model::bubble<CloseApp>(n, {index});
}
})
);
index++;
index--;
}

return Ui::stack(apps);
Expand Down Expand Up @@ -230,7 +236,7 @@ Ui::Child app(bool isMobile) {
{
.isMobile = isMobile,
.dateTime = Sys::dateTime(),
.background = Media::loadImageOrFallback("bundle://skift-wallpapers/images/abstract.qoi"_url).unwrap(),
.background = Media::loadImageOrFallback("bundle://skift-wallpapers/images/brutal.qoi"_url).unwrap(),
.noti = {
{
1,
Expand Down
1 change: 0 additions & 1 deletion src/apps/hideo-shell/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ void reduce(State &s, Action a) {
);
},
[&](MoveApp move) {
logInfo("{}", move.off);
s.activePanel = Panel::NIL;
auto bound = s.surfaces[move.index].bound;
bound.xy = bound.xy + move.off;
Expand Down
20 changes: 0 additions & 20 deletions src/libs/karm-gfx/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,6 @@ Media::Font &Context::textFont() {
return current().textFont;
}

ShadowStyle const &Context::shadowStyle() {
return current().shadowStyle;
}

Context &Context::fillStyle(Paint paint) {
current().paint = paint;
return *this;
Expand All @@ -153,11 +149,6 @@ Context &Context::textFont(Media::Font font) {
return *this;
}

Context &Context::shadowStyle(ShadowStyle style) {
current().shadowStyle = style;
return *this;
}

/* --- Drawing -------------------------------------------------------------- */

void Context::clear(Color color) { clear(pixels().bound(), color); }
Expand Down Expand Up @@ -534,17 +525,6 @@ void Context::stroke(StrokeStyle style) {
_fill(style.paint);
}

void Context::shadow() {
shadow(shadowStyle());
}

void Context::shadow(ShadowStyle style) {
layer(style.offset, [&](Context &ctx) {
ctx.fill(style.paint);
ctx.apply(BlurFilter{(isize)style.radius});
});
}

/* --- Effects -------------------------------------------------------------- */

void Context::apply(Filter filter) {
Expand Down
13 changes: 0 additions & 13 deletions src/libs/karm-gfx/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct Context {
Paint paint = Gfx::WHITE;
StrokeStyle strokeStyle{};
Media::Font textFont = Media::Font::fallback();
ShadowStyle shadowStyle{};

Math::Vec2i origin{};
Math::Recti clip{};
Expand Down Expand Up @@ -154,9 +153,6 @@ struct Context {
// Get the current text font.
Media::Font &textFont();

// Get the current shadow style.
ShadowStyle const &shadowStyle();

// Set the current fill style.
Context &fillStyle(Paint style);

Expand All @@ -166,9 +162,6 @@ struct Context {
// Set the current text font.
Context &textFont(Media::Font style);

// Set the current shadow style.
Context &shadowStyle(ShadowStyle style);

/* --- Drawing ---------------------------------------------------------- */

// Clear all pixels with respect to the current origin and clip.
Expand Down Expand Up @@ -322,12 +315,6 @@ struct Context {
// Stroke the current path with the given style.
void stroke(StrokeStyle style);

// Draw a drop shadow for the current path.
void shadow();

// Draw a drop shadow for the current path with the given style.
void shadow(ShadowStyle style);

/* --- Filters ---------------------------------------------------------- */

// Apply the given filter to the current pixels.
Expand Down
21 changes: 21 additions & 0 deletions src/libs/karm-gfx/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ struct Gradient {
Gradient(Type type, Math::Vec2f start, Math::Vec2f end, Strong<Buf> buf)
: _type(type), _start(start), _end(end), _buf(buf) {}

Gradient &withType(Type type) {
_type = type;
return *this;
}

Gradient &withStart(Math::Vec2f start) {
_start = start;
return *this;
}

Gradient &withEnd(Math::Vec2f end) {
_end = end;
return *this;
}

Gradient &withPoints(Math::Vec2f start, Math::Vec2f end) {
_start = start;
_end = end;
return *this;
}

always_inline f64 transform(Math::Vec2f pos) const {
pos = pos - _start;
pos = pos.rotate(-(_end - _start).angle());
Expand Down
181 changes: 181 additions & 0 deletions src/libs/karm-gfx/shadow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#pragma once

#include "context.h"

namespace Karm::Gfx {

struct DropShadow {
Paint fill = Gfx::BLACK;
f64 radius{8};
Math::Vec2i offset{};

static DropShadow elevated(f64 v) {
return {
Gfx::BLACK.withOpacity(0.7),
v * 2,
{0, (int)v},
};
}

auto &withFill(Paint p) {
fill = p;
return *this;
}

auto &withRadius(f64 r) {
radius = r;
return *this;
}

auto &withOffset(Math::Vec2i o) {
offset = o;
return *this;
}

void paint(Gfx::Context &g) {
g.layer(offset, [&](Context &ctx) {
ctx.fill(fill);
ctx.apply(BlurFilter{(isize)radius});
});
}
};

inline DropShadow dropShadow(auto... args) {
return DropShadow(args...);
}

struct BoxShadow {
Gfx::Color fill;
f64 blur;
f64 spread;
Math::Vec2i offset;

static BoxShadow elevated(f64 v) {
return {
Gfx::BLACK.withOpacity(0.5),
v * 2,
-v,
{0, (int)v},
};
}

auto &withFill(Gfx::Color p) {
fill = p;
return *this;
}

auto &withBlur(f64 r) {
blur = r;
return *this;
}

auto &withSpread(f64 r) {
spread = r;
return *this;
}

auto &withOffset(Math::Vec2i o) {
offset = o;
return *this;
}

void paint(Gfx::Context &g, Math::Recti bound) const {
/// 1 / sqrt(2)
static constexpr f64 IS2 = 0.7071067811865475;

// 1 - (1 / sqrt(2))
static constexpr f64 IS2M = 1 - IS2;

bound = bound.grow(spread);
bound = bound.offset(offset);

auto grad = Gfx::Gradient::linear().withColors(fill, fill.withOpacity(0)).bake();

auto topStart = Math::Recti::fromTwoPoint(
bound.topStart(),
bound.topStart() - Math::Vec2i{(int)blur, (int)blur}
);

auto topEnd = Math::Recti::fromTwoPoint(
bound.topEnd(),
bound.topEnd() + Math::Vec2i{(int)blur, -(int)blur}
);

auto bottomStart = Math::Recti::fromTwoPoint(
bound.bottomStart(),
bound.bottomStart() + Math::Vec2i{-(int)blur, (int)blur}
);

auto bottomEnd = Math::Recti::fromTwoPoint(
bound.bottomEnd(),
bound.bottomEnd() + Math::Vec2i{(int)blur, (int)blur}
);

auto top = Math::Recti::fromTwoPoint(
bound.topStart() - Math::Vec2i{0, (int)blur},
bound.topEnd()
);

auto bottom = Math::Recti::fromTwoPoint(
bound.bottomStart(),
bound.bottomEnd() + Math::Vec2i{0, (int)blur}
);

auto start = Math::Recti::fromTwoPoint(
bound.topStart() - Math::Vec2i{(int)blur, 0},
bound.bottomStart()
);

auto end = Math::Recti::fromTwoPoint(
bound.topEnd(),
bound.bottomEnd() + Math::Vec2i{(int)blur, 0}
);

grad.withType(Gradient::RADIAL);
g.fillStyle(grad.withPoints({1, 1}, {IS2M, IS2M}));
g.fill(topStart);

g.fillStyle(grad.withPoints({0, 1}, {IS2, IS2M}));
g.fill(topEnd);

g.fillStyle(grad.withPoints({1, 0}, {IS2M, IS2}));
g.fill(bottomStart);

g.fillStyle(grad.withPoints({0, 0}, {IS2, IS2}));
g.fill(bottomEnd);

grad.withType(Gradient::LINEAR);
g.fillStyle(grad.withPoints({0, 1}, {0, 0}));
g.fill(top);

g.fillStyle(grad.withPoints({0, 0}, {0, 1}));
g.fill(bottom);

g.fillStyle(grad.withPoints({1, 0}, {0, 0}));
g.fill(start);

g.fillStyle(grad.withPoints({0, 0}, {1, 0}));
g.fill(end);

g.fillStyle(fill);
g.fill(bound);

// Debug overlay
return;
g.plot(topStart, Gfx::GREEN);
g.plot(topEnd, Gfx::RED);
g.plot(bottomStart, Gfx::BLUE);
g.plot(bottomEnd, Gfx::YELLOW);

g.plot(top, Gfx::AMBER);
g.plot(bottom, Gfx::INDIGO);
g.plot(start, Gfx::PINK);
g.plot(end, Gfx::CYAN);
}
};

Gfx::BoxShadow boxShadow(auto... args) {
return Gfx::BoxShadow(args...);
}

} // namespace Karm::Gfx
35 changes: 0 additions & 35 deletions src/libs/karm-gfx/style.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,39 +87,4 @@ inline StrokeStyle stroke(auto... args) {
return {args...};
}

/* --- Shadow Style --------------------------------------------------------- */

struct ShadowStyle {
Paint paint = Gfx::BLACK;
f64 radius{8};
Math::Vec2i offset{};

static ShadowStyle elevated(f64 v) {
return {
Gfx::BLACK.withOpacity(0.7),
v * 2,
{0, (int)v},
};
}

auto &withPaint(Paint p) {
paint = p;
return *this;
}

auto &withRadius(f64 r) {
radius = r;
return *this;
}

auto &withOffset(Math::Vec2i o) {
offset = o;
return *this;
}
};

inline ShadowStyle shadow(auto... args) {
return ShadowStyle(args...);
}

} // namespace Karm::Gfx
Loading

0 comments on commit b3d5bf6

Please sign in to comment.