Graphics Enhancements (#8)

* typedef pen and constexpr create_pen for #6

* Prevent out of bounds clip permitting write outside buffer

* camelcase rect, point, and pen types

* added triangle(p1, p2, p3) and polygon(std::vector<Point> points) methods to graphics library

* change all uses of pen that were uint16_t into Pen type

* updated micropython modules to use new rect, point, pen naming

* added line(p1, p2) method to pico graphics library with faster vertical/horizontal special cases

Co-authored-by: Jonathan Williamson <jon@pimoroni.com>
pull/13/head
Philip Howard 2021-01-23 23:41:09 +00:00 zatwierdzone przez GitHub
rodzic 51d95db154
commit 7d4ca4a86b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 309 dodań i 105 usunięć

Wyświetl plik

@ -122,13 +122,44 @@ int main() {
if(shape.y >= pico_display.bounds.h) shape.dy *= -1;
pico_display.set_pen(shape.pen);
pico_display.circle(point(shape.x, shape.y), shape.r);
pico_display.circle(Point(shape.x, shape.y), shape.r);
}
float led_step = fmod(i / 20.0f, M_PI * 2.0f);
int r = (sin(led_step) * 25.0f) + 25.0f;
pico_display.set_led(r, r / 1.2f, r);
std::vector<Point> poly;
poly.push_back(Point(30, 30));
poly.push_back(Point(50, 35));
poly.push_back(Point(70, 25));
poly.push_back(Point(80, 65));
poly.push_back(Point(50, 85));
poly.push_back(Point(30, 45));
pico_display.set_pen(255, 255, 0);
pico_display.polygon(poly);
pico_display.set_pen(0, 255, 255);
pico_display.triangle(Point(50, 50), Point(130, 80), Point(80, 110));
pico_display.set_pen(255, 255, 255);
pico_display.line(Point(50, 50), Point(120, 80));
pico_display.line(Point(20, 20), Point(120, 20));
pico_display.line(Point(20, 20), Point(20, 120));
for(int r = 0; r < 30; r++) {
for(int j = 0; j < 10; j++) {
float rads = ((M_PI * 2) / 30.0f) * float(r);
rads += (float(i) / 100.0f);
rads += (float(j) / 100.0f);
float cx = sin(rads) * 300.0f;
float cy = cos(rads) * 300.0f;
pico_display.line(Point(120, 67), Point(cx + 120, cy + 67));
}
}
/*
if(pico_display.is_pressed(pico_display.A)) {
pico_display.rectangle(0, 0, 18, 18);

Wyświetl plik

@ -100,26 +100,26 @@ int main() {
if(shape.y >= pico_explorer.bounds.h) shape.dy *= -1;
pico_explorer.set_pen(shape.pen);
pico_explorer.circle(point(shape.x, shape.y), shape.r);
pico_explorer.circle(Point(shape.x, shape.y), shape.r);
}
float rv = pico_explorer.get_adc(pico_explorer.ADC0);
pico_explorer.set_pen(255, 255, 255);
pico_explorer.circle(point(rv * 140 + 50, 110), 20);
pico_explorer.circle(Point(rv * 140 + 50, 110), 20);
pico_explorer.set_pen(rv * 255, 0, 0);
pico_explorer.circle(point(rv * 140 + 50, 110), 15);
pico_explorer.circle(Point(rv * 140 + 50, 110), 15);
float gv = pico_explorer.get_adc(pico_explorer.ADC1);
pico_explorer.set_pen(255, 255, 255);
pico_explorer.circle(point(gv * 140 + 50, 160), 20);
pico_explorer.circle(Point(gv * 140 + 50, 160), 20);
pico_explorer.set_pen(0, gv * 255, 0);
pico_explorer.circle(point(gv * 140 + 50, 160), 15);
pico_explorer.circle(Point(gv * 140 + 50, 160), 15);
float bv = pico_explorer.get_adc(pico_explorer.ADC2);
pico_explorer.set_pen(255, 255, 255);
pico_explorer.circle(point(bv * 140 + 50, 210), 20);
pico_explorer.circle(Point(bv * 140 + 50, 210), 20);
pico_explorer.set_pen(0, 0, bv * 255);
pico_explorer.circle(point(bv * 140 + 50, 210), 15);
pico_explorer.circle(Point(bv * 140 + 50, 210), 15);
pico_explorer.set_motor(pico_explorer.MOTOR1, pico_explorer.FORWARD, bv);
pico_explorer.set_motor(pico_explorer.MOTOR2, pico_explorer.FORWARD, rv);
@ -128,32 +128,32 @@ int main() {
if(pico_explorer.is_pressed(pico_explorer.A)) {
pico_explorer.set_pen(255, 255, 255);
pico_explorer.character('A', point(120, 180), 5);
pico_explorer.character('A', Point(120, 180), 5);
}
if(pico_explorer.is_pressed(pico_explorer.B)) {
pico_explorer.set_pen(255, 255, 255);
pico_explorer.character('B', point(120, 180), 5);
pico_explorer.character('B', Point(120, 180), 5);
}
if(pico_explorer.is_pressed(pico_explorer.X)) {
pico_explorer.set_pen(255, 255, 255);
pico_explorer.character('X', point(120, 180), 5);
pico_explorer.character('X', Point(120, 180), 5);
}
if(pico_explorer.is_pressed(pico_explorer.Y)) {
pico_explorer.set_pen(255, 255, 255);
pico_explorer.character('Y', point(120, 180), 5);
pico_explorer.character('Y', Point(120, 180), 5);
}
float tyoff = cos(i / 20.0f) * 50.0f - 50.0f;
rect text_box(10, 10, 150, 150);
Rect text_box(10, 10, 150, 150);
pico_explorer.set_pen(55, 65, 75);
pico_explorer.rectangle(text_box);
text_box.deflate(10);
pico_explorer.set_clip(text_box);
pico_explorer.set_pen(255, 255, 255);
pico_explorer.text("This is a test of some text data that should wrap nicely onto multiple lines which is dead useful like.", point(text_box.x, text_box.y + tyoff), 100);
pico_explorer.text("This is a test of some text data that should wrap nicely onto multiple lines which is dead useful like.", Point(text_box.x, text_box.y + tyoff), 100);
float xoff = sin(i / 20.0f) * 50.0f;
xoff += 120 - (81 / 2);
@ -168,23 +168,23 @@ int main() {
uint8_t b = *src++;
pico_explorer.set_pen(r, g, b);
pico_explorer.pixel(point(x + xoff, 68 - y + yoff));
pico_explorer.pixel(Point(x + xoff, 68 - y + yoff));
}
}
pico_explorer.remove_clip();
pico_explorer.set_pen(255, 255, 255);
pico_explorer.text("x: " + std::to_string(int(msa301.get_axis(msa301.X, 16) * 100)), point(10, 190), 100);
pico_explorer.text("y: " + std::to_string(int(msa301.get_axis(msa301.Y, 16) * 100)), point(10, 205), 100);
pico_explorer.text("z: " + std::to_string(int(msa301.get_axis(msa301.Z, 16) * 100)), point(10, 220), 100);
pico_explorer.text("x: " + std::to_string(int(msa301.get_axis(msa301.X, 16) * 100)), Point(10, 190), 100);
pico_explorer.text("y: " + std::to_string(int(msa301.get_axis(msa301.Y, 16) * 100)), Point(10, 205), 100);
pico_explorer.text("z: " + std::to_string(int(msa301.get_axis(msa301.Z, 16) * 100)), Point(10, 220), 100);
uint16_t xpos = (msa301.get_axis(msa301.X, 16) * 120) + 120;
uint16_t ypos = (msa301.get_axis(msa301.Z, 16) * 120) + 120;
pico_explorer.set_pen(255, 255, 255);
pico_explorer.circle(point(xpos, ypos), 20);
pico_explorer.circle(Point(xpos, ypos), 20);
pico_explorer.set_pen(255, 0, 255);
pico_explorer.circle(point(xpos, ypos), 15);
pico_explorer.circle(Point(xpos, ypos), 15);
/*

Wyświetl plik

@ -9,35 +9,27 @@ namespace pimoroni {
pen = create_pen(r, g, b);
}
void PicoGraphics::set_pen(uint16_t p) {
void PicoGraphics::set_pen(Pen p) {
pen = p;
}
uint16_t PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {
uint16_t p = ((r & 0b11111000) << 8) |
((g & 0b11111100) << 3) |
((b & 0b11111000) >> 3);
return __builtin_bswap16(p);
}
void PicoGraphics::set_clip(const rect &r) {
clip = r;
void PicoGraphics::set_clip(const Rect &r) {
clip = bounds.intersection(r);
}
void PicoGraphics::remove_clip() {
clip = bounds;
}
uint16_t* PicoGraphics::ptr(const rect &r) {
Pen* PicoGraphics::ptr(const Rect &r) {
return frame_buffer + r.x + r.y * bounds.w;
}
uint16_t* PicoGraphics::ptr(const point &p) {
Pen* PicoGraphics::ptr(const Point &p) {
return frame_buffer + p.x + p.y * bounds.w;
}
uint16_t* PicoGraphics::ptr(int32_t x, int32_t y) {
Pen* PicoGraphics::ptr(int32_t x, int32_t y) {
return frame_buffer + x + y * bounds.w;
}
@ -45,34 +37,34 @@ namespace pimoroni {
rectangle(clip);
}
void PicoGraphics::pixel(const point &p) {
void PicoGraphics::pixel(const Point &p) {
if(!clip.contains(p)) return;
*ptr(p) = pen;
}
void PicoGraphics::pixel_span(const point &p, int32_t l) {
void PicoGraphics::pixel_span(const Point &p, int32_t l) {
// check if span in bounds
if( p.x + l < clip.x || p.x >= clip.x + clip.w ||
p.y < clip.y || p.y >= clip.y + clip.h) return;
// clamp span horizontally
point clipped = p;
Point clipped = p;
if(clipped.x < clip.x) {l += clipped.x - clip.x; clipped.x = clip.x;}
if(clipped.x + l >= clip.x + clip.w) {l = clip.x + clip.w - clipped.x;}
uint16_t *dest = ptr(clipped);
Pen *dest = ptr(clipped);
while(l--) {
*dest++ = pen;
}
}
void PicoGraphics::rectangle(const rect &r) {
void PicoGraphics::rectangle(const Rect &r) {
// clip and/or discard depending on rectangle visibility
rect clipped = r.intersection(clip);
Rect clipped = r.intersection(clip);
if(clipped.empty()) return;
uint16_t *dest = ptr(clipped);
Pen *dest = ptr(clipped);
while(clipped.h--) {
// draw span of pixels for this row
for(uint32_t i = 0; i < clipped.w; i++) {
@ -84,9 +76,9 @@ namespace pimoroni {
}
}
void PicoGraphics::circle(const point &p, int32_t radius) {
void PicoGraphics::circle(const Point &p, int32_t radius) {
// circle in screen bounds?
rect bounds = rect(p.x - radius, p.y - radius, radius * 2, radius * 2);
Rect bounds = Rect(p.x - radius, p.y - radius, radius * 2, radius * 2);
if(!bounds.intersects(clip)) return;
int ox = radius, oy = 0, err = -radius;
@ -96,15 +88,15 @@ namespace pimoroni {
err += oy; oy++; err += oy;
pixel_span(point(p.x - ox, p.y + last_oy), ox * 2 + 1);
pixel_span(Point(p.x - ox, p.y + last_oy), ox * 2 + 1);
if (last_oy != 0) {
pixel_span(point(p.x - ox, p.y - last_oy), ox * 2 + 1);
pixel_span(Point(p.x - ox, p.y - last_oy), ox * 2 + 1);
}
if(err >= 0 && ox != last_oy) {
pixel_span(point(p.x - last_oy, p.y + ox), last_oy * 2 + 1);
pixel_span(Point(p.x - last_oy, p.y + ox), last_oy * 2 + 1);
if (ox != 0) {
pixel_span(point(p.x - last_oy, p.y - ox), last_oy * 2 + 1);
pixel_span(Point(p.x - last_oy, p.y - ox), last_oy * 2 + 1);
}
err -= ox; ox--; err -= ox;
@ -112,9 +104,9 @@ namespace pimoroni {
}
}
void PicoGraphics::character(const char c, const point &p, uint8_t scale) {
void PicoGraphics::character(const char c, const Point &p, uint8_t scale) {
uint8_t char_index = c - 32;
rect char_bounds(p.x, p.y, character_widths[char_index] * scale, 6 * scale);
Rect char_bounds(p.x, p.y, character_widths[char_index] * scale, 6 * scale);
if(!clip.intersects(char_bounds)) return;
@ -122,7 +114,7 @@ namespace pimoroni {
for(uint8_t cx = 0; cx < character_widths[char_index]; cx++) {
for(uint8_t cy = 0; cy < 6; cy++) {
if((1U << cy) & *d) {
rectangle(rect(p.x + (cx * scale), p.y + (cy * scale), scale, scale));
rectangle(Rect(p.x + (cx * scale), p.y + (cy * scale), scale, scale));
}
}
@ -130,7 +122,7 @@ namespace pimoroni {
}
}
void PicoGraphics::text(const std::string &t, const point &p, int32_t wrap, uint8_t scale) {
void PicoGraphics::text(const std::string &t, const Point &p, int32_t wrap, uint8_t scale) {
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
size_t i = 0;
@ -156,7 +148,7 @@ namespace pimoroni {
// draw word
for(size_t j = i; j < next_space; j++) {
character(t[j], point(p.x + co, p.y + lo), scale);
character(t[j], Point(p.x + co, p.y + lo), scale);
co += character_widths[t[j] - 32] * scale;
}
@ -166,4 +158,172 @@ namespace pimoroni {
}
}
int32_t orient2d(Point p1, Point p2, Point p3) {
return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
}
bool is_top_left(const Point &p1, const Point &p2) {
return (p1.y == p2.y && p1.x > p2.x) || (p1.y < p2.y);
}
void PicoGraphics::triangle(Point p1, Point p2, Point p3) {
Rect triangle_bounds(
Point(std::min(p1.x, std::min(p2.x, p3.x)), std::min(p1.y, std::min(p2.y, p3.y))),
Point(std::max(p1.x, std::max(p2.x, p3.x)), std::max(p1.y, std::max(p2.y, p3.y))));
// clip extremes to frame buffer size
triangle_bounds = clip.intersection(triangle_bounds);
// if triangle completely out of bounds then don't bother!
if (triangle_bounds.empty()) {
return;
}
// fix "winding" of vertices if needed
int32_t winding = orient2d(p1, p2, p3);
if (winding < 0) {
Point t;
t = p1; p1 = p3; p3 = t;
}
// bias ensures no overdraw between neighbouring triangles
int8_t bias0 = is_top_left(p2, p3) ? 0 : -1;
int8_t bias1 = is_top_left(p3, p1) ? 0 : -1;
int8_t bias2 = is_top_left(p1, p2) ? 0 : -1;
int32_t a01 = p1.y - p2.y;
int32_t b01 = p2.x - p1.x;
int32_t a12 = p2.y - p3.y;
int32_t b12 = p3.x - p2.x;
int32_t a20 = p3.y - p1.y;
int32_t b20 = p1.x - p3.x;
Point tl(triangle_bounds.x, triangle_bounds.y);
int32_t w0row = orient2d(p2, p3, tl) + bias0;
int32_t w1row = orient2d(p3, p1, tl) + bias1;
int32_t w2row = orient2d(p1, p2, tl) + bias2;
for (uint32_t y = 0; y < triangle_bounds.h; y++) {
int32_t w0 = w0row;
int32_t w1 = w1row;
int32_t w2 = w2row;
Pen *dest = ptr(triangle_bounds.x, triangle_bounds.y + y);
for (uint32_t x = 0; x < triangle_bounds.w; x++) {
if ((w0 | w1 | w2) >= 0) {
*dest = pen;
}
dest++;
w0 += a12;
w1 += a20;
w2 += a01;
}
w0row += b12;
w1row += b20;
w2row += b01;
}
}
void PicoGraphics::polygon(const std::vector<Point> &points) {
static int32_t nodes[64]; // maximum allowed number of nodes per scanline for polygon rendering
int32_t miny = points[0].y, maxy = points[0].y;
for (uint16_t i = 1; i < points.size(); i++) {
miny = std::min(miny, points[i].y);
maxy = std::max(maxy, points[i].y);
}
// for each scanline within the polygon bounds (clipped to clip rect)
Point p;
for (p.y = std::max(clip.y, miny); p.y <= std::min(clip.y + clip.h, maxy); p.y++) {
uint8_t n = 0;
for (uint16_t i = 0; i < points.size(); i++) {
uint16_t j = (i + 1) % points.size();
int32_t sy = points[i].y;
int32_t ey = points[j].y;
int32_t fy = p.y;
if ((sy < fy && ey >= fy) || (ey < fy && sy >= fy)) {
int32_t sx = points[i].x;
int32_t ex = points[j].x;
int32_t px = int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx));
nodes[n++] = px < clip.x ? clip.x : (px >= clip.x + clip.w ? clip.x + clip.w - 1 : px);// clamp(int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx)), clip.x, clip.x + clip.w);
}
}
uint16_t i = 0;
while (i < n - 1) {
if (nodes[i] > nodes[i + 1]) {
int32_t s = nodes[i]; nodes[i] = nodes[i + 1]; nodes[i + 1] = s;
if (i) i--;
}
else {
i++;
}
}
for (uint16_t i = 0; i < n; i += 2) {
pixel_span(Point(nodes[i], p.y), nodes[i + 1] - nodes[i] + 1);
}
}
}
void PicoGraphics::line(Point p1, Point p2) {
// fast horizontal line
if(p1.y == p2.y) {
int32_t start = std::max(clip.x, std::min(p1.x, p2.x));
int32_t end = std::min(clip.x + clip.w, std::max(p1.x, p2.x));
pixel_span(Point(start, p1.y), end - start);
return;
}
// fast vertical line
if(p1.x == p2.x) {
int32_t start = std::max(clip.y, std::min(p1.y, p2.y));
int32_t length = std::min(clip.y + clip.h, std::max(p1.y, p2.y)) - start;
Pen *dest = ptr(p1.x, start);
while(length--) {
*dest = pen;
dest += bounds.w;
}
return;
}
// general purpose line
// lines are either "shallow" or "steep" based on whether the x delta
// is greater than the y delta
int32_t dx = p2.x - p1.x;
int32_t dy = p2.y - p1.y;
bool shallow = std::abs(dx) > std::abs(dy);
if(shallow) {
// shallow version
int32_t s = std::abs(dx); // number of steps
int32_t sx = dx < 0 ? -1 : 1; // x step value
int32_t sy = (dy << 16) / s; // y step value in fixed 16:16
int32_t x = p1.x;
int32_t y = p1.y << 16;
while(s--) {
pixel(Point(x, y >> 16));
y += sy;
x += sx;
}
}else{
// steep version
int32_t s = std::abs(dy); // number of steps
int32_t sy = dy < 0 ? -1 : 1; // x step value
int32_t sx = (dx << 16) / s; // y step value in fixed 16:16
int32_t y = p1.y;
int32_t x = p1.x << 16;
while(s--) {
pixel(Point(x >> 16, y));
y += sy;
x += sx;
}
}
}
}

Wyświetl plik

@ -3,36 +3,40 @@
#include <string>
#include <cstdint>
#include <algorithm>
#include <vector>
// a tiny little graphics library for our Pico products
// supports only 16-bit (565) RGB framebuffers
namespace pimoroni {
struct rect;
typedef uint16_t Pen;
struct point {
struct Rect;
struct Point {
int32_t x = 0, y = 0;
point() = default;
point(int32_t x, int32_t y) : x(x), y(y) {}
Point() = default;
Point(int32_t x, int32_t y) : x(x), y(y) {}
inline point& operator-= (const point &a) { x -= a.x; y -= a.y; return *this; }
inline point& operator+= (const point &a) { x += a.x; y += a.y; return *this; }
inline Point& operator-= (const Point &a) { x -= a.x; y -= a.y; return *this; }
inline Point& operator+= (const Point &a) { x += a.x; y += a.y; return *this; }
point clamp(const rect &r) const;
Point clamp(const Rect &r) const;
};
struct rect {
struct Rect {
int32_t x = 0, y = 0, w = 0, h = 0;
rect() = default;
rect(int32_t x, int32_t y, int32_t w, int32_t h) : x(x), y(y), w(w), h(h) {}
Rect() = default;
Rect(int32_t x, int32_t y, int32_t w, int32_t h) : x(x), y(y), w(w), h(h) {}
Rect(const Point &tl, const Point &br) : x(tl.x), y(tl.y), w(br.x - tl.x), h(br.y - tl.y) {}
bool empty() const;
bool contains(const point &p) const;
bool contains(const rect &p) const;
bool intersects(const rect &r) const;
rect intersection(const rect &r) const;
bool contains(const Point &p) const;
bool contains(const Rect &p) const;
bool intersects(const Rect &r) const;
Rect intersection(const Rect &r) const;
void inflate(int32_t v);
void deflate(int32_t v);
@ -42,34 +46,43 @@ namespace pimoroni {
public:
uint16_t *frame_buffer;
rect bounds;
rect clip;
Rect bounds;
Rect clip;
uint16_t pen;
Pen pen;
public:
PicoGraphics(uint16_t width, uint16_t height, uint16_t *frame_buffer)
: frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) {}
void set_pen(uint8_t r, uint8_t g, uint8_t b);
void set_pen(uint16_t p);
uint16_t create_pen(uint8_t r, uint8_t g, uint8_t b);
void set_pen(Pen p);
void set_clip(const rect &r);
constexpr Pen create_pen(uint8_t r, uint8_t g, uint8_t b) {
uint16_t p = ((r & 0b11111000) << 8) |
((g & 0b11111100) << 3) |
((b & 0b11111000) >> 3);
return __builtin_bswap16(p);
};
void set_clip(const Rect &r);
void remove_clip();
uint16_t* ptr(const point &p);
uint16_t* ptr(const rect &r);
uint16_t* ptr(int32_t x, int32_t y);
Pen* ptr(const Point &p);
Pen* ptr(const Rect &r);
Pen* ptr(int32_t x, int32_t y);
void clear();
void pixel(const point &p);
void pixel_span(const point &p, int32_t l);
void rectangle(const rect &r);
void circle(const point &p, int32_t r);
void character(const char c, const point &p, uint8_t scale = 2);
void text(const std::string &t, const point &p, int32_t wrap, uint8_t scale = 2);
//void polygon(std::vector);
void pixel(const Point &p);
void pixel_span(const Point &p, int32_t l);
void rectangle(const Rect &r);
void circle(const Point &p, int32_t r);
void character(const char c, const Point &p, uint8_t scale = 2);
void text(const std::string &t, const Point &p, int32_t wrap, uint8_t scale = 2);
void polygon(const std::vector<Point> &points);
void triangle(Point p1, Point p2, Point p3);
void line(Point p1, Point p2);
};
}

Wyświetl plik

@ -5,55 +5,55 @@
namespace pimoroni {
point point::clamp(const rect &r) const {
return point(
Point Point::clamp(const Rect &r) const {
return Point(
std::min(std::max(x, r.x), r.x + r.w),
std::min(std::max(y, r.y), r.y + r.h)
);
}
point operator- (point lhs, const point &rhs) {
Point operator- (Point lhs, const Point &rhs) {
lhs -= rhs;
return lhs;
}
point operator- (const point &rhs) {
return point(-rhs.x, -rhs.y);
Point operator- (const Point &rhs) {
return Point(-rhs.x, -rhs.y);
}
point operator+ (point lhs, const point &rhs) {
Point operator+ (Point lhs, const Point &rhs) {
lhs += rhs;
return lhs;
}
bool rect::empty() const {
bool Rect::empty() const {
return w <= 0 || h <= 0;
}
bool rect::contains(const point &p) const {
bool Rect::contains(const Point &p) const {
return p.x >= x && p.y >= y && p.x < x + w && p.y < y + h;
}
bool rect::contains(const rect &p) const {
bool Rect::contains(const Rect &p) const {
return p.x >= x && p.y >= y && p.x + p.w < x + w && p.y + p.h < y + h;
}
bool rect::intersects(const rect &r) const {
bool Rect::intersects(const Rect &r) const {
return !(x > r.x + r.w || x + w < r.x || y > r.y + r.h || y + h < r.y);
}
rect rect::intersection(const rect &r) const {
return rect(std::max(x, r.x),
Rect Rect::intersection(const Rect &r) const {
return Rect(std::max(x, r.x),
std::max(y, r.y),
std::min(x + w, r.x + r.w) - std::max(x, r.x),
std::min(y + h, r.y + r.h) - std::max(y, r.y));
}
void rect::inflate(int32_t v) {
void Rect::inflate(int32_t v) {
x -= v; y -= v; w += v * 2; h += v * 2;
}
void rect::deflate(int32_t v) {
void Rect::deflate(int32_t v) {
x += v; y += v; w -= v * 2; h -= v * 2;
}

Wyświetl plik

@ -146,7 +146,7 @@ mp_obj_t picodisplay_create_pen(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj)
mp_raise_ValueError("b out of range. Expected 0 to 255");
else
pen = display->create_pen(r, g, b);
return mp_obj_new_int(pen);
}
@ -158,7 +158,7 @@ mp_obj_t picodisplay_set_clip(mp_uint_t n_args, const mp_obj_t *args) {
int w = mp_obj_get_int(args[2]);
int h = mp_obj_get_int(args[3]);
rect r(x, y, w, h);
Rect r(x, y, w, h);
display->set_clip(r);
return mp_const_none;
@ -178,9 +178,9 @@ mp_obj_t picodisplay_pixel(mp_obj_t x_obj, mp_obj_t y_obj) {
int x = mp_obj_get_int(x_obj);
int y = mp_obj_get_int(y_obj);
point p(x, y);
Point p(x, y);
display->pixel(p);
return mp_const_none;
}
@ -189,7 +189,7 @@ mp_obj_t picodisplay_pixel_span(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t l_obj)
int y = mp_obj_get_int(y_obj);
int l = mp_obj_get_int(l_obj);
point p(x, y);
Point p(x, y);
display->pixel_span(p, l);
return mp_const_none;
@ -203,7 +203,7 @@ mp_obj_t picodisplay_rectangle(mp_uint_t n_args, const mp_obj_t *args) {
int w = mp_obj_get_int(args[2]);
int h = mp_obj_get_int(args[3]);
rect r(x, y, w, h);
Rect r(x, y, w, h);
display->rectangle(r);
return mp_const_none;
@ -214,7 +214,7 @@ mp_obj_t picodisplay_circle(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t r_obj) {
int y = mp_obj_get_int(y_obj);
int r = mp_obj_get_int(r_obj);
point p(x, y);
Point p(x, y);
display->circle(p, r);
return mp_const_none;
@ -225,7 +225,7 @@ mp_obj_t picodisplay_character(mp_uint_t n_args, const mp_obj_t *args) {
int x = mp_obj_get_int(args[1]);
int y = mp_obj_get_int(args[2]);
point p(x, y);
Point p(x, y);
if(n_args == 4) {
int scale = mp_obj_get_int(args[3]);
display->character((char)c, p, scale);
@ -246,7 +246,7 @@ mp_obj_t picodisplay_text(mp_uint_t n_args, const mp_obj_t *args) {
int y = mp_obj_get_int(args[2]);
int wrap = mp_obj_get_int(args[3]);
point p(x, y);
Point p(x, y);
if(n_args == 5) {
int scale = mp_obj_get_int(args[4]);
display->text(t, p, wrap, scale);