@@ -469,6 +469,100 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) {
469469}
470470STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (framebuf_line_obj , 6 , 6 , framebuf_line );
471471
472+ 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 ) {
473+ if (mask && 0 <= x && x < fb -> width && 0 <= y && y < fb -> height ) {
474+ setpixel (fb , x , y , col );
475+ }
476+ }
477+
478+ // Q2 Q1
479+ // Q3 Q4
480+ #define ELLIPSE_MASK_FILL (0x10)
481+ #define ELLIPSE_MASK_ALL (0x0f)
482+ #define ELLIPSE_MASK_Q1 (0x01)
483+ #define ELLIPSE_MASK_Q2 (0x02)
484+ #define ELLIPSE_MASK_Q3 (0x04)
485+ #define ELLIPSE_MASK_Q4 (0x08)
486+
487+ STATIC void draw_ellipse_points (const mp_obj_framebuf_t * fb , mp_int_t cx , mp_int_t cy , mp_int_t x , mp_int_t y , mp_int_t col , mp_int_t mask ) {
488+ if (mask & ELLIPSE_MASK_FILL ) {
489+ if (mask & ELLIPSE_MASK_Q1 ) {
490+ fill_rect (fb , cx , cy - y , x + 1 , 1 , col );
491+ }
492+ if (mask & ELLIPSE_MASK_Q2 ) {
493+ fill_rect (fb , cx - x , cy - y , x + 1 , 1 , col );
494+ }
495+ if (mask & ELLIPSE_MASK_Q3 ) {
496+ fill_rect (fb , cx - x , cy + y , x + 1 , 1 , col );
497+ }
498+ if (mask & ELLIPSE_MASK_Q4 ) {
499+ fill_rect (fb , cx , cy + y , x + 1 , 1 , col );
500+ }
501+ } else {
502+ ellipse_pixel (fb , cx + x , cy - y , col , mask & ELLIPSE_MASK_Q1 );
503+ ellipse_pixel (fb , cx - x , cy - y , col , mask & ELLIPSE_MASK_Q2 );
504+ ellipse_pixel (fb , cx - x , cy + y , col , mask & ELLIPSE_MASK_Q3 );
505+ ellipse_pixel (fb , cx + x , cy + y , col , mask & ELLIPSE_MASK_Q4 );
506+ }
507+ }
508+
509+ STATIC mp_obj_t framebuf_ellipse (size_t n_args , const mp_obj_t * args_in ) {
510+ mp_obj_framebuf_t * self = MP_OBJ_TO_PTR (args_in [0 ]);
511+ mp_int_t args [5 ];
512+ framebuf_args (args_in , args , 5 ); // cx, cy, xradius, yradius, col
513+ mp_int_t mask = (n_args > 6 && mp_obj_is_true (args_in [6 ])) ? ELLIPSE_MASK_FILL : 0 ;
514+ if (n_args > 7 ) {
515+ mask |= mp_obj_get_int (args_in [7 ]) & ELLIPSE_MASK_ALL ;
516+ } else {
517+ mask |= ELLIPSE_MASK_ALL ;
518+ }
519+ mp_int_t two_asquare = 2 * args [2 ] * args [2 ];
520+ mp_int_t two_bsquare = 2 * args [3 ] * args [3 ];
521+ mp_int_t x = args [2 ];
522+ mp_int_t y = 0 ;
523+ mp_int_t xchange = args [3 ] * args [3 ] * (1 - 2 * args [2 ]);
524+ mp_int_t ychange = args [2 ] * args [2 ];
525+ mp_int_t ellipse_error = 0 ;
526+ mp_int_t stoppingx = two_bsquare * args [2 ];
527+ mp_int_t stoppingy = 0 ;
528+ while (stoppingx >= stoppingy ) { // 1st set of points, y' > -1
529+ draw_ellipse_points (self , args [0 ], args [1 ], x , y , args [4 ], mask );
530+ y += 1 ;
531+ stoppingy += two_asquare ;
532+ ellipse_error += ychange ;
533+ ychange += two_asquare ;
534+ if ((2 * ellipse_error + xchange ) > 0 ) {
535+ x -= 1 ;
536+ stoppingx -= two_bsquare ;
537+ ellipse_error += xchange ;
538+ xchange += two_bsquare ;
539+ }
540+ }
541+ // 1st point set is done start the 2nd set of points
542+ x = 0 ;
543+ y = args [3 ];
544+ xchange = args [3 ] * args [3 ];
545+ ychange = args [2 ] * args [2 ] * (1 - 2 * args [3 ]);
546+ ellipse_error = 0 ;
547+ stoppingx = 0 ;
548+ stoppingy = two_asquare * args [3 ];
549+ while (stoppingx <= stoppingy ) { // 2nd set of points, y' < -1
550+ draw_ellipse_points (self , args [0 ], args [1 ], x , y , args [4 ], mask );
551+ x += 1 ;
552+ stoppingx += two_bsquare ;
553+ ellipse_error += xchange ;
554+ xchange += two_bsquare ;
555+ if ((2 * ellipse_error + ychange ) > 0 ) {
556+ y -= 1 ;
557+ stoppingy -= two_asquare ;
558+ ellipse_error += ychange ;
559+ ychange += two_asquare ;
560+ }
561+ }
562+ return mp_const_none ;
563+ }
564+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (framebuf_ellipse_obj , 6 , 8 , framebuf_ellipse );
565+
472566STATIC mp_obj_t framebuf_blit (size_t n_args , const mp_obj_t * args_in ) {
473567 mp_obj_framebuf_t * self = MP_OBJ_TO_PTR (args_in [0 ]);
474568 mp_obj_t source_in = mp_obj_cast_to_native_base (args_in [1 ], MP_OBJ_FROM_PTR (& mp_type_framebuf ));
@@ -603,6 +697,7 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
603697 { MP_ROM_QSTR (MP_QSTR_vline ), MP_ROM_PTR (& framebuf_vline_obj ) },
604698 { MP_ROM_QSTR (MP_QSTR_rect ), MP_ROM_PTR (& framebuf_rect_obj ) },
605699 { MP_ROM_QSTR (MP_QSTR_line ), MP_ROM_PTR (& framebuf_line_obj ) },
700+ { MP_ROM_QSTR (MP_QSTR_ellipse ), MP_ROM_PTR (& framebuf_ellipse_obj ) },
606701 { MP_ROM_QSTR (MP_QSTR_blit ), MP_ROM_PTR (& framebuf_blit_obj ) },
607702 { MP_ROM_QSTR (MP_QSTR_scroll ), MP_ROM_PTR (& framebuf_scroll_obj ) },
608703 { MP_ROM_QSTR (MP_QSTR_text ), MP_ROM_PTR (& framebuf_text_obj ) },
0 commit comments