ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_gfx_text_glyph.c
Go to the documentation of this file.
1
16
17#include <stddef.h>
18#include <stdint.h>
19
20#include "ra8_err.h"
21#include "ra8_gfx.h"
22#include "ra8_gfx_internal.h"
23
32
37typedef enum : uint32_t {
38 k_mask_byte = 0xFFU,
40
45typedef enum : uint8_t {
46 k_idx_r = 0,
47 k_idx_g = 1,
49
79static void internal_blit_glyph_565(int32_t x,
80 int32_t y,
81 int32_t gw,
82 int32_t gh,
83 uint32_t row_bytes,
84 const uint8_t* gd,
85 uint32_t fg,
86 uint32_t bg)
87{
88 /* Clip the glyph cell against the active clip rectangle (within the
89 * framebuffer), so it honours both the panel bounds and any dirty-region clip.
90 * Default full clip => byte-identical to the unclipped blit. */
91 const int32_t cl = g_gfx_text_state.clip_x0;
92 const int32_t ct = g_gfx_text_state.clip_y0;
93 const int32_t cr = g_gfx_text_state.clip_x1;
94 const int32_t cb = g_gfx_text_state.clip_y1;
95 const int32_t cx0 = (x >= cl) ? x : cl;
96 const int32_t cy0 = (y >= ct) ? y : ct;
97 const int64_t xr = (int64_t)x + (int64_t)gw; /* 64-bit: no int32 overflow. */
98 const int64_t yr = (int64_t)y + (int64_t)gh;
99 const int32_t cx1 = (xr < (int64_t)cr) ? (int32_t)xr : cr;
100 const int32_t cy1 = (yr < (int64_t)cb) ? (int32_t)yr : cb;
101 if ((cx1 <= cx0) || (cy1 <= cy0)) {
102 return; /* glyph fully outside the clip. */
103 }
104 const uint16_t vfg = priv_gfx_text_pack_565(fg);
105 const uint16_t vbg = priv_gfx_text_pack_565(bg);
106 const uint8_t flo = (uint8_t)(vfg & (uint16_t)k_mask_byte);
107 const uint8_t fhi = (uint8_t)((vfg >> k_glyph_bits_per_byte) & (uint16_t)k_mask_byte);
108 const uint8_t blo = (uint8_t)(vbg & (uint16_t)k_mask_byte);
109 const uint8_t bhi = (uint8_t)((vbg >> k_glyph_bits_per_byte) & (uint16_t)k_mask_byte);
110 const size_t bpp = (size_t)g_gfx_text_state.bpp;
111 const size_t stride = (size_t)g_gfx_text_state.width * bpp;
112 for (int32_t sy = cy0; sy < cy1; sy++) {
113 const uint32_t grow = (uint32_t)(sy - y);
114 uint8_t* p = g_gfx_text_state.fb + ((size_t)sy * stride) + ((size_t)cx0 * bpp);
115 for (int32_t sx = cx0; sx < cx1; sx++) {
116 const uint32_t gcol = (uint32_t)(sx - x);
117 const uint32_t byte_idx = (grow * row_bytes) + (gcol / (uint32_t)k_glyph_bits_per_byte);
118 const uint8_t bit = (uint8_t)(k_glyph_msb_index - (gcol % (uint32_t)k_glyph_bits_per_byte));
119 const bool on = ((gd[byte_idx] >> bit) & 0x01U) != 0U;
120 p[k_idx_r] = on ? flo : blo;
121 p[k_idx_g] = on ? fhi : bhi;
122 p += bpp;
123 }
124 }
125}
126
145static void internal_render_glyph(int32_t x,
146 int32_t y,
147 const ra8_gfx_font_t* font,
148 uint8_t cp,
149 uint32_t fg,
150 uint32_t bg)
151{
152 uint8_t idx;
153 if ((cp < font->first_codepoint) || (cp > font->last_codepoint)) {
154 idx = 0; /* render as space */
155 } else {
156 idx = (uint8_t)(cp - font->first_codepoint);
157 }
158 const uint32_t row_bytes =
159 ((uint32_t)font->glyph_width + (k_glyph_bits_per_byte - 1U)) / k_glyph_bits_per_byte;
160 const uint8_t* gd = font->glyph_data + ((size_t)idx * (size_t)font->bytes_per_glyph);
163 y,
164 (int32_t)font->glyph_width,
165 (int32_t)font->glyph_height,
166 row_bytes,
167 gd,
168 fg,
169 bg);
170 return;
171 }
172 for (uint32_t row = 0; row < font->glyph_height; row++) {
173 for (uint32_t col = 0; col < font->glyph_width; col++) {
174 const uint32_t byte_idx = (row * row_bytes) + (col / k_glyph_bits_per_byte);
175 const uint8_t bit = (uint8_t)(k_glyph_msb_index - (col % k_glyph_bits_per_byte));
176 const bool on = ((gd[byte_idx] >> bit) & 0x01U) != 0U;
177 priv_gfx_text_plot(x + (int32_t)col, y + (int32_t)row, on ? fg : bg);
178 }
179 }
180}
181
183 int32_t y,
184 const char* str,
185 const ra8_gfx_font_t* font,
186 uint32_t fg_color,
187 uint32_t bg_color)
188{
189 if ((str == nullptr) || (font == nullptr)) {
190 return k_ra8_err_null_ptr;
191 }
192 if (!g_gfx_text_state.initialized) {
194 }
195 int32_t cur_x = x;
196 const int32_t step_x = (int32_t)font->glyph_width;
197 /* Static bound: at most one glyph per pixel column we could ever cover. */
198 const uint32_t max_chars = k_ra8_gfx_max_dim;
199 for (uint32_t i = 0; i < max_chars; i++) {
200 const char c = str[i];
201 if (c == '\0') {
202 break;
203 }
204 internal_render_glyph(cur_x, y, font, (uint8_t)c, fg_color, bg_color);
205 cur_x += step_x;
206 }
207 return k_ra8_ok;
208}
209
211ra8_gfx_text_size(const char* str, const ra8_gfx_font_t* font, uint32_t* out_w, uint32_t* out_h)
212{
213 if ((str == nullptr) || (font == nullptr) || (out_w == nullptr) || (out_h == nullptr)) {
214 return k_ra8_err_null_ptr;
215 }
216 uint32_t n = 0;
217 const uint32_t max_chars = k_ra8_gfx_max_dim;
218 for (uint32_t i = 0; i < max_chars; i++) {
219 if (str[i] == '\0') {
220 break;
221 }
222 n++;
223 }
224 *out_w = n * (uint32_t)font->glyph_width;
225 *out_h = (uint32_t)font->glyph_height;
226 return k_ra8_ok;
227}
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Software 2D graphics primitives layered on top of a caller-ownedframebuffer (DRW / D/AVE 2D / GLCDC r...
@ k_ra8_gfx_format_rgb565
16-bit RGB565, little-endian in memory.
Definition ra8_gfx.h:40
@ k_ra8_gfx_max_dim
Maximum supported edge length.
Definition ra8_gfx.h:51
Module-private declarations shared across the ra8_gfx software rasteriser TUs.
ra8_gfx_state_t g_gfx_text_state
Single module-wide framebuffer binding shared by every ra8_gfx TU.
void priv_gfx_text_plot(int32_t x, int32_t y, uint32_t color)
Plot a single pixel with bounds checking against the active clip.
uint16_t priv_gfx_text_pack_565(uint32_t color)
Pack a 32-bit colour into a single RGB565 word.
ra8_gfx_glyph_bits_t
Constants for monochrome glyph bit extraction.
@ k_glyph_bits_per_byte
Glyph bits per byte.
@ k_glyph_msb_index
Glyph msb index.
ra8_gfx_byte_idx_t
Per-byte indices for RGB888 packing.
@ k_idx_r
Index r.
@ k_idx_g
Index g.
ra8_gfx_color_masks_t
Per-channel masks for colour conversion.
@ k_mask_byte
Mask byte.
static void internal_render_glyph(int32_t x, int32_t y, const ra8_gfx_font_t *font, uint8_t cp, uint32_t fg, uint32_t bg)
Render a single glyph at (x,y).
static void internal_blit_glyph_565(int32_t x, int32_t y, int32_t gw, int32_t gh, uint32_t row_bytes, const uint8_t *gd, uint32_t fg, uint32_t bg)
Blit one 1-bpp glyph cell into an RGB565 framebuffer, clipped on screen.
ra8_err_t ra8_gfx_text_size(const char *str, const ra8_gfx_font_t *font, uint32_t *out_w, uint32_t *out_h)
Compute rendered pixel dimensions of a string.
ra8_err_t ra8_gfx_text_out(int32_t x, int32_t y, const char *str, const ra8_gfx_font_t *font, uint32_t fg_color, uint32_t bg_color)
Render a NUL-terminated ASCII string.
Monochrome, fixed-width bitmap font descriptor.
uint8_t bytes_per_glyph
Bytes occupied by one glyph (rows * ceil(width/8)).
uint8_t last_codepoint
Highest stored codepoint (typically 0x7E, '~').
uint8_t glyph_width
Glyph width in pixels.
uint8_t glyph_height
Glyph height in pixels.
uint8_t first_codepoint
Lowest stored codepoint (typically 0x20, space).
const uint8_t * glyph_data
Packed glyph bitmaps; size = bytes_per_glyph * glyph_count.