Skip to content

Commit 223bf61

Browse files
committed
brush: Convert SmudgeBucket from array to struct
This will make the code slightly more readable.
1 parent 0303431 commit 223bf61

File tree

1 file changed

+77
-64
lines changed

1 file changed

+77
-64
lines changed

mypaint-brush.c

Lines changed: 77 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,26 @@
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

Comments
 (0)