// 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 #include 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(r) << 16) | (static_cast(g) << 8) | static_cast(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