CHGame 0.3.0
Libraries for the CHGame handheld
Loading...
Searching...
No Matches
Draw.h
Go to the documentation of this file.
1/// @file Draw.h
2/// @brief The house drawing: rounded rects and panels, span sprites (plain,
3/// scaled, flipped, rotated), dithering, an in-place colour remap,
4/// convex polygons, column glyphs and PPOT's 3x5 font.
5///
6/// CHGfx 1.3 has its own versions of several of these (gfx_fillRoundRect,
7/// gfx_sprite4, gfx_dither, gfx_textFx with CHGfx_Tiny3x5, the same glyphs),
8/// written for generality; these are the casino games' smaller ones, the text
9/// about 2 KB smaller in flash. Both work on the same framebuffer: use either.
10///
11/// Everything here draws inside CHGfx's clip rectangle (gfx_setClip), like
12/// CHGfx's own primitives.
13///
14/// The rule on this chip: code runs from flash with 3 wait states, so a
15/// function call per pixel costs ~2-3 us. Everything here is built from
16/// gfx_hline spans (word stores, from SRAM) or tight byte and word loops, the
17/// hottest from SRAM.
18#pragma once
19#include <stdint.h>
20#include <CHGfx.h>
21
22/// @defgroup chgame_draw Drawing
23/// @ingroup lib_chgame
24/// @brief Panels, span sprites, dithering, polygons and the 3x5 font, drawn
25/// into CHGfx's framebuffer.
26///
27/// Colours are palette indices (0-15; see @ref chgame_palette). Coordinates
28/// are pixels, (0, 0) top left of the 128x128 screen; anything may lie partly
29/// or wholly off screen. Draw between gfx_wait() and the next flush.
30/// @{
31
32// ---------------------------------------------------------------------------
33// Shapes
34// ---------------------------------------------------------------------------
35/// @brief Fill a rectangle with rounded corners.
36/// @param x,y Top-left corner.
37/// @param w,h Size in pixels.
38/// @param r Corner radius, 0-4 (larger is 4; never more than half of h):
39/// pixel-art corners.
40/// @param c Colour.
41void fillRound(int x, int y, int w, int h, uint8_t r, uint8_t c); // r <= 4: pixel-art corners
42/// @brief Outline a rectangle with rounded corners, 1 px wide.
43/// @param x,y Top-left corner.
44/// @param w,h Size in pixels.
45/// @param r Corner radius, 0-4 as for fillRound(); 0 is a plain rectangle.
46/// @param c Colour.
47void roundRect(int x, int y, int w, int h, uint8_t r, uint8_t c);
48/// @brief A rounded panel: fillRound() in `fill`, then roundRect() in `edge`.
49/// Cards, plates, panels.
50/// @param x,y Top-left corner.
51/// @param w,h Size in pixels.
52/// @param r Corner radius, 0-4.
53/// @param fill Inside colour.
54/// @param edge Edge colour.
55void panel(int x, int y, int w, int h, uint8_t r, uint8_t fill, uint8_t edge);
56/// @brief A panel lit from above.
57/// @details A 1 px INK drop shadow outside (down and right), the edge, then
58/// inside a lighter top line and a darker bottom one (from LIGHTER and
59/// DARKER). The shadow makes it one pixel wider and taller than w x h.
60/// @param x,y Top-left corner.
61/// @param w,h Size in pixels, not counting the shadow.
62/// @param r Corner radius, 0-4.
63/// @param fill Inside colour (a house colour, so LIGHTER/DARKER know its shades).
64/// @param edge Edge colour.
65void panelLit(int x, int y, int w, int h, uint8_t r, uint8_t fill, uint8_t edge);
66/// @brief A raised rectangle's rim: light along the top and left, dark along the
67/// bottom and right.
68/// @param x,y Top-left corner.
69/// @param w,h Size in pixels.
70/// @param c The surface colour: the rim is LIGHTER[c] and DARKER[c].
71void bevel(int x, int y, int w, int h, uint8_t c);
72/// @brief A raised rectangle's rim in two given colours.
73/// @param x,y Top-left corner.
74/// @param w,h Size in pixels.
75/// @param light Colour of the top and left edges.
76/// @param dark Colour of the bottom and right edges.
77void bevel(int x, int y, int w, int h, uint8_t light, uint8_t dark);
78/** @var DARKER
79 * @brief One step darker for each house colour (@ref chgame_palette): the
80 * shading that gives panels, cards and chips their depth.
81 * @details `DARKER[FELT]` is FELT_DK, for instance. */
82/** @var LIGHTER
83 * @brief One step lighter for each house colour (@ref chgame_palette).
84 * @see DARKER */
85extern const uint8_t DARKER[16], LIGHTER[16];
86
87/// @brief A 50% checkerboard of one colour over a rectangle; the pixels in
88/// between are left alone (darkened backdrops, shadows).
89/// @param x,y Top-left corner.
90/// @param w,h Size in pixels.
91/// @param c Colour.
92/// @param phase 0 paints the pixels where x + y is even, 1 where it is odd.
93void dither(int x, int y, int w, int h, uint8_t c, uint8_t phase); // 50% checker
94/// @brief A round spotlight: a disc of dots, on 25% of its pixels (every other
95/// pixel of every other row).
96/// @param cx,cy Centre.
97/// @param r Radius in pixels.
98/// @param c Colour of the dots (WHITE behind the dealer, for instance).
99void spotlight(int cx, int cy, int r, uint8_t c);
100/// @brief A soft shadow (a 50% INK checker) 2 px below and right of a box.
101/// @param x,y Top-left corner of the box casting it.
102/// @param w,h Size of the box.
103void dropShadow(int x, int y, int w, int h);
104/// @brief Recolour a rectangle in place: pixel = remap[pixel] (dimming, highlighting).
105/// @param x,y Top-left corner.
106/// @param w,h Size in pixels.
107/// @param remap Sixteen colours, the new colour for each old one.
108void remapRect(int x, int y, int w, int h, const uint8_t *remap);
109/// @brief Fill a convex polygon.
110/// @details Filled by pixel centres, so polygons sharing an edge neither
111/// overlap nor leave a gap. The corners may go in either winding order.
112/// @param xy n corners as x, y pairs, in 1/16 px.
113/// @param n Number of corners, at most 8.
114/// @param c Colour.
115/// @param dither -1 (default): solid. 0 or 1: a 50% checker of c instead,
116/// with that phase as dither()'s.
117void fillConvex(const int16_t *xy, uint8_t n, uint8_t c, int dither = -1);
118
119// ---------------------------------------------------------------------------
120// Span sprites
121// ---------------------------------------------------------------------------
122/// @brief sprite4() flags.
123enum : uint8_t {
124 SPR_FLIP_V = 1, ///< Upside down.
125 SPR_FLIP_H = 2 ///< Mirrored left to right (1:1 scale only).
127/// @brief Draw span4 art, through a remap and at a scale.
128/// @details span4 art (tools/assets.py pack_span4): w, h, then per row a count
129/// and (len-1)<<4|colour bytes, colour 15 = skip. Every pixel goes through
130/// the remap, so one image serves many looks (a team colour, a hit flash).
131/// @param data The art.
132/// @param x,y Where its top-left corner goes.
133/// @param remap A colour for each of 0..14; nullptr or RM_ID: as drawn.
134/// @param scale Q8: 256 = 1:1 (the fast path), 512 = double, 128 = half.
135/// @param flip 0, or SPR_FLIP_V and/or SPR_FLIP_H.
136void sprite4(const uint8_t *data, int x, int y, const uint8_t *remap = nullptr, int scale = 256,
137 uint8_t flip = 0);
138/// @brief The identity remap (every colour to itself).
139extern const uint8_t RM_ID[16]; // the identity remap
140/// @brief Draw span4 art turned and scaled about a pivot.
141/// @details Decodes into the CHGfx chunk scratch, so it is for drawing time
142/// only (between gfx_wait() and the flush), and the art must unpack to 1 KB
143/// at most (e.g. 32x60). Larger art draws nothing.
144/// @param data The art (as sprite4()).
145/// @param ax,ay The pivot, a pixel of the art.
146/// @param px,py Where the pivot lands on screen.
147/// @param angle The turn, 256 = one full turn, clockwise on screen.
148/// @param scale Q8, 256 = 1:1.
149/// @param remap As sprite4() (nullptr: as drawn).
150void spriteRot(const uint8_t *data, int ax, int ay, int px, int py, uint8_t angle, int scale,
151 const uint8_t *remap);
152/// @brief spriteRot() for raw 4 bpp art the caller has put in the chunk scratch.
153/// @param w,h Size of the art in gfx_chunkScratch(): rows of (w + 1) / 2
154/// bytes, low nibble first, 15 = clear.
155/// @param ax,ay The pivot, a pixel of the art.
156/// @param px,py Where the pivot lands on screen.
157/// @param angle The turn, 256 = one full turn.
158/// @param scale Q8, 256 = 1:1.
159/// @param remap As sprite4() (nullptr: as drawn).
160void rotRaw(int w, int h, int ax, int ay, int px, int py, uint8_t angle, int scale,
161 const uint8_t *remap);
162
163// ---------------------------------------------------------------------------
164// Glyphs and the 3x5 font
165// ---------------------------------------------------------------------------
166/// @brief Draw a column-major 1 bpp glyph (bit 0 = top row, up to 8 rows).
167/// @param x,y Top-left corner.
168/// @param cols One byte per column.
169/// @param ncols Number of columns.
170/// @param c Colour of the set bits; clear bits are left alone.
171void glyph(int x, int y, const uint8_t *cols, uint8_t ncols, uint8_t c);
172/// @brief Draw a row-major 1 bpp glyph up to 16 wide (the leftmost pixel in bit 15).
173/// @param x,y Top-left corner.
174/// @param rows One uint16_t per row.
175/// @param nrows Number of rows.
176/// @param c Colour of the set bits; clear bits are left alone.
177void glyph16(int x, int y, const uint16_t *rows, uint8_t nrows, uint8_t c);
178
179/// @brief Draw text in PPOT's 3x5 font.
180/// @details Capitals, lower case (with descenders), figures and punctuation.
181/// 4 px advance, '~' = a 2 px space, '\\n' = 7 px down (back to x).
182/// Characters the font lacks are skipped (a 4 px gap).
183/// @param x,y Top-left corner of the first character.
184/// @param str The text.
185/// @param c Colour.
186/// @return The advance of the last line in pixels (4 a character, 2 a '~').
187int text35(int x, int y, const char *str, uint8_t c);
188/// @brief The width of text in the 3x5 font, without the trailing gap: for centring.
189/// @param str The text; with '\\n', the widest line.
190/// @return Its width in pixels (0 for "").
191int text35Width(const char *str);
192/// @brief text35() over its own shade a pixel down and right (embossed).
193/// @param x,y Top-left corner.
194/// @param str The text.
195/// @param c Colour of the letters.
196/// @param shade Colour of the shade (default INK).
197/// @return As text35().
198int text35s(int x, int y, const char *str, uint8_t c, uint8_t shade = 0);
199/// @brief The 3x5 font doubled (8 px advance, 12 rows with the descender): menus.
200/// @details Each font pixel is a 2x2 block; '\\n' goes 14 px down. Drawn from
201/// flash: for menus and titles, not for text redrawn every frame.
202/// @param x,y Top-left corner.
203/// @param str The text.
204/// @param c Colour.
205void text35x2(int x, int y, const char *str, uint8_t c);
206/// @brief text35x2() over its own shade a pixel down and right.
207/// @param x,y Top-left corner.
208/// @param str The text.
209/// @param c Colour of the letters.
210/// @param shade Colour of the shade (default INK).
211void text35x2s(int x, int y, const char *str, uint8_t c, uint8_t shade = 0);
212/// @brief The width of text drawn with text35x2().
213/// @param str The text.
214/// @return Its width in pixels: twice text35Width().
215inline int text35x2Width(const char *str) { return text35Width(str) * 2; }
216/// @brief A character of the 3x5 font, for drawing it yourself with glyph().
217/// @param ch The character.
218/// @return Its three column bytes, or nullptr if the font has no such character.
219const uint8_t *glyph35(char ch); // its three column bytes, nullptr = none
220
221/// @}
CHGfx: a maximum-throughput ST7735 driver for the CHGame board (CH32X035G8U6 @ 48 MHz,...
void fillRound(int x, int y, int w, int h, uint8_t r, uint8_t c)
Fill a rectangle with rounded corners.
void spriteRot(const uint8_t *data, int ax, int ay, int px, int py, uint8_t angle, int scale, const uint8_t *remap)
Draw span4 art turned and scaled about a pivot.
void sprite4(const uint8_t *data, int x, int y, const uint8_t *remap=nullptr, int scale=256, uint8_t flip=0)
Draw span4 art, through a remap and at a scale.
void spotlight(int cx, int cy, int r, uint8_t c)
A round spotlight: a disc of dots, on 25% of its pixels (every other pixel of every other row).
void glyph16(int x, int y, const uint16_t *rows, uint8_t nrows, uint8_t c)
Draw a row-major 1 bpp glyph up to 16 wide (the leftmost pixel in bit 15).
void rotRaw(int w, int h, int ax, int ay, int px, int py, uint8_t angle, int scale, const uint8_t *remap)
spriteRot() for raw 4 bpp art the caller has put in the chunk scratch.
int text35Width(const char *str)
The width of text in the 3x5 font, without the trailing gap: for centring.
int text35(int x, int y, const char *str, uint8_t c)
Draw text in PPOT's 3x5 font.
void dropShadow(int x, int y, int w, int h)
A soft shadow (a 50% INK checker) 2 px below and right of a box.
void glyph(int x, int y, const uint8_t *cols, uint8_t ncols, uint8_t c)
Draw a column-major 1 bpp glyph (bit 0 = top row, up to 8 rows).
int text35x2Width(const char *str)
The width of text drawn with text35x2().
Definition Draw.h:215
void roundRect(int x, int y, int w, int h, uint8_t r, uint8_t c)
Outline a rectangle with rounded corners, 1 px wide.
const uint8_t RM_ID[16]
The identity remap (every colour to itself).
int text35s(int x, int y, const char *str, uint8_t c, uint8_t shade=0)
text35() over its own shade a pixel down and right (embossed).
void text35x2(int x, int y, const char *str, uint8_t c)
The 3x5 font doubled (8 px advance, 12 rows with the descender): menus.
void fillConvex(const int16_t *xy, uint8_t n, uint8_t c, int dither=-1)
Fill a convex polygon.
void panelLit(int x, int y, int w, int h, uint8_t r, uint8_t fill, uint8_t edge)
A panel lit from above.
void bevel(int x, int y, int w, int h, uint8_t c)
A raised rectangle's rim: light along the top and left, dark along the bottom and right.
void panel(int x, int y, int w, int h, uint8_t r, uint8_t fill, uint8_t edge)
A rounded panel: fillRound() in fill, then roundRect() in edge.
void text35x2s(int x, int y, const char *str, uint8_t c, uint8_t shade=0)
text35x2() over its own shade a pixel down and right.
const uint8_t LIGHTER[16]
One step lighter for each house colour (Palette).
Definition Draw.h:85
const uint8_t DARKER[16]
One step darker for each house colour (Palette): the shading that gives panels, cards and chips their...
void dither(int x, int y, int w, int h, uint8_t c, uint8_t phase)
A 50% checkerboard of one colour over a rectangle; the pixels in between are left alone (darkened bac...
void remapRect(int x, int y, int w, int h, const uint8_t *remap)
Recolour a rectangle in place: pixel = remap[pixel] (dimming, highlighting).
const uint8_t * glyph35(char ch)
A character of the 3x5 font, for drawing it yourself with glyph().
@ SPR_FLIP_V
Upside down.
Definition Draw.h:124
@ SPR_FLIP_H
Mirrored left to right (1:1 scale only).
Definition Draw.h:125