7 fills.c - implements the basic general fills
15 fill = i_new_fill_solidf(&fc1, combine);
16 fill = i_new_fill_solid(&c1, combine);
17 fill = i_new_fill_hatchf(&fc1, &fc2, combine, hatch, cust_hash, dx, dy);
18 fill = i_new_fill_hatch(&c1, &c2, combine, hatch, cust_hash, dx, dy);
19 fill = i_new_fill_image(im, matrix, xoff, yoff, combine);
24 Implements the basic general fills, which can be used for filling some
25 shapes and for flood fills.
27 Each fill can implement up to 3 functions:
33 called for fills on 8-bit images. This can be NULL in which case the
34 fill_with_colorf function is called.
36 =item fill_with_fcolor
38 called for fills on non-8-bit images or when fill_with_color is NULL.
42 called by i_fill_destroy() if non-NULL, to release any extra resources
43 that the fill may need.
47 fill_with_color and fill_with_fcolor are basically the same function
48 except that the first works with lines of i_color and the second with
51 If the combines member if non-zero the line data is populated from the
52 target image before calling fill_with_*color.
54 fill_with_color needs to fill the I<data> parameter with the fill
55 pixels. If combines is non-zero it the fill pixels should be combined
56 with the existing data.
58 The current fills are:
76 Fountain fill is implemented by L<filters.c>.
78 Other fills that could be implemented include:
84 image - an image tiled over the fill area, with an offset either
85 horizontally or vertically.
89 checkerboard - combine 2 fills in a checkerboard
93 combine - combine the levels of 2 other fills based in the levels of
98 regmach - use the register machine to generate colors
107 static i_color fcolor_to_color(i_fcolor *c) {
111 for (ch = 0; ch < MAXCHANNELS; ++ch)
112 out.channel[ch] = SampleFTo8(c->channel[ch]);
117 static i_fcolor color_to_fcolor(i_color *c) {
121 for (ch = 0; ch < MAXCHANNELS; ++ch)
122 out.channel[ch] = Sample8ToF(c->channel[ch]);
127 /* alpha combine in with out */
128 #define COMBINE(out, in, channels) \
131 for (ch = 0; ch < (channels); ++ch) { \
132 (out).channel[ch] = ((out).channel[ch] * (255 - (in).channel[3]) \
133 + (in).channel[ch] * (in).channel[3]) / 255; \
137 /* alpha combine in with out, in this case in is a simple array of
138 samples, potentially not integers - the mult combiner uses doubles
140 #define COMBINEA(out, in, channels) \
143 for (ch = 0; ch < (channels); ++ch) { \
144 (out).channel[ch] = ((out).channel[ch] * (255 - (in)[3]) \
145 + (in)[ch] * (in)[3]) / 255; \
149 #define COMBINEF(out, in, channels) \
152 for (ch = 0; ch < (channels); ++ch) { \
153 (out).channel[ch] = (out).channel[ch] * (1.0 - (in).channel[3]) \
154 + (in).channel[ch] * (in).channel[3]; \
165 static void fill_solid(i_fill_t *, int x, int y, int width, int channels,
167 static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
169 static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
171 static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
172 int channels, i_fcolor *);
174 static i_fill_solid_t base_solid_fill =
184 static i_fill_solid_t base_solid_fill_comb =
196 =item i_fill_destroy(fill)
200 Call to destroy any fill object.
206 i_fill_destroy(i_fill_t *fill) {
208 (fill->destroy)(fill);
213 =item i_new_fill_solidf(color, combine)
217 Create a solid fill based on a float color.
219 If combine is non-zero then alpha values will be combined.
225 i_new_fill_solidf(i_fcolor *c, int combine) {
227 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
230 *fill = base_solid_fill_comb;
231 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
234 *fill = base_solid_fill;
236 for (ch = 0; ch < MAXCHANNELS; ++ch) {
237 fill->c.channel[ch] = SampleFTo8(c->channel[ch]);
244 =item i_new_fill_solid(color, combine)
248 Create a solid fill based on an 8-bit color.
250 If combine is non-zero then alpha values will be combined.
256 i_new_fill_solid(i_color *c, int combine) {
258 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
261 *fill = base_solid_fill_comb;
262 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
265 *fill = base_solid_fill;
267 for (ch = 0; ch < MAXCHANNELS; ++ch) {
268 fill->fc.channel[ch] = Sample8ToF(c->channel[ch]);
275 builtin_hatches[][8] =
278 /* 1x1 checkerboard */
279 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
282 /* 2x2 checkerboard */
283 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33,
286 /* 4 x 4 checkerboard */
287 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
290 /* single vertical lines */
291 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
294 /* double vertical lines */
295 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
298 /* quad vertical lines */
299 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
303 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
311 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
315 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
319 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
323 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88,
327 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11,
331 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
335 0xFF, 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88,
339 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA,
343 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
351 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
355 0x48, 0x84, 0x00, 0x00, 0x84, 0x48, 0x00, 0x00,
359 0x55, 0xFD, 0x05, 0xFD, 0x55, 0xDF, 0x50, 0xDF,
362 /* single cross hatch */
363 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x01,
366 /* double cross hatch */
367 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11,
370 /* vertical lozenge */
371 0x11, 0x11, 0x11, 0xAA, 0x44, 0x44, 0x44, 0xAA,
374 /* horizontal lozenge */
375 0x88, 0x70, 0x88, 0x07, 0x88, 0x70, 0x88, 0x07,
378 /* scales overlapping downwards */
379 0x80, 0x80, 0x41, 0x3E, 0x08, 0x08, 0x14, 0xE3,
382 /* scales overlapping upwards */
383 0xC7, 0x28, 0x10, 0x10, 0x7C, 0x82, 0x01, 0x01,
386 /* scales overlapping leftwards */
387 0x83, 0x84, 0x88, 0x48, 0x38, 0x48, 0x88, 0x84,
390 /* scales overlapping rightwards */
391 0x21, 0x11, 0x12, 0x1C, 0x12, 0x11, 0x21, 0xC1,
395 0x44, 0x88, 0x22, 0x11, 0x44, 0x88, 0x22, 0x11,
399 0xFF, 0x84, 0x84, 0x9C, 0x94, 0x9C, 0x90, 0x90,
403 0x80, 0x40, 0x20, 0x00, 0x02, 0x04, 0x08, 0x00,
412 unsigned char hatch[8];
416 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
418 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
422 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
423 int combine, int hatch, unsigned char *cust_hatch,
427 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
431 Creates a new hatched fill with the fg color used for the 1 bits in
432 the hatch and bg for the 0 bits. If combine is non-zero alpha values
435 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
436 hash definition, with the high-bits to the left.
438 If cust_hatch is NULL then one of the standard hatches is used.
440 (dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
445 i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
446 unsigned char *cust_hatch, int dx, int dy) {
447 return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch,
452 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
456 Creates a new hatched fill with the fg color used for the 1 bits in
457 the hatch and bg for the 0 bits. If combine is non-zero alpha values
460 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
461 hash definition, with the high-bits to the left.
463 If cust_hatch is NULL then one of the standard hatches is used.
465 (dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
470 i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
471 unsigned char *cust_hatch, int dx, int dy) {
472 return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch,
476 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
478 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
480 struct i_fill_image_t {
489 =item i_new_fill_image(im, matrix, xoff, yoff, combine)
493 Create an image based fill.
495 matrix is an array of 9 doubles representing a transformation matrix.
497 xoff and yoff are the offset into the image to start filling from.
502 i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine) {
503 struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); /* checked 14jul05 tonyc */
505 fill->base.fill_with_color = fill_image;
506 fill->base.fill_with_fcolor = fill_imagef;
507 fill->base.destroy = NULL;
510 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
513 fill->base.combine = NULL;
514 fill->base.combinef = NULL;
524 fill->has_matrix = 1;
525 memcpy(fill->matrix, matrix, sizeof(fill->matrix));
528 fill->has_matrix = 0;
534 #define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
539 =head1 INTERNAL FUNCTIONS
543 =item fill_solid(fill, x, y, width, channels, data)
545 The 8-bit sample fill function for non-combining solid fills.
550 fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
552 while (width-- > 0) {
553 *data++ = T_SOLID_FILL(fill)->c;
558 =item fill_solid(fill, x, y, width, channels, data)
560 The floating sample fill function for non-combining solid fills.
565 fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
567 while (width-- > 0) {
568 *data++ = T_SOLID_FILL(fill)->fc;
573 =item fill_solid_comb(fill, x, y, width, channels, data)
575 The 8-bit sample fill function for combining solid fills.
580 fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
582 i_color c = T_SOLID_FILL(fill)->c;
584 while (width-- > 0) {
590 =item fill_solidf_comb(fill, x, y, width, channels, data)
592 The floating sample fill function for combining solid fills.
597 fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
599 i_fcolor c = T_SOLID_FILL(fill)->fc;
601 while (width-- > 0) {
607 =item i_new_hatch_low(fg, bg, ffg, fbg, combine, hatch, cust_hatch, dx, dy)
609 Implements creation of hatch fill objects.
615 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
616 int combine, int hatch, unsigned char *cust_hatch,
618 i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */
620 fill->base.fill_with_color = fill_hatch;
621 fill->base.fill_with_fcolor = fill_hatchf;
622 fill->base.destroy = NULL;
623 fill->fg = fg ? *fg : fcolor_to_color(ffg);
624 fill->bg = bg ? *bg : fcolor_to_color(fbg);
625 fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
626 fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
628 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
631 fill->base.combine = NULL;
632 fill->base.combinef = NULL;
635 memcpy(fill->hatch, cust_hatch, 8);
638 if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
640 memcpy(fill->hatch, builtin_hatches[hatch], 8);
649 =item fill_hatch(fill, x, y, width, channels, data)
651 The 8-bit sample fill function for hatched fills.
655 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
657 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
658 int byte = f->hatch[(y + f->dy) & 7];
659 int xpos = (x + f->dx) & 7;
660 int mask = 128 >> xpos;
662 while (width-- > 0) {
663 *data++ = (byte & mask) ? f->fg : f->bg;
665 if ((mask >>= 1) == 0)
671 =item fill_hatchf(fill, x, y, width, channels, data)
673 The floating sample fill function for hatched fills.
677 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
679 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
680 int byte = f->hatch[(y + f->dy) & 7];
681 int xpos = (x + f->dx) & 7;
682 int mask = 128 >> xpos;
684 while (width-- > 0) {
685 *data++ = (byte & mask) ? f->ffg : f->fbg;
687 if ((mask >>= 1) == 0)
692 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
693 /* linear interpolation */
694 static i_color interp_i_color(i_color before, i_color after, double pos,
700 for (ch = 0; ch < channels; ++ch)
701 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
703 for (ch = 0; ch < channels; ++ch)
705 int temp = out.channel[ch] * 255 / out.channel[3];
708 out.channel[ch] = temp;
714 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
715 /* linear interpolation */
716 static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos,
722 for (ch = 0; ch < channels; ++ch)
723 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
725 for (ch = 0; ch < channels; ++ch)
727 int temp = out.channel[ch] / out.channel[3];
730 out.channel[ch] = temp;
737 =item fill_image(fill, x, y, width, channels, data, work)
741 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
743 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
750 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
751 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
752 double ix = floor(rx / f->src->xsize);
753 double iy = floor(ry / f->src->ysize);
760 ix = floor(rx / f->src->xsize);
764 iy = floor(ry / f->src->ysize);
766 rx -= ix * f->src->xsize;
767 ry -= iy * f->src->ysize;
769 for (dy = 0; dy < 2; ++dy) {
770 if ((int)rx == f->src->xsize-1) {
771 i_gpix(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
772 i_gpix(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
775 i_glin(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
778 c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
780 *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
786 /* this should be possible to optimize to use i_glin() */
790 int ix = rx / f->src->xsize;
791 int iy = ry / f->src->ysize;
795 ix = rx / f->src->xsize;
799 iy = ry / f->src->xsize;
801 rx -= ix * f->src->xsize;
802 ry -= iy * f->src->ysize;
803 i_gpix(f->src, rx, ry, out);
808 if (f->src->channels == 3) {
809 /* just set the alpha */
810 for (i = 0; i < width; ++i) {
811 data->channel[3] = 255;
815 else if (f->src->channels == 2) {
816 /* copy the alpha to channel 3, duplicate the grey value */
817 for (i = 0; i < width; ++i) {
818 data->channel[3] = data->channel[1];
819 data->channel[1] = data->channel[2] = data->channel[0];
823 else if (f->src->channels == 1) {
824 /* set the alpha, duplicate grey */
825 for (i = 0; i < width; ++i) {
826 data->channel[3] = 255;
827 data->channel[1] = data->channel[2] = data->channel[0];
834 =item fill_image(fill, x, y, width, channels, data, work)
838 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
840 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
846 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
847 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
848 double ix = floor(rx / f->src->xsize);
849 double iy = floor(ry / f->src->ysize);
856 ix = floor(rx / f->src->xsize);
860 iy = floor(ry / f->src->ysize);
862 rx -= ix * f->src->xsize;
863 ry -= iy * f->src->ysize;
865 for (dy = 0; dy < 2; ++dy) {
866 if ((int)rx == f->src->xsize-1) {
867 i_gpixf(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
868 i_gpixf(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
871 i_glinf(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
874 c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
876 *data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
882 /* this should be possible to optimize to use i_glin() */
886 int ix = rx / f->src->xsize;
887 int iy = ry / f->src->ysize;
891 ix = rx / f->src->xsize;
895 iy = ry / f->src->xsize;
897 rx -= ix * f->src->xsize;
898 ry -= iy * f->src->ysize;
899 i_gpixf(f->src, rx, ry, data);
904 if (f->src->channels == 3) {
905 /* just set the alpha */
906 for (i = 0; i < width; ++i) {
907 data->channel[3] = 1.0;
911 else if (f->src->channels == 2) {
912 /* copy the alpha to channel 3, duplicate the grey value */
913 for (i = 0; i < width; ++i) {
914 data->channel[3] = data->channel[1];
915 data->channel[1] = data->channel[2] = data->channel[0];
919 else if (f->src->channels == 1) {
920 /* set the alpha, duplicate grey */
921 for (i = 0; i < width; ++i) {
922 data->channel[3] = 1.0;
923 data->channel[1] = data->channel[2] = data->channel[0];
929 static void combine_replace(i_color *, i_color *, int, int);
930 static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
931 static void combine_alphablend(i_color *, i_color *, int, int);
932 static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
933 static void combine_mult(i_color *, i_color *, int, int);
934 static void combine_multf(i_fcolor *, i_fcolor *, int, int);
935 static void combine_dissolve(i_color *, i_color *, int, int);
936 static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
937 static void combine_add(i_color *, i_color *, int, int);
938 static void combine_addf(i_fcolor *, i_fcolor *, int, int);
939 static void combine_subtract(i_color *, i_color *, int, int);
940 static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
941 static void combine_diff(i_color *, i_color *, int, int);
942 static void combine_difff(i_fcolor *, i_fcolor *, int, int);
943 static void combine_darken(i_color *, i_color *, int, int);
944 static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
945 static void combine_lighten(i_color *, i_color *, int, int);
946 static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
947 static void combine_hue(i_color *, i_color *, int, int);
948 static void combine_huef(i_fcolor *, i_fcolor *, int, int);
949 static void combine_sat(i_color *, i_color *, int, int);
950 static void combine_satf(i_fcolor *, i_fcolor *, int, int);
951 static void combine_value(i_color *, i_color *, int, int);
952 static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
953 static void combine_color(i_color *, i_color *, int, int);
954 static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
956 static struct i_combines {
957 i_fill_combine_f combine;
958 i_fill_combinef_f combinef;
1021 =item i_get_combine(combine, color_func, fcolor_func)
1026 void i_get_combine(int combine, i_fill_combine_f *color_func,
1027 i_fill_combinef_f *fcolor_func) {
1028 if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
1031 *color_func = combines[combine].combine;
1032 *fcolor_func = combines[combine].combinef;
1035 static void combine_replace(i_color *out, i_color *in, int channels, int count) {
1041 static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1047 static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
1049 COMBINE(*out, *in, channels);
1055 static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1057 COMBINEF(*out, *in, channels);
1063 static void combine_mult(i_color *out, i_color *in, int channels, int count) {
1067 double mult[MAXCHANNELS];
1068 mult[3] = in->channel[3];
1069 for (ch = 0; ch < (channels); ++ch) {
1071 mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
1073 COMBINEA(*out, mult, channels);
1079 static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1084 for (ch = 0; ch < channels; ++ch) {
1086 c.channel[ch] = out->channel[ch] * in->channel[ch];
1088 COMBINEF(*out, c, channels);
1094 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
1096 if (in->channel[3] > rand() * (255.0 / RAND_MAX))
1097 COMBINE(*out, *in, channels);
1103 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1105 if (in->channel[3] > rand() * (1.0 / RAND_MAX))
1106 COMBINEF(*out, *in, channels);
1112 static void combine_add(i_color *out, i_color *in, int channels, int count) {
1117 for (ch = 0; ch < (channels); ++ch) {
1119 int total = out->channel[ch] + in->channel[ch];
1122 c.channel[ch] = total;
1125 COMBINE(*out, c, channels);
1131 static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1136 for (ch = 0; ch < (channels); ++ch) {
1138 double total = out->channel[ch] + in->channel[ch];
1141 out->channel[ch] = total;
1144 COMBINEF(*out, c, channels);
1150 static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
1155 for (ch = 0; ch < (channels); ++ch) {
1157 int total = out->channel[ch] - in->channel[ch];
1160 c.channel[ch] = total;
1163 COMBINE(*out, c, channels);
1169 static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1174 for (ch = 0; ch < channels; ++ch) {
1176 double total = out->channel[ch] - in->channel[ch];
1179 c.channel[ch] = total;
1182 COMBINEF(*out, c, channels);
1188 static void combine_diff(i_color *out, i_color *in, int channels, int count) {
1193 for (ch = 0; ch < (channels); ++ch) {
1195 c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
1197 COMBINE(*out, c, channels)
1203 static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
1208 for (ch = 0; ch < (channels); ++ch) {
1210 c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
1212 COMBINEF(*out, c, channels);
1218 static void combine_darken(i_color *out, i_color *in, int channels, int count) {
1222 for (ch = 0; ch < channels; ++ch) {
1223 if (ch != 3 && out->channel[ch] < in->channel[ch])
1224 in->channel[ch] = out->channel[ch];
1226 COMBINE(*out, *in, channels);
1232 static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1236 for (ch = 0; ch < channels; ++ch) {
1237 if (ch != 3 && out->channel[ch] < in->channel[ch])
1238 in->channel[ch] = out->channel[ch];
1240 COMBINEF(*out, *in, channels);
1246 static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
1250 for (ch = 0; ch < channels; ++ch) {
1251 if (ch != 3 && out->channel[ch] > in->channel[ch])
1252 in->channel[ch] = out->channel[ch];
1254 COMBINE(*out, *in, channels);
1260 static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1264 for (ch = 0; ch < channels; ++ch) {
1265 if (ch != 3 && out->channel[ch] > in->channel[ch])
1266 in->channel[ch] = out->channel[ch];
1268 COMBINEF(*out, *in, channels);
1274 static void combine_hue(i_color *out, i_color *in, int channels, int count) {
1279 c.channel[0] = in->channel[0];
1281 c.channel[3] = in->channel[3];
1282 COMBINE(*out, c, channels);
1288 static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1293 c.channel[0] = in->channel[0];
1295 c.channel[3] = in->channel[3];
1296 COMBINEF(*out, c, channels);
1302 static void combine_sat(i_color *out, i_color *in, int channels, int count) {
1307 c.channel[1] = in->channel[1];
1309 c.channel[3] = in->channel[3];
1310 COMBINE(*out, c, channels);
1316 static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1321 c.channel[1] = in->channel[1];
1323 c.channel[3] = in->channel[3];
1324 COMBINEF(*out, c, channels);
1330 static void combine_value(i_color *out, i_color *in, int channels, int count) {
1335 c.channel[2] = in->channel[2];
1337 c.channel[3] = in->channel[3];
1338 COMBINE(*out, c, channels);
1344 static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
1350 c.channel[2] = in->channel[2];
1352 c.channel[3] = in->channel[3];
1353 COMBINEF(*out, c, channels);
1359 static void combine_color(i_color *out, i_color *in, int channels, int count) {
1364 c.channel[0] = in->channel[0];
1365 c.channel[1] = in->channel[1];
1367 c.channel[3] = in->channel[3];
1368 COMBINE(*out, c, channels);
1374 static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
1380 c.channel[0] = in->channel[0];
1381 c.channel[1] = in->channel[1];
1383 c.channel[3] = in->channel[3];
1384 COMBINEF(*out, c, channels);
1396 Tony Cook <tony@develop-help.com>