Files
2026-08-09 22:20:01 +08:00

92 lines
3.4 KiB
C

/* deshab/fb.h - 帧缓冲绘制原语
*
* 整合 desktop_app.h 的 da_pixel/pixel_read/blend/fill_rect/fill_bg/
* fill_rounded_rect/rect_outline,统一前缀为 dsb_。
* 假设 32bpp BGRA 帧缓冲(Limine framebuffer 标准格式)。
*/
#ifndef DESHAB_FB_H
#define DESHAB_FB_H
#include "types.h"
#include "app.h"
static inline void dsb_pixel(dsb_app_context *ac, i64 x, i64 y, u32 color) {
if (x < 0 || (u64)x >= ac->fb_w || y < 0 || (u64)y >= ac->fb_h) return;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)y * ac->fb_pitch);
line[x] = color;
}
static inline u32 dsb_pixel_read(dsb_app_context *ac, i64 x, i64 y) {
if (x < 0 || (u64)x >= ac->fb_w || y < 0 || (u64)y >= ac->fb_h) return 0;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)y * ac->fb_pitch);
return line[x];
}
static inline u32 dsb_blend(u32 bg, u32 fg, u32 alpha) {
u32 na = 256 - alpha;
u32 r = ((bg & 0xFF) * na + (fg & 0xFF) * alpha) >> 8;
u32 g = (((bg >> 8) & 0xFF) * na + ((fg >> 8) & 0xFF) * alpha) >> 8;
u32 b = (((bg >> 16) & 0xFF) * na + ((fg >> 16) & 0xFF) * alpha) >> 8;
return 0xFF000000u | (b << 16) | (g << 8) | r;
}
static inline void dsb_fill_rect(dsb_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color) {
for (i64 r = 0; r < h; r++) {
i64 yy = y + r;
if (yy < 0 || (u64)yy >= ac->fb_h) continue;
u32 *line = (u32 *)((u8 *)ac->fb + (u64)yy * ac->fb_pitch);
for (i64 c = 0; c < w; c++) {
i64 xx = x + c;
if (xx < 0 || (u64)xx >= ac->fb_w) continue;
line[xx] = color;
}
}
}
static inline void dsb_fill_bg(dsb_app_context *ac, u32 color) {
dsb_fill_rect(ac, 0, 0, (i64)ac->fb_w, (i64)ac->fb_h, color);
}
static inline void dsb_fill_rounded_rect(dsb_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color, i64 radius) {
i64 r = radius;
if (r > w / 2) r = w / 2;
if (r > h / 2) r = h / 2;
dsb_fill_rect(ac, x + r, y, w - 2 * r, h, color);
dsb_fill_rect(ac, x, y + r, r, h - 2 * r, color);
dsb_fill_rect(ac, x + w - r, y + r, r, h - 2 * r, color);
for (i64 dy = 0; dy < r; dy++)
for (i64 dx = 0; dx < r; dx++)
if (dx * dx + dy * dy <= r * r) {
dsb_pixel(ac, x + r - 1 - dx, y + r - 1 - dy, color);
dsb_pixel(ac, x + w - r + dx, y + r - 1 - dy, color);
dsb_pixel(ac, x + r - 1 - dx, y + h - r + dy, color);
dsb_pixel(ac, x + w - r + dx, y + h - r + dy, color);
}
}
static inline void dsb_rect_outline(dsb_app_context *ac, i64 x, i64 y, i64 w, i64 h, u32 color, i64 radius) {
i64 r = radius;
if (r > w / 2) r = w / 2;
if (r > h / 2) r = h / 2;
for (i64 c = r; c < w - r; c++) {
dsb_pixel(ac, x + c, y, color);
dsb_pixel(ac, x + c, y + h - 1, color);
}
for (i64 rr = r; rr < h - r; rr++) {
dsb_pixel(ac, x, y + rr, color);
dsb_pixel(ac, x + w - 1, y + rr, color);
}
for (i64 dy = 0; dy <= r; dy++)
for (i64 dx = 0; dx <= r; dx++) {
i64 d2 = dx * dx + dy * dy;
if (d2 <= r * r && d2 > (r - 1) * (r - 1)) {
dsb_pixel(ac, x + r - dx, y + r - dy, color);
dsb_pixel(ac, x + w - 1 - r + dx, y + r - dy, color);
dsb_pixel(ac, x + r - dx, y + h - 1 - r + dy, color);
dsb_pixel(ac, x + w - 1 - r + dx, y + h - 1 - r + dy, color);
}
}
}
#endif /* DESHAB_FB_H */