@@ -24,6 +24,7 @@ typedef struct _PNG_decode_target {
24
24
Point position = {0 , 0 };
25
25
Rect source = {0 , 0 , 0 , 0 };
26
26
Point scale = {1 , 1 };
27
+ int rotation = 0 ;
27
28
} _PNG_decode_target;
28
29
29
30
typedef struct _PNG_obj_t {
@@ -125,14 +126,37 @@ MICROPY_EVENT_POLL_HOOK
125
126
Point current_position = target->position ;
126
127
uint8_t current_mode = target->mode ;
127
128
Point scale = target->scale ;
129
+ int rotation = target->rotation ;
130
+ Point step = {0 , 0 };
131
+
128
132
// "pixel" is slow and clipped,
129
133
// guaranteeing we wont draw png data out of the framebuffer..
130
134
// Can we clip beforehand and make this faster?
131
135
132
136
if (pDraw->y < target->source .y || pDraw->y >= target->source .y + target->source .h ) return ;
133
137
134
- current_position.y += pDraw->y * scale.y ;
135
- current_position -= Point (0 , target->source .y );
138
+ switch (rotation) {
139
+ case 0 :
140
+ current_position.y += (pDraw->y - target->source .y ) * scale.y ;
141
+ step = {scale.x , 0 };
142
+ break ;
143
+ case 90 :
144
+ current_position.y += target->source .w * scale.y ;
145
+ current_position.x += target->source .h * scale.x ;
146
+ current_position.x += (pDraw->y - target->source .y ) * -scale.x ;
147
+ step = {0 , -scale.y };
148
+ break ;
149
+ case 180 :
150
+ current_position.x += target->source .w * scale.x ;
151
+ current_position.y += target->source .h * scale.y ;
152
+ current_position.y += (pDraw->y - target->source .y ) * -scale.y ;
153
+ step = {-scale.x , 0 };
154
+ break ;
155
+ case 270 :
156
+ current_position.x += (pDraw->y - target->source .y ) * scale.x ;
157
+ step = {0 , scale.y };
158
+ break ;
159
+ }
136
160
137
161
// mp_printf(&mp_plat_print, "Drawing scanline at %d, %dbpp, type: %d, width: %d pitch: %d alpha: %d\n", y, pDraw->iBpp, pDraw->iPixelType, pDraw->iWidth, pDraw->iPitch, pDraw->iHasAlpha);
138
162
uint8_t *pixel = (uint8_t *)pDraw->pPixels ;
@@ -144,7 +168,7 @@ MICROPY_EVENT_POLL_HOOK
144
168
if (x < target->source .x || x >= target->source .x + target->source .w ) continue ;
145
169
current_graphics->set_pen (r, g, b);
146
170
current_graphics->rectangle ({current_position.x , current_position.y , scale.x , scale.y });
147
- current_position. x += scale. x ;
171
+ current_position += step ;
148
172
}
149
173
} else if (pDraw->iPixelType == PNG_PIXEL_TRUECOLOR_ALPHA) {
150
174
for (int x = 0 ; x < pDraw->iWidth ; x++) {
@@ -157,7 +181,7 @@ MICROPY_EVENT_POLL_HOOK
157
181
current_graphics->set_pen (r, g, b);
158
182
current_graphics->rectangle ({current_position.x , current_position.y , scale.x , scale.y });
159
183
}
160
- current_position. x += scale. x ;
184
+ current_position += step ;
161
185
}
162
186
} else if (pDraw->iPixelType == PNG_PIXEL_INDEXED) {
163
187
for (int x = 0 ; x < pDraw->iWidth ; x++) {
@@ -219,7 +243,7 @@ MICROPY_EVENT_POLL_HOOK
219
243
current_graphics->rectangle ({current_position.x , current_position.y , scale.x , scale.y });
220
244
}
221
245
}
222
- current_position. x += scale. x ;
246
+ current_position += step ;
223
247
}
224
248
}
225
249
}
@@ -292,14 +316,15 @@ mp_obj_t _PNG_openRAM(mp_obj_t self_in, mp_obj_t buffer) {
292
316
293
317
// decode
294
318
mp_obj_t _PNG_decode (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
295
- enum { ARG_self, ARG_x, ARG_y, ARG_scale, ARG_mode, ARG_source };
319
+ enum { ARG_self, ARG_x, ARG_y, ARG_scale, ARG_mode, ARG_source, ARG_rotate };
296
320
static const mp_arg_t allowed_args[] = {
297
321
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
298
322
{ MP_QSTR_x, MP_ARG_INT, {.u_int = 0 } },
299
323
{ MP_QSTR_y, MP_ARG_INT, {.u_int = 0 } },
300
324
{ MP_QSTR_scale, MP_ARG_OBJ, {.u_obj = nullptr } },
301
325
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = 0 } },
302
326
{ MP_QSTR_source, MP_ARG_OBJ, {.u_obj = nullptr } },
327
+ { MP_QSTR_rotate, MP_ARG_INT, {.u_int = 0 } },
303
328
};
304
329
305
330
mp_arg_val_t args[MP_ARRAY_SIZE (allowed_args)];
@@ -322,6 +347,18 @@ mp_obj_t _PNG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
322
347
self->decode_target ->source = {0 , 0 , self->width , self->height };
323
348
}
324
349
350
+ self->decode_target ->rotation = args[ARG_rotate].u_int ;
351
+ switch (self->decode_target ->rotation ) {
352
+ case 0 :
353
+ case 90 :
354
+ case 180 :
355
+ case 270 :
356
+ break ;
357
+ default :
358
+ mp_raise_ValueError (" decode(): rotation must be one of 0, 90, 180 or 270" );
359
+ break ;
360
+ }
361
+
325
362
// Scale is a single int, corresponds to both width/height
326
363
if (mp_obj_is_int (args[ARG_scale].u_obj )) {
327
364
self->decode_target ->scale = {
0 commit comments