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

gfx: the RGB565 (16-bit red, green, blue) rasteriser. See include/gfx.h. More...

#include "gfx_int.h"
#include "gfx_subpixel.h"
#include "gfx_work.h"
#include <limits.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

Data Structures

struct  span_t
 A run of pixels of one row, from lo up to hi. More...
struct  ring_cut_t
 The directions of a partial ring that need no angle worked out: the middle of its lit part, drawn in the full colour at the full coverage, and the middle of its gap, drawn not at all. More...
struct  arc_dirs_t
 The directions an arc is walked in, as arc_window() finds them: from lo over span degrees, 360 for all of them. More...

Macros

#define GFX_INL_FORCE
#define GFX_MIN(a, b)
#define GFX_MAX(a, b)

Typedefs

typedef uint32_t gfx_u32_alias

Functions

static void fill_span (gfx_color_t *p, int n, gfx_color_t color)
gfx_color_t gfx_lerp (gfx_color_t a, gfx_color_t b, uint8_t t)
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)
void gfx_clip_reset (gfx_canvas_t *c)
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_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_clear (gfx_canvas_t *c, 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_draw_rect (gfx_canvas_t *c, int x, int y, int w, 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 (gfx_canvas_t *c, int cx, int cy, int r, gfx_color_t color)
static int clamp_radius (int w, int h, int r)
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_draw_round_rect (gfx_canvas_t *c, int x, int y, int w, int h, int r, gfx_color_t color)
static int clamp_cut (int w, int h, int cut)
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_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_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 (gfx_canvas_t *c, int x, int y, int w, int h, int cut, 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)
static void cov_blend (gfx_canvas_t *c, int x, int y, gfx_color_t col, float cov)
 One antialiased pixel: col over what is there, by cov.
static bool cov_box (const gfx_canvas_t *c, float cx, float cy, float reach, int *x0, int *y0, int *x1, int *y1)
static bool span_round (float cx, float dy, float reach, span_t *sp)
 Narrow sp to the columns of the row dy from a centre at cx that can lie nearer the centre than reach: those more than a pixel further are left out, so a loop over a shape's box walks the shape's own pixels.
static bool span_inside (float cx, float dy, float reach, span_t *sp)
 Set sp to columns of the row dy from a centre at cx that lie at least a pixel nearer the centre than reach: inside it whatever a float's rounding does to the distance.
void gfx_fill_circle_aaf (gfx_canvas_t *c, float cx, float cy, float r, gfx_color_t col)
 A disc of radius r centred on (cx, cy), anti-aliased from each pixel's distance to the centre.
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.
static bool span_capsule (float ax, float ay, float ex, float ey, float reach, float y, span_t *sp)
 Narrow sp to the columns of row y that can lie nearer than reach to the segment from (ax, ay) along (ex, ey): the part of the segment within a pixel more than reach of the row, widened by that much and a pixel either side.
void gfx_capsule_aaf (gfx_canvas_t *c, float ax, float ay, float bx, float by, float thickness, gfx_color_t col)
 A capsule, a thick line with round ends, from (ax, ay) to (bx, by), anti-aliased from each pixel's distance to its spine.
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.
static float arc_depth (float ang_deg, float a0_deg, float span)
 How far into the arc from a0_deg over span degrees the direction ang_deg lies, in degrees: positive inside, from the nearer end; negative outside, to the nearer end.
static ring_cut_t ring_cut (float lo, float span, float inner, float fade_deg)
 The cut of a ring from lo over span degrees whose band starts at inner px, fading over fade_deg.
void gfx_ring_aaf (gfx_canvas_t *c, float cx, float cy, float r, float thickness, float a0_deg, float a1_deg, gfx_color_t col, gfx_color_t into, float fade_deg)
 A ring, or an arc of one, solved per pixel from its distance and direction to the centre.
static float dir_of (int x, int y, int cx, int cy)
 The direction of (x, y) from (cx, cy), degrees, up the screen as +90, as arc_walk() places its pixels.
static bool arc_window (const gfx_canvas_t *c, int cx, int cy, float r0, float r1, arc_dirs_t *out)
 Where an arc round (cx, cy) between radii r0 and r1 can reach the clip of c.
static bool arc_dir_in (const arc_dirs_t *w, float a_deg)
 Whether the direction a_deg is one of w's.
static void arc_walk (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_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)

Variables

int s_trace_hold
 The fit check's hold depth: 0 reports, more holds back.

Detailed Description

gfx: the RGB565 (16-bit red, green, blue) rasteriser. See include/gfx.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ GFX_MAX

#define GFX_MAX ( a,
b )
Value:
((a) > (b) ? (a) : (b))

◆ GFX_MIN

#define GFX_MIN ( a,
b )
Value:
((a) < (b) ? (a) : (b))

Function Documentation

◆ arc_depth()

float arc_depth ( float ang_deg,
float a0_deg,
float span )
static

How far into the arc from a0_deg over span degrees the direction ang_deg lies, in degrees: positive inside, from the nearer end; negative outside, to the nearer end.

Parameters
ang_degthe pixel's direction, -180 to 180deg
a0_degwhere the arc starts
spanits length, 0 to 360deg
Returns
the signed distance in degrees

