mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 16:38:16 +01:00
display: Add helper methods to Display::clip
and Display::clamp_x/y_
(#5003)
* display: `Rect` make most of methods `const` * display: add `clip` and `clamp_x/y_` methods for clipping to `Display`
This commit is contained in:
parent
f8df694aa3
commit
1691c13b47
4 changed files with 57 additions and 15 deletions
|
@ -269,10 +269,7 @@ void Display::do_update_() {
|
|||
} else if (this->writer_.has_value()) {
|
||||
(*this->writer_)(*this);
|
||||
}
|
||||
// remove all not ended clipping regions
|
||||
while (is_clipping()) {
|
||||
end_clipping();
|
||||
}
|
||||
this->clear_clipping_();
|
||||
}
|
||||
void DisplayOnPageChangeTrigger::process(DisplayPage *from, DisplayPage *to) {
|
||||
if ((this->from_ == nullptr || this->from_ == from) && (this->to_ == nullptr || this->to_ == to))
|
||||
|
@ -322,13 +319,51 @@ void Display::shrink_clipping(Rect add_rect) {
|
|||
this->clipping_rectangle_.back().shrink(add_rect);
|
||||
}
|
||||
}
|
||||
Rect Display::get_clipping() {
|
||||
Rect Display::get_clipping() const {
|
||||
if (this->clipping_rectangle_.empty()) {
|
||||
return Rect();
|
||||
} else {
|
||||
return this->clipping_rectangle_.back();
|
||||
}
|
||||
}
|
||||
void Display::clear_clipping_() { this->clipping_rectangle_.clear(); }
|
||||
bool Display::clip(int x, int y) {
|
||||
if (x < 0 || x >= this->get_width() || y < 0 || y >= this->get_height())
|
||||
return false;
|
||||
if (!this->get_clipping().inside(x, y))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
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());
|
||||
|
||||
if (!this->clipping_rectangle_.empty()) {
|
||||
const auto &rect = this->clipping_rectangle_.back();
|
||||
if (!rect.is_set())
|
||||
return false;
|
||||
|
||||
min_x = std::max(min_x, (int) rect.x);
|
||||
max_x = std::min(max_x, (int) rect.x2());
|
||||
}
|
||||
|
||||
return min_x < max_x;
|
||||
}
|
||||
bool Display::clamp_y_(int y, int h, int &min_y, int &max_y) {
|
||||
min_y = std::max(y, 0);
|
||||
max_y = std::min(y + h, this->get_height());
|
||||
|
||||
if (!this->clipping_rectangle_.empty()) {
|
||||
const auto &rect = this->clipping_rectangle_.back();
|
||||
if (!rect.is_set())
|
||||
return false;
|
||||
|
||||
min_y = std::max(min_y, (int) rect.y);
|
||||
max_y = std::min(max_y, (int) rect.y2());
|
||||
}
|
||||
|
||||
return min_y < max_y;
|
||||
}
|
||||
|
||||
DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {}
|
||||
void DisplayPage::show() { this->parent_->show_page(this); }
|
||||
|
|
|
@ -472,14 +472,21 @@ class Display {
|
|||
*
|
||||
* return rect for active clipping region
|
||||
*/
|
||||
Rect get_clipping();
|
||||
Rect get_clipping() const;
|
||||
|
||||
bool is_clipping() const { return !this->clipping_rectangle_.empty(); }
|
||||
|
||||
/** Check if pixel is within region of display.
|
||||
*/
|
||||
bool clip(int x, int y);
|
||||
|
||||
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);
|
||||
void vprintf_(int x, int y, BaseFont *font, Color color, TextAlign align, const char *format, va_list arg);
|
||||
|
||||
void do_update_();
|
||||
void clear_clipping_();
|
||||
|
||||
DisplayRotation rotation_{DISPLAY_ROTATION_0_DEGREES};
|
||||
optional<display_writer_t> writer_{};
|
||||
|
|
|
@ -60,11 +60,11 @@ void Rect::shrink(Rect rect) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Rect::equal(Rect rect) {
|
||||
bool Rect::equal(Rect rect) const {
|
||||
return (rect.x == this->x) && (rect.w == this->w) && (rect.y == this->y) && (rect.h == this->h);
|
||||
}
|
||||
|
||||
bool Rect::inside(int16_t test_x, int16_t test_y, bool absolute) { // NOLINT
|
||||
bool Rect::inside(int16_t test_x, int16_t test_y, bool absolute) const { // NOLINT
|
||||
if (!this->is_set()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ bool Rect::inside(int16_t test_x, int16_t test_y, bool absolute) { // NOLINT
|
|||
}
|
||||
}
|
||||
|
||||
bool Rect::inside(Rect rect, bool absolute) {
|
||||
bool Rect::inside(Rect rect, bool absolute) const {
|
||||
if (!this->is_set() || !rect.is_set()) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,19 +16,19 @@ class Rect {
|
|||
|
||||
Rect() : x(VALUE_NO_SET), y(VALUE_NO_SET), w(VALUE_NO_SET), h(VALUE_NO_SET) {} // NOLINT
|
||||
inline Rect(int16_t x, int16_t y, int16_t w, int16_t h) ALWAYS_INLINE : x(x), y(y), w(w), h(h) {}
|
||||
inline int16_t x2() { return this->x + this->w; }; ///< X coordinate of corner
|
||||
inline int16_t y2() { return this->y + this->h; }; ///< Y coordinate of corner
|
||||
inline int16_t x2() const { return this->x + this->w; }; ///< X coordinate of corner
|
||||
inline int16_t y2() const { return this->y + this->h; }; ///< Y coordinate of corner
|
||||
|
||||
inline bool is_set() ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); }
|
||||
inline bool is_set() const ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); }
|
||||
|
||||
void expand(int16_t horizontal, int16_t vertical);
|
||||
|
||||
void extend(Rect rect);
|
||||
void shrink(Rect rect);
|
||||
|
||||
bool inside(Rect rect, bool absolute = true);
|
||||
bool inside(int16_t test_x, int16_t test_y, bool absolute = true);
|
||||
bool equal(Rect rect);
|
||||
bool inside(Rect rect, bool absolute = true) const;
|
||||
bool inside(int16_t test_x, int16_t test_y, bool absolute = true) const;
|
||||
bool equal(Rect rect) const;
|
||||
void info(const std::string &prefix = "rect info:");
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue