Files
MeowOS-SDK/tuku/ui/reader/reader.h
T
AskaEth 462cfd5bc0 图库: 阅读器翻页按显示尺寸解码(零重采样)+ 多页闪退防御 + 从第 N 张开始(M17)
用户反馈「横竖翻页都卡(40 页也卡)」「140 张图的文件夹一打开就闪退」
「要从中间某张开始看」三条,本次分别处理:

翻页卡顿(真因:每帧一次重采样)
- 解码目标从「屏长边」改成「当前 fit/zoom 的显示尺寸」:适宽 3:4 页原来解成
  540x720、显示 480x640,draw_page_at 于是每帧走 meow_ui_img_scaled —— 每页每帧
  多一遍全图最近邻重采样 + 一次 1.2MB 临时 malloc/free(>128KB 走 mmap)。
- 现在解码结果与显示框一致(±2px 容差)→ 翻页/滚动热路径只有原生 blit。
- fit/zoom 变化时按新几何重解(slot_ready 判据 + 同页替换),不再残留缩放;
  已到解码预算或已是原始分辨率的小图不会反复重解。
- 拖动/吸附/fling 帧只 invalidate 内容区(顶栏静态,不再每帧重绘标题文字);
  异步落位只在「该页真的在屏幕上」时才重绘,预取邻居不刷屏。
- 页原始尺寸按册缓存(8B/页),绘制几何不再每帧 fopen probe 文件。

多页闪退(宿主未能复现,按内存边界防御)
- 常驻页图改为「显示尺寸」并加上限:单页 ≤3MB、整窗 ≤9MB(超限淘汰最远页);
  常驻内存只与解码窗大小有关,不随页数增长。
- 解码中间峰值 >12MB 的页直接跳过并显示占位 + WARN(旧代码 PNG/BMP 放到 40MB,
  3000x3000 就是 36MB 瞬时分配;JPEG 完全没上限)。140 页夹具(含坏图/超大图)
  走真实 UI 链路打开、翻页、跳页、条漫全部通过。

新增 mr_reader_open_dir_at(dir, start_index)(文件管理器模式入口)
- 显式下标优先于续读记录;-1=续读(旧入口语义),其它负数钳到 0,≥页数钳到末页。
- mr_reader_open_dir 保留为 (dir, MR_READER_START_RESUME) 的包装;reader.h 导出。

测试:新增 test_reader_perf(翻页零重采样/fit 切换/驻留上界)与
test_reader_many_pages(140 页 + 坏图/超大图 + 起始下标/钳制/续读优先级 + 条漫跳页)。
2026-11-05 18:06:26 +08:00

42 lines
2.0 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.
/* ui/reader/reader.h — 阅读页给 app.c 的事件接缝(跟手拖动/平移)。
*
* app.c 只做最小路由:ACT_READER 时的 on_touch_down/move 转给这里(镜像 library 分支)。
* 其余入口(on_tap / view on_event / mr_reader_open_dir)仍走 tuku_internal.h 的既有声明。
*/
#ifndef TUKU_UI_READER_READER_H
#define TUKU_UI_READER_READER_H
#ifdef __cplusplus
extern "C" {
#endif
void reader_on_touch_down(int x, int y);
void reader_on_touch_move(int x, int y);
/* 书库 → 阅读器(文件管理器模式用):按目录内图片自然序从 start_index 开始。
* - start_index >= 册页数:钳到末页;其它负数按 0 处理;
* - start_index == MR_READER_START_RESUME(-1):沿用该册续读记录(= mr_reader_open_dir)。
* 显式下标优先于续读记录:用户在列表里点了某张图,就不该被上次的页码带走。 */
#define MR_READER_START_RESUME (-1)
void mr_reader_open_dir_at(const char *dir, int start_index);
/* 保留旧入口:等价于 mr_reader_open_dir_at(dir, MR_READER_START_RESUME)。 */
void mr_reader_open_dir(const char *dir);
#ifdef MR_READER_HOST_TEST
/* 宿主集成测试专用:只读观察本页状态(不参与产品逻辑)。 */
int mr_reader_ui_mode(void); /* MR_MODE_PAGED / MR_MODE_WEBTOON */
int mr_reader_ui_page(void); /* 当前页(条漫=视口顶端所在页) */
int mr_reader_ui_count(void); /* 当前册页数 */
int mr_reader_ui_jump_open(void); /* 1=跳页滑块已展开 */
int mr_reader_ui_jump_pending(void);/* 1=跳页目标等待解码 */
long mr_reader_ui_resident_kb(void);/* 驻留页图字节(KB) */
int mr_reader_ui_failed_pages(void);/* 解码失败/超预算被跳过的页数 */
int mr_reader_ui_blit_draws(void); /* 累计原生 blit 绘页次数(热路径应为纯 blit) */
int mr_reader_ui_scaled_draws(void);/* 累计重采样绘页次数(每帧重采样=卡顿) */
#endif
#ifdef __cplusplus
}
#endif
#endif /* TUKU_UI_READER_READER_H */