From df73e91c088f47a6bc247d5437fa0f744f79ca62 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 7 Mar 2018 01:38:51 +0100 Subject: [PATCH] Implement "corner to corner" Gradient ellipses --- src/graph.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/graph.h | 2 ++ src/operatio.c | 37 ++++++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/src/graph.c b/src/graph.c index 0af8c078..7a7f7db3 100644 --- a/src/graph.c +++ b/src/graph.c @@ -2,6 +2,7 @@ */ /* Grafx2 - The Ultimate 256-color bitmap paint program + Copyright 2018 Thomas Bernard Copyright 2008 Franck Charlet Copyright 2007-2017 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) @@ -2435,6 +2436,82 @@ void Draw_grad_ellipse(short center_x,short center_y,short horizontal_radius,sho Update_part_of_screen(start_x,start_y,end_x-start_x+1,end_y-start_y+1); } +void Draw_grad_inscribed_ellipse(short x1, short y1, short x2, short y2, short spot_x, short spot_y) +{ + short left, right, top, bottom; + short dbl_center_x; // double of center_x + short dbl_center_y; // double of center_y + short dbl_x_radius; // double of horizontal radius + short dbl_y_radius; // double of vertical radius + long sq_dbl_x_radius; + long sq_dbl_y_radius; + qword sq_dbl_radius_product; + short x_pos; + short y_pos; + long sq_dist_x; // Square horizontal distance with the lightning point + long sq_dist_y; // Square vertical distance with the lightning point + + if (x1 > x2) + { + left = x2; + right = x1; + } + else + { + left = x1; + right = x2; + } + if (y1 > y2) + { + top = y2; + bottom = y1; + } + else + { + top = y1; + bottom = y2; + } + dbl_center_x = left+right; + dbl_center_y = top+bottom; + dbl_x_radius = right-left+1; + dbl_y_radius = bottom-top+1; + sq_dbl_x_radius = (long)dbl_x_radius*dbl_x_radius; + sq_dbl_y_radius = (long)dbl_y_radius*dbl_y_radius; + sq_dbl_radius_product = (qword)sq_dbl_x_radius * sq_dbl_y_radius; + + // calculate grandient range + Gradient_total_range= (sq_dbl_x_radius + sq_dbl_y_radius) / 4 + + ((dbl_center_x/2-spot_x)*(dbl_center_x/2-spot_x))+ + ((dbl_center_y/2-spot_y)*(dbl_center_y/2-spot_y))+ + (sqrt(sq_dbl_x_radius + sq_dbl_y_radius) + *sqrt( + ((dbl_center_x/2-spot_x)*(dbl_center_x/2-spot_x))+ + ((dbl_center_y/2-spot_y)*(dbl_center_y/2-spot_y)))); + + if (Gradient_total_range==0) + Gradient_total_range=1; + + for (y_pos = top; y_pos <= bottom; y_pos++) + { + long dbl_y = 2*y_pos - dbl_center_y; + long sq_dbl_y = dbl_y*dbl_y; + sq_dist_y =(y_pos-spot_y); + sq_dist_y *= sq_dist_y; + for (x_pos = left; x_pos <= right; x_pos++) + { + long dbl_x = 2*x_pos - dbl_center_x; + long sq_dbl_x = dbl_x*dbl_x; + if (((qword)sq_dbl_x * sq_dbl_y_radius + (qword)sq_dbl_y * sq_dbl_x_radius) < sq_dbl_radius_product) + { + sq_dist_x =(x_pos-spot_x); + sq_dist_x *= sq_dist_x; + Gradient_function(sq_dist_x+sq_dist_y,x_pos,y_pos); + } + } + } + + Update_part_of_screen(left, top, right-left+1, bottom-top+1); +} // Tracé d'un rectangle (rax ray - rbx rby) dégradé selon le vecteur (vax vay - vbx - vby) void Draw_grad_rectangle(short rax,short ray,short rbx,short rby,short vax,short vay, short vbx, short vby) diff --git a/src/graph.h b/src/graph.h index c298652f..a5872cba 100644 --- a/src/graph.h +++ b/src/graph.h @@ -2,6 +2,7 @@ */ /* Grafx2 - The Ultimate 256-color bitmap paint program + Copyright 2018 Thomas Bernard Copyright 2007-2008 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) @@ -104,6 +105,7 @@ void Degrade_aleatoire (long index,short x_pos,short y_pos); void Draw_grad_circle (short center_x,short center_y,long sqradius,short spot_x,short spot_y); void Draw_grad_ellipse(short center_x,short center_y,short horizontal_radius,short vertical_radius,short spot_x,short spot_y); +void Draw_grad_inscribed_ellipse(short x1, short y1, short x2, short y2, short spot_x, short spot_y); void Draw_grad_rectangle(short rax,short ray,short rbx,short rby,short vax,short vay, short vbx, short vby); void Polyfill_general(int vertices, short * points, int color); diff --git a/src/operatio.c b/src/operatio.c index 9088cf5e..0d51768a 100644 --- a/src/operatio.c +++ b/src/operatio.c @@ -3272,8 +3272,10 @@ void Grad_ellipse_12_6(void) short center_x; short center_y; short color; +#ifndef INSCRIBED_ELLIPSE short horizontal_radius; short vertical_radius; +#endif Operation_pop(&tangent_y); Operation_pop(&tangent_x); @@ -3284,9 +3286,12 @@ void Grad_ellipse_12_6(void) if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) { Hide_cursor(); +#ifndef INSCRIBED_ELLIPSE Cursor_shape=CURSOR_SHAPE_TARGET; +#endif Display_coords_rel_or_abs(center_x,center_y); +#ifndef INSCRIBED_ELLIPSE horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y @@ -3298,6 +3303,10 @@ void Grad_ellipse_12_6(void) vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y :center_y-Paintbrush_Y; Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); +#else + Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y); + Draw_empty_inscribed_ellipse_preview(center_x,center_y,Paintbrush_X,Paintbrush_Y,color); +#endif Display_cursor(); } @@ -3326,8 +3335,10 @@ void Grad_ellipse_0_6(void) short color; short click; //short radius; +#ifndef INSCRIBED_ELLIPSE short horizontal_radius; short vertical_radius; +#endif Operation_pop(&tangent_y); Operation_pop(&tangent_x); @@ -3354,7 +3365,11 @@ void Grad_ellipse_0_6(void) Cursor_shape=CURSOR_SHAPE_XOR_TARGET; // On affiche une croix XOR au centre du cercle +#ifndef INSCRIBED_ELLIPSE Draw_curve_cross(center_x,center_y); +#else + Draw_curve_cross((center_x+tangent_x)/2, (center_y+tangent_y)/2); +#endif if (Menu_is_visible) { @@ -3367,16 +3382,24 @@ void Grad_ellipse_0_6(void) } else { +#ifndef INSCRIBED_ELLIPSE horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); +#else + Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y); +#endif Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_TARGET; +#ifndef INSCRIBED_ELLIPSE Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Back_color); +#else + Draw_filled_inscribed_ellipse(center_x,center_y,tangent_x,tangent_y,Back_color); +#endif End_of_modification(); if ((Config.Coords_rel) && (Menu_is_visible)) @@ -3402,8 +3425,10 @@ void Grad_ellipse_12_8(void) short center_x; short center_y; short color; +#ifndef INSCRIBED_ELLIPSE short horizontal_radius; short vertical_radius; +#endif short old_mouse_k; Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile @@ -3416,19 +3441,31 @@ void Grad_ellipse_12_8(void) Hide_cursor(); // On efface la croix XOR au centre de l'ellipse +#ifndef INSCRIBED_ELLIPSE Draw_curve_cross(center_x,center_y); +#else + Draw_curve_cross((center_x+tangent_x)/2, (center_y+tangent_y)/2); +#endif +#ifndef INSCRIBED_ELLIPSE horizontal_radius=(tangent_x>center_x)?tangent_x-center_x :center_x-tangent_x; vertical_radius =(tangent_y>center_y)?tangent_y-center_y :center_y-tangent_y; Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); +#else + Hide_empty_inscribed_ellipse_preview(center_x,center_y,tangent_x,tangent_y); +#endif Paintbrush_hidden=Paintbrush_hidden_before_scroll; Cursor_shape=CURSOR_SHAPE_XOR_TARGET; if (Mouse_K==old_mouse_k) +#ifndef INSCRIBED_ELLIPSE Draw_grad_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Paintbrush_X,Paintbrush_Y); +#else + Draw_grad_inscribed_ellipse(center_x,center_y,tangent_x,tangent_y,Paintbrush_X,Paintbrush_Y); +#endif Display_cursor(); End_of_modification();