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

gfx text: UTF-8 (Unicode Transformation Format, 8-bit) decoding, glyph drawing, string measuring and the rotated dither stencil. See include/gfx.h and gfx_int.h. More...

#include "gfx_int.h"
#include "gfx_work.h"
#include <math.h>

Functions

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)
static int glyph_index (const gfx_font_t *font, uint32_t cp)
 The glyph index of code point cp, or -1 when the font has none. The extra list is a handful long, so a scan costs less than a table would.
static const uint8_t * glyph_rows (const gfx_font_t *font, uint32_t cp)
 The rows of cp's glyph, or of '?' when the font has none; NULL when it has neither.
static uint8_t glyph_cov (const gfx_font_t *font, const uint8_t *line, int col)
 One glyph pixel's coverage, 0 transparent to 255 solid.
int gfx_text_height (const gfx_font_t *font, int scale)
int gfx_text_width (const gfx_font_t *font, const char *s, int scale)
static bool cell_meets_clip (const gfx_canvas_t *c, int x, int y, int w, int h)
 Whether a glyph's cell at (x, y), w by h px, reaches the clip of c. A cell wholly outside it draws nothing, so its rows are not walked: a repaint clipped to a box pays for the glyphs in the box, not for every glyph of the card.
static int draw_glyph (gfx_canvas_t *c, int x, int y, uint32_t cp, const gfx_font_t *font, gfx_color_t fg, int scale)
 The glyph of cp at (x, y) in fg, scale times its size; a cell wholly outside the clip is not walked.
int gfx_char (gfx_canvas_t *c, int x, int y, char ch, const gfx_font_t *font, gfx_color_t fg, int scale)
static int text_run (gfx_canvas_t *c, int x, int y, const char *s, const gfx_font_t *font, gfx_color_t fg, int scale)
 The string, decoded; the public calls below trace it first.
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)
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)
static int rotated_stencil (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, uint32_t *out, int max_out)
 One scan of the rotated stencil. With out NULL the covered pixels are written; otherwise they are recorded as packed y:x and nothing is drawn, and the return is the count, or -1 when more than max_out are covered.
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).
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)

Variables

static const uint8_t k_bayer8 [64]
 An 8x8 ordered-dither threshold, used by gfx_text_rotated below.

Detailed Description

gfx text: UTF-8 (Unicode Transformation Format, 8-bit) decoding, glyph drawing, string measuring and the rotated dither stencil. See include/gfx.h and gfx_int.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ cell_meets_clip()

bool cell_meets_clip ( const gfx_canvas_t * c,
int x,
int y,
int w,
int h )
static

Whether a glyph's cell at (x, y), w by h px, reaches the clip of c. A cell wholly outside it draws nothing, so its rows are not walked: a repaint clipped to a box pays for the glyphs in the box, not for every glyph of the card.

Parameters
cthe canvas, or NULL
xthe cell's left edge, px
yits top, px
wits width, px
hits height, px
Returns
true when some of the cell is inside the clip

◆ draw_glyph()

int draw_glyph ( gfx_canvas_t * c,
int x,
int y,
uint32_t cp,
const gfx_font_t * font,
gfx_color_t fg,
int scale )
static

The glyph of cp at (x, y) in fg, scale times its size; a cell wholly outside the clip is not walked.

Returns
the advance, px

◆ 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_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_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.

◆ glyph_cov()

uint8_t glyph_cov ( const gfx_font_t * font,
const uint8_t * line,
int col )
static

One glyph pixel's coverage, 0 transparent to 255 solid.

Both formats go through here so the blitters below do not each carry a branch on the font's depth: a 1bpp face answers 0 or 255 and an 8bpp one answers what it stored.

◆ rotated_stencil()

int rotated_stencil ( 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,
uint32_t * out,
int max_out )
static

One scan of the rotated stencil. With out NULL the covered pixels are written; otherwise they are recorded as packed y:x and nothing is drawn, and the return is the count, or -1 when more than max_out are covered.

The mark covers under 1% of a canvas it spans corner to corner, so a caller that draws it every frame records the points once and replays them rather than rotating and dividing per pixel across the whole canvas again.

Variable Documentation

◆ k_bayer8

const uint8_t k_bayer8[64]
static
Initial value:
= {
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21,
}

An 8x8 ordered-dither threshold, used by gfx_text_rotated below.