ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
zoom.c
Go to the documentation of this file.
1
20
21#include "zoom.h"
22
23#include <stdint.h>
24
25#include "ra8_attributes.h"
26#include "ra8_check.h"
27#include "ra8_err.h"
28#include "ra8_ui.h"
29#include "zoom_internal.h"
30
32static const char* const s_tag = "zoom";
33
54typedef enum : uint8_t {
58
59RA8_PRIV void
60priv_zoom_axis(int32_t anchor, int32_t extent, int32_t scale, int32_t src_dim, zoom_axis_t* out)
61{
62 const int32_t plane = src_dim * scale;
63 int32_t d0 = -anchor;
64 if (d0 < 0) {
65 d0 = 0;
66 }
67 int32_t d1 = plane - anchor;
68 if (d1 > extent) {
69 d1 = extent;
70 }
71 if (d1 < d0) {
72 d1 = d0;
73 }
74 out->d0 = d0;
75 out->d1 = d1;
76 out->s0 = 0U;
77 /* Beyond this point `anchor + d0 >= 0` by construction, so the source-index
78 * divisions never touch a negative numerator. */
79 if (d1 <= d0) {
80 out->count = 0U;
81 return;
82 }
83 const int32_t s0 = (anchor + d0) / scale;
84 const int32_t s1 = (anchor + d1 - 1) / scale;
85 /* `span` is a named object rather than the composite `(s1 - s0) + 1` inline,
86 * so the widening cast below converts a simple expression: casting the
87 * composite would change essential type mid-expression (MISRA 10.8). It is
88 * positive by construction -- s1 >= s0 whenever d1 > d0. */
89 const int32_t span = (s1 - s0) + 1;
90 out->s0 = (uint32_t)s0;
91 out->count = (uint32_t)span;
92}
93
111static bool internal_dim_ok(uint32_t dim)
112{
113 return (dim != 0U) && (dim <= (uint32_t)k_zoom_dim_max);
114}
115
134static int32_t internal_sat_add(int32_t a, int32_t b)
135{
136 const int64_t sum = (int64_t)a + (int64_t)b;
137 if (sum > (int64_t)INT32_MAX) {
138 return INT32_MAX;
139 }
140 if (sum < (int64_t)INT32_MIN) {
141 return INT32_MIN;
142 }
143 return (int32_t)sum;
144}
145
167static int32_t internal_clamp_anchor(int32_t anchor, int32_t plane, int32_t extent)
168{
169 if (plane <= extent) {
170 /* Image smaller than the viewport at this zoom: centre it, letting the
171 * anchor go negative. The render reads that as a letterbox. */
172 return -((extent - plane) / 2);
173 }
174 if (anchor < 0) {
175 return 0;
176 }
177 if (anchor > (plane - extent)) {
178 return plane - extent;
179 }
180 return anchor;
181}
182
200{
201 const int32_t scale = (int32_t)v->scale;
202 v->anchor_x = internal_clamp_anchor(v->anchor_x, (int32_t)v->src.width * scale, v->dst.w);
203 v->anchor_y = internal_clamp_anchor(v->anchor_y, (int32_t)v->src.height * scale, v->dst.h);
204}
205
224static void internal_touch(zoom_view_t* v, uint32_t now_ms)
225{
226 const bool responsive = (v->policy == k_zoom_policy_responsive);
227 v->last_input_ms = now_ms;
228 v->pending = true;
230 v->settle_armed = responsive;
231}
232
251{
252 RA8_CHECK_NULL_PTR(cfg->src.read, s_tag, "source read seam must not be nullptr");
253 RA8_CHECK_NULL_PTR(cfg->scratch.row, s_tag, "scratch.row must not be nullptr");
254 RA8_CHECK_NULL_PTR(cfg->scratch.strip, s_tag, "scratch.strip must not be nullptr");
255 RA8_CHECK_NULL_PTR(cfg->scratch.packed, s_tag, "scratch.packed must not be nullptr");
256 return k_ra8_ok;
257}
258
278{
279 if ((cfg->dst.w <= 0) || (cfg->dst.h <= 0)) {
280 ra8_log_error(s_tag, "viewport must have positive width and height");
282 }
283 if (!internal_dim_ok(cfg->src.width) || !internal_dim_ok(cfg->src.height)) {
284 ra8_log_error(s_tag, "source extent is zero or exceeds k_zoom_dim_max");
286 }
287 return k_ra8_ok;
288}
289
309static ra8_err_t internal_cfg_scratch_ok(const zoom_view_cfg_t* cfg, uint16_t* out_strip_rows)
310{
311 const uint32_t width = (uint32_t)cfg->dst.w;
312 if ((cfg->scratch.row_cap < width) || (cfg->scratch.strip_cap < width)) {
313 ra8_log_error(s_tag, "scratch row/strip buffer is narrower than the viewport");
314 return k_ra8_err_no_mem;
315 }
316 uint32_t rows = cfg->scratch.strip_cap / width;
317 if (rows > (uint32_t)k_zoom_strip_rows_max) {
318 rows = (uint32_t)k_zoom_strip_rows_max;
319 }
320 if (rows > (uint32_t)cfg->dst.h) {
321 rows = (uint32_t)cfg->dst.h;
322 }
323 if (cfg->scratch.packed_cap < (((width * rows) + 1U) / 2U)) {
324 ra8_log_error(s_tag, "scratch packed buffer cannot hold one dithered strip");
325 return k_ra8_err_no_mem;
326 }
327 *out_strip_rows = (uint16_t)rows;
328 return k_ra8_ok;
329}
330
351static ra8_err_t
352internal_cfg_ladder_ok(const zoom_view_cfg_t* cfg, uint8_t* out_scale, uint8_t* out_ceiling)
353{
354 /* The "0 means default" rewrite happens first and lifts both values to at
355 * least k_zoom_scale_min, so a `< min` half in either check below could
356 * never be true. Testing it anyway would be a condition that cannot vary --
357 * unreachable by construction, and dead weight in an MC/DC argument. Each
358 * check is therefore the one bound that can actually fail. */
359 const uint8_t ceiling = (cfg->scale_max == 0U) ? (uint8_t)k_zoom_scale_max : cfg->scale_max;
360 const uint8_t opening = (cfg->scale == 0U) ? (uint8_t)k_zoom_scale_min : cfg->scale;
361 if (ceiling > (uint8_t)k_zoom_scale_max) {
362 ra8_log_error(s_tag, "scale_max is outside the engine ladder");
364 }
365 if (opening > ceiling) {
366 ra8_log_error(s_tag, "opening scale is outside the configured ladder");
368 }
369 *out_scale = opening;
370 *out_ceiling = ceiling;
371 return k_ra8_ok;
372}
373
375zoom_source_init(zoom_source_t* out, zoom_read_fn read, void* ctx, uint32_t width, uint32_t height)
376{
377 RA8_CHECK_NULL_PTR(out, s_tag, "source out must not be nullptr");
378 RA8_CHECK_NULL_PTR(read, s_tag, "source read seam must not be nullptr");
379 if (!internal_dim_ok(width) || !internal_dim_ok(height)) {
380 ra8_log_error(s_tag, "source extent is zero or exceeds k_zoom_dim_max");
382 }
383 out->read = read;
384 out->ctx = ctx;
385 out->width = width;
386 out->height = height;
387 return k_ra8_ok;
388}
389
419 uint16_t* out_strip_rows,
420 uint8_t* out_scale,
421 uint8_t* out_ceiling)
422{
423 RA8_RETURN_ON_ERROR(internal_cfg_ptrs_ok(cfg), s_tag, "cfg pointer check");
424 RA8_RETURN_ON_ERROR(internal_cfg_extent_ok(cfg), s_tag, "cfg extent check");
425 RA8_RETURN_ON_ERROR(internal_cfg_scratch_ok(cfg, out_strip_rows), s_tag, "cfg scratch check");
426 return internal_cfg_ladder_ok(cfg, out_scale, out_ceiling);
427}
428
459 const zoom_view_cfg_t* cfg,
460 uint8_t opening,
461 uint8_t ceiling,
462 uint16_t strip_rows)
463{
464 v->src = cfg->src;
465 v->scratch = cfg->scratch;
466 v->dst = cfg->dst;
467 v->scale = opening;
468 v->scale_max = ceiling;
469 v->policy = cfg->policy;
470 v->settle_ms = (cfg->settle_ms == 0U) ? (uint16_t)k_zoom_settle_ms_default : cfg->settle_ms;
471 v->strip_rows = strip_rows;
472 v->anchor_x = (cfg->focus_x * (int32_t)opening) - (cfg->dst.w / 2);
473 v->anchor_y = (cfg->focus_y * (int32_t)opening) - (cfg->dst.h / 2);
474 v->last_input_ms = 0U;
475 v->settle_armed = false;
476 v->pending = true;
478 v->active = true;
480}
481
483{
484 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
485 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
486 v->active = false;
487 uint16_t strip_rows = 0U;
488 uint8_t opening = 0U;
489 uint8_t ceiling = 0U;
490 RA8_RETURN_ON_ERROR(internal_cfg_ok(cfg, &strip_rows, &opening, &ceiling), s_tag, "cfg check");
491 internal_view_adopt(v, cfg, opening, ceiling, strip_rows);
492 return k_ra8_ok;
493}
494
495ra8_err_t zoom_view_rebind(zoom_view_t* v, const zoom_source_t* src, uint32_t now_ms)
496{
497 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
498 RA8_CHECK_NULL_PTR(src, s_tag, "src must not be nullptr");
499 RA8_CHECK_NULL_PTR(src->read, s_tag, "source read seam must not be nullptr");
500 if (!v->active) {
501 ra8_log_error(s_tag, "rebind on a closed view");
503 }
504 if (!internal_dim_ok(src->width) || !internal_dim_ok(src->height)) {
505 ra8_log_error(s_tag, "source extent is zero or exceeds k_zoom_dim_max");
507 }
508 v->src = *src;
510 internal_touch(v, now_ms);
511 return k_ra8_ok;
512}
513
515{
516 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
517 if (!v->active) {
518 ra8_log_error(s_tag, "invalidate on a closed view");
520 }
521 internal_touch(v, now_ms);
522 return k_ra8_ok;
523}
524
526{
527 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
528 v->active = false;
529 v->pending = false;
530 v->settle_armed = false;
531 return k_ra8_ok;
532}
533
535{
536 return (v != nullptr) && v->active;
537}
538
539uint8_t zoom_scale_cycle(uint8_t scale, uint8_t min, uint8_t max)
540{
541 const uint8_t floor_v = (min == 0U) ? (uint8_t)k_zoom_scale_min : min;
542 const uint8_t ceiling_v = (max < floor_v) ? floor_v : max;
543 if (scale >= ceiling_v) {
544 return floor_v;
545 }
546 const uint16_t doubled = (uint16_t)((uint16_t)scale * (uint16_t)k_zoom_scale_dbl);
547 if (doubled >= (uint16_t)ceiling_v) {
548 return ceiling_v;
549 }
550 if (doubled < (uint16_t)floor_v) {
551 return floor_v;
552 }
553 return (uint8_t)doubled;
554}
555
557 uint8_t scale,
558 int32_t focus_x,
559 int32_t focus_y,
560 uint32_t now_ms)
561{
562 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
563 if (!v->active) {
564 ra8_log_error(s_tag, "set_scale on a closed view");
566 }
567 if ((scale < (uint8_t)k_zoom_scale_min) || (scale > v->scale_max)) {
568 ra8_log_error(s_tag, "requested scale is off the ladder");
570 }
571 if (scale == v->scale) {
572 return k_ra8_ok;
573 }
574 /* Keep the plane point under (focus_x, focus_y) fixed: rescale that plane
575 * coordinate by new/old, then re-derive the anchor from it. The intermediate
576 * product is 64-bit (a plane coordinate times the new scale can exceed int32
577 * before the divide brings it back), and each narrowing cast takes a NAMED
578 * 64-bit object rather than a composite expression -- casting the quotient
579 * in place would change essential type mid-expression (MISRA 10.8). */
580 const int32_t off_x = focus_x - v->dst.x;
581 const int32_t off_y = focus_y - v->dst.y;
582 const int64_t old = (int64_t)v->scale;
583 const int64_t plane_x = (int64_t)(v->anchor_x + off_x) * (int64_t)scale;
584 const int64_t plane_y = (int64_t)(v->anchor_y + off_y) * (int64_t)scale;
585 const int64_t scaled_x = plane_x / old;
586 const int64_t scaled_y = plane_y / old;
587 v->anchor_x = (int32_t)scaled_x - off_x;
588 v->anchor_y = (int32_t)scaled_y - off_y;
589 v->scale = scale;
591 internal_touch(v, now_ms);
592 return k_ra8_ok;
593}
594
595ra8_err_t zoom_view_pan(zoom_view_t* v, int32_t dx, int32_t dy, uint32_t now_ms)
596{
597 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
598 if (!v->active) {
599 ra8_log_error(s_tag, "pan on a closed view");
601 }
602 const int32_t was_x = v->anchor_x;
603 const int32_t was_y = v->anchor_y;
607 /* Decision: a pan that clamped to no movement owes the panel nothing. */
608 if ((v->anchor_x != was_x) || (v->anchor_y != was_y)) {
609 internal_touch(v, now_ms);
610 }
611 return k_ra8_ok;
612}
613
615{
616 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
617 if (!v->active) {
618 ra8_log_error(s_tag, "pan_dir on a closed view");
620 }
621 const int32_t step_x = v->dst.w - (v->dst.w / (int32_t)k_zoom_overlap_div);
622 const int32_t step_y = v->dst.h - (v->dst.h / (int32_t)k_zoom_overlap_div);
623 int32_t dx = 0;
624 int32_t dy = 0;
625 switch (dir) {
626 case k_zoom_pan_left:
627 dx = -step_x;
628 break;
629 case k_zoom_pan_right:
630 dx = step_x;
631 break;
632 case k_zoom_pan_up:
633 dy = -step_y;
634 break;
635 case k_zoom_pan_down:
636 dy = step_y;
637 break;
638 case k_zoom_pan_none:
639 default:
640 break;
641 }
642 return zoom_view_pan(v, dx, dy, now_ms);
643}
644
646{
647 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
648 RA8_CHECK_NULL_PTR(out, s_tag, "out rect must not be nullptr");
649 if (!v->active) {
650 ra8_log_error(s_tag, "window query on a closed view");
652 }
653 zoom_axis_t ax = {};
654 zoom_axis_t ay = {};
655 priv_zoom_axis(v->anchor_x, v->dst.w, (int32_t)v->scale, (int32_t)v->src.width, &ax);
656 priv_zoom_axis(v->anchor_y, v->dst.h, (int32_t)v->scale, (int32_t)v->src.height, &ay);
657 out->x = (int32_t)ax.s0;
658 out->w = (int32_t)ax.count;
659 out->y = (int32_t)ay.s0;
660 out->h = (int32_t)ay.count;
661 return k_ra8_ok;
662}
663
664bool zoom_view_tick(zoom_view_t* v, uint32_t now_ms)
665{
666 if (v == nullptr) {
667 return false;
668 }
669 /* Decision: only an open view with an armed settle can promote to quality. */
670 if (!v->active || !v->settle_armed) {
671 return false;
672 }
673 /* Unsigned difference, so a wrapping millisecond counter settles early
674 * rather than never. */
675 if ((now_ms - v->last_input_ms) < (uint32_t)v->settle_ms) {
676 return false;
677 }
678 v->settle_armed = false;
679 v->pending = true;
681 return true;
682}
683
685{
686 RA8_CHECK_NULL_PTR(v, s_tag, "view must not be nullptr");
687 RA8_CHECK_NULL_PTR(out, s_tag, "present out must not be nullptr");
688 if (!v->active) {
689 ra8_log_error(s_tag, "present on a closed view");
691 }
692 out->rect = v->dst;
693 out->refresh = v->pending_kind;
694 out->present = v->pending;
695 v->pending = false;
696 return k_ra8_ok;
697}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Bounded UI interaction core: hit-testing, screen stack, paging.
Axis-aligned rectangle in framebuffer pixel coordinates.
Definition ra8_ui.h:72
int32_t w
Width (pixels, >= 0).
Definition ra8_ui.h:75
int32_t h
Height (pixels, >= 0).
Definition ra8_ui.h:76
int32_t x
Left edge (pixels).
Definition ra8_ui.h:73
int32_t y
Top edge (pixels).
Definition ra8_ui.h:74
One axis of the viewport resolved against the image: coverage + source span.
uint32_t count
Source indices feeding the covered span (0 if none).
int32_t d1
One past the last covered destination offset.
uint32_t s0
First source index feeding the covered span.
int32_t d0
First covered destination offset inside the viewport.
What the reader must flush, and with which waveform.
Definition zoom.h:371
zoom_refresh_t refresh
Waveform class for that flush.
Definition zoom.h:373
ra8_ui_rect_t rect
Panel rectangle to flush.
Definition zoom.h:372
bool present
False: nothing changed, do not flush at all.
Definition zoom.h:374
uint8_t * packed
The strip packed to 4 bpp (2 px/byte).
Definition zoom.h:340
uint32_t row_cap
Capacity of row, bytes.
Definition zoom.h:337
uint8_t * row
One source row, >= dst.w bytes.
Definition zoom.h:336
uint32_t packed_cap
Capacity of packed, bytes.
Definition zoom.h:341
uint32_t strip_cap
Capacity of strip, bytes.
Definition zoom.h:339
uint8_t * strip
gray8 destination strip, dst.w * strip_rows.
Definition zoom.h:338
A magnifiable full-resolution image behind the gray8 sub-rect seam.
Definition zoom.h:296
uint32_t height
Full-resolution source height, pixels.
Definition zoom.h:300
uint32_t width
Full-resolution source width, pixels.
Definition zoom.h:299
zoom_read_fn read
gray8 sub-rectangle reader (never NULL once bound).
Definition zoom.h:297
void * ctx
Opaque context handed back to read.
Definition zoom.h:298
Everything zoom_view_open needs; nothing it does not.
Definition zoom.h:404
ra8_ui_rect_t dst
Viewport in framebuffer pixels.
Definition zoom.h:407
zoom_source_t src
Bound source (see zoom_source_init).
Definition zoom.h:405
int32_t focus_x
Opening centre, source pixels (x).
Definition zoom.h:412
uint8_t scale
Opening magnification (0 => scale_min).
Definition zoom.h:408
uint8_t scale_max
Ladder ceiling (0 => k_zoom_scale_max).
Definition zoom.h:409
int32_t focus_y
Opening centre, source pixels (y).
Definition zoom.h:413
uint16_t settle_ms
Settle window (0 => the module default).
Definition zoom.h:411
zoom_policy_t policy
Waveform scheduling policy.
Definition zoom.h:410
zoom_scratch_t scratch
Caller-owned composite buffers.
Definition zoom.h:406
Live viewport: where it is looking, how magnified, and what it owes the panel.
Definition zoom.h:472
uint32_t last_input_ms
Timestamp of the last viewport change.
Definition zoom.h:478
uint8_t scale_max
Ladder ceiling for this view.
Definition zoom.h:482
zoom_refresh_t pending_kind
Waveform the owed flush should use.
Definition zoom.h:484
zoom_policy_t policy
Waveform scheduling policy.
Definition zoom.h:483
bool settle_armed
A quality repaint is still due after settling.
Definition zoom.h:486
uint8_t scale
Current integer magnification.
Definition zoom.h:481
zoom_source_t src
Bound source.
Definition zoom.h:473
zoom_scratch_t scratch
Caller-owned composite buffers.
Definition zoom.h:474
ra8_ui_rect_t dst
Viewport in framebuffer pixels.
Definition zoom.h:475
uint16_t strip_rows
Destination rows per composite strip.
Definition zoom.h:480
int32_t anchor_y
Plane row shown at dst.y.
Definition zoom.h:477
bool active
The view is open.
Definition zoom.h:487
bool pending
A flush is owed.
Definition zoom.h:485
int32_t anchor_x
Plane column shown at dst.x.
Definition zoom.h:476
uint16_t settle_ms
Input silence before the quality repaint.
Definition zoom.h:479
#define min(x, y)
Untyped minimum shim used by the SOUP's buffer clamping.
Definition xz_config.h:157
ra8_err_t zoom_source_init(zoom_source_t *out, zoom_read_fn read, void *ctx, uint32_t width, uint32_t height)
Bind a gray8 sub-rectangle reader and its extent as a magnifiable source.
Definition zoom.c:375
ra8_err_t zoom_view_invalidate(zoom_view_t *v, uint32_t now_ms)
Declare the viewport's pixels stale for a reason the engine cannot see.
Definition zoom.c:514
bool zoom_view_active(const zoom_view_t *v)
Whether a view is open.
Definition zoom.c:534
zoom_step_t
Pan-step geometry and the ladder multiplier (no magic numbers).
Definition zoom.c:54
@ k_zoom_overlap_div
Viewport fraction retained across a pan step.
Definition zoom.c:55
@ k_zoom_scale_dbl
Ladder multiplier (doubling, not increment).
Definition zoom.c:56
ra8_err_t zoom_view_rebind(zoom_view_t *v, const zoom_source_t *src, uint32_t now_ms)
Point an open view at a different source, keeping zoom and position.
Definition zoom.c:495
static int32_t internal_sat_add(int32_t a, int32_t b)
Saturating signed addition (never wraps at the int32 boundary).
Definition zoom.c:134
static bool internal_dim_ok(uint32_t dim)
Whether a source dimension is inside the engine's addressable range.
Definition zoom.c:111
ra8_err_t zoom_view_close(zoom_view_t *v)
Close a view; it stops owing the panel anything.
Definition zoom.c:525
static void internal_view_adopt(zoom_view_t *v, const zoom_view_cfg_t *cfg, uint8_t opening, uint8_t ceiling, uint16_t strip_rows)
Publish a validated configuration into a view and open it.
Definition zoom.c:458
ra8_err_t zoom_view_pan_dir(zoom_view_t *v, zoom_pan_t dir, uint32_t now_ms)
Pan by a discrete step in one direction (the tap-band interaction).
Definition zoom.c:614
static ra8_err_t internal_cfg_ptrs_ok(const zoom_view_cfg_t *cfg)
Validate every pointer a configuration must carry.
Definition zoom.c:250
void priv_zoom_axis(int32_t anchor, int32_t extent, int32_t scale, int32_t src_dim, zoom_axis_t *out)
Resolve one viewport axis against the image at the current magnification.
Definition zoom.c:60
static int32_t internal_clamp_anchor(int32_t anchor, int32_t plane, int32_t extent)
Clamp one anchor against the magnified plane and the viewport extent.
Definition zoom.c:167
static ra8_err_t internal_cfg_ok(const zoom_view_cfg_t *cfg, uint16_t *out_strip_rows, uint8_t *out_scale, uint8_t *out_ceiling)
Run every configuration check, in the order they depend on each other.
Definition zoom.c:418
static ra8_err_t internal_cfg_extent_ok(const zoom_view_cfg_t *cfg)
Validate the viewport extent and the source extent.
Definition zoom.c:277
static void internal_reclamp(zoom_view_t *v)
Re-clamp both anchors against the current source, scale and viewport.
Definition zoom.c:199
ra8_err_t zoom_view_pan(zoom_view_t *v, int32_t dx, int32_t dy, uint32_t now_ms)
Pan the viewport by a destination-pixel delta.
Definition zoom.c:595
bool zoom_view_tick(zoom_view_t *v, uint32_t now_ms)
Advance the settle timer; promote a bi-level view to full quality.
Definition zoom.c:664
ra8_err_t zoom_view_window(const zoom_view_t *v, ra8_ui_rect_t *out)
The source rectangle currently visible, in source pixels.
Definition zoom.c:645
ra8_err_t zoom_view_present(zoom_view_t *v, zoom_present_t *out)
Take the pending flush plan, clearing it.
Definition zoom.c:684
static ra8_err_t internal_cfg_ladder_ok(const zoom_view_cfg_t *cfg, uint8_t *out_scale, uint8_t *out_ceiling)
Resolve and validate the magnification ladder a configuration asks for.
Definition zoom.c:352
static ra8_err_t internal_cfg_scratch_ok(const zoom_view_cfg_t *cfg, uint16_t *out_strip_rows)
Derive the strip height from the scratch budget and check every capacity.
Definition zoom.c:309
uint8_t zoom_scale_cycle(uint8_t scale, uint8_t min, uint8_t max)
Next magnification on the doubling ladder, wrapping back to the minimum.
Definition zoom.c:539
static void internal_touch(zoom_view_t *v, uint32_t now_ms)
Record an interactive viewport change and schedule the flush it owes.
Definition zoom.c:224
ra8_err_t zoom_view_open(zoom_view_t *v, const zoom_view_cfg_t *cfg)
Open a viewport onto a source, centred on a source-pixel focus.
Definition zoom.c:482
ra8_err_t zoom_view_set_scale(zoom_view_t *v, uint8_t scale, int32_t focus_x, int32_t focus_y, uint32_t now_ms)
Set the magnification, keeping a panel point fixed under the finger.
Definition zoom.c:556
Tap-to-zoom image viewer: viewport state machine + tiled magnifying render (#478).
@ k_zoom_policy_responsive
Fast during a burst, quality once settled.
Definition zoom.h:204
@ k_zoom_strip_rows_max
Destination rows composited per strip.
Definition zoom.h:120
@ k_zoom_scale_max
Engine ceiling on integer magnification.
Definition zoom.h:119
@ k_zoom_scale_min
1:1 – one source pixel per panel pixel.
Definition zoom.h:118
@ k_zoom_dim_max
Largest accepted source width or height, pixels.
Definition zoom.h:139
@ k_zoom_settle_ms_default
Default input-silence settle window, ms.
Definition zoom.h:157
ra8_err_t(* zoom_read_fn)(void *ctx, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t *out, uint32_t out_stride)
Read a sub-rectangle of the magnified source as gray8 (the DIP seam).
Definition zoom.h:267
@ k_zoom_refresh_quality
Settled: panel GC16 (all 16 levels, slow).
Definition zoom.h:176
@ k_zoom_refresh_fast
Interactive burst: panel A2 (bi-level, fast).
Definition zoom.h:175
zoom_pan_t
Discrete pan direction for tap-band navigation.
Definition zoom.h:222
@ k_zoom_pan_right
Viewport travels toward +x.
Definition zoom.h:225
@ k_zoom_pan_left
Viewport travels toward -x.
Definition zoom.h:224
@ k_zoom_pan_none
No movement.
Definition zoom.h:223
@ k_zoom_pan_down
Viewport travels toward +y.
Definition zoom.h:227
@ k_zoom_pan_up
Viewport travels toward -y.
Definition zoom.h:226
Module-private seam shared by the zoom state machine and its render.