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,
166 i_color *, i_color *);
167 static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
168 i_fcolor *, i_fcolor *);
169 static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
170 i_color *, i_color *);
171 static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
172 int channels, i_fcolor *, 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)
198 Call to destroy any fill object.
204 i_fill_destroy(i_fill_t *fill) {
206 (fill->destroy)(fill);
211 =item i_new_fill_solidf(color, combine)
213 Create a solid fill based on a float color.
215 If combine is non-zero then alpha values will be combined.
221 i_new_fill_solidf(i_fcolor *c, int combine) {
223 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
226 *fill = base_solid_fill_comb;
227 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
230 *fill = base_solid_fill;
232 for (ch = 0; ch < MAXCHANNELS; ++ch) {
233 fill->c.channel[ch] = SampleFTo8(c->channel[ch]);
240 =item i_new_fill_solid(color, combine)
242 Create a solid fill based.
244 If combine is non-zero then alpha values will be combined.
250 i_new_fill_solid(i_color *c, int combine) {
252 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
255 *fill = base_solid_fill_comb;
256 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
259 *fill = base_solid_fill;
261 for (ch = 0; ch < MAXCHANNELS; ++ch) {
262 fill->fc.channel[ch] = Sample8ToF(c->channel[ch]);
269 builtin_hatches[][8] =
272 /* 1x1 checkerboard */
273 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
276 /* 2x2 checkerboard */
277 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33,
280 /* 4 x 4 checkerboard */
281 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
284 /* single vertical lines */
285 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
288 /* double vertical lines */
289 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
292 /* quad vertical lines */
293 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
297 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
305 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
309 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
313 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
317 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88,
321 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11,
325 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
329 0xFF, 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88,
333 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA,
337 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
345 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
349 0x48, 0x84, 0x00, 0x00, 0x84, 0x48, 0x00, 0x00,
353 0x55, 0xFD, 0x05, 0xFD, 0x55, 0xDF, 0x50, 0xDF,
356 /* single cross hatch */
357 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x01,
360 /* double cross hatch */
361 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11,
364 /* vertical lozenge */
365 0x11, 0x11, 0x11, 0xAA, 0x44, 0x44, 0x44, 0xAA,
368 /* horizontal lozenge */
369 0x88, 0x70, 0x88, 0x07, 0x88, 0x70, 0x88, 0x07,
372 /* scales overlapping downwards */
373 0x80, 0x80, 0x41, 0x3E, 0x08, 0x08, 0x14, 0xE3,
376 /* scales overlapping upwards */
377 0xC7, 0x28, 0x10, 0x10, 0x7C, 0x82, 0x01, 0x01,
380 /* scales overlapping leftwards */
381 0x83, 0x84, 0x88, 0x48, 0x38, 0x48, 0x88, 0x84,
384 /* scales overlapping rightwards */
385 0x21, 0x11, 0x12, 0x1C, 0x12, 0x11, 0x21, 0xC1,
389 0x44, 0x88, 0x22, 0x11, 0x44, 0x88, 0x22, 0x11,
393 0xFF, 0x84, 0x84, 0x9C, 0x94, 0x9C, 0x90, 0x90,
397 0x80, 0x40, 0x20, 0x00, 0x02, 0x04, 0x08, 0x00,
406 unsigned char hatch[8];
410 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
411 i_color *data, i_color *work);
412 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
413 i_fcolor *data, i_fcolor *work);
416 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
417 int combine, int hatch, unsigned char *cust_hatch,
421 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
423 Creates a new hatched fill with the fg color used for the 1 bits in
424 the hatch and bg for the 0 bits. If combine is non-zero alpha values
427 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
428 hash definition, with the high-bits to the left.
430 If cust_hatch is NULL then one of the standard hatches is used.
432 (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.
437 i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
438 unsigned char *cust_hatch, int dx, int dy) {
439 return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch,
444 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
446 Creates a new hatched fill with the fg color used for the 1 bits in
447 the hatch and bg for the 0 bits. If combine is non-zero alpha values
450 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
451 hash definition, with the high-bits to the left.
453 If cust_hatch is NULL then one of the standard hatches is used.
455 (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.
460 i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
461 unsigned char *cust_hatch, int dx, int dy) {
462 return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch,
466 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
467 i_color *data, i_color *work);
468 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
469 i_fcolor *data, i_fcolor *work);
470 struct i_fill_image_t {
479 =item i_new_fill_image(im, matrix, xoff, yoff, combine)
481 Create an image based fill.
486 i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine) {
487 struct i_fill_image_t *fill = mymalloc(sizeof(*fill));
489 fill->base.fill_with_color = fill_image;
490 fill->base.fill_with_fcolor = fill_imagef;
491 fill->base.destroy = NULL;
494 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
497 fill->base.combine = NULL;
498 fill->base.combinef = NULL;
508 fill->has_matrix = 1;
509 memcpy(fill->matrix, matrix, sizeof(fill->matrix));
512 fill->has_matrix = 0;
518 #define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
523 =head1 INTERNAL FUNCTIONS
527 =item fill_solid(fill, x, y, width, channels, data)
529 The 8-bit sample fill function for non-combining solid fills.
534 fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
535 i_color *data, i_color *work) {
536 while (width-- > 0) {
537 *data++ = T_SOLID_FILL(fill)->c;
542 =item fill_solid(fill, x, y, width, channels, data)
544 The floating sample fill function for non-combining solid fills.
549 fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
550 i_fcolor *data, i_fcolor *work) {
551 while (width-- > 0) {
552 *data++ = T_SOLID_FILL(fill)->fc;
557 =item fill_solid_comb(fill, x, y, width, channels, data)
559 The 8-bit sample fill function for combining solid fills.
564 fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
565 i_color *data, i_color *work) {
566 i_color c = T_SOLID_FILL(fill)->c;
568 i_color *wstart = work;
570 while (width-- > 0) {
573 (fill->combine)(data, wstart, channels, count);
577 =item fill_solidf_comb(fill, x, y, width, channels, data)
579 The floating sample fill function for combining solid fills.
584 fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
585 i_fcolor *data, i_fcolor *work) {
586 i_fcolor c = T_SOLID_FILL(fill)->fc;
588 i_fcolor *wstart = work;
590 while (width-- > 0) {
593 (fill->combinef)(data, wstart, channels, count);
597 =item i_new_hatch_low(fg, bg, ffg, fbg, combine, hatch, cust_hatch, dx, dy)
599 Implements creation of hatch fill objects.
605 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
606 int combine, int hatch, unsigned char *cust_hatch,
608 i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t));
610 fill->base.fill_with_color = fill_hatch;
611 fill->base.fill_with_fcolor = fill_hatchf;
612 fill->base.destroy = NULL;
613 fill->fg = fg ? *fg : fcolor_to_color(ffg);
614 fill->bg = bg ? *bg : fcolor_to_color(fbg);
615 fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
616 fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
618 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
621 fill->base.combine = NULL;
622 fill->base.combinef = NULL;
625 memcpy(fill->hatch, cust_hatch, 8);
628 if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
630 memcpy(fill->hatch, builtin_hatches[hatch], 8);
639 =item fill_hatch(fill, x, y, width, channels, data)
641 The 8-bit sample fill function for hatched fills.
645 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
646 i_color *data, i_color *work) {
647 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
648 int byte = f->hatch[(y + f->dy) & 7];
649 int xpos = (x + f->dx) & 7;
650 int mask = 128 >> xpos;
654 i_color *wstart = work;
656 while (count-- > 0) {
657 *work++ = (byte & mask) ? f->fg : f->bg;
659 if ((mask >>= 1) == 0)
662 (fill->combine)(data, wstart, channels, width);
665 while (width-- > 0) {
666 *data++ = (byte & mask) ? f->fg : f->bg;
668 if ((mask >>= 1) == 0)
675 =item fill_hatchf(fill, x, y, width, channels, data)
677 The floating sample fill function for hatched fills.
681 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
682 i_fcolor *data, i_fcolor *work) {
683 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
684 int byte = f->hatch[(y + f->dy) & 7];
685 int xpos = (x + f->dx) & 7;
686 int mask = 128 >> xpos;
688 if (fill->combinef) {
690 i_fcolor *wstart = work;
692 while (count-- > 0) {
693 *work++ = (byte & mask) ? f->ffg : f->fbg;
695 if ((mask >>= 1) == 0)
698 (fill->combinef)(data, wstart, channels, width);
701 while (width-- > 0) {
702 *data++ = (byte & mask) ? f->ffg : f->fbg;
704 if ((mask >>= 1) == 0)
710 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
711 /* linear interpolation */
712 static i_color interp_i_color(i_color before, i_color after, double pos,
718 for (ch = 0; ch < channels; ++ch)
719 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
721 for (ch = 0; ch < channels; ++ch)
723 int temp = out.channel[ch] * 255 / out.channel[3];
726 out.channel[ch] = temp;
732 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
733 /* linear interpolation */
734 static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos,
740 for (ch = 0; ch < channels; ++ch)
741 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
743 for (ch = 0; ch < channels; ++ch)
745 int temp = out.channel[ch] / out.channel[3];
748 out.channel[ch] = temp;
755 =item fill_image(fill, x, y, width, channels, data, work)
759 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
760 i_color *data, i_color *work) {
761 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
762 i_color *out = fill->combine ? work : data;
769 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
770 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
771 double ix = floor(rx / f->src->xsize);
772 double iy = floor(ry / f->src->ysize);
779 ix = floor(rx / f->src->xsize);
783 iy = floor(ry / f->src->ysize);
785 rx -= ix * f->src->xsize;
786 ry -= iy * f->src->ysize;
788 for (dy = 0; dy < 2; ++dy) {
789 if ((int)rx == f->src->xsize-1) {
790 i_gpix(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
791 i_gpix(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
794 i_glin(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
797 c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
799 *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
805 /* this should be possible to optimize to use i_glin() */
809 int ix = rx / f->src->xsize;
810 int iy = ry / f->src->ysize;
814 ix = rx / f->src->xsize;
818 iy = ry / f->src->xsize;
820 rx -= ix * f->src->xsize;
821 ry -= iy * f->src->ysize;
822 i_gpix(f->src, rx, ry, out);
829 (fill->combine)(data, work, channels, width);
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,
839 i_fcolor *data, i_fcolor *work) {
840 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
841 i_fcolor *out = fill->combine ? work : data;
848 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
849 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
850 double ix = floor(rx / f->src->xsize);
851 double iy = floor(ry / f->src->ysize);
858 ix = floor(rx / f->src->xsize);
862 iy = floor(ry / f->src->ysize);
864 rx -= ix * f->src->xsize;
865 ry -= iy * f->src->ysize;
867 for (dy = 0; dy < 2; ++dy) {
868 if ((int)rx == f->src->xsize-1) {
869 i_gpixf(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
870 i_gpixf(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
873 i_glinf(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
876 c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
878 *out++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
884 /* this should be possible to optimize to use i_glin() */
888 int ix = rx / f->src->xsize;
889 int iy = ry / f->src->ysize;
893 ix = rx / f->src->xsize;
897 iy = ry / f->src->xsize;
899 rx -= ix * f->src->xsize;
900 ry -= iy * f->src->ysize;
901 i_gpixf(f->src, rx, ry, out);
907 if (fill->combinef) {
908 (fill->combinef)(data, work, channels, width);
912 static void combine_replace(i_color *, i_color *, int, int);
913 static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
914 static void combine_alphablend(i_color *, i_color *, int, int);
915 static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
916 static void combine_mult(i_color *, i_color *, int, int);
917 static void combine_multf(i_fcolor *, i_fcolor *, int, int);
918 static void combine_dissolve(i_color *, i_color *, int, int);
919 static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
920 static void combine_add(i_color *, i_color *, int, int);
921 static void combine_addf(i_fcolor *, i_fcolor *, int, int);
922 static void combine_subtract(i_color *, i_color *, int, int);
923 static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
924 static void combine_diff(i_color *, i_color *, int, int);
925 static void combine_difff(i_fcolor *, i_fcolor *, int, int);
926 static void combine_darken(i_color *, i_color *, int, int);
927 static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
928 static void combine_lighten(i_color *, i_color *, int, int);
929 static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
930 static void combine_hue(i_color *, i_color *, int, int);
931 static void combine_huef(i_fcolor *, i_fcolor *, int, int);
932 static void combine_sat(i_color *, i_color *, int, int);
933 static void combine_satf(i_fcolor *, i_fcolor *, int, int);
934 static void combine_value(i_color *, i_color *, int, int);
935 static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
936 static void combine_color(i_color *, i_color *, int, int);
937 static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
940 i_fill_combine_f combine;
941 i_fill_combinef_f combinef;
1004 =item i_get_combine(combine, color_func, fcolor_func)
1009 void i_get_combine(int combine, i_fill_combine_f *color_func,
1010 i_fill_combinef_f *fcolor_func) {
1011 if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
1014 *color_func = combines[combine].combine;
1015 *fcolor_func = combines[combine].combinef;
1018 static void combine_replace(i_color *out, i_color *in, int channels, int count) {
1024 static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1030 static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
1032 COMBINE(*out, *in, channels);
1038 static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1040 COMBINEF(*out, *in, channels);
1046 static void combine_mult(i_color *out, i_color *in, int channels, int count) {
1051 double mult[MAXCHANNELS];
1052 mult[3] = in->channel[3];
1053 for (ch = 0; ch < (channels); ++ch) {
1055 mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
1057 COMBINEA(*out, mult, channels);
1063 static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1068 for (ch = 0; ch < channels; ++ch) {
1070 c.channel[ch] = out->channel[ch] * in->channel[ch];
1072 COMBINEF(*out, c, channels);
1078 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
1082 if (in->channel[3] > rand() * (255.0 / RAND_MAX))
1083 COMBINE(*out, *in, channels);
1089 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1093 if (in->channel[3] > rand() * (1.0 / RAND_MAX))
1094 COMBINEF(*out, *in, channels);
1100 static void combine_add(i_color *out, i_color *in, int channels, int count) {
1105 for (ch = 0; ch < (channels); ++ch) {
1107 int total = out->channel[ch] + in->channel[ch];
1110 c.channel[ch] = total;
1113 COMBINE(*out, c, channels);
1119 static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1124 for (ch = 0; ch < (channels); ++ch) {
1126 double total = out->channel[ch] + in->channel[ch];
1129 out->channel[ch] = total;
1132 COMBINEF(*out, c, channels);
1138 static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
1143 for (ch = 0; ch < (channels); ++ch) {
1145 int total = out->channel[ch] - in->channel[ch];
1148 c.channel[ch] = total;
1151 COMBINE(*out, c, channels);
1157 static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1162 for (ch = 0; ch < channels; ++ch) {
1164 double total = out->channel[ch] - in->channel[ch];
1167 c.channel[ch] = total;
1170 COMBINEF(*out, c, channels);
1176 static void combine_diff(i_color *out, i_color *in, int channels, int count) {
1181 for (ch = 0; ch < (channels); ++ch) {
1183 c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
1185 COMBINE(*out, c, channels)
1191 static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
1196 for (ch = 0; ch < (channels); ++ch) {
1198 c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
1200 COMBINEF(*out, c, channels);
1206 static void combine_darken(i_color *out, i_color *in, int channels, int count) {
1210 for (ch = 0; ch < channels; ++ch) {
1211 if (ch != 3 && out->channel[ch] < in->channel[ch])
1212 in->channel[ch] = out->channel[ch];
1214 COMBINE(*out, *in, channels);
1220 static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1224 for (ch = 0; ch < channels; ++ch) {
1225 if (ch != 3 && out->channel[ch] < in->channel[ch])
1226 in->channel[ch] = out->channel[ch];
1228 COMBINEF(*out, *in, channels);
1234 static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
1238 for (ch = 0; ch < channels; ++ch) {
1239 if (ch != 3 && out->channel[ch] > in->channel[ch])
1240 in->channel[ch] = out->channel[ch];
1242 COMBINE(*out, *in, channels);
1248 static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1252 for (ch = 0; ch < channels; ++ch) {
1253 if (ch != 3 && out->channel[ch] > in->channel[ch])
1254 in->channel[ch] = out->channel[ch];
1256 COMBINEF(*out, *in, channels);
1262 static void combine_hue(i_color *out, i_color *in, int channels, int count) {
1267 c.channel[0] = in->channel[0];
1269 c.channel[3] = in->channel[3];
1270 COMBINE(*out, c, channels);
1276 static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1281 c.channel[0] = in->channel[0];
1283 c.channel[3] = in->channel[3];
1284 COMBINEF(*out, c, channels);
1290 static void combine_sat(i_color *out, i_color *in, int channels, int count) {
1295 c.channel[1] = in->channel[1];
1297 c.channel[3] = in->channel[3];
1298 COMBINE(*out, c, channels);
1304 static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1309 c.channel[1] = in->channel[1];
1311 c.channel[3] = in->channel[3];
1312 COMBINEF(*out, c, channels);
1318 static void combine_value(i_color *out, i_color *in, int channels, int count) {
1323 c.channel[2] = in->channel[2];
1325 c.channel[3] = in->channel[3];
1326 COMBINE(*out, c, channels);
1332 static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
1338 c.channel[2] = in->channel[2];
1340 c.channel[3] = in->channel[3];
1341 COMBINEF(*out, c, channels);
1347 static void combine_color(i_color *out, i_color *in, int channels, int count) {
1352 c.channel[0] = in->channel[0];
1353 c.channel[1] = in->channel[1];
1355 c.channel[3] = in->channel[3];
1356 COMBINE(*out, c, channels);
1362 static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
1368 c.channel[0] = in->channel[0];
1369 c.channel[1] = in->channel[1];
1371 c.channel[3] = in->channel[3];
1372 COMBINEF(*out, c, channels);
1384 Tony Cook <tony@develop-help.com>