-static void combine_replace(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_mult(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- double mult[MAXCHANNELS];
- mult[3] = in->channel[3];
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
- }
- COMBINEA(*out, mult, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3)
- c.channel[ch] = out->channel[ch] * in->channel[ch];
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (255.0 / RAND_MAX))
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (1.0 / RAND_MAX))
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_add(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] + in->channel[ch];
- if (total > 255)
- total = 255;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] + in->channel[ch];
- if (total > 1.0)
- total = 1.0;
- out->channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_diff(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
- }
- COMBINE(*out, c, channels)
- ++out;
- ++in;
- }
-}
-
-static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darken(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_hue(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_sat(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_value(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
- int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_color(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[0] = in->channel[0];
- c.channel[1] = in->channel[1];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
+static void
+fill_opacity(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *data) {
+ struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill;
+ int alpha_chan = channels > 2 ? 3 : 1;
+ i_color *datap = data;
+
+ (f->other_fill->f_fill_with_color)(f->other_fill, x, y, width, channels, data);
+ while (width--) {
+ double new_alpha = datap->channel[alpha_chan] * f->alpha_mult;
+ if (new_alpha < 0)
+ datap->channel[alpha_chan] = 0;
+ else if (new_alpha > 255)
+ datap->channel[alpha_chan] = 255;
+ else datap->channel[alpha_chan] = (int)(new_alpha + 0.5);
+
+ ++datap;
+ }
+}
+static void
+fill_opacityf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *data) {
+ struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill;
+ int alpha_chan = channels > 2 ? 3 : 1;
+ i_fcolor *datap = data;
+
+ (f->other_fill->f_fill_with_fcolor)(f->other_fill, x, y, width, channels, data);
+
+ while (width--) {
+ double new_alpha = datap->channel[alpha_chan] * f->alpha_mult;
+ if (new_alpha < 0)
+ datap->channel[alpha_chan] = 0;
+ else if (new_alpha > 1.0)
+ datap->channel[alpha_chan] = 1.0;
+ else datap->channel[alpha_chan] = new_alpha;