15
16
17
18
19
20
21
22
23
24template <
typename PixelT>
39 return resize(width_, height_);
51 void setPixel(size_t x, size_t y, PixelT color)
override = 0;
54 PixelT
getPixel(size_t x, size_t y)
const override = 0;
69 bool resize(size_t newWidth, size_t newHeight)
override {
72 return resizeBuffer(newWidth, newHeight);
85 void clear(PixelT color = PixelT())
override {
86 for (size_t y = 0; y < height_; ++y) {
87 for (size_t x = 0; x < width_; ++x) {
88 setPixel(x, y, color);
95 if (dx == 0 && dy == 0)
return;
96 Vector<PixelT> newBuffer(width_ * height_);
97 for (size_t y = 0; y < height_; ++y) {
98 for (size_t x = 0; x < width_; ++x) {
99 int srcX = (
int)x + dx;
100 int srcY = (
int)y + dy;
101 PixelT color = (srcX >= 0 && srcX < (
int)width_ && srcY >= 0 &&
103 ? getPixel(srcX, srcY)
105 newBuffer[y * width_ + x] = color;
109 for (size_t i = 0; i < newBuffer.size(); ++i) {
110 setPixel(i % width_, i / width_, newBuffer[i]);
115 void drawLine(size_t x0, size_t y0, size_t x1, size_t y1,
116 PixelT color)
override {
117 int dx = std::abs((
int)x1 - (
int)x0), sx = x0 < x1 ? 1 : -1;
118 int dy = -std::abs((
int)y1 - (
int)y0), sy = y0 < y1 ? 1 : -1;
119 int err = dx + dy, e2;
121 setPixelClipped(x0, y0, color);
122 if (x0 == x1 && y0 == y1)
break;
136 void drawRect(size_t x, size_t y, size_t w, size_t h, PixelT color)
override {
137 if (w == 0 || h == 0)
return;
138 size_t x1 = x + w - 1, y1 = y + h - 1;
139 drawLine(x, y, x1, y, color);
140 drawLine(x, y1, x1, y1, color);
141 drawLine(x, y, x, y1, color);
142 drawLine(x1, y, x1, y1, color);
146 void fillRect(size_t x, size_t y, size_t w, size_t h, PixelT color)
override {
147 if (w == 0 || h == 0)
return;
148 size_t endX = std::min(x + w, width_);
149 size_t endY = std::min(y + h, height_);
150 for (size_t yy = y; yy < endY; ++yy) {
151 for (size_t xx = x; xx < endX; ++xx) {
152 setPixel(xx, yy, color);
158 void drawCircle(size_t x, size_t y, size_t r, PixelT color)
override {
159 int offsetX = r, offsetY = 0, decision = 1 - (
int)offsetX;
160 while (offsetX >= offsetY) {
161 setPixelClipped(x + offsetX, y + offsetY, color);
162 setPixelClipped(x + offsetY, y + offsetX, color);
163 setPixelClipped(x - offsetY, y + offsetX, color);
164 setPixelClipped(x - offsetX, y + offsetY, color);
165 setPixelClipped(x - offsetX, y - offsetY, color);
166 setPixelClipped(x - offsetY, y - offsetX, color);
167 setPixelClipped(x + offsetY, y - offsetX, color);
168 setPixelClipped(x + offsetX, y - offsetY, color);
171 decision += 2 * offsetY + 1;
174 decision += 2 * (offsetY - offsetX) + 1;
180 void fillCircle(size_t x, size_t y, size_t r, PixelT color)
override {
181 int offsetX = r, offsetY = 0, decision = 1 - (
int)offsetX;
182 while (offsetX >= offsetY) {
183 drawHorizontalLineClipped(x - offsetX, x + offsetX, y + offsetY, color);
184 drawHorizontalLineClipped(x - offsetX, x + offsetX, y - offsetY, color);
185 drawHorizontalLineClipped(x - offsetY, x + offsetY, y + offsetX, color);
186 drawHorizontalLineClipped(x - offsetY, x + offsetY, y - offsetX, color);
189 decision += 2 * offsetY + 1;
192 decision += 2 * (offsetY - offsetX) + 1;
198 void drawSprite(size_t x, size_t y,
const ISurface<PixelT>& sprite,
199 PixelT invisibleColor = PixelT())
override {
200 for (size_t spriteY = 0; spriteY < sprite.height(); ++spriteY) {
201 for (size_t spriteX = 0; spriteX < sprite.width(); ++spriteX) {
202 PixelT color = sprite.getPixel(spriteX, spriteY);
203 if (color != invisibleColor) {
204 setPixelClipped(x + spriteX, y + spriteY, color);
212 PixelT clearColor = PixelT())
override {
213 for (size_t spriteY = 0; spriteY < sprite.height(); ++spriteY) {
214 for (size_t spriteX = 0; spriteX < sprite.width(); ++spriteX) {
215 setPixelClipped(x + spriteX, y + spriteY, clearColor);
221 void copySprite(size_t x, size_t y,
const ISurface<PixelT>& sprite)
override {
222 for (size_t spriteY = 0; spriteY < sprite.height(); ++spriteY) {
223 for (size_t spriteX = 0; spriteX < sprite.width(); ++spriteX) {
224 size_t framebufferX = x + spriteX;
225 size_t framebufferY = y + spriteY;
226 PixelT color = (framebufferX < width_ && framebufferY < height_)
227 ? getPixel(framebufferX, framebufferY)
229 const_cast<ISurface<PixelT>&>(sprite).setPixel(spriteX, spriteY, color);
236 void drawText(int16_t x, int16_t y,
const char* text, PixelT foreground,
237 PixelT background = PixelT(),
bool opaque =
false,
238 uint8_t scale = 1, uint8_t spacing = 1,
239 uint8_t lineSpacing = 1)
override {
240 font_->drawText(*
this, x, y, text, foreground, background, opaque, scale,
241 spacing, lineSpacing);
253 return x < width_ && y < height_;
257 if (isInBounds(x, y)) setPixel(x, y, color);
261 if (y < 0 || (size_t)y >= height_)
return;
262 int startX = std::max(0, std::min(x0, x1));
263 int endX = std::min((
int)width_ - 1, std::max(x0, x1));
264 if (startX > endX)
return;
265 for (
int x = startX; x <= endX; ++x) setPixel(x, y, color);
Font rendering interface for TinyGPU-compatible framebuffers.
Definition: IFont.h:19
Helper for printing wrapped lines of text onto a TinyGPU target.
Definition: LinePrinter.h:17
Base class for 2D surfaces with drawing and text rendering support.
Definition: SurfaceBase.h:25
void drawLine(size_t x0, size_t y0, size_t x1, size_t y1, PixelT color) override
Draw a line from (x0, y0) to (x1, y1) with the given color.
Definition: SurfaceBase.h:115
void fillRect(size_t x, size_t y, size_t w, size_t h, PixelT color) override
Fill a rectangle at (x, y) with width w, height h, and color.
Definition: SurfaceBase.h:146
void setPixelClipped(size_t x, size_t y, PixelT color)
Set a pixel only if (x, y) is in bounds.
Definition: SurfaceBase.h:256
void clearSprite(size_t x, size_t y, ISurface< PixelT > &sprite, PixelT clearColor=PixelT()) override
Clear the region covered by a sprite at (x, y) to clearColor.
Definition: SurfaceBase.h:211
PixelT getPixel(size_t x, size_t y) const override=0
Abstract method: get the pixel color at (x, y).
IFont< PixelT > * font_
Definition: SurfaceBase.h:271
void drawSprite(size_t x, size_t y, const ISurface< PixelT > &sprite, PixelT invisibleColor=PixelT()) override
Draw a sprite at (x, y), skipping pixels matching invisibleColor.
Definition: SurfaceBase.h:198
void drawCircle(size_t x, size_t y, size_t r, PixelT color) override
Draw a circle outline centered at (x, y) with radius r and color.
Definition: SurfaceBase.h:158
void setFont(IFont< PixelT > &font)
Set the font for text rendering.
Definition: SurfaceBase.h:57
size_t width_
Definition: SurfaceBase.h:269
IFont< PixelT > & font() override
Get the current font (mutable).
Definition: SurfaceBase.h:63
bool begin()
Initializes the surface by resizing it to the current dimensions.
Definition: SurfaceBase.h:38
size_t height_
Definition: SurfaceBase.h:270
const IFont< PixelT > & font() const
Get the current font (const).
Definition: SurfaceBase.h:66
void drawRect(size_t x, size_t y, size_t w, size_t h, PixelT color) override
Draw a rectangle outline at (x, y) with width w, height h, and color.
Definition: SurfaceBase.h:136
size_t height() const override
Get the height of the surface.
Definition: SurfaceBase.h:79
SurfaceBase(size_t width, size_t height, IFont< PixelT > &font)
Construct with width, height, and font.
Definition: SurfaceBase.h:31
LinePrinter< PixelT > & linePrinter()
Get the line printer for this surface.
Definition: SurfaceBase.h:245
void clear(PixelT color=PixelT()) override
Clears the framebuffer with a single color.
Definition: SurfaceBase.h:85
void drawText(int16_t x, int16_t y, const char *text, PixelT foreground, PixelT background=PixelT(), bool opaque=false, uint8_t scale=1, uint8_t spacing=1, uint8_t lineSpacing=1) override
Definition: SurfaceBase.h:236
void setPixel(size_t x, size_t y, PixelT color) override=0
Abstract method: set a pixel at (x, y) to the specified color.
void fillCircle(size_t x, size_t y, size_t r, PixelT color) override
Fill a circle centered at (x, y) with radius r and color.
Definition: SurfaceBase.h:180
void scroll(int dx, int dy)
Scroll the surface content by (dx, dy) pixels.
Definition: SurfaceBase.h:94
void end()
Clears the surface and releases any allocated resources.
Definition: SurfaceBase.h:43
virtual bool resizeBuffer(size_t, size_t)=0
SurfaceBase()=default
Default constructor.
size_t width() const override
Get the width of the surface.
Definition: SurfaceBase.h:76
LinePrinter< PixelT > linePrinter_
Definition: SurfaceBase.h:272
~SurfaceBase() override=default
Virtual destructor.
bool resize(size_t newWidth, size_t newHeight) override
Resize the surface to new dimensions.
Definition: SurfaceBase.h:69
void copySprite(size_t x, size_t y, const ISurface< PixelT > &sprite) override
Copy the framebuffer region at (x, y) into the sprite.
Definition: SurfaceBase.h:221
void drawHorizontalLineClipped(int x0, int x1, int y, PixelT color)
Draw a horizontal line from x0 to x1 at y, clipped to bounds.
Definition: SurfaceBase.h:260
bool isInBounds(size_t x, size_t y) const
Returns true if (x, y) is within the surface bounds.
Definition: SurfaceBase.h:252
Definition: AVIWriter.h:9