Skip to content

Commit 8a94d9a

Browse files
authored
Merge pull request #5784 from WarriorOfWire/vectorio_contains
vectorio contains(x, y)
2 parents 7cea858 + 8de5f90 commit 8a94d9a

File tree

6 files changed

+82
-45
lines changed

6 files changed

+82
-45
lines changed

shared-bindings/vectorio/Circle.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ const mp_obj_property_t vectorio_circle_radius_obj = {
9797
//|
9898

9999
STATIC const mp_rom_map_elem_t vectorio_circle_locals_dict_table[] = {
100+
// Functions
101+
{ MP_ROM_QSTR(MP_QSTR_contains), MP_ROM_PTR(&vectorio_vector_shape_contains_obj) },
100102
// Properties
101103
{ MP_ROM_QSTR(MP_QSTR_radius), MP_ROM_PTR(&vectorio_circle_radius_obj) },
102104
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },

shared-bindings/vectorio/Polygon.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ const mp_obj_property_t vectorio_polygon_points_obj = {
103103
//|
104104

105105
STATIC const mp_rom_map_elem_t vectorio_polygon_locals_dict_table[] = {
106+
// Functions
107+
{ MP_ROM_QSTR(MP_QSTR_contains), MP_ROM_PTR(&vectorio_vector_shape_contains_obj) },
106108
// Properties
107109
{ MP_ROM_QSTR(MP_QSTR_points), MP_ROM_PTR(&vectorio_polygon_points_obj) },
108110
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },

shared-bindings/vectorio/Rectangle.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ const mp_obj_property_t vectorio_rectangle_height_obj = {
122122
//|
123123

124124
STATIC const mp_rom_map_elem_t vectorio_rectangle_locals_dict_table[] = {
125+
// Functions
126+
{ MP_ROM_QSTR(MP_QSTR_contains), MP_ROM_PTR(&vectorio_vector_shape_contains_obj) },
125127
// Properties
126128
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },
127129
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&vectorio_vector_shape_y_obj) },

shared-bindings/vectorio/VectorShape.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ vectorio_draw_protocol_impl_t vectorio_vector_shape_draw_protocol_impl = {
8080
.draw_get_refresh_areas = (draw_get_refresh_areas_fun)vectorio_vector_shape_get_refresh_areas,
8181
};
8282

83+
// Stub checker does not approve of these shared properties.
84+
// x: int
85+
// y: int
86+
// """true if x,y lies inside the shape."""
87+
//
88+
STATIC mp_obj_t vectorio_vector_shape_obj_contains(mp_obj_t wrapper_shape, mp_obj_t x_obj, mp_obj_t y_obj) {
89+
// Relies on the fact that only vector_shape impl gets matched with a VectorShape.
90+
const vectorio_draw_protocol_t *draw_protocol = mp_proto_get(MP_QSTR_protocol_draw, wrapper_shape);
91+
vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(draw_protocol->draw_get_protocol_self(wrapper_shape));
92+
93+
mp_int_t x = mp_obj_get_int(x_obj);
94+
mp_int_t y = mp_obj_get_int(y_obj);
95+
return mp_obj_new_bool(common_hal_vectorio_vector_shape_contains(self, x, y));
96+
}
97+
MP_DEFINE_CONST_FUN_OBJ_3(vectorio_vector_shape_contains_obj, vectorio_vector_shape_obj_contains);
8398

8499
// Stub checker does not approve of these shared properties.
85100
// x: int

shared-bindings/vectorio/VectorShape.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ void common_hal_vectorio_vector_shape_construct(vectorio_vector_shape_t *self,
1818
vectorio_ishape_t ishape,
1919
mp_obj_t pixel_shader, int32_t x, int32_t y);
2020

21+
bool common_hal_vectorio_vector_shape_contains(vectorio_vector_shape_t *self, mp_int_t x, mp_int_t y);
22+
2123
void common_hal_vectorio_vector_shape_set_dirty(void *self);
2224

2325
mp_int_t common_hal_vectorio_vector_shape_get_x(vectorio_vector_shape_t *self);
@@ -40,5 +42,6 @@ extern const mp_obj_property_t vectorio_vector_shape_x_obj;
4042
extern const mp_obj_property_t vectorio_vector_shape_y_obj;
4143
extern const mp_obj_property_t vectorio_vector_shape_location_obj;
4244
extern const mp_obj_property_t vectorio_vector_shape_pixel_shader_obj;
45+
extern const mp_obj_fun_builtin_fixed_t vectorio_vector_shape_contains_obj;
4346

4447
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_SHAPE_H

shared-module/vectorio/VectorShape.c

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ static uint32_t min(uint32_t a, uint32_t b) {
7272
return a < b ? a : b;
7373
}
7474

75+
static void short_bound_check(mp_int_t i, qstr name) {
76+
if (i < SHRT_MIN || i > SHRT_MAX) {
77+
mp_raise_ValueError_varg(translate("%q must be between %d and %d"), name, SHRT_MIN, SHRT_MAX);
78+
}
79+
}
80+
7581
inline __attribute__((always_inline))
7682
static void area_transpose(displayio_area_t *to_transpose) {
7783
int16_t swap = to_transpose->y1;
@@ -124,21 +130,50 @@ static void _get_screen_area(vectorio_vector_shape_t *self, displayio_area_t *ou
124130
VECTORIO_SHAPE_DEBUG(" out:{(%5d,%5d), (%5d,%5d)}\n", out_area->x1, out_area->y1, out_area->x2, out_area->y2);
125131
}
126132

133+
// Get the target pixel based on the shape's coordinate space
134+
static void screen_to_shape_coordinates(vectorio_vector_shape_t *self, uint16_t x, uint16_t y, int16_t *out_shape_x, int16_t *out_shape_y) {
135+
if (self->absolute_transform->transpose_xy) {
136+
*out_shape_x = y - self->absolute_transform->y - self->absolute_transform->dy * self->x;
137+
*out_shape_y = x - self->absolute_transform->x - self->absolute_transform->dx * self->y;
127138

128-
STATIC
129-
void check_bounds_and_set_x(vectorio_vector_shape_t *self, mp_int_t x) {
130-
if (x < SHRT_MIN || x > SHRT_MAX) {
131-
mp_raise_ValueError_varg(translate("%q must be between %d and %d"), MP_QSTR_x, SHRT_MIN, SHRT_MAX);
139+
VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", *out_shape_x, *out_shape_y);
140+
if (self->absolute_transform->dx < 1) {
141+
*out_shape_y *= -1;
142+
}
143+
if (self->absolute_transform->dy < 1) {
144+
*out_shape_x *= -1;
145+
}
146+
VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", *out_shape_x, *out_shape_y);
147+
} else {
148+
*out_shape_x = x - self->absolute_transform->x - self->absolute_transform->dx * self->x;
149+
*out_shape_y = y - self->absolute_transform->y - self->absolute_transform->dy * self->y;
150+
151+
VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", *out_shape_x, *out_shape_y);
152+
if (self->absolute_transform->dx < 1) {
153+
*out_shape_x *= -1;
154+
}
155+
if (self->absolute_transform->dy < 1) {
156+
*out_shape_y *= -1;
157+
}
158+
VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", *out_shape_x, *out_shape_y);
159+
160+
// It's mirrored via dx. Maybe we need to add support for also separately mirroring?
161+
// if (self->absolute_transform->mirror_x) {
162+
// pixel_to_get_x = (shape_area.x2 - shape_area.x1) - (pixel_to_get_x - shape_area.x1) + shape_area.x1 - 1;
163+
// }
164+
// if (self->absolute_transform->mirror_y) {
165+
// pixel_to_get_y = (shape_area.y2 - shape_area.y1) - (pixel_to_get_y - shape_area.y1) + +shape_area.y1 - 1;
166+
// }
132167
}
133-
self->x = x;
134168
}
135169

170+
static void check_bounds_and_set_x(vectorio_vector_shape_t *self, mp_int_t x) {
171+
short_bound_check(x, MP_QSTR_x);
172+
self->x = x;
173+
}
136174

137-
STATIC
138-
void check_bounds_and_set_y(vectorio_vector_shape_t *self, mp_int_t y) {
139-
if (y < SHRT_MIN || y > SHRT_MAX) {
140-
mp_raise_ValueError_varg(translate("%q must be between %d and %d"), MP_QSTR_y, SHRT_MIN, SHRT_MAX);
141-
}
175+
static void check_bounds_and_set_y(vectorio_vector_shape_t *self, mp_int_t y) {
176+
short_bound_check(y, MP_QSTR_y);
142177
self->y = y;
143178
}
144179

@@ -195,6 +230,17 @@ void common_hal_vectorio_vector_shape_construct(vectorio_vector_shape_t *self,
195230
_get_screen_area(self, &self->current_area);
196231
}
197232

233+
bool common_hal_vectorio_vector_shape_contains(vectorio_vector_shape_t *self, mp_int_t x, mp_int_t y) {
234+
VECTORIO_SHAPE_DEBUG("%p contains(%d, %d)", self);
235+
short_bound_check(x, MP_QSTR_x);
236+
short_bound_check(y, MP_QSTR_y);
237+
int16_t shape_x;
238+
int16_t shape_y;
239+
screen_to_shape_coordinates(self, x, y, &shape_x, &shape_y);
240+
bool shape_contains_coordinates = 0 != self->ishape.get_pixel(self->ishape.shape, shape_x, shape_y);
241+
return shape_contains_coordinates;
242+
}
243+
198244

199245
mp_int_t common_hal_vectorio_vector_shape_get_x(vectorio_vector_shape_t *self) {
200246
VECTORIO_SHAPE_DEBUG("%p get_x\n", self);
@@ -277,7 +323,6 @@ void common_hal_vectorio_vector_shape_set_pixel_shader(vectorio_vector_shape_t *
277323
common_hal_vectorio_vector_shape_set_dirty(self);
278324
}
279325

280-
281326
bool vectorio_vector_shape_fill_area(vectorio_vector_shape_t *self, const _displayio_colorspace_t *colorspace, const displayio_area_t *area, uint32_t *mask, uint32_t *buffer) {
282327
// Shape areas are relative to 0,0. This will allow rotation about a known axis.
283328
// The consequence is that the area reported by the shape itself is _relative_ to 0,0.
@@ -335,42 +380,10 @@ bool vectorio_vector_shape_fill_area(vectorio_vector_shape_t *self, const _displ
335380
}
336381
output_pixel.pixel = 0;
337382

338-
// Get the target pixel based on the shape's coordinate space
383+
// Cast input screen coordinates to shape coordinates to pick the pixel to draw
339384
int16_t pixel_to_get_x;
340385
int16_t pixel_to_get_y;
341-
if (self->absolute_transform->transpose_xy) {
342-
pixel_to_get_x = input_pixel.y - self->absolute_transform->y - self->absolute_transform->dy * self->x;
343-
pixel_to_get_y = input_pixel.x - self->absolute_transform->x - self->absolute_transform->dx * self->y;
344-
345-
VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", pixel_to_get_x, pixel_to_get_y);
346-
if (self->absolute_transform->dx < 1) {
347-
pixel_to_get_y *= -1;
348-
}
349-
if (self->absolute_transform->dy < 1) {
350-
pixel_to_get_x *= -1;
351-
}
352-
VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", pixel_to_get_x, pixel_to_get_y);
353-
} else {
354-
pixel_to_get_x = input_pixel.x - self->absolute_transform->x - self->absolute_transform->dx * self->x;
355-
pixel_to_get_y = input_pixel.y - self->absolute_transform->y - self->absolute_transform->dy * self->y;
356-
357-
VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", pixel_to_get_x, pixel_to_get_y);
358-
if (self->absolute_transform->dx < 1) {
359-
pixel_to_get_x *= -1;
360-
}
361-
if (self->absolute_transform->dy < 1) {
362-
pixel_to_get_y *= -1;
363-
}
364-
VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", pixel_to_get_x, pixel_to_get_y);
365-
366-
// It's mirrored via dx. Maybe we need to add support for also separately mirroring?
367-
// if (self->absolute_transform->mirror_x) {
368-
// pixel_to_get_x = (shape_area.x2 - shape_area.x1) - (pixel_to_get_x - shape_area.x1) + shape_area.x1 - 1;
369-
// }
370-
// if (self->absolute_transform->mirror_y) {
371-
// pixel_to_get_y = (shape_area.y2 - shape_area.y1) - (pixel_to_get_y - shape_area.y1) + +shape_area.y1 - 1;
372-
// }
373-
}
386+
screen_to_shape_coordinates(self, input_pixel.x, input_pixel.y, &pixel_to_get_x, &pixel_to_get_y);
374387

375388
VECTORIO_SHAPE_PIXEL_DEBUG(" get_pixel %p (%3d, %3d) -> ( %3d, %3d )", self->ishape.shape, input_pixel.x, input_pixel.y, pixel_to_get_x, pixel_to_get_y);
376389
#ifdef VECTORIO_PERF

0 commit comments

Comments
 (0)