Introduce a local coordinate drawing system to display and display_buffer

This commit is contained in:
Michael Davidson 2023-12-17 19:20:03 +11:00
parent a6f1701902
commit 313cb2bff5
No known key found for this signature in database
GPG Key ID: B8D1A99712B8B0EB
4 changed files with 85 additions and 0 deletions

View File

@ -334,6 +334,35 @@ bool Display::clip(int x, int y) {
return false;
return true;
}
void Display::set_local_coordinates_relative_to_current(int x_offset, int y_offset) {
Point p(0, 0);
if (!this->local_coordinate_.empty()) {
p = this->local_coordinate_.back();
}
p.x += x_offset;
p.y += y_offset;
this->local_coordinate_.push_back(p);
}
void Display::pop_local_coordinates() {
if (this->local_coordinate_.empty()) {
ESP_LOGE(TAG, "pop_local_coordinates: No local coordinates set");
} else {
this->local_coordinate_.pop_back();
}
}
Point Display::get_local_coordinates() {
Point p(0, 0);
if (!this->local_coordinate_.empty()) {
p = this->local_coordinate_.back();
}
return p;
}
bool Display::clamp_x_(int x, int w, int &min_x, int &max_x) {
min_x = std::max(x, 0);
max_x = std::min(x + w, this->get_width());

View File

@ -4,6 +4,7 @@
#include <vector>
#include "rect.h"
#include "point.h"
#include "esphome/core/color.h"
#include "esphome/core/automation.h"
@ -480,6 +481,36 @@ class Display : public PollingComponent {
*/
bool clip(int x, int y);
/** Changes the local coordinates to be relative to (x, y). After calling a pixel
* drawn at (10, 20) would be drawn to the screen at (x + 10, y + 20)
*
* @param[in] x: x coordinate as the new local. Absolute to the displays underlying 0
* @param[in] y: y coordinate as the new local. Absolute to the displays underlying 0
*/
void set_local_coordinate(int x, int y) { this->local_coordinate_.push_back(Point(x, y)); };
/** Changes the local coordinates to be to be (x_local + x_offset, y_local + y_offset)
* After calling a pixel drawn at (10, 20) would be drawn to the screen at
* (x_local + x_offset + 10, y_local + y_offset + 20)
*
* @param[in] x_offset: x offset from the current local. Relative to the local x
* @param[in] y_offset: y offset from the current local. Relative to the local y
*/
void set_local_coordinates_relative_to_current(int x_offset, int y_offset);
/** Removes the most recent local coordinate system from use
*/
void pop_local_coordinates();
/** Gets the current local coordinates in the displays absolute coordinate system
*/
Point get_local_coordinates();
/** Clears all the local coordinate systems and revers to the displays absolute coordinate
* system
*/
void clear_local_coordinates() { this->local_coordinate_.clear(); };
protected:
bool clamp_x_(int x, int w, int &min_x, int &max_x);
bool clamp_y_(int y, int h, int &min_y, int &max_y);
@ -495,6 +526,7 @@ class Display : public PollingComponent {
std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
bool auto_clear_enabled_{true};
std::vector<Rect> clipping_rectangle_;
std::vector<Point> local_coordinate_;
};
class DisplayPage {

View File

@ -4,6 +4,7 @@
#include "esphome/core/application.h"
#include "esphome/core/log.h"
#include "point.h"
namespace esphome {
namespace display {
@ -45,6 +46,11 @@ int DisplayBuffer::get_height() {
}
void HOT DisplayBuffer::draw_pixel_at(int x, int y, Color color) {
// Convert (x, y) from the local coordinate system to the display absolute coordinate system
Point local_coord = this->get_local_coordinates();
x += local_coord.x;
y += local_coord.y;
if (!this->get_clipping().inside(x, y))
return; // NOLINT

View File

@ -0,0 +1,18 @@
#pragma once
#include "esphome/core/helpers.h"
namespace esphome {
namespace display {
class Point {
public:
int16_t x;
int16_t y;
Point() : x(VALUE_NO_SET), y(VALUE_NO_SET) {};
inline Point(int16_t x, int16_t y) ALWAYS_INLINE : x(x), y(y) {};
};
} // namespace display
} // namespace esphome