feat: M6.40批 — 阅读器UI改版(书架list·grid+空态骨架+界面设置+App设置页+header·footer+背景黑默认) + 系统级音量翻页映射 + P1 MD3(select面板28/对话框按钮胶囊) + MeowPanel写端点护栏 + SDK公开仓·文档同步
- reader: app.c/shelf.c/reader.c 全套UI; 新增 reader_conf(reader.conf)/settings(App设置页)/reader_ipc(音量翻页IPC响应); app.json加volume_page - launcher: keys.c meow_volpage_*门 + util.c app_id→fd映射(HELLO记fd/断开清) + app_launcher.c 前台三处接线(进入sink/按键路径volpage_key/离开clear) → 前台声明volume_page的App音量键→MSG_KEY_PAGEUP/PAGEDOWN翻页(非阅读器前台音量照旧) - sdk: meow_select.c 底部面板28 + meow_ui_dialog.c 对话框按钮胶囊(h/2) + test_meow_ui_select.c修采样 - meowpanel: /api/net/policy·/api/power/policy 加防自锁+policy默认关两条护栏(panel.policy_enabled默认0) - 文档: MEOW_APP_SDK.md §12.6 + meowpanel README端点表 0warning;宿主测试全过;二进制留批量批次未入库
This commit is contained in:
1 parent
b364b6371a
commit
2826c1e905
27 files changed
+1704
-129
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include "meow_ui_internal.h" /* back_buf/pitch/bpp 访问器(决策见报告) */
|
||||
#include "book.h"
|
||||
#include "progress.h"
|
||||
#include "reader_conf.h"
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -17,7 +18,10 @@
|
||||
#include <time.h>
|
||||
|
||||
#define RD_MENU_H 64
|
||||
#define RD_MENU_BTN 7
|
||||
#define RD_MENU_BTN 4 /* 返回 | 目录 | 界面 | 设置(MVP 单条) */
|
||||
#define RD_HEADER_H 30 /* 页头条高(书名+章节名) */
|
||||
#define RD_FOOT_H 18 /* 页底条高(章节+页码) */
|
||||
#define RD_UI_H 268 /* 「界面」排版面板高 */
|
||||
|
||||
static rd_book *g_book;
|
||||
static int g_reader_active;
|
||||
@@ -29,6 +33,7 @@ static int g_fs, g_ls;
|
||||
static uint16_t *g_page_buf[RD_PAGE_CACHE]; /* [0]=prev [1]=cur [2]=next(FreeType 页位图) */
|
||||
static int g_has_font; /* 1=FreeType 路径;0=SDK 字库兜底 */
|
||||
static int g_menu_open;
|
||||
static int g_ui_open; /* 「界面」排版面板(B) */
|
||||
static int g_dir_open; /* 目录覆盖层 */
|
||||
static int g_dir_top, g_dir_row_h; /* 目录列表几何(rdsrc 目录项) */
|
||||
static char g_font_path[400];
|
||||
@@ -49,6 +54,8 @@ static int g_enc_idx; /* g_enc_cycle[] 下标(当前有效
|
||||
|
||||
static uint32_t g_page_bg, g_page_fg; /* 正文页底/字色(24bit) */
|
||||
static char g_chapter[128]; /* 顶栏章节名(TXT 无章节=文件名) */
|
||||
static int g_show_header, g_show_footer; /* 页头条/底条显隐(rdconf.rd.header/footer) */
|
||||
static volatile int g_volpage_pending; /* 系统翻页信号待消费(IPC 线程置位,UI tick 消费,E) */
|
||||
|
||||
#define RD_READER_DEFAULT_FS 20
|
||||
#define RD_READER_DEFAULT_LS 130
|
||||
@@ -87,6 +94,41 @@ static uint16_t rgb565(uint32_t c)
|
||||
return (uint16_t)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
|
||||
}
|
||||
|
||||
/* 按 rdconf.bg/theme 解析阅读页底/字色(默认纯黑,B 定案)。 */
|
||||
static void reader_resolve_bg(uint32_t *bg, uint32_t *fg)
|
||||
{
|
||||
const rdconf *c = rdconf_get();
|
||||
if (!c) { *bg = 0x000000; *fg = 0x9AA4C8; return; }
|
||||
if (strcmp(c->bg, "black") == 0) { *bg = 0x000000; *fg = 0x9AA4C8; return; }
|
||||
if (strcmp(c->bg, "white") == 0) { *bg = 0xFFFFFF; *fg = 0x1A1A2A; return; }
|
||||
if (strcmp(c->bg, "sepia") == 0) { *bg = 0xF5EFDC; *fg = 0x3B3A32; return; }
|
||||
/* auto:跟随主题(rd.theme=light/dark 时强制该明暗的 surface/onSurface) */
|
||||
meow_theme_mode m = MEOW_THEME_AUTO;
|
||||
if (strcmp(c->theme, "light") == 0) m = MEOW_THEME_LIGHT;
|
||||
else if (strcmp(c->theme, "dark") == 0) m = MEOW_THEME_DARK;
|
||||
if (m == MEOW_THEME_AUTO) {
|
||||
const meow_theme *th = meow_theme_get();
|
||||
*bg = th->surface; *fg = th->onSurface;
|
||||
} else {
|
||||
meow_theme t = meow_theme_defaults(m);
|
||||
*bg = t.surface; *fg = t.onSurface;
|
||||
}
|
||||
}
|
||||
|
||||
/* 「界面」面板改背景(写 rdconf.bg + 重解析颜色 + 重排版页缓冲)。 */
|
||||
static void reader_set_bg(const char *bg)
|
||||
{
|
||||
rdconf *c = rdconf_get();
|
||||
if (!c) return;
|
||||
strncpy(c->bg, bg, sizeof c->bg - 1); c->bg[sizeof c->bg - 1] = 0;
|
||||
if (strcmp(c->bg, "black") && strcmp(c->bg, "white") &&
|
||||
strcmp(c->bg, "sepia") && strcmp(c->bg, "auto")) strcpy(c->bg, "black");
|
||||
rdconf_persist();
|
||||
reader_resolve_bg(&g_page_bg, &g_page_fg);
|
||||
reader_refill_page();
|
||||
reader_redraw();
|
||||
}
|
||||
|
||||
/* 递归(深度≤3)扫 MeowOS/fonts/ 找第一个 .otf/.ttf。0=找到。 */
|
||||
static int find_font_rec(const char *dir, int depth)
|
||||
{
|
||||
@@ -220,6 +262,152 @@ static void reader_draw_scrub(const meow_theme *th)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------「界面」排版面板(B:字号/行距/背景/顶底栏/编码) ----------------
|
||||
* 自绘 + 自制命中(README §5.2 建议:W_CUSTOM 画布 + 自制 hit,零 SDK widget 协同)。
|
||||
* 几何 draw/hit 共用(常量)。 */
|
||||
#define UI_LABEL_X 20
|
||||
#define UI_CTRL_X 130
|
||||
#define UI_CTRL_W (480 - UI_CTRL_X - 16)
|
||||
#define UI_ROW_H 34
|
||||
static int ui_panel_y(void) { return g_ph - RD_UI_H; }
|
||||
|
||||
/* 单个「值按钮」:[-]/[+] 或文本钮。cx=控件区起点;返回该按钮中点 x。 */
|
||||
static void ui_draw_step(int x, int w, int y, const char *tag, int active, const meow_theme *th)
|
||||
{
|
||||
if (active) meow_ui_fill_rect(x, y, w, 28, th->primaryContainer);
|
||||
else meow_ui_fill_rect(x, y, w, 28, th->surfaceContainerHighest);
|
||||
uint32_t tc = active ? th->onPrimaryContainer : th->fg;
|
||||
meow_ui_text_center(x + w / 2, y + 4, tag, 20, tc);
|
||||
}
|
||||
static void ui_draw_chips(const char *const *labels, int n, int cur, int x, int y, int w, const meow_theme *th)
|
||||
{
|
||||
int gap = 4;
|
||||
int cw = (w - (n - 1) * gap) / n;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int cx = x + i * (cw + gap);
|
||||
if (i == cur) meow_gfx_fill_round(cx, y, cw, 28, 14, th->primaryContainer);
|
||||
else meow_gfx_fill_round(cx, y, cw, 28, 14, th->surfaceContainerHighest);
|
||||
uint32_t tc = (i == cur) ? th->onPrimaryContainer : th->fg;
|
||||
meow_ui_text_center(cx + cw / 2, y + 4, labels[i], 20, tc);
|
||||
}
|
||||
}
|
||||
|
||||
static void reader_draw_ui_panel(const meow_theme *th)
|
||||
{
|
||||
int y0 = ui_panel_y();
|
||||
int top = y0 + 30;
|
||||
int ry;
|
||||
const rdconf *c = rdconf_get();
|
||||
/* 面板底 + scrim */
|
||||
meow_ui_fill_rect_alpha(0, g_top, g_pw, g_ph - g_top, 0x000000, 150);
|
||||
meow_ui_fill_rect(0, y0, g_pw, RD_UI_H, th->surfaceContainer);
|
||||
meow_ui_draw_rect(0, y0, g_pw, 1, th->outlineVariant);
|
||||
meow_ui_text_center(240, y0 + 5, "界面 · 排版", 20, th->fg);
|
||||
|
||||
/* 0 字号 */
|
||||
ry = top + 0 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "字号", 20, th->fg);
|
||||
char v[16]; snprintf(v, sizeof v, "%d", g_fs);
|
||||
ui_draw_step(UI_CTRL_X, 40, ry + 3, "-", 0, th);
|
||||
meow_ui_text_center(UI_CTRL_X + 40 + (UI_CTRL_W - 80) / 2, ry + 6, v, 20, th->fg);
|
||||
ui_draw_step(UI_CTRL_X + UI_CTRL_W - 40, 40, ry + 3, "+", 0, th);
|
||||
|
||||
/* 1 行距 */
|
||||
ry = top + 1 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "行距", 20, th->fg);
|
||||
snprintf(v, sizeof v, "%d", g_ls);
|
||||
ui_draw_step(UI_CTRL_X, 40, ry + 3, "-", 0, th);
|
||||
meow_ui_text_center(UI_CTRL_X + 40 + (UI_CTRL_W - 80) / 2, ry + 6, v, 20, th->fg);
|
||||
ui_draw_step(UI_CTRL_X + UI_CTRL_W - 40, 40, ry + 3, "+", 0, th);
|
||||
|
||||
/* 2 背景(4 档:黑/白/米黄/自动;当前=标亮) */
|
||||
ry = top + 2 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "背景", 20, th->fg);
|
||||
static const char *bg_lbl[4] = { "黑", "白", "米黄", "自动" };
|
||||
int bgcur = 0;
|
||||
if (c) { if (!strcmp(c->bg, "white")) bgcur = 1; else if (!strcmp(c->bg, "sepia")) bgcur = 2;
|
||||
else if (!strcmp(c->bg, "auto")) bgcur = 3; }
|
||||
ui_draw_chips(bg_lbl, 4, bgcur, UI_CTRL_X, ry + 3, UI_CTRL_W, th);
|
||||
|
||||
/* 3 顶栏显隐(开/关) */
|
||||
ry = top + 3 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "顶栏", 20, th->fg);
|
||||
static const char *yn[2] = { "开", "关" };
|
||||
ui_draw_chips(yn, 2, g_show_header ? 0 : 1, UI_CTRL_X, ry + 3, UI_CTRL_W, th);
|
||||
|
||||
/* 4 底栏显隐 */
|
||||
ry = top + 4 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "底栏", 20, th->fg);
|
||||
ui_draw_chips(yn, 2, g_show_footer ? 0 : 1, UI_CTRL_X, ry + 3, UI_CTRL_W, th);
|
||||
|
||||
/* 5 编码(TXT;显示当前,点循环) */
|
||||
ry = top + 5 * UI_ROW_H;
|
||||
meow_ui_text(UI_LABEL_X, ry + 6, "编码", 20, th->fg);
|
||||
if (g_book && !rd_book_is_image(g_book)) {
|
||||
ui_draw_step(UI_CTRL_X + UI_CTRL_W - 120, 120, ry + 3, enc_cycle_name(g_enc_idx), 0, th);
|
||||
} else {
|
||||
meow_ui_text(UI_CTRL_X, ry + 6, "—", 20, th->dim);
|
||||
}
|
||||
|
||||
/* 6 返回阅读 */
|
||||
ry = top + 6 * UI_ROW_H;
|
||||
ui_draw_step(UI_CTRL_X, UI_CTRL_W, ry + 2, "返回阅读", 1, th);
|
||||
}
|
||||
|
||||
/* 「界面」面板命中;返回动作码(见下方 enum)。0=无。 */
|
||||
enum {
|
||||
UI_NONE = 0, UI_FS_DEC, UI_FS_INC, UI_LS_DEC, UI_LS_INC,
|
||||
UI_BG_0, UI_BG_1, UI_BG_2, UI_BG_3, UI_HDR_TOGGLE, UI_FTR_TOGGLE, UI_ENC, UI_CLOSE
|
||||
};
|
||||
static int reader_ui_hit(int x, int y)
|
||||
{
|
||||
int y0 = ui_panel_y();
|
||||
if (y < y0) return UI_NONE;
|
||||
int top = y0 + 30;
|
||||
int ry;
|
||||
int cx = UI_CTRL_X, cw = UI_CTRL_W;
|
||||
/* 0 字号 */
|
||||
ry = top + 0 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H) {
|
||||
if (x >= cx && x < cx + 40) return UI_FS_DEC;
|
||||
if (x >= cx + cw - 40 && x < cx + cw) return UI_FS_INC;
|
||||
return UI_NONE;
|
||||
}
|
||||
/* 1 行距 */
|
||||
ry = top + 1 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H) {
|
||||
if (x >= cx && x < cx + 40) return UI_LS_DEC;
|
||||
if (x >= cx + cw - 40 && x < cx + cw) return UI_LS_INC;
|
||||
return UI_NONE;
|
||||
}
|
||||
/* 2 背景 4 chips */
|
||||
ry = top + 2 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H && x >= cx && x < cx + cw) {
|
||||
int gap = 4, cwp = (cw - 3 * gap) / 4;
|
||||
int k = (x - cx) / (cwp + gap);
|
||||
if (k < 0) k = 0;
|
||||
if (k > 3) k = 3;
|
||||
return UI_BG_0 + k;
|
||||
}
|
||||
/* 3 顶栏 */
|
||||
ry = top + 3 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H && x >= cx && x < cx + cw)
|
||||
return UI_HDR_TOGGLE;
|
||||
/* 4 底栏 */
|
||||
ry = top + 4 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H && x >= cx && x < cx + cw)
|
||||
return UI_FTR_TOGGLE;
|
||||
/* 5 编码 */
|
||||
ry = top + 5 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H && x >= cx && x < cx + cw)
|
||||
return UI_ENC;
|
||||
/* 6 返回阅读 */
|
||||
ry = top + 6 * UI_ROW_H;
|
||||
if (y >= ry && y < ry + UI_ROW_H && x >= cx && x < cx + cw)
|
||||
return UI_CLOSE;
|
||||
return UI_NONE;
|
||||
}
|
||||
|
||||
static void reader_canvas_render(meow_widget *w, const meow_theme *th, void *ctx)
|
||||
{
|
||||
(void)w; (void)ctx;
|
||||
@@ -233,40 +421,44 @@ static void reader_canvas_render(meow_widget *w, const meow_theme *th, void *ctx
|
||||
rd_book_render_text(g_book, page, reader_draw_line_atlas, NULL);
|
||||
}
|
||||
}
|
||||
/* 顶栏:章节名 + 页 n/N + 进度% + (TXT)编码 */
|
||||
/* 页头条(书名 + 章节名;可选,rd.header) */
|
||||
int sbh = meow_ui_statusbar_height();
|
||||
int pages = g_book ? rd_book_pages(g_book) : 0;
|
||||
int page = g_book ? rd_book_current(g_book) : 0;
|
||||
char right[40];
|
||||
int p = pages > 0 ? (page * 100 / pages) : 0;
|
||||
if (pages > 0) snprintf(right, sizeof right, "%d/%d %d%%", page + 1, pages, p);
|
||||
else snprintf(right, sizeof right, "%d%%", p);
|
||||
meow_ui_fill_rect(0, sbh, g_pw, (g_top - 4 - sbh), g_page_bg);
|
||||
meow_ui_text(16, sbh + 4, g_chapter[0] ? g_chapter : "阅读", 20, th->fg);
|
||||
meow_ui_text_right(g_pw - 16, sbh + 4, right, 20, th->fg);
|
||||
meow_ui_draw_rect(0, g_top - 5, g_pw, 1, th->outline);
|
||||
const char *bk = g_book ? rd_book_basename(g_book) : "阅读";
|
||||
if (g_show_header) {
|
||||
meow_ui_fill_rect(0, sbh, g_pw, RD_HEADER_H, g_page_bg);
|
||||
meow_ui_text(16, sbh + 6, bk, 16, g_page_fg);
|
||||
meow_ui_text_right(g_pw - 16, sbh + 6, g_chapter[0] ? g_chapter : "阅读", 16, g_page_fg);
|
||||
meow_ui_draw_rect(0, sbh + RD_HEADER_H - 1, g_pw, 1, th->outlineVariant);
|
||||
}
|
||||
/* 页底条(章节 + 页码;可选,rd.footer) */
|
||||
if (g_show_footer) {
|
||||
char ft[48];
|
||||
if (pages > 0) snprintf(ft, sizeof ft, "%d/%d", page + 1, pages);
|
||||
else snprintf(ft, sizeof ft, "0/0");
|
||||
int fy = g_ph - RD_FOOT_H;
|
||||
meow_ui_fill_rect(0, fy, g_pw, RD_FOOT_H, g_page_bg);
|
||||
meow_ui_text(16, fy + 1, g_chapter[0] ? g_chapter : bk, 16, g_page_fg);
|
||||
meow_ui_text_right(g_pw - 16, fy + 1, ft, 16, g_page_fg);
|
||||
}
|
||||
|
||||
/* R3 刮擦指示条(非目录覆盖时显示;菜单为底部条,与右缘条并存即可) */
|
||||
if (g_book && !g_dir_open) reader_draw_scrub(th);
|
||||
/* R3 刮擦指示条(非目录/面板覆盖时显示;菜单为底部条,与右缘条并存即可) */
|
||||
if (g_book && !g_dir_open && !g_ui_open) reader_draw_scrub(th);
|
||||
|
||||
if (g_menu_open) {
|
||||
int y = g_ph - RD_MENU_H;
|
||||
meow_ui_fill_rect_alpha(0, y, g_pw, RD_MENU_H, 0x000000, 160);
|
||||
/* 当前编码提示(菜单上方淡条;仅文本类书有意义) */
|
||||
if (g_book && !rd_book_is_image(g_book)) {
|
||||
char en[64]; snprintf(en, sizeof en, "编码:%s", enc_cycle_name(g_enc_idx));
|
||||
meow_ui_fill_rect_alpha(0, y - 26, g_pw, 24, 0x000000, 130);
|
||||
meow_ui_text_right(g_pw - 16, y - 22, en, 16, th->dim);
|
||||
}
|
||||
/* 7 按钮:返回 | 目录 | 字− | 字+ | 距− | 距+ | 编码 */
|
||||
/* 4 按钮(MVP 单条):返回 | 目录 | 界面 | 设置 */
|
||||
int bw = g_pw / RD_MENU_BTN;
|
||||
const char *labels[RD_MENU_BTN] = { "返回", "目录", "字-", "字+", "距-", "距+", "编码" };
|
||||
const char *labels[RD_MENU_BTN] = { "返回", "目录", "界面", "设置" };
|
||||
for (int i = 0; i < RD_MENU_BTN; i++) {
|
||||
int bx = i * bw;
|
||||
meow_ui_fill_rect(bx + 4, y + 12, bw - 8, RD_MENU_H - 24, th->surfaceContainer);
|
||||
meow_ui_text_center(bx + bw / 2, y + (RD_MENU_H - 20) / 2 - 6, labels[i], 20, th->fg);
|
||||
meow_ui_text_center(bx + bw / 2, y + (RD_MENU_H - 20) / 2, labels[i], 20, th->fg);
|
||||
}
|
||||
}
|
||||
if (g_ui_open && g_book) reader_draw_ui_panel(th);
|
||||
if (g_dir_open && g_book) {
|
||||
/* 目录覆盖层:半透明底 + 条目列表(当前行高亮) */
|
||||
int n = rd_book_toc_n(g_book);
|
||||
@@ -389,28 +581,28 @@ static void reader_scrub_jump(int page)
|
||||
reader_redraw(); /* 整页落定:正文 + 顶栏 + 刮擦条 */
|
||||
reader_reflow_persist();
|
||||
}
|
||||
/* 拖动中局部重绘(不动正文页,仅顶栏 n/N + 右缘条/预览)。内容页保持(预览语义)。 */
|
||||
/* 拖动中局部重绘(不动正文页,仅页底页码 + 右缘条/预览)。内容页保持(预览语义)。 */
|
||||
static void reader_scrub_preview(int page)
|
||||
{
|
||||
g_scrub_page = page;
|
||||
if (!g_book) return;
|
||||
const meow_theme *th = meow_theme_get();
|
||||
int sbh = meow_ui_statusbar_height();
|
||||
int pages = rd_book_pages(g_book);
|
||||
int y0 = rect_y0(), y1 = rect_y1();
|
||||
char right[40];
|
||||
int p = pages > 0 ? (g_scrub_page * 100 / pages) : 0;
|
||||
if (pages > 0) snprintf(right, sizeof right, "%d/%d %d%%", g_scrub_page + 1, pages, p);
|
||||
else snprintf(right, sizeof right, "%d%%", p);
|
||||
/* 顶栏重画 */
|
||||
meow_ui_fill_rect(0, sbh, g_pw, (g_top - 4 - sbh), g_page_bg);
|
||||
meow_ui_text(16, sbh + 4, g_chapter[0] ? g_chapter : "阅读", 20, th->fg);
|
||||
meow_ui_text_right(g_pw - 16, sbh + 4, right, 20, th->fg);
|
||||
meow_ui_draw_rect(0, g_top - 5, g_pw, 1, th->outline);
|
||||
char ft[48];
|
||||
if (pages > 0) snprintf(ft, sizeof ft, "%d/%d", g_scrub_page + 1, pages);
|
||||
else snprintf(ft, sizeof ft, "0/0");
|
||||
/* 页底条页码重画(页码已移到底条) */
|
||||
if (g_show_footer) {
|
||||
int fy = g_ph - RD_FOOT_H;
|
||||
meow_ui_fill_rect(0, fy, g_pw, RD_FOOT_H, g_page_bg);
|
||||
meow_ui_text(16, fy + 1, g_chapter[0] ? g_chapter : "阅读", 16, g_page_fg);
|
||||
meow_ui_text_right(g_pw - 16, fy + 1, ft, 16, g_page_fg);
|
||||
}
|
||||
/* 右缘条区清残留(恢复页面内容)再画条 + 预览框;无页位图(字库兜底)则跳过恢复 */
|
||||
if (g_page_buf[RD_PAGE_SLOT_CUR]) blit_sub(g_page_buf[RD_PAGE_SLOT_CUR], g_pw - 120, y0, 120, y1 - y0);
|
||||
reader_draw_scrub(th);
|
||||
meow_ui_flush_region(0, sbh, g_pw, g_top - sbh);
|
||||
if (g_show_footer) meow_ui_flush_region(0, g_ph - RD_FOOT_H, g_pw, RD_FOOT_H);
|
||||
meow_ui_flush_region(g_pw - 120, y0, 120, y1 - y0);
|
||||
}
|
||||
static void reader_scrub_begin(int x, int y)
|
||||
@@ -435,7 +627,13 @@ void reader_open(const char *path)
|
||||
|
||||
const char *fp = resolve_font();
|
||||
g_has_font = (fp != NULL);
|
||||
g_fs = RD_READER_DEFAULT_FS; g_ls = RD_READER_DEFAULT_LS;
|
||||
|
||||
/* 全局默认字号/行距(reader.conf;进度里的每书偏好随后覆盖) */
|
||||
const rdconf *rdc = rdconf_get();
|
||||
g_fs = (rdc && rdc->fs >= 14 && rdc->fs <= 40) ? rdc->fs : RD_READER_DEFAULT_FS;
|
||||
g_ls = (rdc && rdc->ls >= 100 && rdc->ls <= 200) ? rdc->ls : RD_READER_DEFAULT_LS;
|
||||
g_show_header = rdc ? (rdc->header ? 1 : 0) : 1;
|
||||
g_show_footer = rdc ? (rdc->footer ? 1 : 0) : 1;
|
||||
|
||||
/* 进度(含字号/行距偏好) */
|
||||
rdprog prog;
|
||||
@@ -444,10 +642,10 @@ void reader_open(const char *path)
|
||||
|
||||
int sbh = meow_ui_statusbar_height();
|
||||
g_pw = meow_ui_width(); g_ph = meow_ui_height();
|
||||
g_top = sbh + 34; g_mx = 16; g_my = 20;
|
||||
g_top = sbh + RD_HEADER_H; g_mx = 16; g_my = 20;
|
||||
|
||||
const meow_theme *th = meow_theme_get();
|
||||
g_page_bg = th->surface; g_page_fg = th->onSurface;
|
||||
/* 阅读页底/字色:rd.bg(默认纯黑,B)→ 覆盖 th->surface */
|
||||
reader_resolve_bg(&g_page_bg, &g_page_fg);
|
||||
|
||||
/* 开书(FreeType 路径带齐几何;无字体则 g_has_font=0 → atlas 兜底) */
|
||||
int rc = rd_book_open(&g_book, path, fp, g_fs, g_ls, g_pw, g_ph, g_mx, g_my, g_top);
|
||||
@@ -469,7 +667,7 @@ void reader_open(const char *path)
|
||||
|
||||
/* 复位动画/刮擦状态(跨书) */
|
||||
if (g_anim) { meow_anim_cancel(g_anim); g_anim = NULL; }
|
||||
g_scrub = 0; g_menu_open = 0; g_dir_open = 0;
|
||||
g_scrub = 0; g_menu_open = 0; g_dir_open = 0; g_ui_open = 0;
|
||||
|
||||
/* 编码:初始 = 打开探测结果;进度里的显式编码(Big5 用户选定)优先重开 */
|
||||
if (g_book && !rd_book_is_image(g_book)) {
|
||||
@@ -517,7 +715,7 @@ static void reader_on_destroy(meow_view *v, void *ctx)
|
||||
if (g_book) rd_book_close(g_book);
|
||||
g_book = NULL;
|
||||
reader_free_page_bufs();
|
||||
g_menu_open = 0; g_dir_open = 0; g_scrub = 0; g_reader_active = 0;
|
||||
g_menu_open = 0; g_dir_open = 0; g_ui_open = 0; g_scrub = 0; g_reader_active = 0;
|
||||
}
|
||||
|
||||
meow_view *reader_view_create(void)
|
||||
@@ -565,6 +763,44 @@ void reader_on_tap(int x, int y)
|
||||
g_dir_open = 0; reader_redraw();
|
||||
return;
|
||||
}
|
||||
if (g_ui_open) {
|
||||
int a = reader_ui_hit(x, y);
|
||||
switch (a) {
|
||||
case UI_FS_DEC: if (g_fs > 14) { g_fs -= 2; reader_reflow(); } break;
|
||||
case UI_FS_INC: if (g_fs < 40) { g_fs += 2; reader_reflow(); } break;
|
||||
case UI_LS_DEC: if (g_ls > 100) { g_ls -= 5; reader_reflow(); } break;
|
||||
case UI_LS_INC: if (g_ls < 200) { g_ls += 5; reader_reflow(); } break;
|
||||
case UI_BG_0: reader_set_bg("black"); break;
|
||||
case UI_BG_1: reader_set_bg("white"); break;
|
||||
case UI_BG_2: reader_set_bg("sepia"); break;
|
||||
case UI_BG_3: reader_set_bg("auto"); break;
|
||||
case UI_HDR_TOGGLE:
|
||||
g_show_header = !g_show_header;
|
||||
if (rdconf_get()) { rdconf_get()->header = g_show_header; rdconf_persist(); }
|
||||
reader_redraw();
|
||||
break;
|
||||
case UI_FTR_TOGGLE:
|
||||
g_show_footer = !g_show_footer;
|
||||
if (rdconf_get()) { rdconf_get()->footer = g_show_footer; rdconf_persist(); }
|
||||
reader_redraw();
|
||||
break;
|
||||
case UI_ENC: /* 编码切换(TXT/Big5 繁体书) */
|
||||
if (g_book && !rd_book_is_image(g_book)) {
|
||||
int ni = (g_enc_idx + 1) % RD_ENC_CYCLE_N;
|
||||
if (rd_book_set_enc(g_book, g_enc_cycle[ni]) == 0) {
|
||||
g_enc_idx = ni;
|
||||
chapter_name();
|
||||
reader_refill_page();
|
||||
reader_redraw();
|
||||
reader_reflow_persist();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UI_CLOSE: g_ui_open = 0; reader_redraw(); break;
|
||||
default: if (a == UI_NONE) { g_ui_open = 0; reader_redraw(); } break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (g_menu_open) {
|
||||
/* 菜单按钮命中 */
|
||||
int y0 = g_ph - RD_MENU_H;
|
||||
@@ -581,22 +817,13 @@ void reader_on_tap(int x, int y)
|
||||
if (rd_book_toc_n(g_book) > 0) { g_dir_open = 1; g_menu_open = 0; reader_redraw(); }
|
||||
else { g_menu_open = 0; reader_redraw(); }
|
||||
return;
|
||||
case 2: if (g_fs > 14) { g_fs -= 2; reader_reflow(); } break;
|
||||
case 3: if (g_fs < 40) { g_fs += 2; reader_reflow(); } break;
|
||||
case 4: if (g_ls > 100) { g_ls -= 5; reader_reflow(); } break;
|
||||
case 5: if (g_ls < 200) { g_ls += 5; reader_reflow(); } break;
|
||||
case 6: /* 编码切换(TXT/Big5 繁体书) */
|
||||
if (g_book && !rd_book_is_image(g_book)) {
|
||||
int ni = (g_enc_idx + 1) % RD_ENC_CYCLE_N;
|
||||
if (rd_book_set_enc(g_book, g_enc_cycle[ni]) == 0) {
|
||||
g_enc_idx = ni;
|
||||
chapter_name();
|
||||
reader_refill_page();
|
||||
reader_redraw();
|
||||
reader_reflow_persist();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: /* 界面(阅读排版设置) */
|
||||
g_ui_open = 1; g_menu_open = 0; reader_redraw();
|
||||
return;
|
||||
case 3: /* 设置 → App 设置页 */
|
||||
reader_reflow_persist();
|
||||
meow_view_page_push(ACT_SETTINGS);
|
||||
return;
|
||||
}
|
||||
if (y >= y0) return;
|
||||
}
|
||||
@@ -615,6 +842,7 @@ void reader_on_swipe(int dir, int dx, int dy)
|
||||
(void)dx; (void)dy;
|
||||
if (!g_book) return;
|
||||
if (g_scrub) g_scrub = 0; /* 刮擦中被滑走 → 退出刮擦 */
|
||||
if (g_ui_open) { g_ui_open = 0; reader_redraw(); return; }
|
||||
if (g_menu_open) { g_menu_open = 0; reader_redraw(); return; }
|
||||
if (dir == MEOW_SWIPE_LEFT) reader_turn_animated(1);
|
||||
else if (dir == MEOW_SWIPE_RIGHT) reader_turn_animated(-1);
|
||||
@@ -628,8 +856,24 @@ void reader_on_touch_move(int x, int y)
|
||||
if (g_scrub && g_book) reader_scrub_preview(scrub_page_for_y(y));
|
||||
}
|
||||
|
||||
/* 系统翻页信号(E):reader_ipc 线程收到 MSG_KEY_PAGEUP/PAGEDOWN 后置 pending 计数;
|
||||
* 真正翻页在 UI 线程 reader_on_tick 消费(避免跨线程直接改页面状态)。 */
|
||||
void reader_page_key(int dir)
|
||||
{
|
||||
int p = g_volpage_pending + dir;
|
||||
if (p > 2) p = 2;
|
||||
if (p < -2) p = -2;
|
||||
g_volpage_pending = p;
|
||||
}
|
||||
|
||||
void reader_on_tick(uint64_t now)
|
||||
{
|
||||
(void)now;
|
||||
if (g_volpage_pending) {
|
||||
int dir = g_volpage_pending > 0 ? 1 : -1;
|
||||
g_volpage_pending = 0;
|
||||
if (g_book && !g_menu_open && !g_dir_open && !g_ui_open)
|
||||
reader_turn_animated(dir);
|
||||
}
|
||||
if (g_notice_ms > 0) { g_notice_ms--; if (g_notice_ms == 0) reader_redraw(); }
|
||||
}
|
||||
Reference in new issue
Block a user