/* logic/reader/nav.c — 阅读导航纯逻辑实现(见 nav.h 的方向语义说明)。 */ #include "logic/reader/nav.h" int mr_nav_tap_zone(int x, int view_w) { if (view_w <= 0) return MR_ZONE_MIDDLE; if (x < view_w / 3) return MR_ZONE_LEFT; if (x >= (view_w * 2) / 3) return MR_ZONE_RIGHT; return MR_ZONE_MIDDLE; } int mr_nav_tap_delta(int rtl, int zone) { if (zone == MR_ZONE_MIDDLE) return 0; if (rtl) return (zone == MR_ZONE_LEFT) ? 1 : -1; /* RTL:左进右退 */ return (zone == MR_ZONE_LEFT) ? -1 : 1; /* LTR:右进左退 */ } int mr_nav_swipe_delta(int rtl, int dx) { if (dx == 0) return 0; if (rtl) return dx > 0 ? 1 : -1; return dx > 0 ? -1 : 1; } int mr_nav_clamp_page(int page, int count) { if (count <= 0) return -1; if (page < 0) return 0; if (page >= count) return count - 1; return page; } int mr_nav_commit_dist(int view_w) { int t = view_w / 4; if (t < 60) t = 60; if (t > 160) t = 160; return t; } int mr_nav_commit(int dx, int view_w) { int adx = dx < 0 ? -dx : dx; return adx >= mr_nav_commit_dist(view_w); } int mr_nav_fit_size(int fit, int src_w, int src_h, int vw, int vh, int *out_w, int *out_h) { if (!out_w || !out_h || src_w <= 0 || src_h <= 0 || vw <= 0 || vh <= 0) return -1; long long w, h; if (fit == MR_FIT_ORIGINAL) { w = src_w; h = src_h; } else if (fit == MR_FIT_HEIGHT) { h = vh; w = (long long)src_w * vh / src_h; } else { w = vw; h = (long long)src_h * vw / src_w; } if (w < 1) w = 1; if (h < 1) h = 1; *out_w = (int)w; *out_h = (int)h; return 0; } int mr_nav_zoom_size(int w, int h, int zoom_pct, int *out_w, int *out_h) { if (!out_w || !out_h || w <= 0 || h <= 0 || zoom_pct <= 0) return -1; long long ww = (long long)w * zoom_pct / 100; long long hh = (long long)h * zoom_pct / 100; if (ww < 1) ww = 1; if (hh < 1) hh = 1; *out_w = (int)ww; *out_h = (int)hh; return 0; } void mr_nav_pan_limit(int content_w, int content_h, int vw, int vh, int *lim_x, int *lim_y) { int lx = content_w - vw; int ly = content_h - vh; if (lx < 0) lx = 0; if (ly < 0) ly = 0; /* 平移量是「中心偏移」:可左右各移动溢出量的一半,两边才都看得到。 */ if (lim_x) *lim_x = lx / 2; if (lim_y) *lim_y = ly / 2; } void mr_nav_pan_clamp(int content_w, int content_h, int vw, int vh, int *pan_x, int *pan_y) { int lx, ly; mr_nav_pan_limit(content_w, content_h, vw, vh, &lx, &ly); if (pan_x) { if (*pan_x > lx) *pan_x = lx; if (*pan_x < -lx) *pan_x = -lx; } if (pan_y) { if (*pan_y > ly) *pan_y = ly; if (*pan_y < -ly) *pan_y = -ly; } } int mr_nav_slide_from(int rtl, int delta, int view_w) { if (!delta) return 0; int from = rtl ? -delta : delta; return from * view_w; } int mr_nav_fit_next(int fit) { if (fit < 0 || fit >= MR_FIT_COUNT) return MR_FIT_WIDTH; return (fit + 1) % MR_FIT_COUNT; }