@@ -241,11 +241,17 @@ STATIC mp_framebuf_p_t formats[] = {
241
241
[FRAMEBUF_MHMSB ] = {mono_horiz_setpixel , mono_horiz_getpixel , mono_horiz_fill_rect },
242
242
};
243
243
244
- static inline void setpixel (const mp_obj_framebuf_t * fb , unsigned int x , unsigned int y , uint32_t col ) {
244
+ STATIC inline void setpixel (const mp_obj_framebuf_t * fb , unsigned int x , unsigned int y , uint32_t col ) {
245
245
formats [fb -> format ].setpixel (fb , x , y , col );
246
246
}
247
247
248
- static inline uint32_t getpixel (const mp_obj_framebuf_t * fb , unsigned int x , unsigned int y ) {
248
+ STATIC void setpixel_checked (const mp_obj_framebuf_t * fb , mp_int_t x , mp_int_t y , mp_int_t col , mp_int_t mask ) {
249
+ if (mask && 0 <= x && x < fb -> width && 0 <= y && y < fb -> height ) {
250
+ setpixel (fb , x , y , col );
251
+ }
252
+ }
253
+
254
+ STATIC inline uint32_t getpixel (const mp_obj_framebuf_t * fb , unsigned int x , unsigned int y ) {
249
255
return formats [fb -> format ].getpixel (fb , x , y );
250
256
}
251
257
@@ -470,12 +476,6 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) {
470
476
}
471
477
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (framebuf_line_obj , 6 , 6 , framebuf_line );
472
478
473
- STATIC void ellipse_pixel (const mp_obj_framebuf_t * fb , mp_int_t x , mp_int_t y , mp_int_t col , mp_int_t mask ) {
474
- if (mask && 0 <= x && x < fb -> width && 0 <= y && y < fb -> height ) {
475
- setpixel (fb , x , y , col );
476
- }
477
- }
478
-
479
479
// Q2 Q1
480
480
// Q3 Q4
481
481
#define ELLIPSE_MASK_FILL (0x10)
@@ -500,10 +500,10 @@ STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int
500
500
fill_rect (fb , cx , cy + y , x + 1 , 1 , col );
501
501
}
502
502
} else {
503
- ellipse_pixel (fb , cx + x , cy - y , col , mask & ELLIPSE_MASK_Q1 );
504
- ellipse_pixel (fb , cx - x , cy - y , col , mask & ELLIPSE_MASK_Q2 );
505
- ellipse_pixel (fb , cx - x , cy + y , col , mask & ELLIPSE_MASK_Q3 );
506
- ellipse_pixel (fb , cx + x , cy + y , col , mask & ELLIPSE_MASK_Q4 );
503
+ setpixel_checked (fb , cx + x , cy - y , col , mask & ELLIPSE_MASK_Q1 );
504
+ setpixel_checked (fb , cx - x , cy - y , col , mask & ELLIPSE_MASK_Q2 );
505
+ setpixel_checked (fb , cx - x , cy + y , col , mask & ELLIPSE_MASK_Q3 );
506
+ setpixel_checked (fb , cx + x , cy + y , col , mask & ELLIPSE_MASK_Q4 );
507
507
}
508
508
}
509
509
@@ -619,11 +619,23 @@ STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) {
619
619
620
620
// Don't include the bottom pixel of a given edge to avoid
621
621
// duplicating the node with the start of the next edge. This
622
- // will miss some pixels on the boundary, but we get them at
623
- // the end when we unconditionally draw the outline .
622
+ // will miss some pixels on the boundary, and in particular
623
+ // at a local minima or inflection point .
624
624
if (py1 != py2 && ((py1 > row && py2 <= row ) || (py1 <= row && py2 > row ))) {
625
625
mp_int_t node = (32 * px1 + 32 * (px2 - px1 ) * (row - py1 ) / (py2 - py1 ) + 16 ) / 32 ;
626
626
nodes [n_nodes ++ ] = node ;
627
+ } else if (row == MAX (py1 , py2 )) {
628
+ // At local-minima, try and manually fill in the pixels that get missed above.
629
+ if (py1 < py2 ) {
630
+ setpixel_checked (self , x + px2 , y + py2 , col , 1 );
631
+ } else if (py2 < py1 ) {
632
+ setpixel_checked (self , x + px1 , y + py1 , col , 1 );
633
+ } else {
634
+ // Even though this is a hline and would be faster to
635
+ // use fill_rect, use line() because it handles x2 <
636
+ // x1.
637
+ line (self , x + px1 , y + py1 , x + px2 , y + py2 , col );
638
+ }
627
639
}
628
640
629
641
px1 = px2 ;
@@ -654,21 +666,20 @@ STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) {
654
666
fill_rect (self , x + nodes [i ], y + row , (nodes [i + 1 ] - nodes [i ]) + 1 , 1 , col );
655
667
}
656
668
}
669
+ } else {
670
+ // Outline only.
671
+ mp_int_t px1 = poly_int (& bufinfo , 0 );
672
+ mp_int_t py1 = poly_int (& bufinfo , 1 );
673
+ int i = n_poly * 2 - 1 ;
674
+ do {
675
+ mp_int_t py2 = poly_int (& bufinfo , i -- );
676
+ mp_int_t px2 = poly_int (& bufinfo , i -- );
677
+ line (self , x + px1 , y + py1 , x + px2 , y + py2 , col );
678
+ px1 = px2 ;
679
+ py1 = py2 ;
680
+ } while (i >= 0 );
657
681
}
658
682
659
- // Always draw the outline (either because fill=False, or to fix the
660
- // boundary pixels for a fill, see above).
661
- mp_int_t px1 = poly_int (& bufinfo , 0 );
662
- mp_int_t py1 = poly_int (& bufinfo , 1 );
663
- int i = n_poly * 2 - 1 ;
664
- do {
665
- mp_int_t py2 = poly_int (& bufinfo , i -- );
666
- mp_int_t px2 = poly_int (& bufinfo , i -- );
667
- line (self , x + px1 , y + py1 , x + px2 , y + py2 , col );
668
- px1 = px2 ;
669
- py1 = py2 ;
670
- } while (i >= 0 );
671
-
672
683
return mp_const_none ;
673
684
}
674
685
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (framebuf_poly_obj , 5 , 6 , framebuf_poly );
0 commit comments