rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
gfx.h File Reference

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.

Detailed Description

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

Macro Definition Documentation

◆ GFX_GREY

#define GFX_GREY ( v)
Value:
GFX_RGB(v, v, v)
#define GFX_RGB(r, g, b)
Definition gfx.h:49

◆ GFX_RGB

#define GFX_RGB ( r,
g,
b )
Value:
((gfx_color_t)((((uint16_t)(r) & 0xF8u) << 8) | \
(((uint16_t)(g) & 0xFCu) << 3) | \
(((uint16_t)(b) & 0xF8u) >> 3)))

Pack 8-bit R/G/B into RGB565.

Function Documentation

◆ gfx_blit()

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.

◆ gfx_blit_1bpp()

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).

◆ gfx_blit_key()

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.

◆ gfx_canvas_init()

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).

◆ gfx_canvas_sub()

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.

◆ gfx_capsule_aa()

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.

Parameters
cthe canvas
axone end's column, px
ayits row, px
bxthe other end's column, px
byits row, px
thicknessthe width, px; 0 or less draws nothing
colthe colour

◆ gfx_char()

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().

◆ gfx_clip_intersect()

bool gfx_clip_intersect ( gfx_canvas_t * c,
gfx_rect_t r )

Restrict further, relative to the current clip. False if empty.

◆ gfx_clip_set()

bool gfx_clip_set ( gfx_canvas_t * c,
gfx_rect_t r )

Restrict drawing to r (intersected with the canvas). False if empty.

◆ gfx_fill_circle_aa()

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.

Parameters
cthe canvas
cxthe centre's column, px
cythe centre's row, px
rthe radius, px; 0 or less draws nothing
colthe colour

◆ gfx_fill_rect_gradient()

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_lerp()

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_pixel_get()

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.

◆ gfx_rect_intersect()

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.

◆ gfx_seg_text()

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.

◆ gfx_seg_width()

int gfx_seg_width ( const char * s,
const gfx_seg_style_t * st )

Width s would occupy, without drawing it.

◆ gfx_text()

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.

◆ gfx_text_bg()

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.

◆ gfx_text_cells()

int gfx_text_cells ( const char * s)

Cells s occupies in a monospaced face: its code point count.

◆ gfx_text_height()

int gfx_text_height ( const gfx_font_t * font,
int scale )

Pixel height of one line at integer scale.

◆ gfx_text_in()

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.

◆ gfx_text_prefix()

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.

◆ gfx_text_rotated()

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).

Parameters
cthe canvas
cxthe centre's column, px
cythe centre's row, px
sthe text, UTF-8
fontthe face
fgthe colour
scalethe glyphs' size, a whole multiple
alphathe share of pixels drawn, 0 to 255
angle_degthe rotation, degrees

◆ gfx_text_rotated_points()

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.

◆ gfx_text_width()

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).

◆ gfx_thick_line()

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).

Parameters
cthe canvas
x0one end's column, px
y0its row, px
x1the other end's column, px
y1its row, px
thicknessthe width, px; 1 or less is gfx_line()
colorthe colour

◆ gfx_unpack()

void gfx_unpack ( gfx_color_t c,
uint8_t * r,
uint8_t * g,
uint8_t * b )
inlinestatic

Split RGB565 back into 8-bit components (values are quantised).

◆ gfx_utf8_next()

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.

Variable Documentation

◆ gfx_font_16x28

const gfx_font_t gfx_font_16x28
extern

16x28 monospaced, ASCII 0x20..0x7E and the German letters. Headings and medium readouts.

◆ gfx_font_8x16

const gfx_font_t gfx_font_8x16
extern

8x16 monospaced, code points 0x20..0x7E (printable ASCII, the American Standard Code for Information Interchange) and the German letters. Labels, units, dense text.

◆ gfx_font_num_24x30

const gfx_font_t gfx_font_num_24x30
extern

24x30 digits and punctuation, 0x20..0x3A. Hero numerals.