ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
longstrip.c File Reference

Continuous vertical-scroll (longstrip) engine over a JOF atlas (#289). More...

#include "longstrip.h"
#include <stdint.h>
#include "jof.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_tile_cache.h"
Include dependency graph for longstrip.c:

Go to the source code of this file.

Enumerations

enum  wt_consts_t : uint8_t {
  k_wt_fling_num = 7U ,
  k_wt_fling_den = 8U ,
  k_wt_tile_x = 0U ,
  k_wt_zoom = 0U
}
 Fixed engine constants (no magic numbers). More...

Functions

ra8_err_t longstrip_tile_decode (void *ctx, const ra8_tile_key_t *key, uint8_t *cell, uint32_t cell_bytes, uint16_t *out_w, uint16_t *out_h)
 JOF-backed ra8_tile_decode_fn: page one band in on a cache miss.
static void internal_bind (longstrip_t *wt, const longstrip_cfg_t *cfg, const jof_info_t *info)
 Bind the parsed atlas geometry and config into the engine state.
static ra8_err_t internal_check_ptrs (const longstrip_t *wt, const longstrip_cfg_t *cfg)
 Reject a NULL engine, config, or any NULL callback / cache it carries.
ra8_err_t longstrip_open (longstrip_t *wt, const longstrip_cfg_t *cfg)
 Open a longstrip strip over a parsed + validated JOF atlas.
ra8_err_t longstrip_set_viewport (longstrip_t *wt, uint16_t viewport_w, uint16_t viewport_h)
 Resize the viewport of an open strip and re-derive the scroll clamp.
int32_t longstrip_clamp_scroll (const longstrip_t *wt, int32_t y)
 Clamp a candidate scroll position to the strip's legal range.
ra8_err_t longstrip_band_at_y (const longstrip_t *wt, uint32_t y, uint16_t *out_band)
 Report the band index containing canvas row y.
ra8_err_t longstrip_visible_bands (const longstrip_t *wt, int32_t scroll_y, uint16_t *out_first, uint16_t *out_last)
 Compute the inclusive visible band range for a scroll position.
static int32_t internal_sat_add (int32_t a, int32_t b)
 Saturating signed 32-bit add: pins at the int32 limits, never wraps.
ra8_err_t longstrip_scroll_by (longstrip_t *wt, int32_t delta)
 Scroll by a signed pixel delta (a finger drag), clamping at the ends.
ra8_err_t longstrip_fling (longstrip_t *wt, int32_t v0)
 Start a momentum fling with initial velocity v0.
static int32_t internal_apply_friction (int32_t v)
 Decay a velocity one friction step toward zero (magnitude down).
static bool internal_at_top (const longstrip_t *wt)
 Report whether the viewport is pinned at the top of the strip.
static bool internal_at_bottom (const longstrip_t *wt)
 Report whether the viewport is pinned at the bottom of the strip.
static bool internal_fling_should_stop (const longstrip_t *wt)
 True when a fling has hit the boundary it is travelling toward.
bool longstrip_tick (longstrip_t *wt)
 Advance the fling one physics step (integer velocity + friction).
static void internal_warm_band (longstrip_t *wt, uint16_t band)
 Fetch a band into the cache then release it (warm, no held pin).
ra8_err_t longstrip_prefetch (longstrip_t *wt, uint16_t depth)
 Warm the cache with bands just beyond the viewport, in scroll order.
static void internal_accumulate_coverage (const longstrip_t *wt, int32_t dst_y, uint16_t band_h, longstrip_render_stats_t *stats)
 Add the on-screen row span of one blitted band to the coverage.
static ra8_err_t internal_draw_band (longstrip_t *wt, uint16_t band, int32_t dst_x, longstrip_render_stats_t *stats)
 Fetch, composite and release one visible band; update stats.
ra8_err_t longstrip_render (longstrip_t *wt, longstrip_render_stats_t *stats)
 Composite every visible band at the current scroll position.

Variables

static const char *const s_tag = "longstrip"
 Component tag for RA8_CHECK_* log lines.

Detailed Description

Continuous vertical-scroll (longstrip) engine over a JOF atlas (#289).

Implements longstrip.h: virtual-canvas geometry, the scroll + fling state machine, bounded directional prefetch and the visible band composite. The whole file is pure integer arithmetic over the parsed atlas geometry plus calls into ra8_tile_cache (band paging) and jof (per-band decode) – no MMIO, so it runs identically on the target, in ra8_emulator and on the unit-test host.

[Ring 4 / Domain] {World: NS}

Since
0.1.0

Definition in file longstrip.c.

Enumeration Type Documentation

◆ wt_consts_t

enum wt_consts_t : uint8_t

Fixed engine constants (no magic numbers).

k_wt_fling_num / k_wt_fling_den are the per-tick velocity retention ratio: integer v = v * num / den decays magnitude monotonically to zero (truncation toward zero snaps small speeds to rest), so a fling always terminates in a bounded number of ticks. k_wt_tile_x is the single full-width band column; a longstrip strip has exactly one.

Since
0.1.0
Enumerator
k_wt_fling_num 

Velocity retained per tick (numerator).

k_wt_fling_den 

Velocity retention denominator.

k_wt_tile_x 

Longstrip band column index (single column).

k_wt_zoom 

Native zoom / mip level.

Definition at line 46 of file longstrip.c.

Function Documentation

◆ internal_accumulate_coverage()

void internal_accumulate_coverage ( const longstrip_t * wt,
int32_t dst_y,
uint16_t band_h,
longstrip_render_stats_t * stats )
static

Add the on-screen row span of one blitted band to the coverage.

Intersects the band's destination rows [dst_y, dst_y + band_h) with the viewport [0, viewport_h) and adds the overlap to stats->covered_rows. Bands are contiguous and non-overlapping, so summing per-band intersections yields the exact covered-row total with no double counting – the seamless-frame check.

Parameters
[in]wtOpened strip (for the viewport height).
[in]dst_yBand destination top in the viewport (may be negative).
[in]band_hBand height, pixels.
[in,out]statsFrame accounting whose covered_rows is advanced.
Precondition
wt was opened by longstrip_open.
stats is a live per-frame accumulator.
Postcondition
stats->covered_rows grew by the clipped on-screen row count (>= 0).
No other field of stats or wt is mutated.
Note
Not thread-safe (mutates stats).
Since
0.1.0

Definition at line 486 of file longstrip.c.

References longstrip_render_stats_t::covered_rows, and longstrip_t::viewport_h.

Referenced by internal_draw_band().

◆ internal_apply_friction()

int32_t internal_apply_friction ( int32_t v)
static

Decay a velocity one friction step toward zero (magnitude down).

Integer proportional decay v * num / den (7/8) with truncation toward zero, so |v| strictly decreases and small speeds snap to rest – a fling always terminates in a bounded number of ticks.

Parameters
[in]vCurrent velocity, px/tick (signed).
Returns
The decayed velocity, same sign, |result| <= |v|.
Return values
0The input magnitude was small enough to snap to rest.
Precondition
v is the engine's current velocity.
num < den so the magnitude cannot grow.
Postcondition
No state is mutated.
|result| <= |v| (magnitude never increases).
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 307 of file longstrip.c.

References k_wt_fling_den, and k_wt_fling_num.

Referenced by longstrip_tick().

◆ internal_at_bottom()

bool internal_at_bottom ( const longstrip_t * wt)
static

Report whether the viewport is pinned at the bottom of the strip.

Mirror of internal_at_top over the max_scroll end; the clamp keeps scroll_y <= max_scroll, so equality is the pinned case.

Parameters
[in]wtOpened strip (non-NULL by caller contract).
Returns
true when scroll_y >= max_scroll, else false.
Return values
trueThe viewport is at the strip bottom.
falseThe viewport is above the bottom.
Precondition
wt was opened by longstrip_open.
The clamp invariant scroll_y <= max_scroll holds.
Postcondition
No state is mutated.
The result depends only on scroll_y and max_scroll.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 349 of file longstrip.c.

References longstrip_t::max_scroll, and longstrip_t::scroll_y.

Referenced by internal_fling_should_stop().

◆ internal_at_top()

bool internal_at_top ( const longstrip_t * wt)
static

Report whether the viewport is pinned at the top of the strip.

A pure boundary predicate over scroll_y; the clamp keeps scroll_y >= 0, so equality is the pinned case.

Parameters
[in]wtOpened strip (non-NULL by caller contract).
Returns
true when scroll_y <= 0, else false.
Return values
trueThe viewport top is at the strip top.
falseThe viewport has scrolled below the top.
Precondition
wt was opened by longstrip_open.
The clamp invariant scroll_y >= 0 holds.
Postcondition
No state is mutated.
The result depends only on scroll_y.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 328 of file longstrip.c.

References longstrip_t::scroll_y.

Referenced by internal_fling_should_stop().

◆ internal_bind()

void internal_bind ( longstrip_t * wt,
const longstrip_cfg_t * cfg,
const jof_info_t * info )
static

Bind the parsed atlas geometry and config into the engine state.

The state-population half of longstrip_open, split out to keep the entry point under the statement-complexity threshold. Homes the scroll to the top and derives the max-scroll clamp from the canvas height against the viewport (a strip no taller than the viewport cannot scroll, so the clamp floors at zero).

Parameters
[out]wtEngine state to populate (every field written).
[in]cfgValidated open configuration.
[in]infoParsed, shape-checked JOF atlas geometry.
Precondition
wt, cfg and info are non-NULL (the caller validated them).
info describes a single full-width band column.
Postcondition
Every field of wt is initialised; the scroll is homed to the top.
wt->max_scroll >= 0.
Note
Not thread-safe (mutates wt).
Since
0.1.0

Definition at line 101 of file longstrip.c.

References longstrip_t::band_count, longstrip_t::band_h, longstrip_cfg_t::blit, longstrip_t::blit, longstrip_cfg_t::blit_ctx, longstrip_t::blit_ctx, longstrip_cfg_t::cache, longstrip_t::cache, longstrip_t::canvas_h, longstrip_t::canvas_w, jof_info_t::height, longstrip_cfg_t::image_id, longstrip_t::image_id, longstrip_t::info, longstrip_t::max_scroll, longstrip_t::scroll_y, jof_info_t::tile_h, jof_info_t::tile_rows, longstrip_t::velocity, longstrip_cfg_t::viewport_h, longstrip_t::viewport_h, longstrip_cfg_t::viewport_w, longstrip_t::viewport_w, and jof_info_t::width.

Referenced by longstrip_open().

◆ internal_check_ptrs()

ra8_err_t internal_check_ptrs ( const longstrip_t * wt,
const longstrip_cfg_t * cfg )
static

Reject a NULL engine, config, or any NULL callback / cache it carries.

The null-guard half of longstrip_open, split out so the entry point stays under the statement-complexity threshold. Validates the three seams the engine must hold before it can page or composite.

Parameters
[in]wtEngine state handle to validate.
[in]cfgOpen configuration to validate.
Returns
ra8_err_t Error code.
Return values
k_ra8_okwt, cfg and every required callback are non-NULL.
k_ra8_err_null_ptrOne of them is NULL.
Precondition
s_tag is initialised (always true for this TU).
The caller propagates a non-OK result unchanged.
Postcondition
No state is modified.
A k_ra8_ok result guarantees cfg->pread/cache/blit are non-NULL.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 144 of file longstrip.c.

References longstrip_cfg_t::blit, longstrip_cfg_t::cache, k_ra8_ok, longstrip_cfg_t::pread, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by longstrip_open().

◆ internal_draw_band()

ra8_err_t internal_draw_band ( longstrip_t * wt,
uint16_t band,
int32_t dst_x,
longstrip_render_stats_t * stats )
static

Fetch, composite and release one visible band; update stats.

Gets the band from the tile cache (decode-on-miss reads the JOF tile), computes dst_y = band_top - scroll_y, blits it through the sink, accumulates coverage and releases the pin. A cache/decode miss is recorded as a skip and the frame continues (returns k_ra8_ok); a blit-sink or cache-release failure is fatal and propagates.

Parameters
[in,out]wtOpened strip.
[in]bandVisible band index to draw.
[in]dst_xDestination left (viewport-centred column origin).
[in,out]statsFrame accounting (bands_drawn / skipped / covered_rows).
Returns
Result code.
Return values
k_ra8_okThe band drew, or a miss was recorded as a skip.
otherThe blit sink or the cache release failed (fatal).
Precondition
wt was opened by longstrip_open.
stats is a live per-frame accumulator.
Postcondition
The band was blitted at most once and no pin remains held.
Exactly one of bands_drawn / skipped advanced for this band.
Note
Not thread-safe.
Since
0.1.0

Definition at line 525 of file longstrip.c.

References longstrip_t::band_h, longstrip_render_stats_t::bands_drawn, longstrip_t::blit, longstrip_t::blit_ctx, jof_info_t::bpp, longstrip_t::cache, ra8_tile_t::height, longstrip_t::image_id, ra8_tile_key_t::image_id, longstrip_t::info, internal_accumulate_coverage(), k_ra8_ok, k_wt_tile_x, k_wt_zoom, ra8_tile_t::pixels, ra8_tile_cache_get(), ra8_tile_cache_put(), longstrip_t::scroll_y, longstrip_render_stats_t::skipped, ra8_tile_key_t::tile_x, ra8_tile_key_t::tile_y, ra8_tile_t::width, and ra8_tile_key_t::zoom.

Referenced by longstrip_render().

◆ internal_fling_should_stop()

bool internal_fling_should_stop ( const longstrip_t * wt)
static

True when a fling has hit the boundary it is travelling toward.

The caller (longstrip_tick) only reaches this with a non-zero velocity – a zeroed velocity already short-circuits the tick to rest – so the sign alone decides which end halts the fling: an upward (velocity < 0) fling stops only at the top, a downward (velocity > 0) fling only at the bottom; a fling moving away from a boundary keeps going. Testing the sign once (not twice) keeps both arms independently reachable rather than folding the mutually exclusive sign tests into one compound decision.

Parameters
[in]wtOpened strip (non-NULL by caller contract).
Returns
true if the fling should come to rest this tick, else false.
Return values
trueThe velocity is driving into the boundary it has reached.
falseThe fling can keep moving (away from, or not yet at, a bound).
Precondition
wt was opened by longstrip_open.
wt->velocity is the non-zero post-friction velocity for this tick.
Postcondition
No state is mutated.
The result depends only on the velocity sign and the pinned ends.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 378 of file longstrip.c.

References internal_at_bottom(), internal_at_top(), and longstrip_t::velocity.

Referenced by longstrip_tick().

◆ internal_sat_add()

int32_t internal_sat_add ( int32_t a,
int32_t b )
static

Saturating signed 32-bit add: pins at the int32 limits, never wraps.

Widens to int64 for the sum so a hostile scroll delta cannot overflow scroll_y + delta before it is clamped to the strip.

Parameters
[in]aFirst addend.
[in]bSecond addend.
Returns
The clamped sum in [INT32_MIN, INT32_MAX].
Return values
INT32_MAXThe true sum exceeded the signed 32-bit range (positive).
INT32_MINThe true sum fell below the signed 32-bit range.
Precondition
a and b are valid signed integers.
The result is only ever used as an argument to the range clamp.
Postcondition
No state is mutated.
The result never wraps around the int32 boundary.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 261 of file longstrip.c.

Referenced by longstrip_scroll_by(), and longstrip_tick().

◆ internal_warm_band()

void internal_warm_band ( longstrip_t * wt,
uint16_t band )
static

Fetch a band into the cache then release it (warm, no held pin).

Directional prefetch primitive: a get + immediate put makes the band resident and MRU without holding a pin, so the tile cache's LRU still bounds residency. A decode miss is best-effort – the visible render decodes it on demand – so any error is intentionally swallowed.

Parameters
[in,out]wtOpened strip whose cache is warmed.
[in]bandBand index to warm (caller keeps it in range).
Precondition
wt was opened by longstrip_open.
band is a valid band index for wt.
Postcondition
No engine geometry or scroll state is mutated.
No cache pin is held on return.
Note
Not thread-safe.
Since
0.1.0

Definition at line 417 of file longstrip.c.

References longstrip_t::cache, longstrip_t::image_id, ra8_tile_key_t::image_id, k_ra8_ok, k_wt_tile_x, k_wt_zoom, ra8_tile_t::pixels, ra8_tile_cache_get(), ra8_tile_cache_put(), ra8_tile_key_t::tile_x, ra8_tile_key_t::tile_y, and ra8_tile_key_t::zoom.

Referenced by longstrip_prefetch().

◆ longstrip_band_at_y()

ra8_err_t longstrip_band_at_y ( const longstrip_t * wt,
uint32_t y,
uint16_t * out_band )
nodiscard

Report the band index containing canvas row y.

Parameters
[in]wtOpened strip.
[in]yCanvas row, pixels.
[out]out_bandReceives the band index in [0, band_count).
Returns
ra8_err_t
Return values
k_ra8_okBand reported.
k_ra8_err_null_ptrwt or out_band is NULL.
k_ra8_err_out_of_rangey is at/beyond canvas_h.
Precondition
wt was opened by longstrip_open.
out_band is writable.
Postcondition
On success *out_band < wt->band_count.
On any error *out_band is unmodified.
Note
Thread-safe (pure). O(1): a single division.
Since
0.1.0

Definition at line 209 of file longstrip.c.

References longstrip_t::band_h, longstrip_t::canvas_h, k_ra8_err_out_of_range, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

◆ longstrip_clamp_scroll()

int32_t longstrip_clamp_scroll ( const longstrip_t * wt,
int32_t y )
nodiscard

Clamp a candidate scroll position to the strip's legal range.

Parameters
[in]wtOpened strip.
[in]yCandidate viewport-top position, pixels (may be out of range).
Returns
The clamped position in [0, wt->max_scroll].
Return values
0y was at/below the top, or the strip fits fully.
wt->max_scrolly was at/beyond the bottom.
Precondition
wt was opened by longstrip_open.
wt->max_scroll >= 0 (guaranteed by open).
Postcondition
The result is in [0, wt->max_scroll].
No engine state is modified.
Note
Thread-safe (pure over its inputs). Returns 0 on a NULL wt.
Since
0.1.0

Definition at line 195 of file longstrip.c.

References longstrip_t::max_scroll.

Referenced by longstrip_render(), longstrip_scroll_by(), longstrip_set_viewport(), longstrip_tick(), and longstrip_visible_bands().

◆ longstrip_fling()

ra8_err_t longstrip_fling ( longstrip_t * wt,
int32_t v0 )
nodiscard

Start a momentum fling with initial velocity v0.

Parameters
[in,out]wtOpened strip.
[in]v0Initial velocity, px/tick (down positive, up negative).
Returns
ra8_err_t
Return values
k_ra8_okFling armed.
k_ra8_err_null_ptrwt is NULL.
Precondition
wt was opened by longstrip_open.
A caller ticks the engine to animate the fling.
Postcondition
wt->velocity == v0.
wt->scroll_y is unchanged until the first longstrip_tick.
Note
Not thread-safe.
See also
longstrip_tick()
Since
0.1.0

Definition at line 284 of file longstrip.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and longstrip_t::velocity.

◆ longstrip_open()

ra8_err_t longstrip_open ( longstrip_t * wt,
const longstrip_cfg_t * cfg )
nodiscard

Open a longstrip strip over a parsed + validated JOF atlas.

Parses the atlas through jof_parse() and then fail-closed rejects anything that is not a single full-width band column (tile_w == width and tile_cols == 1), because the O(1) y -> band math relies on one band per row. On success the virtual-canvas geometry is cached and scroll_y/velocity are zeroed (top of strip, at rest).

Parameters
[out]wtEngine state to populate (need not be pre-zeroed).
[in]cfgConfiguration (see the struct contract).
Returns
ra8_err_t
Return values
k_ra8_okStrip opened; positioned at the top.
k_ra8_err_null_ptrwt, cfg, or a required cfg seam (pread, cache, blit) is NULL.
k_ra8_err_invalid_argviewport_w or viewport_h is zero.
k_ra8_err_not_supportedAtlas is not a full-width band column.
otherPropagated from jof_parse().
Precondition
cfg->cache was initialised with longstrip_tile_decode over the SAME atlas cfg->pread serves.
cfg->pread serves [0, cfg->atlas_size) of the atlas.
Postcondition
On success *wt satisfies the documented invariants.
On any error *wt must not be used.
Note
Not thread-safe.
See also
longstrip_render()
Since
0.1.0

Definition at line 154 of file longstrip.c.

References longstrip_cfg_t::atlas_size, internal_bind(), internal_check_ptrs(), jof_parse(), k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_ok, longstrip_cfg_t::pread, longstrip_cfg_t::pread_ctx, jof_info_t::tile_w, longstrip_cfg_t::viewport_h, longstrip_cfg_t::viewport_w, and jof_info_t::width.

Referenced by internal_wire(), and ls_open_strip().

◆ longstrip_prefetch()

ra8_err_t longstrip_prefetch ( longstrip_t * wt,
uint16_t depth )
nodiscard

Warm the cache with bands just beyond the viewport, in scroll order.

Directional decode-ahead: with a non-negative velocity (or at rest) it warms up to depth bands below the visible range; with a negative velocity it warms above it. Each band is fetched and immediately released, so it becomes resident + MRU without holding a pin – the tile cache's LRU then bounds residency and reclaims stale prefetches. A reversal simply prefetches the other side on the next call, so stale-direction bands age out naturally.

Parameters
[in,out]wtOpened strip.
[in]depthBands to warm ahead (clamped to k_longstrip_max_prefetch).
Returns
ra8_err_t
Return values
k_ra8_okPrefetch attempted (misses that fail to decode are skipped, not fatal – the visible render still decodes on demand).
k_ra8_err_null_ptrwt is NULL.
Precondition
wt was opened by longstrip_open.
wt->cache has at least one unpinned cell to spare.
Postcondition
No engine geometry or scroll state changed.
At most min(depth, k_longstrip_max_prefetch) bands were touched.
Note
Not thread-safe.
Since
0.1.0

Definition at line 430 of file longstrip.c.

References longstrip_t::band_count, internal_warm_band(), k_longstrip_max_prefetch, k_ra8_ok, longstrip_visible_bands(), RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::velocity.

◆ longstrip_render()

ra8_err_t longstrip_render ( longstrip_t * wt,
longstrip_render_stats_t * stats )
nodiscard

Composite every visible band at the current scroll position.

For each band in the visible range, fetches it from the cache (decode-on-miss reads the JOF tile), computes its destination (dst_x, dst_y)dst_x centres the column in the viewport, dst_y = band_top - scroll_y (negative for the partly-scrolled top band) – blits it through the sink, then releases the pin. Because bands are contiguous and the whole visible range is drawn, the result is seamless with no gap; stats->skipped counts any band that failed to composite and must be zero for a clean frame.

Parameters
[in,out]wtOpened strip.
[out]statsReceives per-frame accounting (may be NULL to ignore).
Returns
ra8_err_t
Return values
k_ra8_okFrame attempted; stats->skipped == 0 means every visible band composited (a clean, seamless frame), > 0 means a band failed to page in.
k_ra8_err_null_ptrwt is NULL.
otherPropagated from the blit sink or the cache release (a genuine I/O failure aborts the frame).
Precondition
wt was opened by longstrip_open.
The blit sink clips to the framebuffer.
Postcondition
Each visible band was blitted at most once; all pins are released.
stats->covered_rows == min(viewport_h, canvas_h - scroll_y) when stats->skipped == 0.
Note
Not thread-safe.
Since
0.1.0

Definition at line 550 of file longstrip.c.

References longstrip_t::canvas_w, internal_draw_band(), k_ra8_ok, longstrip_clamp_scroll(), longstrip_visible_bands(), RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::viewport_w.

Referenced by ls_redraw(), priv_viewer_render_jof(), and priv_viewer_tile_jof().

◆ longstrip_scroll_by()

ra8_err_t longstrip_scroll_by ( longstrip_t * wt,
int32_t delta )
nodiscard

Scroll by a signed pixel delta (a finger drag), clamping at the ends.

Adds delta to scroll_y and clamps. When the clamp pins the position at an end, velocity is zeroed so a fling that ran into the boundary comes to rest instead of pushing further.

Parameters
[in,out]wtOpened strip.
[in]deltaSigned pixel delta (down positive, up negative).
Returns
ra8_err_t
Return values
k_ra8_okPosition updated.
k_ra8_err_null_ptrwt is NULL.
Precondition
wt was opened by longstrip_open.
The engine invariant 0 <= scroll_y <= max_scroll held on entry.
Postcondition
0 <= wt->scroll_y <= wt->max_scroll.
velocity is 0 if the new position pinned at an end.
Note
Not thread-safe.
Since
0.1.0

Definition at line 273 of file longstrip.c.

References internal_sat_add(), k_ra8_ok, longstrip_clamp_scroll(), longstrip_t::max_scroll, RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::velocity.

Referenced by internal_seek(), and ls_apply_nav().

◆ longstrip_set_viewport()

ra8_err_t longstrip_set_viewport ( longstrip_t * wt,
uint16_t viewport_w,
uint16_t viewport_h )
nodiscard

Resize the viewport of an open strip and re-derive the scroll clamp.

max_scroll is a function of the viewport height (canvas_h - viewport_h), so a viewport that changes after open – a resized window, or a paginated caller rendering a short final page – leaves the clamp stale. A stale clamp is not a cosmetic problem: it silently pins scroll_y short of the position the caller asked for, and the strip then composites a window it has already shown. This entry point recomputes the clamp and re-applies it to the current scroll_y so the invariant 0 <= scroll_y <= max_scroll still holds.

A paginated caller must set the viewport to the height of the page it is about to draw. For the final page of a strip whose height is not a whole multiple of the page height, that content height is exactly canvas_h - page_index * page_height, which makes the requested scroll position land exactly on the recomputed max_scroll instead of being clamped backwards into the previous page.

Parameters
[in,out]wtOpened strip to resize (non-NULL).
[in]viewport_wNew viewport width, pixels (non-zero).
[in]viewport_hNew viewport height, pixels (non-zero).
Returns
ra8_err_t
Return values
k_ra8_okViewport applied; max_scroll re-derived.
k_ra8_err_null_ptrwt is NULL.
k_ra8_err_invalid_argviewport_w or viewport_h is zero.
Precondition
wt was opened by longstrip_open.
The caller passes the viewport it is about to composite into.
Postcondition
wt->max_scroll == max(0, canvas_h - viewport_h).
0 <= wt->scroll_y <= wt->max_scroll.
Example:
// Paginated draw: page `p` of `page_h`-tall pages over an H-tall strip.
const uint16_t content_h = (uint16_t)((H - (p * page_h) < page_h)
? (H - (p * page_h)) : page_h);
(void)longstrip_set_viewport(&strip, strip_w, content_h);
ra8_err_t longstrip_set_viewport(longstrip_t *wt, uint16_t viewport_w, uint16_t viewport_h)
Resize the viewport of an open strip and re-derive the scroll clamp.
Definition longstrip.c:180
Note
Not thread-safe (mutates wt).
See also
longstrip_clamp_scroll()
Since
0.1.0

Definition at line 180 of file longstrip.c.

References longstrip_t::canvas_h, k_ra8_err_invalid_arg, k_ra8_ok, longstrip_clamp_scroll(), longstrip_t::max_scroll, RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, longstrip_t::viewport_h, and longstrip_t::viewport_w.

Referenced by internal_seek().

◆ longstrip_tick()

bool longstrip_tick ( longstrip_t * wt)

Advance the fling one physics step (integer velocity + friction).

Applies the current velocity to scroll_y (clamped), then decays |velocity| by one friction step toward zero. Motion stops when the velocity reaches zero OR the position pins against the end it is travelling toward. Call once per display tick until it returns false.

Parameters
[in,out]wtOpened strip.
Returns
true while the strip is still moving; false once it has come to rest (also false for a NULL wt).
Return values
trueThe fling advanced and still has velocity to run.
falseThe fling came to rest this tick, or wt is NULL.
Precondition
wt was opened by longstrip_open.
A prior longstrip_fling (or scroll) set the velocity.
Postcondition
0 <= wt->scroll_y <= wt->max_scroll.
|velocity| did not increase.
Note
Not thread-safe.
Since
0.1.0

Definition at line 383 of file longstrip.c.

References internal_apply_friction(), internal_fling_should_stop(), internal_sat_add(), longstrip_clamp_scroll(), longstrip_t::scroll_y, and longstrip_t::velocity.

◆ longstrip_tile_decode()

ra8_err_t longstrip_tile_decode ( void * ctx,
const ra8_tile_key_t * key,
uint8_t * cell,
uint32_t cell_bytes,
uint16_t * out_w,
uint16_t * out_h )
nodiscard

JOF-backed ra8_tile_decode_fn: page one band in on a cache miss.

Adapts ::ra8_tile_cache's decode-on-miss to jof_read_tile: the tile key's (tile_x, tile_y) select the band (tile_x is always 0 for a longstrip column), and the tile is read + decoded into the cache cell in bounded RAM. Bind this as the cache's decode with a longstrip_decode_ctx_t as decode_ctx.

Parameters
[in]ctxA longstrip_decode_ctx_t*.
[in]keyBand to decode (tile_y = band index).
[out]cellDestination cell pixels.
[in]cell_bytesCell capacity in bytes.
[out]out_wDecoded band width, pixels.
[out]out_hDecoded band height, pixels (clamped for last band).
Returns
ra8_err_t
Return values
k_ra8_okBand decoded into cell.
k_ra8_err_null_ptrctx, key, cell, out_w or out_h is NULL.
otherPropagated from jof_read_tile().
Precondition
ctx->info was parsed over ctx->pread's atlas.
cell holds cell_bytes writable bytes.
Postcondition
On success (*out_w) * (*out_h) * info.bpp cell bytes are valid.
On any error the cell contents are unspecified.
Note
Not thread-safe (shares the decode context's scratch).
See also
longstrip_open()
Since
0.1.0

Definition at line 53 of file longstrip.c.

References longstrip_decode_ctx_t::info, jof_read_tile(), longstrip_decode_ctx_t::pread, longstrip_decode_ctx_t::pread_ctx, RA8_CHECK_NULL_PTR, s_tag, longstrip_decode_ctx_t::scratch, longstrip_decode_ctx_t::scratch_cap, ra8_tile_key_t::tile_x, and ra8_tile_key_t::tile_y.

Referenced by internal_wire().

◆ longstrip_visible_bands()

ra8_err_t longstrip_visible_bands ( const longstrip_t * wt,
int32_t scroll_y,
uint16_t * out_first,
uint16_t * out_last )
nodiscard

Compute the inclusive visible band range for a scroll position.

The viewport [scroll_y, scroll_y + viewport_h) intersects bands first = scroll_y / band_h through last = (bottom - 1) / band_h, with last clamped to the final band. scroll_y is clamped internally, so an out-of-range value yields the nearest legal range.

Parameters
[in]wtOpened strip.
[in]scroll_yViewport-top position, pixels.
[out]out_firstReceives the first visible band index.
[out]out_lastReceives the last visible band index (>= first).
Returns
ra8_err_t
Return values
k_ra8_okRange reported.
k_ra8_err_null_ptrwt, out_first or out_last is NULL.
Precondition
wt was opened by longstrip_open.
out_first and out_last are writable.
Postcondition
*out_first <= *out_last < wt->band_count.
No engine state is modified.
Note
Thread-safe (pure).
Since
0.1.0

Definition at line 220 of file longstrip.c.

References longstrip_t::band_count, longstrip_t::band_h, longstrip_t::canvas_h, k_ra8_ok, longstrip_clamp_scroll(), RA8_CHECK_NULL_PTR, s_tag, and longstrip_t::viewport_h.

Referenced by longstrip_prefetch(), and longstrip_render().

Variable Documentation

◆ s_tag

const char* const s_tag = "longstrip"
static

Component tag for RA8_CHECK_* log lines.

Definition at line 31 of file longstrip.c.