rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
gfx.h
Go to the documentation of this file.
1
33
34#pragma once
35
36#include <stdbool.h>
37#include <stddef.h>
38#include <stdint.h>
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44/* ------------------------------------------------------------------ colour */
45
46typedef uint16_t gfx_color_t;
47
49#define GFX_RGB(r, g, b) \
50 ((gfx_color_t)((((uint16_t)(r) & 0xF8u) << 8) | \
51 (((uint16_t)(g) & 0xFCu) << 3) | \
52 (((uint16_t)(b) & 0xF8u) >> 3)))
53
54#define GFX_BLACK GFX_RGB(0, 0, 0)
55#define GFX_WHITE GFX_RGB(255, 255, 255)
56#define GFX_RED GFX_RGB(255, 0, 0)
57#define GFX_GREEN GFX_RGB(0, 255, 0)
58#define GFX_BLUE GFX_RGB(0, 0, 255)
59#define GFX_YELLOW GFX_RGB(255, 255, 0)
60#define GFX_CYAN GFX_RGB(0, 255, 255)
61#define GFX_MAGENTA GFX_RGB(255, 0, 255)
62#define GFX_GREY(v) GFX_RGB(v, v, v)
63
64
66static inline void gfx_unpack(gfx_color_t c, uint8_t *r, uint8_t *g, uint8_t *b)
67{
68 uint8_t r5 = (uint8_t)((c >> 11) & 0x1Fu);
69 uint8_t g6 = (uint8_t)((c >> 5) & 0x3Fu);
70 uint8_t b5 = (uint8_t)(c & 0x1Fu);
71 if (r) { *r = (uint8_t)((r5 << 3) | (r5 >> 2)); }
72 if (g) { *g = (uint8_t)((g6 << 2) | (g6 >> 4)); }
73 if (b) { *b = (uint8_t)((b5 << 3) | (b5 >> 2)); }
74}
75
77gfx_color_t gfx_lerp(gfx_color_t a, gfx_color_t b, uint8_t t);
78
79/* ----------------------------------------------------------------- geometry */
80
81typedef struct {
82 int16_t x, y, w, h;
84
85/*
86 * Saturate rather than truncate. The fields are int16_t and the arguments are
87 * int, so a plain cast draws a shape that is entirely off-screen back onto the
88 * panel at a wrapped position -- which is the opposite of clipping, and turns
89 * an out-of-range blit's source offset into a read far outside its buffer.
90 */
91static inline int16_t gfx_i16(int v)
92{
93 if (v < INT16_MIN) { return INT16_MIN; }
94 if (v > INT16_MAX) { return INT16_MAX; }
95 return (int16_t)v;
96}
97
98static inline gfx_rect_t gfx_rect_make(int x, int y, int w, int h)
99{
100 /* Clamp the far edge in int, so a saturated origin cannot silently shrink
101 * or grow the extent. */
102 long x1 = (long)x + (long)w;
103 long y1 = (long)y + (long)h;
104 int16_t rx = gfx_i16(x);
105 int16_t ry = gfx_i16(y);
106 if (x1 > INT16_MAX) { x1 = INT16_MAX; }
107 if (x1 < INT16_MIN) { x1 = INT16_MIN; }
108 if (y1 > INT16_MAX) { y1 = INT16_MAX; }
109 if (y1 < INT16_MIN) { y1 = INT16_MIN; }
110 gfx_rect_t r = { rx, ry, gfx_i16((int)(x1 - rx)), gfx_i16((int)(y1 - ry)) };
111 return r;
112}
113
114static inline bool gfx_rect_empty(gfx_rect_t r)
115{
116 return r.w <= 0 || r.h <= 0;
117}
118
119static inline bool gfx_rect_contains(gfx_rect_t r, int x, int y)
120{
121 return x >= r.x && y >= r.y && x < r.x + r.w && y < r.y + r.h;
122}
123
126
127/* ------------------------------------------------------------------- canvas */
128
129typedef struct {
130 gfx_color_t *pixels;
131 int16_t width;
132 int16_t height;
133 int32_t stride;
136
141void gfx_canvas_init(gfx_canvas_t *c, gfx_color_t *pixels,
142 int width, int height, int32_t stride);
143
145bool gfx_canvas_sub(const gfx_canvas_t *src, gfx_rect_t window, gfx_canvas_t *out);
146
151void gfx_clip_reset(gfx_canvas_t *c);
152static inline gfx_rect_t gfx_clip_get(const gfx_canvas_t *c) { return c->clip; }
153
154/* --------------------------------------------------------------- primitives */
155
156void gfx_clear(gfx_canvas_t *c, gfx_color_t color);
157void gfx_pixel(gfx_canvas_t *c, int x, int y, gfx_color_t color);
159gfx_color_t gfx_pixel_get(const gfx_canvas_t *c, int x, int y);
160
161void gfx_fill_rect(gfx_canvas_t *c, int x, int y, int w, int h, gfx_color_t color);
162void gfx_draw_rect(gfx_canvas_t *c, int x, int y, int w, int h, gfx_color_t color);
163void gfx_hline(gfx_canvas_t *c, int x, int y, int w, gfx_color_t color);
164void gfx_vline(gfx_canvas_t *c, int x, int y, int h, gfx_color_t color);
165void gfx_line(gfx_canvas_t *c, int x0, int y0, int x1, int y1, gfx_color_t color);
166void gfx_thick_line(gfx_canvas_t *c, int x0, int y0, int x1, int y1,
167 int thickness, gfx_color_t color);
168
169void gfx_draw_circle(gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t color);
170
171/*
172 * Antialiased disc and capsule, filled from the distance to their own centre
173 * or spine. The capsule is a thick line with round ends, and its sides and
174 * caps come out of one expression -- so there is no seam where they meet,
175 * which a disc drawn over a rectangle cannot avoid.
176 */
177void gfx_fill_circle_aa(gfx_canvas_t *c, int cx, int cy, int r,
178 gfx_color_t col);
179void gfx_capsule_aa(gfx_canvas_t *c, int ax, int ay, int bx, int by,
180 int thickness, gfx_color_t col);
181void gfx_fill_circle(gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t color);
182
183/*
184 * An arc of @p thickness centred on (cx, cy), from @p a0_deg to @p a1_deg.
185 * Angles are degrees counter-clockwise from the +x axis, so 90 is straight up
186 * on screen. The radial edges are antialiased.
187 */
188void gfx_arc(gfx_canvas_t *c, int cx, int cy, int r, int thickness,
189 float a0_deg, float a1_deg, gfx_color_t col);
190
191/*
192 * The same arc, with each end brought up out of @p into over @p fade_deg and
193 * taken back down into it. An arc that stops dead has two bright full-width
194 * ends that read as breakage; one that dissolves reads as an arc lit over
195 * part of its length.
196 */
197void gfx_arc_fade(gfx_canvas_t *c, int cx, int cy, int r, int thickness,
198 float a0_deg, float a1_deg, gfx_color_t col,
199 gfx_color_t into, float fade_deg);
200
201void gfx_draw_round_rect(gfx_canvas_t *c, int x, int y, int w, int h,
202 int r, gfx_color_t color);
203void gfx_fill_round_rect(gfx_canvas_t *c, int x, int y, int w, int h,
204 int r, gfx_color_t color);
205
206/*
207 * Chamfered (cut-corner) rectangles. The cut is a 45-degree bevel of the
208 * given size, controlled per corner: cutting only the top-left and
209 * bottom-right of a panel gives a different look from cutting all four. A
210 * cut of 0 leaves that corner square.
211 */
212void gfx_fill_chamfer_rect(gfx_canvas_t *c, int x, int y, int w, int h,
213 int cut, gfx_color_t color);
214void gfx_draw_chamfer_rect(gfx_canvas_t *c, int x, int y, int w, int h,
215 int cut, gfx_color_t color);
216void gfx_fill_chamfer_rect_ex(gfx_canvas_t *c, int x, int y, int w, int h,
217 int tl, int tr, int br, int bl, gfx_color_t color);
218void gfx_draw_chamfer_rect_ex(gfx_canvas_t *c, int x, int y, int w, int h,
219 int tl, int tr, int br, int bl, gfx_color_t color);
220
222void gfx_fill_rect_gradient(gfx_canvas_t *c, int x, int y, int w, int h,
223 gfx_color_t a, gfx_color_t b);
224
225/* -------------------------------------------------------------------- blits */
226
228void gfx_blit(gfx_canvas_t *c, int x, int y, const gfx_color_t *src,
229 int w, int h, int32_t src_stride);
231void gfx_blit_key(gfx_canvas_t *c, int x, int y, const gfx_color_t *src,
232 int w, int h, int32_t src_stride, gfx_color_t key);
235void gfx_blit_1bpp(gfx_canvas_t *c, int x, int y, const uint8_t *bits,
236 int w, int h, gfx_color_t fg);
237
238/* --------------------------------------------------------------------- text */
239
240/*
241 * Text is UTF-8 (Unicode Transformation Format, 8-bit). Every string a
242 * primitive below takes is decoded to code points, and one code point is one
243 * cell: the width of a string is its code point count times the cell width,
244 * not its byte count. A font holds the contiguous block first..last and,
245 * after it, `extra_count` further glyphs for the code points listed in
246 * `extra` (the German letters A, O and U with diaeresis, upper and lower
247 * case, and the sharp s). A code point the font does not hold draws as '?',
248 * and a byte that does not start a well-formed sequence is one '?' cell.
249 */
250typedef struct {
251 const uint8_t *glyphs;
253 uint8_t width;
254 uint8_t height;
256 uint8_t bpp;
257 uint8_t first;
258 uint8_t last;
259 uint8_t extra_count;
260 const uint16_t *extra;
261} gfx_font_t;
262
266extern const gfx_font_t gfx_font_8x16;
269extern const gfx_font_t gfx_font_16x28;
271extern const gfx_font_t gfx_font_num_24x30;
274extern const gfx_font_t gfx_font_10x20;
277extern const gfx_font_t gfx_font_12x24;
280extern const gfx_font_t gfx_font_20x36;
283extern const gfx_font_t gfx_font_num_32x44;
284
285/* ------------------------------------------------- seven-segment numerals */
286
287/*
288 * The look of a bench instrument rather than of a screen: digits built from
289 * seven bars, with the unlit ones optionally left showing. Covers 0-9, '-',
290 * '.', ':' and space; anything else draws as blank.
291 */
292typedef struct {
294 int digit_h;
296 int gap;
297 int slant;
298 bool ghost;
300
302int gfx_seg_text(gfx_canvas_t *c, int x, int y, const char *s,
303 const gfx_seg_style_t *st, gfx_color_t on, gfx_color_t off);
305int gfx_seg_width(const char *s, const gfx_seg_style_t *st);
306
313uint32_t gfx_utf8_next(const char **s);
314
316int gfx_text_cells(const char *s);
317
322size_t gfx_text_prefix(const char *s, int cells);
323
325int gfx_text_width(const gfx_font_t *font, const char *s, int scale);
327int gfx_text_height(const gfx_font_t *font, int scale);
328
332int gfx_char(gfx_canvas_t *c, int x, int y, char ch, const gfx_font_t *font,
333 gfx_color_t fg, int scale);
335int gfx_text(gfx_canvas_t *c, int x, int y, const char *s,
336 const gfx_font_t *font, gfx_color_t fg, int scale);
338int gfx_text_bg(gfx_canvas_t *c, int x, int y, const char *s,
339 const gfx_font_t *font, gfx_color_t fg, gfx_color_t bg, int scale);
340
370int gfx_text_rotated_points(gfx_canvas_t *c, int cx, int cy, const char *s,
371 const gfx_font_t *font, int scale, uint8_t alpha,
372 float angle_deg, uint32_t *out, int max_out);
373
374void gfx_text_rotated(gfx_canvas_t *c, int cx, int cy, const char *s,
375 const gfx_font_t *font, gfx_color_t fg, int scale,
376 uint8_t alpha, float angle_deg);
377
378typedef enum {
379 GFX_ALIGN_LEFT = 0,
380 GFX_ALIGN_CENTER,
381 GFX_ALIGN_RIGHT,
382} gfx_align_t;
383
385void gfx_text_in(gfx_canvas_t *c, gfx_rect_t box, const char *s,
386 const gfx_font_t *font, gfx_color_t fg, int scale,
387 gfx_align_t align);
388
389#ifdef GFX_TEXT_TRACE
390/*
391 * The fit check's view of a frame, compiled in only when GFX_TEXT_TRACE is
392 * defined: the panel and the host suite build without it. The harness
393 * that defines GFX_TEXT_TRACE defines these two. Coordinates are the
394 * canvas's own; the harness maps a sub-canvas back to the panel from its
395 * pixel pointer.
396 *
397 * gfx_trace_text() is called for every string drawn: its box, and the box
398 * gfx_text_in() was given (NULL from the other primitives).
399 * gfx_trace_box() is called for every filled rounded or chamfered
400 * rectangle: the shapes a label sits inside.
401 */
402void gfx_trace_text(const gfx_canvas_t *c, int x, int y, int w, int h,
403 const char *s, const gfx_rect_t *box);
404void gfx_trace_box(const gfx_canvas_t *c, int x, int y, int w, int h);
405#endif
406
407#ifdef __cplusplus
408}
409#endif
#define s
Short name for esc_stick_s inside the five stick-class files.
Definition esc_stick_panel_int.h:295
void gfx_blit_key(gfx_canvas_t *c, int x, int y, const gfx_color_t *src, int w, int h, int32_t src_stride, gfx_color_t key)
Definition gfx.c:663
gfx_color_t gfx_pixel_get(const gfx_canvas_t *c, int x, int y)
Definition gfx.c:182
void gfx_thick_line(gfx_canvas_t *c, int x0, int y0, int x1, int y1, int thickness, gfx_color_t color)
A line thickness px wide: a disc of half that radius stamped at each pixel of the line from (x0,...
Definition gfx.c:319
void gfx_blit_1bpp(gfx_canvas_t *c, int x, int y, const uint8_t *bits, int w, int h, gfx_color_t fg)
Definition gfx.c:690
void gfx_blit(gfx_canvas_t *c, int x, int y, const gfx_color_t *src, int w, int h, int32_t src_stride)
Definition gfx.c:639
void gfx_fill_rect_gradient(gfx_canvas_t *c, int x, int y, int w, int h, gfx_color_t a, gfx_color_t b)
Definition gfx.c:625
gfx_color_t gfx_lerp(gfx_color_t a, gfx_color_t b, uint8_t t)
Definition gfx.c:79
bool gfx_canvas_sub(const gfx_canvas_t *src, gfx_rect_t window, gfx_canvas_t *out)
Definition gfx.c:133
void gfx_fill_circle_aa(gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t col)
gfx_fill_circle_aaf() on whole pixels.
Definition gfx.c:867
bool gfx_clip_set(gfx_canvas_t *c, gfx_rect_t r)
Definition gfx.c:161
void gfx_canvas_init(gfx_canvas_t *c, gfx_color_t *pixels, int width, int height, int32_t stride)
Definition gfx.c:114
bool gfx_rect_intersect(gfx_rect_t a, gfx_rect_t b, gfx_rect_t *out)
Definition gfx.c:93
void gfx_capsule_aa(gfx_canvas_t *c, int ax, int ay, int bx, int by, int thickness, gfx_color_t col)
gfx_capsule_aaf() on whole pixels.
Definition gfx.c:966
bool gfx_clip_intersect(gfx_canvas_t *c, gfx_rect_t r)
Definition gfx.c:169
static void gfx_unpack(gfx_color_t c, uint8_t *r, uint8_t *g, uint8_t *b)
Definition gfx.h:66
const gfx_font_t gfx_font_16x28
const gfx_font_t gfx_font_12x24
12x24 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 15px. Prose: help text,...
const gfx_font_t gfx_font_num_32x44
32x44 digits and punctuation, 0x20..0x3A. Cap height 40px. Hero numerals on the 1024 x 600 panel.
const gfx_font_t gfx_font_num_24x30
const gfx_font_t gfx_font_20x36
20x36 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 23px. Headings,...
const gfx_font_t gfx_font_10x20
10x20 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 12px. Labels,...
const gfx_font_t gfx_font_8x16
int gfx_seg_width(const char *s, const gfx_seg_style_t *st)
Definition gfx_seg.c:199
int gfx_seg_text(gfx_canvas_t *c, int x, int y, const char *s, const gfx_seg_style_t *st, gfx_color_t on, gfx_color_t off)
Definition gfx_seg.c:211
int gfx_text_bg(gfx_canvas_t *c, int x, int y, const char *s, const gfx_font_t *font, gfx_color_t fg, gfx_color_t bg, int scale)
Definition gfx_text.c:302
void gfx_text_in(gfx_canvas_t *c, gfx_rect_t box, const char *s, const gfx_font_t *font, gfx_color_t fg, int scale, gfx_align_t align)
Definition gfx_text.c:316
size_t gfx_text_prefix(const char *s, int cells)
Definition gfx_text.c:77
int gfx_text_height(const gfx_font_t *font, int scale)
Definition gfx_text.c:137
int gfx_text_cells(const char *s)
Definition gfx_text.c:65
void gfx_text_rotated(gfx_canvas_t *c, int cx, int cy, const char *s, const gfx_font_t *font, gfx_color_t fg, int scale, uint8_t alpha, float angle_deg)
s rotated by angle_deg about (cx, cy), stencilled onto the share alpha of its pixels by an ordered di...
Definition gfx_text.c:502
int gfx_text_width(const gfx_font_t *font, const char *s, int scale)
Definition gfx_text.c:148
int gfx_text(gfx_canvas_t *c, int x, int y, const char *s, const gfx_font_t *font, gfx_color_t fg, int scale)
Definition gfx_text.c:286
int gfx_text_rotated_points(gfx_canvas_t *c, int cx, int cy, const char *s, const gfx_font_t *font, int scale, uint8_t alpha, float angle_deg, uint32_t *out, int max_out)
Definition gfx_text.c:510
uint32_t gfx_utf8_next(const char **s)
Definition gfx_text.c:17
int gfx_char(gfx_canvas_t *c, int x, int y, char ch, const gfx_font_t *font, gfx_color_t fg, int scale)
Definition gfx_text.c:258
Definition gfx.h:129
gfx_rect_t clip
Definition gfx.h:134
int16_t width
Definition gfx.h:131
int16_t height
Definition gfx.h:132
gfx_color_t * pixels
Definition gfx.h:130
int32_t stride
Definition gfx.h:133
Definition gfx.h:250
const uint16_t * extra
Definition gfx.h:260
uint8_t first
Definition gfx.h:257
uint8_t extra_count
Definition gfx.h:259
uint8_t last
Definition gfx.h:258
uint8_t height
Definition gfx.h:254
uint8_t bpp
Definition gfx.h:256
uint8_t width
Definition gfx.h:253
uint8_t bytes_per_row
Definition gfx.h:255
const uint8_t * glyphs
Definition gfx.h:251
Definition gfx.h:81
Definition gfx.h:292
bool ghost
Definition gfx.h:298
int slant
Definition gfx.h:297
int gap
Definition gfx.h:296
int thickness
Definition gfx.h:295
int digit_w
Definition gfx.h:293