TinyGPU
Loading...
Searching...
No Matches
FrameBuffer.h
Go to the documentation of this file.
1
2#pragma once
3#include <algorithm>
4#include <cmath>
5#include <cstring>
6#include <memory>
7
8#include "TinyGPU/Surface/Surface.h"
9#include "TinyGPU/ThreeD/Vector.h"
10#include "TinyGPUConfig.h"
11#include "TinyGPU/Util/TinyGPULogger.h"
12#include "TinyGPU/Input/TouchDriver.h"
13#include "TinyGPU/Surface/SpriteInfo.h"
14
15namespace tinygpu {
16
17/**
18 * @brief Framebuffer with sprite placement and background restoration support.
19 *
20 * The class extends TinyGPU with sprite bookkeeping so sprites can be added,
21 * moved, scaled, and removed while preserving the pixels behind them.
22 */
23template <typename RGB_T = RGB565, typename SurfaceT = Surface<RGB_T>>
24class FrameBuffer : public ISurface<RGB_T> {
25 public:
26 /// Creates an empty framebuffer.
27 FrameBuffer() = default;
28
29 /// Creates a framebuffer with the specified size and font.
30 FrameBuffer(size_t width, size_t height, IFont<RGB_T>& font)
32
33 bool begin() override { return surface_.begin(); }
34 void end() override { surface_.end(); }
35
36 void setTouchDriver(TouchDriver& touch) { p_touchDriver = &touch; }
37
38 /// Adds a sprite to the framebuffer and draws it at the given position.
39 SpriteInfo<RGB_T, SurfaceT>& addSprite(size_t x, size_t y, const ISurface<RGB_T>& sprite,
40 RGB_T invisibleColor = RGB_T(0)) {
41 TinyGPULogger.log(TinyGPULoggerClass::INFO, "Adding sprite at (%zu, %zu)",
42 x, y);
43 auto info = std::make_unique<SpriteInfo<RGB_T, SurfaceT>>(x, y, sprite, invisibleColor,
44 activeFont());
45
46 info->saveOriginalPixels(surface_);
47 surface_.drawSprite(x, y, info->currentSprite(), invisibleColor);
48
49 sprites_.push_back(std::move(info));
50 return *sprites_.back();
51 }
52
53 /// Adds a sprite with a preallocated max buffer size for transformations.
54 SpriteInfo<RGB_T, SurfaceT>& addSprite(size_t x, size_t y, size_t maxX, size_t maxY,
55 const ISurface<RGB_T>& sprite,
56 RGB_T invisibleColor = RGB_T(0)) {
57 TinyGPULogger.log(TinyGPULoggerClass::INFO,
58 "Adding sprite at (%zu, %zu) with max size (%zu, %zu)", x,
59 y, maxX, maxY);
60 auto info = std::make_unique<SpriteInfo<RGB_T, SurfaceT>>(x, y, sprite, invisibleColor,
61 activeFont());
62 info->setMaxSize(maxX, maxY);
63 info->saveOriginalPixels(surface_);
64 surface_.drawSprite(x, y, info->currentSprite(), invisibleColor);
65 sprites_.push_back(std::move(info));
66 return *sprites_.back();
67 }
68
69 /// Removes a sprite and restores the pixels behind it.
70 void removeSprite(SpriteInfo<RGB_T, SurfaceT>& spriteInfo) {
71 TinyGPULogger.log(TinyGPULoggerClass::INFO, "Removing sprite at (%zu, %zu)",
72 spriteInfo.x, spriteInfo.y);
74 auto it = tinygpu::findSprite(sprites_, spriteInfo);
75 if (it != sprites_.end()) {
76 sprites_.erase(it);
77 }
78 }
79
80 /// Returns a pointer to the sprite at the given position, if any.
81 SpriteInfo<RGB_T, SurfaceT>* getSprite(size_t x, size_t y) {
82 for (auto& sprite : sprites_) {
83 if (x >= sprite->x && x < sprite->x + sprite->currentSprite().width() &&
84 y >= sprite->y && y < sprite->y + sprite->currentSprite().height()) {
85 return sprite.get();
86 }
87 }
88 return nullptr;
89 }
90
91
92 /// Returns the number of sprites currently managed by the framebuffer.
93 size_t getSpriteCount() const { return sprites_.size(); }
94
95 /// Returns a pointer to the sprite at the given index, if valid.
96 SpriteInfo<RGB_T, SurfaceT>* getSprite(int idx) {
97 if (idx < 0 || idx >= static_cast<int>(sprites_.size())) {
98 return nullptr;
99 }
100 return sprites_[idx].get();
101 }
102
103 SpriteInfo<RGB_T, SurfaceT>* getSpritePtr(int idx) {
104 if (idx < 0 || idx >= static_cast<int>(sprites_.size())) {
105 return nullptr;
106 }
107 return sprites_[idx].get();;
108 }
109
110 /// Moves a sprite to a new position and redraws it.
111 void moveSprite(SpriteInfo<RGB_T, SurfaceT>& spriteInfo, size_t newX, size_t newY) {
112 TinyGPULogger.log(TinyGPULoggerClass::INFO,
113 "Moving sprite from (%zu, %zu) to (%zu, %zu)",
114 spriteInfo.x, spriteInfo.y, newX, newY);
115 if (spriteInfo.x == newX && spriteInfo.y == newY) {
116 return;
117 }
118
119 const Rect oldBounds{spriteInfo.x, spriteInfo.y,
120 spriteInfo.currentSprite().width(),
121 spriteInfo.currentSprite().height()};
122
123 // Always fully restore the old footprint before capturing/drawing the
124 // new one - see restoreFullBounds() for why a "just restore the
125 // exposed ring" optimization is unsafe here.
126 restoreFullBounds(spriteInfo, oldBounds);
127
128 Surface<RGB_T> movedBackground(oldBounds.width, oldBounds.height,
130 movedBackground.begin();
131 captureFramebufferRegion(movedBackground, 0, 0, newX, newY,
132 oldBounds.width, oldBounds.height);
133
134 spriteInfo.x = newX;
135 spriteInfo.y = newY;
136 spriteInfo.originalPixels = std::move(movedBackground);
137 surface_.drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.currentSprite(),
138 spriteInfo.invisibleColor);
139 }
140
141 /// Scales a sprite image and redraws it at its current position. Always
142 /// re-renders from the pristine original at (scale, currentAngleDegrees)
143 /// - see renderTransformedSprite() in SpriteInfo.h for why.
144 void scaleSprite(SpriteInfo<RGB_T, SurfaceT>& spriteInfo, float scale) {
146 "Scaling sprite at (%zu, %zu) by %.2f", spriteInfo.x,
147 spriteInfo.y, scale);
148 spriteInfo.currentScale = scale;
150 renderTransformedSprite(spriteInfo, activeFont()));
151 }
152
153 /// Rotates a sprite image and redraws it at its current position. Always
154 /// re-renders from the pristine original at (currentScale, angleDegrees)
155 /// - see renderTransformedSprite() in SpriteInfo.h for why.
156 void rotateSprite(SpriteInfo<RGB_T, SurfaceT>& spriteInfo, float angleDegrees) {
158 "Rotating sprite at (%zu, %zu) by %.2f degrees",
159 spriteInfo.x, spriteInfo.y, angleDegrees);
160 spriteInfo.currentAngleDegrees = angleDegrees;
162 renderTransformedSprite(spriteInfo, activeFont()));
163 }
164
165 /// ISurface<RGB_T> interface delegation
166 void setPixel(size_t x, size_t y, RGB_T color) override {
167 surface_.setPixel(x, y, color);
168 }
169 /// Returns the pixel at the given position.
170 RGB_T getPixel(size_t x, size_t y) const override {
171 return surface_.getPixel(x, y);
172 }
173 /// Resizes the framebuffer surface.
174 bool resize(size_t w, size_t h) override { return surface_.resize(w, h); }
175 /// Returns the framebuffer width in pixels.
176 size_t width() const override { return surface_.width(); }
177 /// Returns the framebuffer height in pixels.
178 size_t height() const override { return surface_.height(); }
179 /// Sets the font for text rendering.
180 void setFont(IFont<RGB_T>& font) { surface_.setFont(font); }
181 /// Returns the currently set font for text rendering.
182 IFont<RGB_T>& font() { return surface_.font(); }
183 /// Clears the framebuffer with a single color.
184 void clear(RGB_T color = RGB_T()) { surface_.clear(color); }
185 /// Scrolls the framebuffer content by the specified offsets.
186 void scroll(int dx, int dy) override { surface_.scroll(dx, dy); }
187 /// Draws a line between two points.
188 void drawLine(size_t x0, size_t y0, size_t x1, size_t y1, RGB_T color) {
189 surface_.drawLine(x0, y0, x1, y1, color);
190 }
191 /// Draws a rectangle outline.
192 void drawRect(size_t x, size_t y, size_t w, size_t h, RGB_T color) {
193 surface_.drawRect(x, y, w, h, color);
194 }
195 /// Fills a rectangle.
196 void fillRect(size_t x, size_t y, size_t w, size_t h, RGB_T color) {
197 surface_.fillRect(x, y, w, h, color);
198 }
199 /// Draws a circle outline.
200 void drawCircle(size_t x, size_t y, size_t r, RGB_T color) {
201 surface_.drawCircle(x, y, r, color);
202 }
203 /// Fills a circle.
204 void fillCircle(size_t x, size_t y, size_t r, RGB_T color) {
205 surface_.fillCircle(x, y, r, color);
206 }
207 /// Draws a sprite.
208 void drawSprite(size_t x, size_t y, const ISurface<RGB_T>& sprite,
209 RGB_T invisibleColor = RGB_T()) {
210 surface_.drawSprite(x, y, sprite, invisibleColor);
211 }
212 /// Clears a sprite.
213 void clearSprite(size_t x, size_t y, ISurface<RGB_T>& sprite,
214 RGB_T clearColor = RGB_T()) {
215 surface_.clearSprite(x, y, sprite, clearColor);
216 }
217 /// Copies a sprite.
218 void copySprite(size_t x, size_t y, const ISurface<RGB_T>& sprite) {
219 surface_.copySprite(x, y, sprite);
220 }
221 /// Draws UTF-8 text.
222 void drawText(int16_t x, int16_t y, const char* text, RGB_T foreground,
223 RGB_T background = RGB_T(), bool opaque = false,
224 uint8_t scale = 1, uint8_t spacing = 1,
225 uint8_t lineSpacing = 1) {
226 surface_.drawText(x, y, text, foreground, background, opaque, scale,
227 spacing, lineSpacing);
228 }
229 /// Returns the line printer for text rendering.
230 LinePrinter<RGB_T>& linePrinter() { return surface_.linePrinter(); }
231 /// Checks if the given coordinates are within the surface bounds.
232 bool isInBounds(size_t x, size_t y) const {
233 return surface_.isInBounds(x, y);
234 }
235 /// Sets a pixel with clipping.
236 void setPixelClipped(size_t x, size_t y, RGB_T color) {
237 surface_.setPixelClipped(x, y, color);
238 }
239 /// Draws a horizontal line with clipping.
240 void drawHorizontalLineClipped(int x0, int x1, int y, RGB_T color) {
241 surface_.drawHorizontalLineClipped(x0, x1, y, color);
242 }
243
244 /// Returns the raw pixel buffer as bytes.
245 const uint8_t* data() const override { return surface_.data(); }
246 /// Returns the size of the buffer in bytes.
247 size_t size() const override { return surface_.size(); }
248
249 /// Sets the framebuffer pixel data directly, replacing the current content.
250 bool setData(uint8_t* data, size_t dataSize) {
251 memset(const_cast<uint8_t*>(surface_.data()), 0, surface_.size());
252 if (dataSize > surface_.size()) {
253 return false;
254 }
255 std::memcpy(const_cast<uint8_t*>(surface_.data()), data, dataSize);
256 }
257
258 /// checks if the given coordinates are within the surface bounds.
259 bool contains(size_t x, size_t y) override { return surface_.contains(x, y); }
260
261 /// Processes touch input and dispatches events to sprites if touched.
264 Point point;
265 if (p_touchDriver->getPoint(point)) {
267 "Touch detected at (%d, %d) with pressure %d",
268 point.x, point.y, point.pressure);
269 auto* sprite = getSprite(point.x, point.y);
270 if (sprite) {
272 "Touch is within sprite at (%zu, %zu)", sprite->x,
273 sprite->y);
274 // Call the sprite's onTouch callback if set
275 sprite->onTouch(point);
276 }
277 }
278 }
279 }
280
281 protected:
282 // Underlying surface for all drawing/storage
283 SurfaceT surface_;
285
286 /// Returns the currently active font used by the framebuffer.
287 IFont<RGB_T>& activeFont() { return surface_.font(); }
289
290 /// Applies a transformed sprite image to the framebuffer and updates
291 /// bookkeeping.
292 void applyTransformedSprite(SpriteInfo<RGB_T, SurfaceT>& spriteInfo,
293 Surface<RGB_T>&& transformedSprite) {
294 const Rect oldBounds{spriteInfo.x, spriteInfo.y,
295 spriteInfo.currentSprite().width(),
296 spriteInfo.currentSprite().height()};
297 // Bounds/anchoring must reflect the size the sprite will actually end
298 // up stored/drawn at (see SpriteInfo::clampedSize()), not
299 // transformedSprite's own raw size - once a fixed max buffer exists,
300 // setTransformedSprite() below clamps to it (e.g. a rotated image's
301 // larger bounding box gets cropped down), and using the raw size here
302 // instead would restore/capture the wrong screen region, leaving
303 // stale sprite pixels un-restored or corrupting the saved background.
304 const Rect clamped = spriteInfo.clampedSize(transformedSprite.width(),
305 transformedSprite.height());
306 const size_t anchoredX =
307 centeredCoordinate(spriteInfo.x, oldBounds.width, clamped.width);
308 const size_t anchoredY =
309 centeredCoordinate(spriteInfo.y, oldBounds.height, clamped.height);
310 const Rect newBounds{anchoredX, anchoredY, clamped.width, clamped.height};
311
312 // Always fully restore the old footprint before capturing/drawing the
313 // new one - see restoreFullBounds() for why a "just restore the
314 // exposed ring" optimization is unsafe here: unlike a pure move,
315 // scaling/rotating can turn a pixel that was opaque at some position
316 // *within* the old and new bounds' geometric overlap into a
317 // background/invisible one (e.g. scaling down shrinks the opaque
318 // area), and drawSprite() below skips writing wherever the new image
319 // is background-colored - so any pixel not explicitly restored here
320 // stays stuck showing the old, larger sprite's color forever.
321 restoreFullBounds(spriteInfo, oldBounds);
322
323 Surface<RGB_T> updatedBackground(newBounds.width, newBounds.height,
325 updatedBackground.begin();
326 captureFramebufferRegion(updatedBackground, 0, 0, newBounds.x,
327 newBounds.y, newBounds.width, newBounds.height);
328
329 spriteInfo.x = anchoredX;
330 spriteInfo.y = anchoredY;
331 spriteInfo.setTransformedSprite(std::move(transformedSprite));
332 spriteInfo.originalPixels = std::move(updatedBackground);
333 this->drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.currentSprite(),
334 spriteInfo.invisibleColor);
335 }
336
337
338 /// Calculates the coordinate to center a new size over an old
339 /// position/size.
341 size_t newSize) {
342 const float centeredPosition =
343 static_cast<float>(oldPosition) +
344 (static_cast<float>(oldSize) - static_cast<float>(newSize)) / 2.0;
345 return centeredPosition <= 0.0
346 ? 0
347 : static_cast<size_t>(std::lround(centeredPosition));
348 }
349
350 /// Unconditionally restores the entire old sprite footprint to its saved
351 /// background pixels.
352 ///
353 /// This used to be an optimization that only restored the "ring" of
354 /// oldBounds exposed by moving/transforming a sprite, reasoning that the
355 /// geometric overlap between oldBounds and newBounds didn't need
356 /// restoring since the upcoming drawSprite() call would cover it anyway.
357 /// That's only true if the sprite's content is unchanged there - but
358 /// scaling/rotating can turn a pixel that was opaque at some position
359 /// *within* the overlap into a background/invisible one (e.g. scaling
360 /// down shrinks the opaque area), and drawSprite() skips writing
361 /// wherever the new image is background-colored. Any such pixel was
362 /// never restored, so it stayed stuck showing the old, larger sprite's
363 /// color - visible as the old and new sprite sizes overlaid on top of
364 /// each other. Always restoring the full footprint costs a few dozen
365 /// extra pixel writes (bounded by the sprite's small max size) in
366 /// exchange for being correct regardless of what changed.
367 void restoreFullBounds(const SpriteInfo<RGB_T, SurfaceT>& spriteInfo,
368 const Rect& oldBounds) {
369 drawSpriteRegion(spriteInfo.originalPixels, 0, 0, oldBounds.x,
370 oldBounds.y, oldBounds.width, oldBounds.height);
371 }
372
373 /// Draws a rectangular region from a source surface onto the framebuffer.
374 void drawSpriteRegion(const ISurface<RGB_T>& source, size_t sourceX,
375 size_t sourceY, size_t destX, size_t destY,
376 size_t width, size_t height) {
377 for (size_t currentY = 0; currentY < height; ++currentY) {
378 for (size_t currentX = 0; currentX < width; ++currentX) {
379 const size_t framebufferX = destX + currentX;
380 const size_t framebufferY = destY + currentY;
381 if (framebufferX < surface_.width() &&
382 framebufferY < surface_.height()) {
383 surface_.setPixel(
384 framebufferX, framebufferY,
385 source.getPixel(sourceX + currentX, sourceY + currentY));
386 }
387 }
388 }
389 }
390
391 /// Captures a rectangular region from the framebuffer into a destination
392 /// surface.
393 void captureFramebufferRegion(Surface<RGB_T>& destination, size_t destX,
394 size_t destY, size_t sourceX, size_t sourceY,
395 size_t width, size_t height) {
396 for (size_t currentY = 0; currentY < height; ++currentY) {
397 for (size_t currentX = 0; currentX < width; ++currentX) {
398 const size_t framebufferX = sourceX + currentX;
399 const size_t framebufferY = sourceY + currentY;
400 const RGB_T color =
401 framebufferX < surface_.width() && framebufferY < surface_.height()
402 ? surface_.getPixel(framebufferX, framebufferY)
403 : RGB_T(0);
404 destination.setPixel(destX + currentX, destY + currentY, color);
405 }
406 }
407 }
408
409 /// Restores the original background pixels behind a sprite.
410 void restoreOriginalPixels(const SpriteInfo<RGB_T, SurfaceT>& spriteInfo) {
411 surface_.drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.originalPixels);
412 }
413};
414
415} // namespace tinygpu
Framebuffer with sprite placement and background restoration support.
Definition: FrameBuffer.h:24
void moveSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, size_t newX, size_t newY)
Moves a sprite to a new position and redraws it.
Definition: FrameBuffer.h:111
SpriteInfo< RGB_T, SurfaceT > & addSprite(size_t x, size_t y, size_t maxX, size_t maxY, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T(0))
Adds a sprite with a preallocated max buffer size for transformations.
Definition: FrameBuffer.h:54
IFont< RGB_T > & font()
Returns the currently set font for text rendering.
Definition: FrameBuffer.h:182
void applyTransformedSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, Surface< RGB_T > &&transformedSprite)
Definition: FrameBuffer.h:292
void captureFramebufferRegion(Surface< RGB_T > &destination, size_t destX, size_t destY, size_t sourceX, size_t sourceY, size_t width, size_t height)
Definition: FrameBuffer.h:393
SurfaceT surface_
Definition: FrameBuffer.h:283
void fillRect(size_t x, size_t y, size_t w, size_t h, RGB_T color)
Fills a rectangle.
Definition: FrameBuffer.h:196
void drawText(int16_t x, int16_t y, const char *text, RGB_T foreground, RGB_T background=RGB_T(), bool opaque=false, uint8_t scale=1, uint8_t spacing=1, uint8_t lineSpacing=1)
Draws UTF-8 text.
Definition: FrameBuffer.h:222
void drawLine(size_t x0, size_t y0, size_t x1, size_t y1, RGB_T color)
Draws a line between two points.
Definition: FrameBuffer.h:188
void scaleSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, float scale)
Definition: FrameBuffer.h:144
void drawSpriteRegion(const ISurface< RGB_T > &source, size_t sourceX, size_t sourceY, size_t destX, size_t destY, size_t width, size_t height)
Draws a rectangular region from a source surface onto the framebuffer.
Definition: FrameBuffer.h:374
bool contains(size_t x, size_t y) override
checks if the given coordinates are within the surface bounds.
Definition: FrameBuffer.h:259
LinePrinter< RGB_T > & linePrinter()
Returns the line printer for text rendering.
Definition: FrameBuffer.h:230
void restoreFullBounds(const SpriteInfo< RGB_T, SurfaceT > &spriteInfo, const Rect &oldBounds)
Definition: FrameBuffer.h:367
size_t getSpriteCount() const
Returns the number of sprites currently managed by the framebuffer.
Definition: FrameBuffer.h:93
void copySprite(size_t x, size_t y, const ISurface< RGB_T > &sprite)
Copies a sprite.
Definition: FrameBuffer.h:218
void setTouchDriver(TouchDriver &touch)
Definition: FrameBuffer.h:36
void setFont(IFont< RGB_T > &font)
Sets the font for text rendering.
Definition: FrameBuffer.h:180
static size_t centeredCoordinate(size_t oldPosition, size_t oldSize, size_t newSize)
Definition: FrameBuffer.h:340
Vector< std::unique_ptr< SpriteInfo< RGB_T, SurfaceT > > > sprites_
Definition: FrameBuffer.h:288
void end() override
Closes the framebuffer and releases resources.
Definition: FrameBuffer.h:34
void clear(RGB_T color=RGB_T())
Clears the framebuffer with a single color.
Definition: FrameBuffer.h:184
size_t height() const override
Returns the framebuffer height in pixels.
Definition: FrameBuffer.h:178
IFont< RGB_T > & activeFont()
Returns the currently active font used by the framebuffer.
Definition: FrameBuffer.h:287
bool setData(uint8_t *data, size_t dataSize)
Sets the framebuffer pixel data directly, replacing the current content.
Definition: FrameBuffer.h:250
void restoreOriginalPixels(const SpriteInfo< RGB_T, SurfaceT > &spriteInfo)
Restores the original background pixels behind a sprite.
Definition: FrameBuffer.h:410
void fillCircle(size_t x, size_t y, size_t r, RGB_T color)
Fills a circle.
Definition: FrameBuffer.h:204
bool resize(size_t w, size_t h) override
Resizes the framebuffer surface.
Definition: FrameBuffer.h:174
void rotateSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, float angleDegrees)
Definition: FrameBuffer.h:156
const uint8_t * data() const override
Returns the raw pixel buffer as bytes.
Definition: FrameBuffer.h:245
SpriteInfo< RGB_T, SurfaceT > & addSprite(size_t x, size_t y, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T(0))
Adds a sprite to the framebuffer and draws it at the given position.
Definition: FrameBuffer.h:39
TouchDriver * p_touchDriver
Definition: FrameBuffer.h:284
void clearSprite(size_t x, size_t y, ISurface< RGB_T > &sprite, RGB_T clearColor=RGB_T())
Clears a sprite.
Definition: FrameBuffer.h:213
FrameBuffer()=default
Creates an empty framebuffer.
SpriteInfo< RGB_T, SurfaceT > * getSpritePtr(int idx)
Definition: FrameBuffer.h:103
FrameBuffer(size_t width, size_t height, IFont< RGB_T > &font)
Creates a framebuffer with the specified size and font.
Definition: FrameBuffer.h:30
void drawCircle(size_t x, size_t y, size_t r, RGB_T color)
Draws a circle outline.
Definition: FrameBuffer.h:200
void drawSprite(size_t x, size_t y, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T())
Draws a sprite.
Definition: FrameBuffer.h:208
SpriteInfo< RGB_T, SurfaceT > * getSprite(size_t x, size_t y)
Returns a pointer to the sprite at the given position, if any.
Definition: FrameBuffer.h:81
SpriteInfo< RGB_T, SurfaceT > * getSprite(int idx)
Returns a pointer to the sprite at the given index, if valid.
Definition: FrameBuffer.h:96
void processTouch()
Processes touch input and dispatches events to sprites if touched.
Definition: FrameBuffer.h:262
size_t width() const override
Returns the framebuffer width in pixels.
Definition: FrameBuffer.h:176
void scroll(int dx, int dy) override
Scrolls the framebuffer content by the specified offsets.
Definition: FrameBuffer.h:186
bool begin() override
Initializes the framebuffer surface.
Definition: FrameBuffer.h:33
void removeSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo)
Removes a sprite and restores the pixels behind it.
Definition: FrameBuffer.h:70
void setPixelClipped(size_t x, size_t y, RGB_T color)
Sets a pixel with clipping.
Definition: FrameBuffer.h:236
void setPixel(size_t x, size_t y, RGB_T color) override
ISurface<RGB_T> interface delegation.
Definition: FrameBuffer.h:166
size_t size() const override
Returns the size of the buffer in bytes.
Definition: FrameBuffer.h:247
void drawRect(size_t x, size_t y, size_t w, size_t h, RGB_T color)
Draws a rectangle outline.
Definition: FrameBuffer.h:192
RGB_T getPixel(size_t x, size_t y) const override
Returns the pixel at the given position.
Definition: FrameBuffer.h:170
void drawHorizontalLineClipped(int x0, int x1, int y, RGB_T color)
Draws a horizontal line with clipping.
Definition: FrameBuffer.h:240
bool isInBounds(size_t x, size_t y) const
Checks if the given coordinates are within the surface bounds.
Definition: FrameBuffer.h:232
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
RGB color stored in 16-bit RGB565 format, byte-swapped from the conventional bit layout.
Definition: RGB565.h:24
In-memory bitmap surface with basic 2D drawing and text rendering.
Definition: Surface.h:38
Simple header-only logger for TinyGPU with log levels and vararg support.
Definition: TinyGPULogger.h:24
@ INFO
General information.
Definition: TinyGPULogger.h:32
void log(Level level, const char *fmt,...)
Log a message with printf-style formatting.
Definition: TinyGPULogger.h:56
Base class for touch controllers.
Definition: TouchDriverCommon.h:72
virtual bool isTouched()=0
Return whether the panel currently appears touched.
virtual bool getPoint(Point &outPoint)=0
Read the current touch point.
Definition: DSIBusESP32.h:19
Touch point.
Definition: TouchDriverCommon.h:32
uint16_t pressure
Definition: TouchDriverCommon.h:35
int16_t x
Definition: TouchDriverCommon.h:33
int16_t y
Definition: TouchDriverCommon.h:34
Represents a rectangular area on the screen or surface.
Definition: SpriteInfo.h:19
Definition: SpriteInfo.h:52