Files
MeowOS-SDK/tuku/logic/reader/page_source.h
T
AskaEth 23c9db73df 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 零警告
2026-11-04 20:58:05 +08:00

92 lines
4.2 KiB
C
Raw 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.
/* 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 */