Files
LinehuandCursor 8554a82677 feat(panic): FUCK [panic] mode=strict|fallback + realtest image variant
- UTSM panic_full returns in fallback mode (logs [PANIC:FALLBACK] + code + hit
  count); panic_halt keeps always-halt sites (CPU exception, VMM-E11 LA57,
  VMM-E15 DSK jump, UTSM-E42 test hook). Call sites given safe continuations.
- Mode passed to DSK/FirstInit/login/desktop via DSK_BOOT_FLAG_PANIC_FALLBACK;
  DKM kernel_api.panic / kern.log.panic return to driver; ext4 fatal aborts the
  op via setjmp/longjmp and DSK falls back to FAT32 ESP.
- build.ps1/Makefile: dev=strict, release=fallback, new realtest (release
  options + strict); default -Variant all; serialized iso packing under -j.
- Fix '*/' inside comments (dkm.h, kernel_api.h, bus.c) that broke the build.
- Includes pending work: dkm_bus service bus, mt7920/wlan drivers, desktop
  files/startmenu/prank, pe-tools, diskinfo, docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 23:57:19 +08:00

649 lines
30 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* fluent_ui.h — Deshab "Win11 Fluent" 视觉组件库
*
* 设计目标:商业化 Windows 11 风格 —— 居中悬浮圆角任务栏、亚克力半透明
* 弹层、圆角窗口、浅色/深色主题(见桌面重构计划第二节)。
*
* 分层:
* L1 wf_theme 主题令牌(色板 + 圆角),g_wf_light / g_wf_dark 预设
* L2 原语 du_wf_acrylic(读背景 alpha 混合圆角面板)、du_wf_shadow、
* du_wf_line(Bresenham 带宽线)、du_wf_ring(圆环/半弧)
* L3 组件 按钮/图标钮/开关/滑块/列表项/卡片/文本框/滚动条/提示 +
* 复选框/进度条/标签页/分隔线/应用瓦片/菜单行/徽标(M3 开始菜单批次)
* L4 图标 du_wf_icon 矢量线性图标(24 网格设计,2px 笔触)
*
* 约定(与 deshab_ui.h 相同):包含本头前,编译单元须已定义 g_ascii
* (include ascii_font.h 或 ascii_bitmaps.c)。所有组件为纯绘制函数,
* hover/press 态由调用方检测并传入。
*
* 中文文本:本库组件标签为 ASCII;中文请调用方用 zh_draw_string +
* 主题令牌色绘制(zhfont.h 在 CODE/desktop/,不进 UTSM 公共头)。
*/
#ifndef DESHAB_FLUENT_UI_H
#define DESHAB_FLUENT_UI_H
#include <utsm/deshab_ui.h>
/* ===================================================================
* L1 — 主题令牌 (wf_theme)
* =================================================================== */
typedef struct {
/* 亚克力面板 */
du_u32 acrylic_tint; /* 混入背景的 tint 色 */
du_u32 acrylic_stroke; /* 1px 边线 */
du_u32 acrylic_solid; /* 不透明回退底色(无 alpha 场景) */
/* 文本 */
du_u32 text_primary;
du_u32 text_secondary;
du_u32 text_dim;
/* 强调色(Win11 accent) */
du_u32 accent;
du_u32 accent_hover;
du_u32 accent_press;
du_u32 on_accent; /* accent 上的文字 */
/* 控件 */
du_u32 control_stroke;
du_u32 window_border;
du_u32 divider;
du_u32 shadow;
/* 语义色 */
du_u32 success, warning, error;
du_u32 close_hover; /* 窗口关闭钮 hover 红 #E81123 */
/* 圆角 */
int radius_sm; /* 4 按钮/输入框 */
int radius_md; /* 8 卡片/窗口 */
int radius_lg; /* 12 任务栏/开始菜单/弹层 */
} wf_theme;
/* 浅色主题(Win11 Light:底 #F3F3F3,accent #0067C0) */
static const wf_theme g_wf_light = {
0xFFF3F3F3u, /* acrylic_tint */
0xFFEDEDEDu, /* acrylic_stroke */
0xFFF6F6F6u, /* acrylic_solid */
0xFF1A1A1Au, 0xFF5D5D5Du, 0xFF8A8A8Au,
0xFF0067C0u, 0xFF0078D4u, 0xFF005A9Eu, 0xFFFFFFFFu,
0xFFD6D6D6u, /* control_stroke */
0xFFE5E5E5u, /* window_border */
0xFFEDEDEDu, /* divider */
0x66000000u, /* shadow */
0xFF0F7B0Fu, 0xFF9D5D00u, 0xFFC42B1Cu,
0xFFC42B1Cu,
4, 8, 12,
};
/* 深色主题(Win11 Dark:底 #202020,accent #4CC2FF) */
static const wf_theme g_wf_dark = {
0xFF202020u,
0xFF3C3C3Cu, /* acrylic_stroke */
0xFF2B2B2Bu,
0xFFFFFFFFu, 0xFFC8C8C8u, 0xFF9A9A9Au,
0xFF4CC2FFu, 0xFF62CBFFu, 0xFF29A8E0u, 0xFF00293Cu,
0xFF3C3C3Cu, /* control_stroke */
0xFF3F3F3Fu, /* window_border */
0xFF3A3A3Au, /* divider */
0x99000000u, /* shadow */
0xFF6CCB5Fu, 0xFFFCE100u, 0xFFFF99A4u,
0xFFC42B1Cu,
4, 8, 12,
};
/* ===================================================================
* L2 — 原语
* =================================================================== */
/* 亚克力面板:逐像素读背景 → alpha 混合 tint → 圆角掩码。
* 真实 backdrop blur 不可行,靠"高透 tint + 1px 边 + 壁纸层透出"模拟。
* 仅用于弹层/任务栏(面积 <40% 屏,性能预算见计划第七节)。 */
static inline void du_wf_acrylic(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 alpha, du_u32 radius,
const wf_theme *t) {
du_i64 r = (du_i64)radius;
if (r * 2 > w) r = w / 2;
if (r * 2 > h) r = h / 2;
for (du_i64 row = 0; row < h; row++) {
for (du_i64 col = 0; col < w; col++) {
du_i64 dx = 0, dy = 0;
int corner = 0;
if (col < r && row < r) { dx = r - 1 - col; dy = r - 1 - row; corner = 1; }
else if (col >= w - r && row < r) { dx = col - (w - r); dy = r - 1 - row; corner = 1; }
else if (col < r && row >= h - r) { dx = r - 1 - col; dy = row - (h - r); corner = 1; }
else if (col >= w - r && row >= h - r) { dx = col - (w - r); dy = row - (h - r); corner = 1; }
if (corner && dx * dx + dy * dy > r * r) continue;
du_u32 bg = du_pixel_read(ctx, x + col, y + row);
du_pixel(ctx, x + col, y + row, du_blend(bg, t->acrylic_tint, alpha));
}
}
du_rect_outline(ctx, x, y, w, h, t->acrylic_stroke, (du_u32)r);
}
/* 投影:外扩 2 圈递减 alpha 描边(比逐像素卷积便宜 100 倍) */
static inline void du_wf_shadow(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 radius,
const wf_theme *t) {
du_u32 base = du_pixel_read(ctx, x, y + h + 2);
for (int i = 2; i >= 1; i--) {
du_u32 alpha = (i == 2) ? 40 : 70;
du_rect_outline(ctx, x - i, y - i, w + 2 * i, h + 2 * i,
du_blend(base, t->shadow, alpha),
radius + (du_u32)i);
}
}
/* 半透明控件蒙层(hover/press 态) */
static inline void du_wf_overlay(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 overlay) {
du_u32 alpha = overlay >> 24;
if (!alpha) return;
for (du_i64 row = 0; row < h; row++)
for (du_i64 col = 0; col < w; col++)
du_pixel(ctx, x + col, y + row,
du_blend(du_pixel_read(ctx, x + col, y + row),
overlay, alpha));
}
/* Bresenham 直线(带厚度 w 像素) */
static inline void du_wf_line(du_context *ctx, du_i64 x0, du_i64 y0,
du_i64 x1, du_i64 y1, du_i64 w, du_u32 color) {
du_i64 dx = (x1 > x0) ? x1 - x0 : x0 - x1;
du_i64 dy = (y1 > y0) ? y1 - y0 : y0 - y1;
du_i64 sx = (x0 < x1) ? 1 : -1;
du_i64 sy = (y0 < y1) ? 1 : -1;
du_i64 err = dx - dy;
du_i64 half = w / 2;
for (;;) {
du_fill_rect(ctx, x0 - half, y0 - half, w, w, color);
if (x0 == x1 && y0 == y1) break;
du_i64 e2 = 2 * err;
if (e2 > -dy) { err -= dy; x0 += sx; }
if (e2 < dx) { err += dx; y0 += sy; }
}
}
/* 圆环:中心 (cx,cy),外半径 r,厚度 s。
* half : 0 全环,1 仅上半(dy<=0),-1 仅下半 */
static inline void du_wf_ring(du_context *ctx, du_i64 cx, du_i64 cy,
du_i64 r, du_i64 s, int half, du_u32 color) {
for (du_i64 dy = -r; dy <= r; dy++) {
if (half == 1 && dy > 0) continue;
if (half == -1 && dy < 0) continue;
for (du_i64 dx = -r; dx <= r; dx++) {
du_i64 d2 = dx * dx + dy * dy;
if (d2 <= r * r && d2 > (r - s) * (r - s))
du_pixel(ctx, cx + dx, cy + dy, color);
}
}
}
/* ===================================================================
* L3 — 组件
* =================================================================== */
/* 按钮态 */
typedef enum { WF_BTN_NORMAL = 0, WF_BTN_HOVER, WF_BTN_PRESS } wf_btn_state;
/* 标准按钮:圆角 4,三态底色,ASCII 标签居中(accent=1 为强调按钮) */
static inline void du_wf_button(du_context *ctx, du_i64 x, du_i64 y, du_i64 w,
const char *label, const wf_theme *t,
wf_btn_state st, int accent) {
du_i64 h = 32;
du_u32 bg = accent ? t->accent : t->acrylic_solid;
du_u32 fg = accent ? t->on_accent : t->text_primary;
if (accent) {
du_fill_rounded_rect(ctx, x, y, w, h, bg, 4);
if (st != WF_BTN_NORMAL)
du_wf_overlay(ctx, x + 1, y + 1, w - 2, h - 2,
(st == WF_BTN_PRESS) ? 0x44FFFFFFu : 0x22FFFFFFu);
} else {
du_fill_rounded_rect(ctx, x, y, w, h, bg, 4);
du_rect_outline(ctx, x, y, w, h, t->control_stroke, 4);
if (st != WF_BTN_NORMAL)
du_wf_overlay(ctx, x + 1, y + 1, w - 2, h - 2,
(st == WF_BTN_PRESS) ? 0x33000000u : 0x22000000u);
}
du_i64 len = 0;
while (label[len]) len++;
du_draw_string(ctx, label,
x + (w - len * (du_i64)DU_ASCII_STEP) / 2,
y + (h - (du_i64)DU_ASCII_CELL_H) / 2,
fg, bg, DU_ASCII_STEP);
}
/* 图标按钮:圆角 4 悬停/按下蒙层(图标由调用方叠加绘制) */
static inline void du_wf_icon_button(du_context *ctx, du_i64 x, du_i64 y,
du_i64 size, const wf_theme *t,
wf_btn_state st) {
(void)t;
if (st == WF_BTN_NORMAL) return;
du_wf_overlay(ctx, x, y, size, size,
(st == WF_BTN_PRESS) ? 0x33000000u : 0x22000000u);
du_rect_outline(ctx, x, y, size, size, 0x33000000u, 4);
}
/* 开关:轨道 40×20 圆角 full + 滑块 */
static inline void du_wf_toggle(du_context *ctx, du_i64 x, du_i64 y,
int on, const wf_theme *t) {
du_u32 track = on ? t->accent : 0xFF8A8A8Au;
du_fill_rounded_rect(ctx, x, y, 40, 20, track, 10);
if (on) du_fill_rounded_rect(ctx, x + 20, y + 2, 16, 16, 0xFFFFFFFFu, 8);
else du_fill_rounded_rect(ctx, x + 4, y + 2, 16, 16, 0xFFFFFFFFu, 8);
}
/* 滑块:细轨 4px 圆头 + 圆形拇指。rect_out 返回可拖拽轨道命中区。 */
static inline void du_wf_slider(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, int val, const wf_theme *t,
int rect_out[4]) {
du_i64 ty = y + 8;
du_fill_rounded_rect(ctx, x, ty, w, 4, t->control_stroke, 2);
du_i64 fw = w * val / 100;
if (fw > 2) du_fill_rounded_rect(ctx, x, ty, fw, 4, t->accent, 2);
du_i64 kx = x + fw - 8;
if (kx < x) kx = x;
if (kx > x + w - 16) kx = x + w - 16;
du_fill_rounded_rect(ctx, kx, y, 16, 16, t->accent, 8);
if (rect_out) {
rect_out[0] = (int)x; rect_out[1] = (int)y - 2;
rect_out[2] = (int)w; rect_out[3] = 20;
}
}
/* 列表项:32px 行高,hover/selected 蒙层 + 左侧 3px accent 条 */
static inline void du_wf_list_item(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const char *label,
const wf_theme *t, int hover, int selected) {
if (selected) du_wf_overlay(ctx, x, y, w, 32, 0x28000000u);
else if (hover) du_wf_overlay(ctx, x, y, w, 32, 0x1A000000u);
if (selected) du_fill_rect(ctx, x, y + 8, 3, 16, t->accent);
du_draw_string(ctx, label, x + 12,
y + (32 - (du_i64)DU_ASCII_CELL_H) / 2,
selected ? t->text_primary : t->text_secondary,
0, DU_ASCII_STEP);
}
/* 卡片:圆角 8 + 投影 + 亚克力 */
static inline void du_wf_card(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 alpha,
const wf_theme *t) {
du_wf_shadow(ctx, x, y, w, h, (du_u32)t->radius_md, t);
du_wf_acrylic(ctx, x, y, w, h, alpha, (du_u32)t->radius_md, t);
}
/* 文本框(搜索框):圆角 4,聚焦时 accent 底边线 + 光标 */
static inline void du_wf_textbox(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const char *text, int cursor_blink,
const wf_theme *t, int focused) {
du_i64 h = 36;
du_fill_rounded_rect(ctx, x, y, w, h, t->acrylic_solid, 4);
du_rect_outline(ctx, x, y, w, h, focused ? t->accent : t->control_stroke, 4);
if (focused) du_fill_rect(ctx, x + 4, y + h - 2, w - 8, 2, t->accent);
du_u32 fg = text[0] ? t->text_primary : t->text_dim;
du_draw_string(ctx, text, x + 12, y + (h - (du_i64)DU_ASCII_CELL_H) / 2,
fg, t->acrylic_solid, DU_ASCII_STEP);
if (focused && cursor_blink) {
du_i64 len = 0;
while (text[len]) len++;
du_fill_rect(ctx, x + 12 + len * (du_i64)DU_ASCII_STEP + 2,
y + 9, 2, (du_i64)DU_ASCII_CELL_H, t->accent);
}
}
/* 滚动条:4px 覆盖式 */
static inline void du_wf_scrollbar(du_context *ctx, du_i64 x, du_i64 y,
du_i64 h, int pos_0_100, int ratio_0_100,
const wf_theme *t) {
if (ratio_0_100 >= 100) return;
du_i64 thumb_h = h * ratio_0_100 / 100;
if (thumb_h < 24) thumb_h = 24;
du_i64 max_travel = h - thumb_h;
du_i64 ty = y + max_travel * pos_0_100 / 100;
du_fill_rounded_rect(ctx, x, ty, 4, thumb_h, t->text_dim, 2);
}
/* 提示(tooltip):小圆角不透明底 */
static inline void du_wf_tooltip(du_context *ctx, du_i64 x, du_i64 y,
const char *label, const wf_theme *t) {
du_i64 len = 0;
while (label[len]) len++;
du_i64 w = len * (du_i64)DU_ASCII_STEP + 16;
du_fill_rounded_rect(ctx, x, y, w, 28, t->acrylic_solid, 4);
du_rect_outline(ctx, x, y, w, 28, t->control_stroke, 4);
du_draw_string(ctx, label, x + 8, y + (28 - (du_i64)DU_ASCII_CELL_H) / 2,
t->text_primary, t->acrylic_solid, DU_ASCII_STEP);
}
/* ============ M3 新增组件(开始菜单/快速设置批次)============ */
/* 复选框:20×20 圆角 4 方框,选中画 accent 对勾 + accent 底 */
static inline void du_wf_checkbox(du_context *ctx, du_i64 x, du_i64 y,
int checked, const wf_theme *t) {
du_fill_rounded_rect(ctx, x, y, 20, 20,
checked ? t->accent : t->acrylic_solid, 4);
du_rect_outline(ctx, x, y, 20, 20,
checked ? t->accent : t->control_stroke, 4);
if (checked) {
du_wf_line(ctx, x + 4, y + 10, x + 8, y + 15, 2, t->on_accent);
du_wf_line(ctx, x + 8, y + 15, x + 16, y + 4, 2, t->on_accent);
}
}
/* 进度条:6px 圆角轨道 + accent 填充(val 0..100) */
static inline void du_wf_progress(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, int val, const wf_theme *t) {
if (val < 0) val = 0;
if (val > 100) val = 100;
du_fill_rounded_rect(ctx, x, y, w, 6, t->control_stroke, 3);
du_i64 fw = w * val / 100;
if (fw < 4) fw = 4;
if (fw > w) fw = w;
du_fill_rounded_rect(ctx, x, y, fw, 6, t->accent, 3);
}
/* 标签页(pill):圆角 full,active 填 accent_secondary 底 */
static inline void du_wf_pill(du_context *ctx, du_i64 x, du_i64 y,
const char *label, const wf_theme *t, int active) {
du_i64 len = 0;
while (label[len]) len++;
du_i64 w = len * (du_i64)DU_ASCII_STEP + 20;
du_fill_rounded_rect(ctx, x, y, w, 26,
active ? t->accent : t->acrylic_solid, 13);
du_draw_string(ctx, label, x + 10, y + (26 - (du_i64)DU_ASCII_CELL_H) / 2,
active ? t->on_accent : t->text_secondary,
active ? t->accent : t->acrylic_solid, DU_ASCII_STEP);
}
/* 分隔线:1px divider */
static inline void du_wf_separator(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const wf_theme *t) {
du_fill_rect(ctx, x, y, w, 1, t->divider);
}
/* 应用瓦片:圆角 8 悬浮底 + 居中图标 + 底部标签区(中文标签由调用方
* zh_draw_string 绘制,ASCII 图标由本组件画)。hover/selected 蒙层。 */
static inline void du_wf_app_tile(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, wf_icon_id icon,
const wf_theme *t, wf_btn_state st,
int selected) {
if (st == WF_BTN_HOVER)
du_wf_overlay(ctx, x, y, w, h, 0x14000000u);
if (selected)
du_wf_overlay(ctx, x, y, w, h, 0x1E000000u);
du_i64 isz = h / 3;
if (isz < 24) isz = 24;
if (isz > 36) isz = 36;
du_wf_icon(ctx, icon, x + (w - isz) / 2, y + (h - isz) / 2 - 8, isz,
selected ? t->accent : t->text_primary);
/* 选中态:底部 3px accent 指示条 */
if (selected)
du_fill_rounded_rect(ctx, x + w / 2 - 8, y + h - 6, 16, 3, t->accent, 1);
}
/* 菜单行:36px 行高 + 左侧图标 + ASCII 标签(右箭头区由调用方补充) */
static inline void du_wf_menu_item(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, wf_icon_id icon, const char *label,
const wf_theme *t, wf_btn_state st) {
if (st == WF_BTN_HOVER)
du_wf_overlay(ctx, x, y, w, 36, 0x14000000u);
du_wf_icon(ctx, icon, x + 10, y + 6, 22, t->text_primary);
du_draw_string(ctx, label, x + 44, y + (36 - (du_i64)DU_ASCII_CELL_H) / 2,
t->text_primary, 0, DU_ASCII_STEP);
}
/* 徽标:8px 圆点(通知/在线状态角标) */
static inline void du_wf_badge(du_context *ctx, du_i64 cx, du_i64 cy,
du_u32 color) {
for (du_i64 dy = -4; dy <= 4; dy++)
for (du_i64 dx = -4; dx <= 4; dx++)
if (dx * dx + dy * dy <= 16)
du_pixel(ctx, cx + dx, cy + dy, color);
}
/* ===================================================================
* L4 — 矢量图标(24 网格设计,线性 2px 笔触,Win11 Segoe 风格)
*
* 所有图标以 (x, y) 为左上角、size 为边长绘制,按 u = size/24 缩放
* (u 为最小单位,笔触 s = 2u)。
* =================================================================== */
typedef enum {
WF_ICON_START = 1, /* 四方块(开始) */
WF_ICON_SEARCH, /* 放大镜 */
WF_ICON_NETWORK, /* WiFi 扇形 */
WF_ICON_VOLUME, /* 喇叭 */
WF_ICON_POWER, /* 电源 */
WF_ICON_TASKMGR, /* 折线图 */
WF_ICON_SETTINGS, /* 齿轮(简化) */
WF_ICON_FOLDER, /* 文件夹 */
WF_ICON_TERMINAL, /* 终端 >_ */
WF_ICON_EDITOR, /* 文档横线 */
WF_ICON_CALC, /* 计算器格子 */
WF_ICON_BROWSER, /* 地球 */
WF_ICON_TASKVIEW, /* 双矩形 */
WF_ICON_WIDGETS, /* 四小件 */
WF_ICON_NOTIFY, /* 铃铛 */
WF_ICON_CLOSE, /* × */
WF_ICON_MIN, /* – */
WF_ICON_MAX, /* □ */
WF_ICON_RESTORE, /* 双层 □ */
WF_ICON_USER, /* 人形 */
/* M3 开始菜单/系统工具批次 */
WF_ICON_APPS, /* 3×3 点阵(应用列表) */
WF_ICON_CLOCK, /* 圆 + 指针 */
WF_ICON_INFO, /* 圆 + i */
WF_ICON_DISK, /* 圆柱(磁盘) */
WF_ICON_PICTURE, /* 山 + 太阳(画板/图片) */
WF_ICON_MUSIC, /* 音符 */
WF_ICON_GAME, /* 手柄 */
WF_ICON_CHIP, /* CPU 芯片 */
WF_ICON_REFRESH, /* 环形箭头 */
WF_ICON_LOCK, /* 挂锁 */
WF_ICON_TRASH, /* 垃圾桶 */
} wf_icon_id;
static inline void du_wf_icon(du_context *ctx, wf_icon_id id,
du_i64 x, du_i64 y, du_i64 size, du_u32 color) {
du_i64 u = size / 24;
if (u < 1) u = 1;
du_i64 s = u * 2; /* 笔触宽 */
switch (id) {
case WF_ICON_START:
du_fill_rounded_rect(ctx, x + 3 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 3 * u, y + 13 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 13 * u, 8 * u, 8 * u, color, (du_u32)u);
break;
case WF_ICON_SEARCH:
du_wf_ring(ctx, x + 10 * u, y + 10 * u, 7 * u, s, 0, color);
du_wf_line(ctx, x + 15 * u, y + 15 * u, x + 20 * u, y + 20 * u, s, color);
break;
case WF_ICON_NETWORK:
du_fill_rounded_rect(ctx, x + 10 * u, y + 17 * u, 3 * u, 3 * u, color, (du_u32)u);
du_wf_ring(ctx, x + 11 * u, y + 19 * u, 6 * u, s, 1, color);
du_wf_ring(ctx, x + 11 * u, y + 21 * u, 10 * u, s, 1, color);
break;
case WF_ICON_VOLUME:
/* 喇叭主体:梯形 */
du_fill_rect(ctx, x + 3 * u, y + 9 * u, 4 * u, 6 * u, color);
du_wf_line(ctx, x + 7 * u, y + 9 * u, x + 11 * u, y + 5 * u, s, color);
du_wf_line(ctx, x + 11 * u, y + 5 * u, x + 11 * u, y + 19 * u, s, color);
du_wf_line(ctx, x + 11 * u, y + 19 * u, x + 7 * u, y + 15 * u, s, color);
/* 声波弧 */
du_wf_ring(ctx, x + 11 * u, y + 12 * u, 7 * u, s, 1, color);
break;
case WF_ICON_POWER:
du_fill_rect(ctx, x + 11 * u, y + 3 * u, s, 8 * u, color);
du_wf_ring(ctx, x + 12 * u, y + 13 * u, 8 * u, s, 0, color);
break;
case WF_ICON_TASKMGR:
du_rect_outline(ctx, x + 2 * u, y + 3 * u, 20 * u, 18 * u, color, (du_u32)u);
du_wf_line(ctx, x + 5 * u, y + 15 * u, x + 9 * u, y + 10 * u, s, color);
du_wf_line(ctx, x + 9 * u, y + 10 * u, x + 13 * u, y + 13 * u, s, color);
du_wf_line(ctx, x + 13 * u, y + 13 * u, x + 19 * u, y + 6 * u, s, color);
break;
case WF_ICON_SETTINGS:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 5 * u, s, 0, color);
for (int i = 0; i < 8; i++) {
/* 8 个齿:每 45° 一个短径向线 */
du_i64 ax[8] = {0, 1, 1, 1, 0, -1, -1, -1};
du_i64 ay[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
du_wf_line(ctx, x + 12 * u + ax[i] * 7 * u, y + 12 * u + ay[i] * 7 * u,
x + 12 * u + ax[i] * 10 * u, y + 12 * u + ay[i] * 10 * u,
s, color);
}
break;
case WF_ICON_FOLDER:
du_fill_rect(ctx, x + 3 * u, y + 6 * u, 7 * u, 3 * u, color);
du_rect_outline(ctx, x + 3 * u, y + 6 * u, 18 * u, 12 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 3 * u, y + 11 * u, 18 * u, u, color);
break;
case WF_ICON_TERMINAL:
du_rect_outline(ctx, x + 2 * u, y + 4 * u, 20 * u, 16 * u, color, (du_u32)u);
du_wf_line(ctx, x + 6 * u, y + 9 * u, x + 10 * u, y + 12 * u, u + 1, color);
du_wf_line(ctx, x + 10 * u, y + 12 * u, x + 6 * u, y + 15 * u, u + 1, color);
du_fill_rect(ctx, x + 12 * u, y + 15 * u, 5 * u, u + 1, color);
break;
case WF_ICON_EDITOR:
du_rect_outline(ctx, x + 5 * u, y + 2 * u, 14 * u, 20 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 8 * u, y + 8 * u, 8 * u, u, color);
du_fill_rect(ctx, x + 8 * u, y + 12 * u, 8 * u, u, color);
du_fill_rect(ctx, x + 8 * u, y + 16 * u, 5 * u, u, color);
break;
case WF_ICON_CALC:
du_rect_outline(ctx, x + 4 * u, y + 2 * u, 16 * u, 20 * u, color, (du_u32)u);
du_rect_outline(ctx, x + 7 * u, y + 5 * u, 10 * u, 4 * u, color, (du_u32)u);
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
du_fill_rect(ctx, x + (7 + c * 4) * u, y + (12 + r * 3) * u,
2 * u, 2 * u, color);
break;
case WF_ICON_BROWSER:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 9 * u, s, 0, color);
du_fill_rect(ctx, x + 3 * u, y + 11 * u, 18 * u, s, color);
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 5 * u, u, 0, 0); /* 清理中圈 */
du_wf_line(ctx, x + 8 * u, y + 4 * u, x + 8 * u, y + 20 * u, u, color);
du_wf_line(ctx, x + 16 * u, y + 4 * u, x + 16 * u, y + 20 * u, u, color);
break;
case WF_ICON_TASKVIEW:
du_rect_outline(ctx, x + 3 * u, y + 5 * u, 13 * u, 11 * u, color, (du_u32)u);
du_rect_outline(ctx, x + 9 * u, y + 8 * u, 12 * u, 11 * u, color, (du_u32)u);
break;
case WF_ICON_WIDGETS:
du_fill_rounded_rect(ctx, x + 3 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 3 * u, y + 13 * u, 5 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 10 * u, y + 13 * u, 11 * u, 8 * u, color, (du_u32)u);
break;
case WF_ICON_NOTIFY:
/* 铃铛:拱顶 + 两侧斜线 + 底线 + 铃锤 */
du_wf_ring(ctx, x + 12 * u, y + 14 * u, 8 * u, s, 1, color);
du_wf_line(ctx, x + 4 * u, y + 14 * u, x + 4 * u, y + 18 * u, s, color);
du_wf_line(ctx, x + 20 * u, y + 14 * u, x + 20 * u, y + 18 * u, s, color);
du_fill_rect(ctx, x + 3 * u, y + 19 * u, 18 * u, s, color);
du_fill_rounded_rect(ctx, x + 10 * u, y + 21 * u, 4 * u, 3 * u, color, (du_u32)u);
break;
case WF_ICON_CLOSE:
du_wf_line(ctx, x + 6 * u, y + 6 * u, x + 18 * u, y + 18 * u, s, color);
du_wf_line(ctx, x + 18 * u, y + 6 * u, x + 6 * u, y + 18 * u, s, color);
break;
case WF_ICON_MIN:
du_fill_rect(ctx, x + 6 * u, y + 11 * u, 12 * u, s, color);
break;
case WF_ICON_MAX:
du_rect_outline(ctx, x + 5 * u, y + 5 * u, 14 * u, 14 * u, color, (du_u32)u);
break;
case WF_ICON_RESTORE:
du_rect_outline(ctx, x + 4 * u, y + 8 * u, 11 * u, 11 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 8 * u, y + 5 * u, 12 * u, s, color);
du_fill_rect(ctx, x + 18 * u, y + 5 * u, s, 6 * u, color);
du_fill_rect(ctx, x + 12 * u, y + 8 * u, 8 * u, u, color);
break;
case WF_ICON_USER:
du_wf_ring(ctx, x + 12 * u, y + 8 * u, 4 * u, s, 0, color);
du_wf_ring(ctx, x + 12 * u, y + 26 * u, 9 * u, s, 1, color);
break;
case WF_ICON_APPS:
for (int gy = 0; gy < 3; gy++)
for (int gx = 0; gx < 3; gx++)
du_fill_rounded_rect(ctx, x + (3 + gx * 7) * u,
y + (3 + gy * 7) * u, 4 * u, 4 * u,
color, (du_u32)u);
break;
case WF_ICON_CLOCK:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 9 * u, s, 0, color);
du_wf_line(ctx, x + 12 * u, y + 12 * u, x + 12 * u, y + 6 * u, u + 1, color);
du_wf_line(ctx, x + 12 * u, y + 12 * u, x + 17 * u, y + 14 * u, u + 1, color);
break;
case WF_ICON_INFO:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 9 * u, s, 0, color);
du_fill_rect(ctx, x + 11 * u, y + 7 * u, s, 5 * u, color);
du_fill_rect(ctx, x + 11 * u, y + 14 * u, s, 4 * u, color);
break;
case WF_ICON_DISK:
/* 圆柱:顶椭圆 + 两侧竖线 + 底弧 */
du_wf_ring(ctx, x + 12 * u, y + 7 * u, 8 * u, s, -1, color);
du_fill_rect(ctx, x + 4 * u, y + 7 * u, s, 10 * u, color);
du_fill_rect(ctx, x + 18 * u, y + 7 * u, s, 10 * u, color);
du_wf_ring(ctx, x + 12 * u, y + 17 * u, 8 * u, s, -1, color);
break;
case WF_ICON_PICTURE:
du_rect_outline(ctx, x + 3 * u, y + 5 * u, 18 * u, 14 * u, color, (du_u32)u);
du_wf_ring(ctx, x + 8 * u, y + 9 * u, u + 1, u + 1, 0, color);
du_wf_line(ctx, x + 5 * u, y + 17 * u, x + 11 * u, y + 11 * u, u + 1, color);
du_wf_line(ctx, x + 11 * u, y + 11 * u, x + 15 * u, y + 15 * u, u + 1, color);
du_wf_line(ctx, x + 15 * u, y + 15 * u, x + 19 * u, y + 9 * u, u + 1, color);
break;
case WF_ICON_MUSIC:
/* 八分音符:符头椭圆 + 符干 + 旗 */
du_fill_rounded_rect(ctx, x + 5 * u, y + 15 * u, 6 * u, 4 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 10 * u, y + 4 * u, s, 12 * u, color);
du_wf_line(ctx, x + 11 * u, y + 4 * u, x + 18 * u, y + 8 * u, s, color);
break;
case WF_ICON_GAME:
du_rect_outline(ctx, x + 2 * u, y + 7 * u, 20 * u, 10 * u, color, (du_u32)(4 * u));
/* 十字键 */
du_fill_rect(ctx, x + 7 * u, y + 9 * u, 2 * u, 6 * u, color);
du_fill_rect(ctx, x + 5 * u, y + 11 * u, 6 * u, 2 * u, color);
/* AB 钮 */
du_wf_ring(ctx, x + 16 * u, y + 12 * u, u + 1, u + 1, 0, color);
du_wf_ring(ctx, x + 19 * u, y + 12 * u, u + 1, u + 1, 0, color);
break;
case WF_ICON_CHIP:
du_rect_outline(ctx, x + 6 * u, y + 6 * u, 12 * u, 12 * u, color, (du_u32)u);
du_rect_outline(ctx, x + 10 * u, y + 10 * u, 4 * u, 4 * u, color, (du_u32)u);
for (int i = 0; i < 3; i++) {
du_fill_rect(ctx, x + (8 + i * 4) * u, y + 2 * u, s, 4 * u, color);
du_fill_rect(ctx, x + (8 + i * 4) * u, y + 18 * u, s, 4 * u, color);
du_fill_rect(ctx, x + 2 * u, y + (8 + i * 4) * u, 4 * u, s, color);
du_fill_rect(ctx, x + 18 * u, y + (8 + i * 4) * u, 4 * u, s, color);
}
break;
case WF_ICON_REFRESH:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 8 * u, s, 1, color);
/* 箭头(右上端点) */
du_wf_line(ctx, x + 16 * u, y + 2 * u, x + 20 * u, y + 7 * u, s, color);
du_wf_line(ctx, x + 20 * u, y + 7 * u, x + 14 * u, y + 8 * u, s, color);
break;
case WF_ICON_LOCK:
du_rect_outline(ctx, x + 5 * u, y + 10 * u, 14 * u, 10 * u, color, (du_u32)u);
du_wf_ring(ctx, x + 12 * u, y + 10 * u, 5 * u, s, 1, color);
du_fill_rect(ctx, x + 11 * u, y + 14 * u, s, 3 * u, color);
break;
case WF_ICON_TRASH:
du_fill_rect(ctx, x + 9 * u, y + 3 * u, 6 * u, s, color);
du_rect_outline(ctx, x + 5 * u, y + 6 * u, 14 * u, 15 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 8 * u, y + 9 * u, s, 9 * u, color);
du_fill_rect(ctx, x + 12 * u, y + 9 * u, s, 9 * u, color);
du_fill_rect(ctx, x + 16 * u, y + 9 * u, s, 9 * u, color);
break;
default:
du_rect_outline(ctx, x + 4 * u, y + 4 * u, 16 * u, 16 * u, color, (du_u32)u);
break;
}
}
#endif /* DESHAB_FLUENT_UI_H */