@@ -469,6 +469,100 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) {
469
469
}
470
470
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (framebuf_line_obj , 6 , 6 , framebuf_line );
471
471
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
+
472
566
STATIC mp_obj_t framebuf_blit (size_t n_args , const mp_obj_t * args_in ) {
473
567
mp_obj_framebuf_t * self = MP_OBJ_TO_PTR (args_in [0 ]);
474
568
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[] = {
603
697
{ MP_ROM_QSTR (MP_QSTR_vline ), MP_ROM_PTR (& framebuf_vline_obj ) },
604
698
{ MP_ROM_QSTR (MP_QSTR_rect ), MP_ROM_PTR (& framebuf_rect_obj ) },
605
699
{ 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 ) },
606
701
{ MP_ROM_QSTR (MP_QSTR_blit ), MP_ROM_PTR (& framebuf_blit_obj ) },
607
702
{ MP_ROM_QSTR (MP_QSTR_scroll ), MP_ROM_PTR (& framebuf_scroll_obj ) },
608
703
{ MP_ROM_QSTR (MP_QSTR_text ), MP_ROM_PTR (& framebuf_text_obj ) },
0 commit comments