Files
GfxCanvas/gfx_canvas.h

177 lines
6.8 KiB
C++

// gfx_canvas.h — Minimal embedded graphics library.
//
// Zero dynamic allocation. No exceptions. C++23 compatible.
// Compatible with glibc and newlib.
//
// Color model: XRGB8888 (uint32_t) everywhere in the public API.
// The HAL subclass converts to whatever the hardware needs.
#ifndef GFX_CANVAS_H
#define GFX_CANVAS_H
#include <cstddef>
#include <cstdint>
namespace gfx {
// ---------------------------------------------------------------------------
// Color
// ---------------------------------------------------------------------------
using Color = uint32_t; // 0x00RRGGBB
namespace colors {
inline constexpr Color black = 0x00000000;
inline constexpr Color white = 0x00FFFFFF;
inline constexpr Color red = 0x00FF0000;
inline constexpr Color green = 0x0000FF00;
inline constexpr Color blue = 0x000000FF;
inline constexpr Color yellow = 0x00FFFF00;
inline constexpr Color cyan = 0x0000FFFF;
inline constexpr Color magenta = 0x00FF00FF;
} // namespace colors
constexpr Color rgb(uint8_t r, uint8_t g, uint8_t b) {
return (static_cast<uint32_t>(r) << 16) |
(static_cast<uint32_t>(g) << 8) |
static_cast<uint32_t>(b);
}
// ---------------------------------------------------------------------------
// Font — fixed-width, column-major encoding
//
// Each glyph occupies glyph_width consecutive bytes.
// Each byte is one column, bit 0 = topmost row, bit (glyph_height-1) = bottom.
// This is the standard encoding used by SSD1306 fonts, u8g2 legacy fonts,
// and the classic Adafruit 5x7 glcdfont.
// ---------------------------------------------------------------------------
struct Font {
const uint8_t* bitmap; // glyph data, column-major
uint8_t glyph_width; // pixels per glyph (all glyphs same width)
uint8_t glyph_height; // pixels tall
uint8_t first_char; // first codepoint (usually 0x20)
uint8_t last_char; // last codepoint (usually 0x7E)
uint8_t x_advance; // horizontal cursor step (width + spacing)
uint8_t y_advance; // vertical line step (height + spacing)
};
// ---------------------------------------------------------------------------
// Rotation
// ---------------------------------------------------------------------------
enum class Rotation : uint8_t {
deg_0 = 0,
deg_90 = 1,
deg_180 = 2,
deg_270 = 3,
};
// ---------------------------------------------------------------------------
// GfxCanvas — abstract base class
// ---------------------------------------------------------------------------
class GfxCanvas {
public:
GfxCanvas(int16_t width, int16_t height);
virtual ~GfxCanvas() = default;
GfxCanvas(const GfxCanvas&) = delete;
GfxCanvas& operator=(const GfxCanvas&) = delete;
GfxCanvas(GfxCanvas&&) = delete;
GfxCanvas& operator=(GfxCanvas&&) = delete;
// --- Pixel ----------------------------------------------------------
void drawPixel(int16_t x, int16_t y, Color color);
// --- Lines ----------------------------------------------------------
void drawHLine(int16_t x, int16_t y, int16_t w, Color color);
void drawVLine(int16_t x, int16_t y, int16_t h, Color color);
void drawLine(int16_t x0, int16_t y0,
int16_t x1, int16_t y1, Color color);
// --- Rectangles -----------------------------------------------------
void drawRect(int16_t x, int16_t y,
int16_t w, int16_t h, Color color);
void fillRect(int16_t x, int16_t y,
int16_t w, int16_t h, Color color);
// --- Circles --------------------------------------------------------
void drawCircle(int16_t cx, int16_t cy, int16_t r, Color color);
void fillCircle(int16_t cx, int16_t cy, int16_t r, Color color);
// --- Rounded rectangles ---------------------------------------------
void drawRoundRect(int16_t x, int16_t y,
int16_t w, int16_t h,
int16_t r, Color color);
void fillRoundRect(int16_t x, int16_t y,
int16_t w, int16_t h,
int16_t r, Color color);
// --- Triangles ------------------------------------------------------
void drawTriangle(int16_t x0, int16_t y0,
int16_t x1, int16_t y1,
int16_t x2, int16_t y2, Color color);
void fillTriangle(int16_t x0, int16_t y0,
int16_t x1, int16_t y1,
int16_t x2, int16_t y2, Color color);
// --- Screen ---------------------------------------------------------
void fillScreen(Color color);
// --- Text -----------------------------------------------------------
void setFont(const Font& font);
void setCursor(int16_t x, int16_t y);
void setTextColor(Color fg);
void setTextColor(Color fg, Color bg);
void setTextWrap(bool wrap);
void drawChar(int16_t x, int16_t y, char c, Color fg, Color bg) const;
void drawString(int16_t x, int16_t y, const char* str, Color color);
void print(const char* str);
void print(char c);
void getTextBounds(const char* str, int16_t cx, int16_t cy,
int16_t& bx, int16_t& by,
uint16_t& bw, uint16_t& bh) const;
// --- Rotation -------------------------------------------------------
void setRotation(Rotation r);
Rotation rotation() const { return rotation_; }
// --- Geometry -------------------------------------------------------
int16_t width() const;
int16_t height() const;
int16_t rawWidth() const { return raw_width_; }
int16_t rawHeight() const { return raw_height_; }
protected:
// === HAL — subclass must implement drawPixelImpl ===================
virtual void drawPixelImpl(int16_t x, int16_t y, Color color) = 0;
// === HAL — optional fast-path overrides ============================
virtual void drawHLineImpl(int16_t x, int16_t y, int16_t w, Color color);
virtual void drawVLineImpl(int16_t x, int16_t y, int16_t h, Color color);
virtual void fillRectImpl(int16_t x, int16_t y,
int16_t w, int16_t h, Color color);
private:
int16_t raw_width_;
int16_t raw_height_;
int16_t cursor_x_ = 0;
int16_t cursor_y_ = 0;
Color text_fg_ = colors::white;
Color text_bg_ = colors::black;
bool text_bg_opaque_ = false;
bool text_wrap_ = true;
Rotation rotation_ = Rotation::deg_0;
const Font* font_ = nullptr;
// Internal helpers for circle quadrant drawing.
void drawCircleQuadrants(int16_t cx, int16_t cy, int16_t r,
uint8_t corners, Color color);
void fillCircleSpans(int16_t cx, int16_t cy, int16_t r,
uint8_t corners, int16_t delta, Color color);
};
} // namespace gfx
#endif // GFX_CANVAS_H