Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 0452a67

Browse files
committed
Pond: Allow windows to blur what's behind them
Work in progress. Adds a new window hint to blur contents behind a window. It currently uses an approximated gaussian blur by applying 3 passes of a box blur. There are currently a few visual artifacts (such as when moving the cursor around a blurred window) due to the way partial redraws work.
1 parent 890cb2a commit 0452a67

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

libraries/libgraphics/Framebuffer.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,79 @@ void Framebuffer::copy_blitting_flipped(const Framebuffer& other, Rect other_are
225225
}
226226
}
227227

228+
void Framebuffer::blur(Gfx::Rect area, int radius) const {
229+
int window_size = radius * 2 + 1;
230+
231+
auto do_pass = [&]() { ;
232+
// First, apply blur horizontally.
233+
for(int y = area.y; y < area.y + area.height; y++) {
234+
int window[3] = {0, 0, 0};
235+
Color window_preblur[window_size];
236+
int preblur_index = 0;
237+
238+
// Populate window
239+
for(int i = -radius; i <= radius; i++) {
240+
auto color = data[(std::min(std::max(area.x + i, 0), width - 1)) + y * width];
241+
window_preblur[i + radius] = color;
242+
window[0] += color.r;
243+
window[1] += color.g;
244+
window[2] += color.b;
245+
}
246+
247+
for(int x = area.x; x < area.x + area.width; x++) {
248+
data[x + y * width] = {
249+
(uint8_t) (window[0] / window_size),
250+
(uint8_t) (window[1] / window_size),
251+
(uint8_t) (window[2] / window_size),
252+
};
253+
auto window_add = data[(std::min(x + 5, width - 1)) + y * width];
254+
auto window_sub = window_preblur[preblur_index];
255+
preblur_index++;
256+
preblur_index %= window_size;
257+
window_preblur[((preblur_index - 1) % window_size + window_size) % window_size] = window_add;
258+
window[0] += (int) window_add.r - (int) window_sub.r;
259+
window[1] += (int) window_add.g - (int) window_sub.g;
260+
window[2] += (int) window_add.b - (int) window_sub.b;
261+
}
262+
}
263+
264+
// Then, apply blur vertically.
265+
for(int x = area.x; x < area.x + area.width; x++) {
266+
int window[3] = {0, 0, 0};
267+
Color window_preblur[window_size];
268+
int preblur_index = 0;
269+
270+
// Populate window
271+
for(int i = -radius; i <= radius; i++) {
272+
auto color = data[(x + std::min(std::max(area.y + i, 0), height - 1)) * width];
273+
window_preblur[i + radius] = color;
274+
window[0] += color.r;
275+
window[1] += color.g;
276+
window[2] += color.b;
277+
}
278+
279+
for(int y = area.y; y < area.y + area.height; y++) {
280+
data[x + y * width] = {
281+
(uint8_t) (window[0] / window_size),
282+
(uint8_t) (window[1] / window_size),
283+
(uint8_t) (window[2] / window_size),
284+
};
285+
auto window_add = data[x + (std::min(y + 5, height - 1)) * width];
286+
auto window_sub = window_preblur[preblur_index];
287+
preblur_index++;
288+
preblur_index %= window_size;
289+
window_preblur[((preblur_index - 1) % window_size + window_size) % window_size] = window_add;
290+
window[0] += (int) window_add.r - (int) window_sub.r;
291+
window[1] += (int) window_add.g - (int) window_sub.g;
292+
window[2] += (int) window_add.b - (int) window_sub.b;
293+
}
294+
}
295+
};
296+
297+
for(int i = 0; i < 3; i++)
298+
do_pass();
299+
}
300+
228301
void Framebuffer::copy_tiled(const Framebuffer& other, Rect other_area, const Point& pos) const {
229302
//Make sure self_area is in bounds of the framebuffer
230303
Rect self_area = {pos.x, pos.y, other_area.width, other_area.height};

libraries/libgraphics/Framebuffer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ namespace Gfx {
9393
*/
9494
void copy_blitting_flipped(const Framebuffer& other, Rect other_area, const Point& pos, bool flip_h, bool flip_v) const;
9595

96+
/**
97+
* Blurs an area of this framebuffer with an approximated gaussian blur.
98+
* @param area The area to blur.
99+
* @param radius The blur radius.
100+
*/
101+
void blur(Rect area, int radius = 4) const;
102+
96103
/**
97104
* Identical to ::copy(), but will tile the Image.
98105
*/

services/pond/Window.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,17 @@ class Window {
271271

272272
/**
273273
* Gets the shadow framebuffers for drawing shadows.
274+
* Sets whether the window should blur contents behind it.
275+
*/
276+
void set_blur_behind(bool blur);
277+
278+
/**
279+
* Returns whether the window blurs contents behind it.
280+
*/
281+
bool blurs_behind() const;
282+
283+
/**
284+
* Gets the shadow framebuffer for drawing shadows.
274285
*/
275286
Gfx::Framebuffer* shadow_buffers() { return _shadow_buffers; }
276287

0 commit comments

Comments
 (0)