feat(tuku): 阅读器左右翻页核心——页源契约/预解码窗口/跟手翻页/方向感知 tap
- 页源契约(logic/reader):count/meta/open/close + 目录册(文件夹即书)为第一个实现; meta 由纯 C 图片头探测(PNG IHDR/JPEG SOF/BMP)提供原始尺寸,条漫可先排版再取图, zip 册(M9/M11)只需另写 mr_book_ops,两种消费方式零改动复用 - 翻页引擎:pthread 后台解码窗口=当前±1 页(目录册 downscale 到屏幕长边),翻页只 blit 缓存页图 + meow_anim 150ms 滑动吸附;未命中立即切页显示加载态、不在翻页路径解码; 只 flush 内容区;decode/flip 首帧/翻页完成/进出内存全部 meow_log 打点 - 阅读页 UI:fit 三档(适宽/适高/原始,TopAppBar 动作循环,标题显示页码 x/y)+ 双击以点击点为锚放大(临时缓冲超上限自动降倍率)+ 单指拖拽/滑动步进平移; tap 三分区方向感知(RTL 默认:左=下一页,LTR 反之),中区切 chrome; 左缘返回交给 app.c、屏底热区交给 SDK 回桌面,两者都不拦截 - 跟手:app.c 仅补 2 处极小路由(ACT_READER 的 down/move),reader 自行算位移; 屏底 28px/左缘 24px 不进拖动,竖向主导放弃横滑 - 内存纪律:驻留 ≤3 张 downscale 页图;放大时窗口收缩到当前页;on_leave 停解码线程、 释放全部页图/册索引/TopAppBar,并记录 VmRSS/MemAvailable 前后对比 - 测试/构建:新增 test_reader_core(契约边界/空册/越界/重复 open-close/首末页/头探测/ 方向语义/fit/平移夹取,108 项);run_tests.sh 与 build_tuku.sh 源列表接线; 宿主 46+108 全 PASS,交叉构建静态 MIPS32r2 ELF、-Wall -Wextra 零警告
This commit is contained in:
1 parent
28b67a7b8d
commit
23c9db73df
10 files changed
+2088
-69
No files matched your search
@@ -0,0 +1,91 @@
|
||||
/* logic/reader/page_source.h — 页源契约(纯 C,不依赖 meow_ui.h)。
|
||||
*
|
||||
* 一册 = 有序页序列。契约只有四件事:
|
||||
* count 总页数
|
||||
* meta(i) 页的原始像素尺寸(可选;条漫连续滚动先用它排版,未知时返回 0)
|
||||
* open(i) 取第 i 页:解码 + downscale 后返回 meow_img*(调用方拥有,必须 close)
|
||||
* close(img) 释放 open 返回的图像
|
||||
*
|
||||
* 两种消费方式共用同一契约,后续实现零改动:
|
||||
* - 左右翻页(本任务):预解码窗口 = 当前 ±1 页,翻页只 blit 窗口内已备好的图;
|
||||
* - 条漫连续滚动(M7):先 meta(i) 累加高度排版,再按滚动位置 open(视口±1 页)。
|
||||
* zip 册(M9/M11)只需另写一套 mr_book_ops,目录册是第一个实现。
|
||||
*
|
||||
* meow_img 在 logic 层是前向声明的不透明句柄;解码/释放由 UI 层注入回调
|
||||
* (logic 不 include SDK,宿主测试用假回调即可覆盖契约边界)。
|
||||
*/
|
||||
#ifndef MR_PAGE_SOURCE_H
|
||||
#define MR_PAGE_SOURCE_H
|
||||
|
||||
#include "logic/library.h" /* mr_path_is_image / mr_natural_cmp / MR_PATH_MAX / MR_NAME_MAX */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct meow_img;
|
||||
typedef struct meow_img meow_img; /* SDK 不透明句柄;logic 层只透传 */
|
||||
|
||||
#define MR_BOOK_MAX_PAGES 4096 /* 单册页数上限(防坏卡/巨目录撑爆内存) */
|
||||
|
||||
/* 解码回调(UI 层注入):解码 path,长边 >maxdim 时等比 downscale;失败返回 NULL。
|
||||
* 必须可在后台线程调用(宿主测试用假实现)。 */
|
||||
typedef meow_img *(*mr_book_load_fn)(const char *path, void *ud, int maxdim);
|
||||
/* 释放 open 返回的图像(UI 层注入 meow_img_free;宿主测试用假实现计数)。 */
|
||||
typedef void (*mr_book_unload_fn)(meow_img *img);
|
||||
|
||||
typedef struct mr_book_ops {
|
||||
int (*count)(void *ctx);
|
||||
/* 页原始尺寸(未 downscale);1=已知,0=未知。可为 NULL。 */
|
||||
int (*meta)(void *ctx, int index, int *w, int *h);
|
||||
/* 取页:越界/解码失败返回 NULL。返回值的所有权交给调用方。 */
|
||||
meow_img *(*open)(void *ctx, int index);
|
||||
/* 释放 open 返回的图像;须容忍 NULL。 */
|
||||
void (*close)(void *ctx, meow_img *img);
|
||||
/* 释放 provider 自身(册内索引等)。可为 NULL。 */
|
||||
void (*destroy)(void *ctx);
|
||||
} mr_book_ops;
|
||||
|
||||
typedef struct mr_book {
|
||||
const mr_book_ops *ops;
|
||||
void *ctx;
|
||||
} mr_book;
|
||||
|
||||
/* ---- 契约包装:所有入口对 NULL/越界安全(越界 open 返回 NULL) ---- */
|
||||
int mr_book_valid(const mr_book *b);
|
||||
int mr_book_count(const mr_book *b);
|
||||
int mr_book_meta(const mr_book *b, int index, int *w, int *h);
|
||||
meow_img *mr_book_open(mr_book *b, int index);
|
||||
void mr_book_close(mr_book *b, meow_img *img);
|
||||
/* 释放 provider 自身(不含已 open 的图像——那些由调用方先 close)。幂等。 */
|
||||
void mr_book_destroy(mr_book *b);
|
||||
|
||||
/* ---- 目录册(文件夹即书):目录直接子文件里的图片按自然序成册 ---- */
|
||||
typedef struct mr_dir_book {
|
||||
char dir[MR_PATH_MAX];
|
||||
char **names; /* 自然序文件名(堆分配) */
|
||||
int count;
|
||||
int maxdim; /* open 时传给解码回调的长边上限 */
|
||||
mr_book_load_fn load;
|
||||
mr_book_unload_fn unload;
|
||||
void *ud; /* 解码回调的宿主上下文 */
|
||||
} mr_dir_book;
|
||||
|
||||
/* 扫描 dir 的直接子文件,收图片名并自然排序。
|
||||
* 返回页数(>=0);参数非法 / 目录不可读 / 内存不足返回 -1(db 已清空、可安全 free)。 */
|
||||
int mr_dir_book_init(mr_dir_book *db, const char *dir, int maxdim,
|
||||
mr_book_load_fn load, mr_book_unload_fn unload, void *ud);
|
||||
void mr_dir_book_free(mr_dir_book *db);
|
||||
/* 第 index 页的完整路径;越界时输出空串。 */
|
||||
void mr_dir_book_path(const mr_dir_book *db, int index, char *out, int outsz);
|
||||
/* 把目录册绑定到通用 mr_book(db 生命周期由调用方持有)。 */
|
||||
void mr_dir_book_bind(mr_book *b, mr_dir_book *db);
|
||||
|
||||
/* 纯 C 头解析:取图片原始像素尺寸(不解码像素)。
|
||||
* PNG(IHDR)/ JPEG(SOF0-15)/ BMP(BITMAPINFOHEADER+)。1=已知,0=未知。 */
|
||||
int mr_probe_size(const char *path, int *w, int *h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MR_PAGE_SOURCE_H */
|
||||
Reference in new issue
Block a user