◆ arc_dir_in()

bool arc_dir_in ( const arc_dirs_t * w,
float a_deg )
static

Whether the direction a_deg is one of w's.

Parameters
wthe directions
a_degthe direction, degrees, any turn
Returns
true when it is

◆ arc_window()

bool arc_window ( const gfx_canvas_t * c,
int cx,
int cy,
float r0,
float r1,
arc_dirs_t * out )
static

Where an arc round (cx, cy) between radii r0 and r1 can reach the clip of c.

A pixel arc_walk() lays lies within 1.5px of its step's point on the ray: its coordinates are truncated, not rounded, on the negative side. So a clip wholly nearer the centre than r0 - 3 or wholly further than r1 + 2 gets nothing, and a clip off the centre is reached only from the directions of its corners, widened by 3px of arc at r0 - 1. A repaint clipped to a box beside a dial walks the part of the dial's arc that passes the box, not all of it.

Parameters
cthe canvas
cxthe centre's column, px
cyits row, px
r0the inner radius, px
r1the outer radius, px
outthe directions to walk, when the clip can be reached
Returns
false when no pixel of the arc can land in the clip

◆ cov_blend()

void cov_blend ( gfx_canvas_t * c,
int x,
int y,
gfx_color_t col,
float cov )
static

One antialiased pixel: col over what is there, by cov.

Not reported to the damage record pixel by pixel: each caller reports the row's span once (GFX_DAMAGE), which in NORMAL saves a test per pixel.

Parameters
cthe canvas
xthe pixel's column
yits row
colthe colour
covthe coverage, 0 to 1; 1 and above writes col

◆ 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_capsule_aaf()

void gfx_capsule_aaf ( gfx_canvas_t * c,
float ax,
float ay,
float bx,
float by,
float thickness,
gfx_color_t col )

A capsule, a thick line with round ends, from (ax, ay) to (bx, by), anti-aliased from each pixel's distance to its spine.

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_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_circle_aaf()

void gfx_fill_circle_aaf ( gfx_canvas_t * c,
float cx,
float cy,
float r,
gfx_color_t col )

A disc of radius r centred on (cx, cy), anti-aliased from each pixel's distance to the centre.

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

void gfx_ring_aaf ( gfx_canvas_t * c,
float cx,
float cy,
float r,
float thickness,
float a0_deg,
float a1_deg,
gfx_color_t col,
gfx_color_t into,
float fade_deg )

A ring, or an arc of one, solved per pixel from its distance and direction to the centre.

gfx_arc_fade() walks its arc and rounds each step to a pixel. This one blends the band's two edges and the arc's two ends over half a pixel either side, the ends measured along the arc at each pixel's radius. A span of 360deg or more is the whole ring. A pixel whose centre lies half a pixel or more beyond the band or past an end is not touched.

Parameters
cthe canvas
cxthe centre's column, px
cythe centre's row, px
rthe band's middle radius, px
thicknessthe band's width, px
a0_degone end, degrees counter-clockwise from +x (90 is up)
a1_degthe other end, degrees
colthe colour
intothe colour each end fades from over fade_deg
fade_degthe fade's length, degrees; 0 for none

◆ 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

◆ ring_cut()

ring_cut_t ring_cut ( float lo,
float span,
float inner,
float fade_deg )
static

The cut of a ring from lo over span degrees whose band starts at inner px, fading over fade_deg.

Parameters
lothe arc's first direction, degrees
spanits length, under 360 degrees
innerthe band's inner edge, px
fade_degthe fade at each end, degrees, 0 for none
Returns
the cut; neither part when inner is under a pixel

◆ span_capsule()

bool span_capsule ( float ax,
float ay,
float ex,
float ey,
float reach,
float y,
span_t * sp )
static

Narrow sp to the columns of row y that can lie nearer than reach to the segment from (ax, ay) along (ex, ey): the part of the segment within a pixel more than reach of the row, widened by that much and a pixel either side.

Parameters
axthe segment's start column, px
ayits start row, px
exits run in columns, px
eyits run in rows, px
reachthe distance, px
ythe row, px
spthe run, narrowed in place
Returns
false when nothing of the row is left

◆ span_inside()

bool span_inside ( float cx,
float dy,
float reach,
span_t * sp )
static

Set sp to columns of the row dy from a centre at cx that lie at least a pixel nearer the centre than reach: inside it whatever a float's rounding does to the distance.

Parameters
cxthe centre's column, px
dythe row's distance from the centre's row, px
reachthe distance, px
spthe run: left empty, at sp->hi, when there is none; kept within the columns it held
Returns
true when the run holds a column

◆ span_round()

bool span_round ( float cx,
float dy,
float reach,
span_t * sp )
static

Narrow sp to the columns of the row dy from a centre at cx that can lie nearer the centre than reach: those more than a pixel further are left out, so a loop over a shape's box walks the shape's own pixels.

Parameters
cxthe centre's column, px
dythe row's distance from the centre's row, px
reachthe distance, px
spthe run, narrowed in place
Returns
false when nothing of the row is left