|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
gfx: an RGB565 (16-bit red, green, blue) rasteriser with no dependencies. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>Go to the source code of this file.
Data Structures | |
| struct | gfx_rect_t |
| struct | gfx_canvas_t |
| struct | gfx_font_t |
| struct | gfx_seg_style_t |
Macros | |
| #define | GFX_RGB(r, g, b) |
| #define | GFX_BLACK GFX_RGB(0, 0, 0) |
| #define | GFX_WHITE GFX_RGB(255, 255, 255) |
| #define | GFX_RED GFX_RGB(255, 0, 0) |
| #define | GFX_GREEN GFX_RGB(0, 255, 0) |
| #define | GFX_BLUE GFX_RGB(0, 0, 255) |
| #define | GFX_YELLOW GFX_RGB(255, 255, 0) |
| #define | GFX_CYAN GFX_RGB(0, 255, 255) |
| #define | GFX_MAGENTA GFX_RGB(255, 0, 255) |
| #define | GFX_GREY(v) |
Typedefs | |
| typedef uint16_t | gfx_color_t |
Enumerations | |
| enum | gfx_align_t { GFX_ALIGN_LEFT = 0 , GFX_ALIGN_CENTER , GFX_ALIGN_RIGHT } |
Functions | |
| static void | gfx_unpack (gfx_color_t c, uint8_t *r, uint8_t *g, uint8_t *b) |
| gfx_color_t | gfx_lerp (gfx_color_t a, gfx_color_t b, uint8_t t) |
| static int16_t | gfx_i16 (int v) |
| static gfx_rect_t | gfx_rect_make (int x, int y, int w, int h) |
| static bool | gfx_rect_empty (gfx_rect_t r) |
| static bool | gfx_rect_contains (gfx_rect_t r, int x, int y) |
| bool | gfx_rect_intersect (gfx_rect_t a, gfx_rect_t b, gfx_rect_t *out) |
| void | gfx_canvas_init (gfx_canvas_t *c, gfx_color_t *pixels, int width, int height, int32_t stride) |
| bool | gfx_canvas_sub (const gfx_canvas_t *src, gfx_rect_t window, gfx_canvas_t *out) |
| bool | gfx_clip_set (gfx_canvas_t *c, gfx_rect_t r) |
| bool | gfx_clip_intersect (gfx_canvas_t *c, gfx_rect_t r) |
| void | gfx_clip_reset (gfx_canvas_t *c) |
| static gfx_rect_t | gfx_clip_get (const gfx_canvas_t *c) |
| void | gfx_clear (gfx_canvas_t *c, gfx_color_t color) |
| void | gfx_pixel (gfx_canvas_t *c, int x, int y, gfx_color_t color) |
| gfx_color_t | gfx_pixel_get (const gfx_canvas_t *c, int x, int y) |
| void | gfx_fill_rect (gfx_canvas_t *c, int x, int y, int w, int h, gfx_color_t color) |
| void | gfx_draw_rect (gfx_canvas_t *c, int x, int y, int w, int h, gfx_color_t color) |
| void | gfx_hline (gfx_canvas_t *c, int x, int y, int w, gfx_color_t color) |
| void | gfx_vline (gfx_canvas_t *c, int x, int y, int h, gfx_color_t color) |
| void | gfx_line (gfx_canvas_t *c, int x0, int y0, int x1, int y1, gfx_color_t color) |
| 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, y0) to (x1, y1). | |
| void | gfx_draw_circle (gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t color) |
| 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. | |
| 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. | |
| void | gfx_fill_circle (gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t color) |
| void | gfx_arc (gfx_canvas_t *c, int cx, int cy, int r, int thickness, float a0_deg, float a1_deg, gfx_color_t col) |
| void | gfx_arc_fade (gfx_canvas_t *c, int cx, int cy, int r, int thickness, float a0_deg, float a1_deg, gfx_color_t col, gfx_color_t into, float fade_deg) |
| void | gfx_draw_round_rect (gfx_canvas_t *c, int x, int y, int w, int h, int r, gfx_color_t color) |
| void | gfx_fill_round_rect (gfx_canvas_t *c, int x, int y, int w, int h, int r, gfx_color_t color) |
| void | gfx_fill_chamfer_rect (gfx_canvas_t *c, int x, int y, int w, int h, int cut, gfx_color_t color) |
| void | gfx_draw_chamfer_rect (gfx_canvas_t *c, int x, int y, int w, int h, int cut, gfx_color_t color) |
| void | gfx_fill_chamfer_rect_ex (gfx_canvas_t *c, int x, int y, int w, int h, int tl, int tr, int br, int bl, gfx_color_t color) |
| void | gfx_draw_chamfer_rect_ex (gfx_canvas_t *c, int x, int y, int w, int h, int tl, int tr, int br, int bl, gfx_color_t color) |
| 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) |
| void | gfx_blit (gfx_canvas_t *c, int x, int y, const gfx_color_t *src, int w, int h, int32_t src_stride) |
| 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) |
| void | gfx_blit_1bpp (gfx_canvas_t *c, int x, int y, const uint8_t *bits, int w, int h, gfx_color_t fg) |
| 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) |
| int | gfx_seg_width (const char *s, const gfx_seg_style_t *st) |
| uint32_t | gfx_utf8_next (const char **s) |
| int | gfx_text_cells (const char *s) |
| size_t | gfx_text_prefix (const char *s, int cells) |
| int | gfx_text_width (const gfx_font_t *font, const char *s, int scale) |
| int | gfx_text_height (const gfx_font_t *font, int scale) |
| int | gfx_char (gfx_canvas_t *c, int x, int y, char ch, const gfx_font_t *font, gfx_color_t fg, int scale) |
| 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) |
| 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) |
| 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) |
| 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 dither (include/gfx.h). | |
| 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) |
| void | gfx_trace_text (const gfx_canvas_t *c, int x, int y, int w, int h, const char *s, const gfx_rect_t *box) |
| void | gfx_trace_box (const gfx_canvas_t *c, int x, int y, int w, int h) |
Variables | |
| const gfx_font_t | gfx_font_8x16 |
| const gfx_font_t | gfx_font_16x28 |
| const gfx_font_t | gfx_font_num_24x30 |
| const gfx_font_t | gfx_font_10x20 |
| 10x20 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 12px. Labels, tabs, buttons and row values on the 1024 x 600 panel. | |
| const gfx_font_t | gfx_font_12x24 |
| 12x24 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 15px. Prose: help text, warnings, questions, run results. | |
| const gfx_font_t | gfx_font_20x36 |
| 20x36 monospaced, ASCII 0x20..0x7E and the German letters. Cap height 23px. Headings, tile names and choice faces on the 1024 x 600 panel. | |
| 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. | |
gfx: an RGB565 (16-bit red, green, blue) rasteriser with no dependencies.
Nothing in this header touches ESP-IDF, FreeRTOS or any hardware. It draws into a plain block of 16-bit pixels described by a gfx_canvas_t, so the same code renders off-screen sprites and runs in the host test suite. The display component binds a canvas to the framebuffer.
The pixel format is RGB565 in the processor's native byte order, which is what the ESP32-S3 RGB peripheral expects on a 16-bit data bus.
Three contracts hold for every primitive below:
Everything clips to canvas->clip. A draw off the edge, or outside a clip a screen has set, is dropped rather than wrapped: a wrapped write lands somewhere else on the panel.
The _aa variants antialias their edges from coverage; the plain ones are hard-edged. Use _aa for anything that is not axis-aligned (a disc, a capsule, a rotated glyph) and the plain rect and line primitives, which are exact, for everything that is.
Alpha and coverage are per call, not stored: a colour is opaque RGB565, and a blend happens where a primitive is given a coverage. Drawing the same translucent shape twice darkens it twice, so an overlay that lands on pixels a screen does not repaint uses an ordered (Bayer) stencil, which is idempotent; see gfx_text_rotated.
SPDX-License-Identifier: MIT
| #define GFX_RGB | ( | r, | |
| g, | |||
| b ) |
Pack 8-bit R/G/B into RGB565.
| void gfx_blit | ( | gfx_canvas_t * | c, |
| int | x, | ||
| int | y, | ||
| const gfx_color_t * | src, | ||
| int | w, | ||
| int | h, | ||
| int32_t | src_stride ) |
Copy a rectangular block of pixels. src_stride is in pixels.
| void gfx_blit_1bpp | ( | gfx_canvas_t * | c, |
| int | x, | ||
| int | y, | ||
| const uint8_t * | bits, | ||
| int | w, | ||
| int | h, | ||
| gfx_color_t | fg ) |
Expand a 1-bit-per-pixel mask (most significant bit first, rows padded to whole bytes).
| 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 ) |
As gfx_blit(), but pixels equal to key are left untouched.
| void gfx_canvas_init | ( | gfx_canvas_t * | c, |
| gfx_color_t * | pixels, | ||
| int | width, | ||
| int | height, | ||
| int32_t | stride ) |
Bind a canvas to a pixel buffer. stride is in pixels; pass 0 to mean "tightly packed" (stride == width).
| bool gfx_canvas_sub | ( | const gfx_canvas_t * | src, |
| gfx_rect_t | window, | ||
| gfx_canvas_t * | out ) |
Carve a sub-canvas out of src. Returns false if the window is empty.
| 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.
| c | the canvas |
| ax | one end's column, px |
| ay | its row, px |
| bx | the other end's column, px |
| by | its row, px |
| thickness | the width, px; 0 or less draws nothing |
| col | the colour |
| int gfx_char | ( | gfx_canvas_t * | c, |
| int | x, | ||
| int | y, | ||
| char | ch, | ||
| const gfx_font_t * | font, | ||
| gfx_color_t | fg, | ||
| int | scale ) |
Draw one glyph, transparent background. Returns the advance in pixels. ch is a single byte, so it reaches ASCII only; a string reaches the rest of the font through gfx_text().
| bool gfx_clip_intersect | ( | gfx_canvas_t * | c, |
| gfx_rect_t | r ) |
Restrict further, relative to the current clip. False if empty.
| bool gfx_clip_set | ( | gfx_canvas_t * | c, |
| gfx_rect_t | r ) |
Restrict drawing to r (intersected with the canvas). False if empty.
| 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.
| c | the canvas |
| cx | the centre's column, px |
| cy | the centre's row, px |
| r | the radius, px; 0 or less draws nothing |
| col | the colour |
| 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 ) |
Vertical gradient fill, top colour a to bottom colour b.
| gfx_color_t gfx_lerp | ( | gfx_color_t | a, |
| gfx_color_t | b, | ||
| uint8_t | t ) |
Linear blend of two colours, t in [0,255] where 0 == a and 255 == b.
| gfx_color_t gfx_pixel_get | ( | const gfx_canvas_t * | c, |
| int | x, | ||
| int | y ) |
Reads back a pixel; returns 0 when (x,y) is outside the canvas.
| bool gfx_rect_intersect | ( | gfx_rect_t | a, |
| gfx_rect_t | b, | ||
| gfx_rect_t * | out ) |
Intersect two rects. Returns false (and zeroes *out) when they miss.
| 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 ) |
Draw s as segment digits. Returns the width drawn.
| int gfx_seg_width | ( | const char * | s, |
| const gfx_seg_style_t * | st ) |
Width s would occupy, without drawing it.
| 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 ) |
Draw a string, transparent background. Returns the advance in pixels.
| 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 ) |
Draw a string over a solid background cell. Returns the advance.
| int gfx_text_cells | ( | const char * | s | ) |
Cells s occupies in a monospaced face: its code point count.
| int gfx_text_height | ( | const gfx_font_t * | font, |
| int | scale ) |
Pixel height of one line at integer scale.
| 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 ) |
Draw s aligned inside box, vertically centred.
| size_t gfx_text_prefix | ( | const char * | s, |
| int | cells ) |
The byte length of the first cells cells of s: where to cut it so the cut falls between two characters, never inside one.
| 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 dither (include/gfx.h).
| c | the canvas |
| cx | the centre's column, px |
| cy | the centre's row, px |
| s | the text, UTF-8 |
| font | the face |
| fg | the colour |
| scale | the glyphs' size, a whole multiple |
| alpha | the share of pixels drawn, 0 to 255 |
| angle_deg | the rotation, degrees |
| 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 ) |
Draw s rotated about (cx, cy) as a stencil over what is already there, covering alpha out of 255 of the glyph pixels.
Inverse-mapped: every destination pixel in the rotated bounding box asks which glyph pixel it comes from. Forward mapping leaves holes at any angle that is not a multiple of 90 degrees.
Only pixels the glyph sets are touched, so the cost is the ink rather than the box; on this panel the frame rate is decided by how many cache lines a frame dirties.
Built for the simulation watermark. It is not a general text transform and is not fast enough for one.
alpha is coverage, not weight: the glyphs are stencilled at full opacity onto that fraction of pixels, chosen by an ordered dither. Drawing this twice over the same pixels equals drawing it once, which a full-screen overlay over selectively repainted screens requires. The pixels gfx_text_rotated() would cover, packed as (y << 16) | x, in scan order and already clipped. Returns the count, or -1 when more than max_out are covered or out is NULL.
The stencil depends only on the geometry and the alpha, so an overlay drawn on every frame records it once and writes the points thereafter, instead of rotating and dividing per pixel over the whole canvas each time.
| int gfx_text_width | ( | const gfx_font_t * | font, |
| const char * | s, | ||
| int | scale ) |
Pixel width of s at integer scale (scale < 1 is treated as 1).
| 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, y0) to (x1, y1).
| c | the canvas |
| x0 | one end's column, px |
| y0 | its row, px |
| x1 | the other end's column, px |
| y1 | its row, px |
| thickness | the width, px; 1 or less is gfx_line() |
| color | the colour |
|
inlinestatic |
Split RGB565 back into 8-bit components (values are quantised).
| uint32_t gfx_utf8_next | ( | const char ** | s | ) |
The next code point of the UTF-8 string at *s, advancing *s past it. Returns 0 at the terminator without advancing. A malformed or truncated sequence returns '?' and advances one byte, so a string cut mid-character costs one cell rather than the rest of the string.
|
extern |
16x28 monospaced, ASCII 0x20..0x7E and the German letters. Headings and medium readouts.
|
extern |
8x16 monospaced, code points 0x20..0x7E (printable ASCII, the American Standard Code for Information Interchange) and the German letters. Labels, units, dense text.
|
extern |
24x30 digits and punctuation, 0x20..0x3A. Hero numerals.