5454
5555#define GRID_SIZE 256.0
5656
57- /* Named indices for the smudge bucket arrays */
58- enum {
59- SMUDGE_R , SMUDGE_G , SMUDGE_B , SMUDGE_A ,
60- PREV_COL_R , PREV_COL_G , PREV_COL_B , PREV_COL_A ,
61- PREV_COL_RECENTNESS ,
62- SMUDGE_BUCKET_SIZE
63- };
57+ /**
58+ * SmudgeBucket:
59+ *
60+ * Optionally used by MyPaintBrush.
61+ *
62+ * Usually used for brushes with multiple offset dabs, where each
63+ * dab is assigned its own bucket containing a smudge state.
64+ */
65+ struct SmudgeBucket {
66+ float smudge_r ,
67+ float smudge_g ,
68+ float smudge_b ,
69+ float smudge_a ,
70+ float prev_col_r ,
71+ float prev_col_g ,
72+ float prev_col_b ,
73+ float prev_col_a ,
74+ float prev_col_recentness ,
75+ float smudge_bucket_size ,
76+ }
6477
6578/* The Brush class stores two things:
6679 b) settings: constant during a stroke (eg. size, spacing, dynamics, color selected by the user)
@@ -94,7 +107,7 @@ struct MyPaintBrush {
94107 // smudge bucket array: part of the state, but stored separately.
95108 // Usually used for brushes with multiple offset dabs, where each
96109 // dab is assigned its own bucket containing a smudge state.
97- float * smudge_buckets ;
110+ SmudgeBucket * smudge_buckets ;
98111 int num_buckets ;
99112 int min_bucket_used ;
100113 int max_bucket_used ;
@@ -158,7 +171,7 @@ brush_reset(MyPaintBrush *self)
158171 int min_index = self -> min_bucket_used ;
159172 if (min_index != -1 ) {
160173 int max_index = self -> max_bucket_used ;
161- size_t num_bytes = (max_index - min_index + 1 ) * sizeof (self -> smudge_buckets [0 ]) * SMUDGE_BUCKET_SIZE ;
174+ size_t num_bytes = (max_index - min_index + 1 ) * sizeof (self -> smudge_buckets [0 ]);
162175 memset (self -> smudge_buckets + min_index , 0 , num_bytes );
163176 self -> min_bucket_used = -1 ;
164177 self -> max_bucket_used = -1 ;
@@ -195,7 +208,7 @@ mypaint_brush_new_with_buckets(int num_smudge_buckets)
195208 }
196209
197210 if (num_smudge_buckets > 0 ) {
198- float * bucket_array = malloc (num_smudge_buckets * SMUDGE_BUCKET_SIZE * sizeof (float ));
211+ float * bucket_array = malloc (num_smudge_buckets * sizeof (SmudgeBucket ));
199212 if (!bucket_array ) {
200213 free (self );
201214 return NULL ;
@@ -460,16 +473,16 @@ mypaint_brush_set_smudge_bucket_state(
460473 float prev_color_recentness )
461474{
462475 if (self -> num_buckets > bucket_index ) {
463- float * bucket = & self -> smudge_buckets [bucket_index ];
464- bucket [ SMUDGE_R ] = r ;
465- bucket [ SMUDGE_G ] = g ;
466- bucket [ SMUDGE_B ] = b ;
467- bucket [ SMUDGE_A ] = a ;
468- bucket [ PREV_COL_R ] = prev_r ;
469- bucket [ PREV_COL_G ] = prev_g ;
470- bucket [ PREV_COL_B ] = prev_b ;
471- bucket [ PREV_COL_A ] = prev_a ;
472- bucket [ PREV_COL_RECENTNESS ] = prev_color_recentness ;
476+ SmudgeBucket * bucket = self -> smudge_buckets [bucket_index ];
477+ bucket -> smudge_r = r ;
478+ bucket -> smudge_g = g ;
479+ bucket -> smudge_b = b ;
480+ bucket -> smudge_a = a ;
481+ bucket -> prev_col_r = prev_r ;
482+ bucket -> prev_col_g = prev_g ;
483+ bucket -> prev_col_b = prev_b ;
484+ bucket -> prev_col_a = prev_a ;
485+ bucket -> prev_col_recentness = prev_color_recentness ;
473486 return TRUE;
474487 }
475488 return FALSE;
@@ -492,16 +505,16 @@ mypaint_brush_get_smudge_bucket_state(
492505 float * prev_color_recentness )
493506{
494507 if (self -> num_buckets > bucket_index ) {
495- float * bucket = & self -> smudge_buckets [bucket_index ];
496- * r = bucket [ SMUDGE_R ] ;
497- * g = bucket [ SMUDGE_G ] ;
498- * b = bucket [ SMUDGE_B ] ;
499- * a = bucket [ SMUDGE_A ] ;
500- * prev_r = bucket [ PREV_COL_R ] ;
501- * prev_g = bucket [ PREV_COL_G ] ;
502- * prev_b = bucket [ PREV_COL_B ] ;
503- * prev_a = bucket [ PREV_COL_A ] ;
504- * prev_color_recentness = bucket [ PREV_COL_RECENTNESS ] ;
508+ SmudgeBucket * bucket = self -> smudge_buckets [bucket_index ];
509+ * r = bucket -> smudge_r ;
510+ * g = bucket -> smudge_g ;
511+ * b = bucket -> smudge_b ;
512+ * a = bucket -> smudge_a ;
513+ * prev_r = bucket -> prev_col_r ;
514+ * prev_g = bucket -> prev_col_g ;
515+ * prev_b = bucket -> prev_col_b ;
516+ * prev_a = bucket -> prev_col_a ;
517+ * prev_color_recentness = bucket -> PREV_COL_RECENTNESS ;
505518 return TRUE;
506519 }
507520 return FALSE;
@@ -903,7 +916,7 @@ void print_inputs(MyPaintBrush *self, float* inputs)
903916 STATE (self , ACTUAL_ELLIPTICAL_DAB_ANGLE ) = mod_arith (SETTING (self , ELLIPTICAL_DAB_ANGLE ) - viewrotation + 180.0 , 180.0 ) - 180.0 ;
904917 }
905918
906- float * fetch_smudge_bucket (MyPaintBrush * self ) {
919+ SmudgeBucket * fetch_smudge_bucket (MyPaintBrush * self ) {
907920 if (!self -> smudge_buckets || !self -> num_buckets ) {
908921 return & STATE (self , SMUDGE_RA );
909922 }
@@ -914,12 +927,12 @@ void print_inputs(MyPaintBrush *self, float* inputs)
914927 if (self -> max_bucket_used < bucket_index ) {
915928 self -> max_bucket_used = bucket_index ;
916929 }
917- return & self -> smudge_buckets [bucket_index * SMUDGE_BUCKET_SIZE ];
930+ return self -> smudge_buckets [bucket_index ];
918931 }
919932
920933 gboolean
921934 update_smudge_color (
922- const MyPaintBrush * self , MyPaintSurface * surface , float * const smudge_bucket , const float smudge_length , int px ,
935+ const MyPaintBrush * self , MyPaintSurface * surface , SmudgeBucket * const smudge_bucket , const float smudge_length , int px ,
923936 int py , const float radius , const float legacy_smudge , const float paint_factor )
924937 {
925938
@@ -934,16 +947,16 @@ void print_inputs(MyPaintBrush *self, float* inputs)
934947 float r , g , b , a ;
935948 const float smudge_length_log = SETTING (self , SMUDGE_LENGTH_LOG );
936949
937- const float recentness = smudge_bucket [ PREV_COL_RECENTNESS ] * update_factor ;
938- smudge_bucket [ PREV_COL_RECENTNESS ] = recentness ;
950+ const float recentness = smudge_bucket -> prev_col_recentness * update_factor ;
951+ smudge_bucket -> prev_col_recentness = recentness ;
939952
940953 const float margin = 0.0000000000000001 ;
941954 if (recentness < MIN (1.0 , powf (0.5 * update_factor , smudge_length_log ) + margin )) {
942955 if (recentness == 0.0 ) {
943956 // first initialization of smudge color (initiate with color sampled from canvas)
944957 update_factor = 0.0 ;
945958 }
946- smudge_bucket [ PREV_COL_RECENTNESS ] = 1.0 ;
959+ smudge_bucket -> prev_col_recentness = 1.0 ;
947960
948961 const float radius_log = SETTING (self , SMUDGE_RADIUS_LOG );
949962 const float smudge_radius = CLAMP (radius * expf (radius_log ), ACTUAL_RADIUS_MIN , ACTUAL_RADIUS_MAX );
@@ -960,45 +973,45 @@ void print_inputs(MyPaintBrush *self, float* inputs)
960973 if ((smudge_op_lim > 0.0 && a < smudge_op_lim ) || (smudge_op_lim < 0.0 && a > - smudge_op_lim )) {
961974 return TRUE; // signals the caller to return early
962975 }
963- smudge_bucket [ PREV_COL_R ] = r ;
964- smudge_bucket [ PREV_COL_G ] = g ;
965- smudge_bucket [ PREV_COL_B ] = b ;
966- smudge_bucket [ PREV_COL_A ] = a ;
976+ smudge_bucket -> prev_col_r = r ;
977+ smudge_bucket -> prev_col_g = g ;
978+ smudge_bucket -> prev_col_b = b ;
979+ smudge_bucket -> prev_col_a = a ;
967980 } else {
968- r = smudge_bucket [ PREV_COL_R ] ;
969- g = smudge_bucket [ PREV_COL_G ] ;
970- b = smudge_bucket [ PREV_COL_B ] ;
971- a = smudge_bucket [ PREV_COL_A ] ;
981+ r = smudge_bucket -> prev_col_r ;
982+ g = smudge_bucket -> prev_col_g ;
983+ b = smudge_bucket -> prev_col_b ;
984+ a = smudge_bucket -> prev_col_a ;
972985 }
973986
974987 if (legacy_smudge ) {
975988 const float fac_old = update_factor ;
976989 const float fac_new = (1.0 - update_factor ) * a ;
977- smudge_bucket [ SMUDGE_R ] = fac_old * smudge_bucket [ SMUDGE_R ] + fac_new * r ;
978- smudge_bucket [ SMUDGE_G ] = fac_old * smudge_bucket [ SMUDGE_G ] + fac_new * g ;
979- smudge_bucket [ SMUDGE_B ] = fac_old * smudge_bucket [ SMUDGE_B ] + fac_new * b ;
980- smudge_bucket [ SMUDGE_A ] = CLAMP ((fac_old * smudge_bucket [ SMUDGE_A ] + fac_new ), 0.0 , 1.0 );
990+ smudge_bucket -> smudge_r = fac_old * smudge_bucket -> smudge_r + fac_new * r ;
991+ smudge_bucket -> smudge_g = fac_old * smudge_bucket -> smudge_g + fac_new * g ;
992+ smudge_bucket -> smudge_b = fac_old * smudge_bucket -> smudge_b + fac_new * b ;
993+ smudge_bucket -> smudge_a = CLAMP ((fac_old * smudge_bucket -> smudge_a + fac_new ), 0.0 , 1.0 );
981994 } else if (a > WGM_EPSILON * 10 ) {
982- float prev_smudge_color [4 ] = {smudge_bucket [ SMUDGE_R ] , smudge_bucket [ SMUDGE_G ] , smudge_bucket [ SMUDGE_B ] ,
983- smudge_bucket [ SMUDGE_A ] };
995+ float prev_smudge_color [4 ] = {smudge_bucket -> smudge_r , smudge_bucket -> smudge_g , smudge_bucket -> smudge_b ,
996+ smudge_bucket -> smudge_a };
984997 float sampled_color [4 ] = {r , g , b , a };
985998
986999 float * smudge_new = mix_colors (prev_smudge_color , sampled_color , update_factor , paint_factor );
987- smudge_bucket [ SMUDGE_R ] = smudge_new [SMUDGE_R ];
988- smudge_bucket [ SMUDGE_G ] = smudge_new [SMUDGE_G ];
989- smudge_bucket [ SMUDGE_B ] = smudge_new [SMUDGE_B ];
990- smudge_bucket [ SMUDGE_A ] = smudge_new [SMUDGE_A ];
1000+ smudge_bucket -> smudge_r = smudge_new [SMUDGE_R ];
1001+ smudge_bucket -> smudge_g = smudge_new [SMUDGE_G ];
1002+ smudge_bucket -> smudge_b = smudge_new [SMUDGE_B ];
1003+ smudge_bucket -> smudge_a = smudge_new [SMUDGE_A ];
9911004 } else {
9921005 // To avoid color noise from spectral mixing with a low alpha,
9931006 // we'll just decrease the alpha of the existing smudge color.
994- smudge_bucket [ SMUDGE_A ] = (smudge_bucket [ SMUDGE_A ] + a ) / 2 ;
1007+ smudge_bucket -> smudge_a = (smudge_bucket -> smudge_a + a ) / 2 ;
9951008 }
9961009 return FALSE; // signals the caller to not return early (the default)
9971010 }
9981011
9991012 float
10001013 apply_smudge (
1001- const float * const smudge_bucket , const float smudge_value , const gboolean legacy_smudge ,
1014+ const SmudgeBucket * const smudge_bucket , const float smudge_value , const gboolean legacy_smudge ,
10021015 const float paint_factor , float * color_r , float * color_g , float * color_b )
10031016 {
10041017 float smudge_factor = MIN (1.0 , smudge_value );
@@ -1007,17 +1020,17 @@ void print_inputs(MyPaintBrush *self, float* inputs)
10071020 // dab will do erasing towards that transparency level.
10081021 // see also ../doc/smudge_math.png
10091022 const float eraser_target_alpha =
1010- CLAMP ((1.0 - smudge_factor ) + smudge_factor * smudge_bucket [ SMUDGE_A ] , 0.0 , 1.0 );
1023+ CLAMP ((1.0 - smudge_factor ) + smudge_factor * smudge_bucket -> smudge_a , 0.0 , 1.0 );
10111024
10121025 if (eraser_target_alpha > 0 ) {
10131026 if (legacy_smudge ) {
10141027 const float col_factor = 1.0 - smudge_factor ;
1015- * color_r = (smudge_factor * smudge_bucket [ SMUDGE_R ] + col_factor * * color_r ) / eraser_target_alpha ;
1016- * color_g = (smudge_factor * smudge_bucket [ SMUDGE_G ] + col_factor * * color_g ) / eraser_target_alpha ;
1017- * color_b = (smudge_factor * smudge_bucket [ SMUDGE_B ] + col_factor * * color_b ) / eraser_target_alpha ;
1028+ * color_r = (smudge_factor * smudge_bucket -> smudge_r + col_factor * * color_r ) / eraser_target_alpha ;
1029+ * color_g = (smudge_factor * smudge_bucket -> smudge_g + col_factor * * color_g ) / eraser_target_alpha ;
1030+ * color_b = (smudge_factor * smudge_bucket -> smudge_b + col_factor * * color_b ) / eraser_target_alpha ;
10181031 } else {
1019- float smudge_color [4 ] = {smudge_bucket [ SMUDGE_R ] , smudge_bucket [ SMUDGE_G ] , smudge_bucket [ SMUDGE_B ] ,
1020- smudge_bucket [ SMUDGE_A ] };
1032+ float smudge_color [4 ] = {smudge_bucket -> smudge_r , smudge_bucket -> smudge_g , smudge_bucket -> smudge_b ,
1033+ smudge_bucket -> smudge_a };
10211034 float brush_color [4 ] = {* color_r , * color_g , * color_b , 1.0 };
10221035 float * color_new = mix_colors (smudge_color , brush_color , smudge_factor , paint_factor );
10231036 * color_r = color_new [SMUDGE_R ];
@@ -1123,7 +1136,7 @@ gboolean prepare_and_draw_dab (MyPaintBrush *self, MyPaintSurface * surface, gbo
11231136 const float smudge_length = SETTING (self , SMUDGE_LENGTH );
11241137 if (smudge_length < 1.0 && // default smudge length is 0.5, so the smudge factor is checked as well
11251138 (SETTING (self , SMUDGE ) != 0.0 || !mypaint_mapping_is_constant (self -> settings [MYPAINT_BRUSH_SETTING_SMUDGE ]))) {
1126- float * const bucket = fetch_smudge_bucket (self );
1139+ SmudgeBucket * const bucket = fetch_smudge_bucket (self );
11271140 gboolean return_early = update_smudge_color (
11281141 self , surface , bucket , smudge_length , ROUND (x ), ROUND (y ), radius , legacy_smudge , paint_factor );
11291142 if (return_early ) {
@@ -1135,7 +1148,7 @@ gboolean prepare_and_draw_dab (MyPaintBrush *self, MyPaintSurface * surface, gbo
11351148 const float smudge_value = SETTING (self , SMUDGE );
11361149
11371150 if (smudge_value > 0.0 ) {
1138- float * const bucket = fetch_smudge_bucket (self );
1151+ SmudgeBucket * const bucket = fetch_smudge_bucket (self );
11391152 eraser_target_alpha =
11401153 apply_smudge (bucket , smudge_value , legacy_smudge , paint_factor , & color_h , & color_s , & color_v );
11411154 }
0 commit comments