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(const 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(const 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(const 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(const 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(const i_color *fg, const i_color *bg, const i_fcolor *ffg, const i_fcolor *fbg,
423 int combine, int hatch, const 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(const i_color *fg, const i_color *bg, int combine, int hatch,
446 const 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(const i_fcolor *fg, const i_fcolor *bg, int combine, int hatch,
471 const 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, const 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(const i_color *fg, const i_color *bg,
616 const i_fcolor *ffg, const i_fcolor *fbg,
617 int combine, int hatch, const unsigned char *cust_hatch,
619 i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */
621 fill->base.fill_with_color = fill_hatch;
622 fill->base.fill_with_fcolor = fill_hatchf;
623 fill->base.destroy = NULL;
624 fill->fg = fg ? *fg : fcolor_to_color(ffg);
625 fill->bg = bg ? *bg : fcolor_to_color(fbg);
626 fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
627 fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
629 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
632 fill->base.combine = NULL;
633 fill->base.combinef = NULL;
636 memcpy(fill->hatch, cust_hatch, 8);
639 if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
641 memcpy(fill->hatch, builtin_hatches[hatch], 8);
650 =item fill_hatch(fill, x, y, width, channels, data)
652 The 8-bit sample fill function for hatched fills.
656 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
658 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
659 int byte = f->hatch[(y + f->dy) & 7];
660 int xpos = (x + f->dx) & 7;
661 int mask = 128 >> xpos;
663 while (width-- > 0) {
664 *data++ = (byte & mask) ? f->fg : f->bg;
666 if ((mask >>= 1) == 0)
672 =item fill_hatchf(fill, x, y, width, channels, data)
674 The floating sample fill function for hatched fills.
678 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
680 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
681 int byte = f->hatch[(y + f->dy) & 7];
682 int xpos = (x + f->dx) & 7;
683 int mask = 128 >> xpos;
685 while (width-- > 0) {
686 *data++ = (byte & mask) ? f->ffg : f->fbg;
688 if ((mask >>= 1) == 0)
693 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
694 /* linear interpolation */
695 static i_color interp_i_color(i_color before, i_color after, double pos,
701 for (ch = 0; ch < channels; ++ch)
702 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
704 for (ch = 0; ch < channels; ++ch)
706 int temp = out.channel[ch] * 255 / out.channel[3];
709 out.channel[ch] = temp;
715 /* hopefully this will be inlined (it is with -O3 with gcc 2.95.4) */
716 /* linear interpolation */
717 static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos,
723 for (ch = 0; ch < channels; ++ch)
724 out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
726 for (ch = 0; ch < channels; ++ch)
728 int temp = out.channel[ch] / out.channel[3];
731 out.channel[ch] = temp;
738 =item fill_image(fill, x, y, width, channels, data, work)
742 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
744 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
751 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
752 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
753 double ix = floor(rx / f->src->xsize);
754 double iy = floor(ry / f->src->ysize);
761 ix = floor(rx / f->src->xsize);
765 iy = floor(ry / f->src->ysize);
767 rx -= ix * f->src->xsize;
768 ry -= iy * f->src->ysize;
770 for (dy = 0; dy < 2; ++dy) {
771 if ((int)rx == f->src->xsize-1) {
772 i_gpix(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
773 i_gpix(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
776 i_glin(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
779 c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
781 *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
787 /* this should be possible to optimize to use i_glin() */
791 int ix = rx / f->src->xsize;
792 int iy = ry / f->src->ysize;
796 ix = rx / f->src->xsize;
800 iy = ry / f->src->xsize;
802 rx -= ix * f->src->xsize;
803 ry -= iy * f->src->ysize;
804 i_gpix(f->src, rx, ry, out);
809 if (f->src->channels == 3) {
810 /* just set the alpha */
811 for (i = 0; i < width; ++i) {
812 data->channel[3] = 255;
816 else if (f->src->channels == 2) {
817 /* copy the alpha to channel 3, duplicate the grey value */
818 for (i = 0; i < width; ++i) {
819 data->channel[3] = data->channel[1];
820 data->channel[1] = data->channel[2] = data->channel[0];
824 else if (f->src->channels == 1) {
825 /* set the alpha, duplicate grey */
826 for (i = 0; i < width; ++i) {
827 data->channel[3] = 255;
828 data->channel[1] = data->channel[2] = data->channel[0];
835 =item fill_image(fill, x, y, width, channels, data, work)
839 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
841 struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
847 double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
848 double ry = f->matrix[3] * (x+i) + f->matrix[4] * y + f->matrix[5];
849 double ix = floor(rx / f->src->xsize);
850 double iy = floor(ry / f->src->ysize);
857 ix = floor(rx / f->src->xsize);
861 iy = floor(ry / f->src->ysize);
863 rx -= ix * f->src->xsize;
864 ry -= iy * f->src->ysize;
866 for (dy = 0; dy < 2; ++dy) {
867 if ((int)rx == f->src->xsize-1) {
868 i_gpixf(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
869 i_gpixf(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
872 i_glinf(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
875 c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
877 *data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
883 /* this should be possible to optimize to use i_glin() */
887 int ix = rx / f->src->xsize;
888 int iy = ry / f->src->ysize;
892 ix = rx / f->src->xsize;
896 iy = ry / f->src->xsize;
898 rx -= ix * f->src->xsize;
899 ry -= iy * f->src->ysize;
900 i_gpixf(f->src, rx, ry, data);
905 if (f->src->channels == 3) {
906 /* just set the alpha */
907 for (i = 0; i < width; ++i) {
908 data->channel[3] = 1.0;
912 else if (f->src->channels == 2) {
913 /* copy the alpha to channel 3, duplicate the grey value */
914 for (i = 0; i < width; ++i) {
915 data->channel[3] = data->channel[1];
916 data->channel[1] = data->channel[2] = data->channel[0];
920 else if (f->src->channels == 1) {
921 /* set the alpha, duplicate grey */
922 for (i = 0; i < width; ++i) {
923 data->channel[3] = 1.0;
924 data->channel[1] = data->channel[2] = data->channel[0];
930 static void combine_replace(i_color *, i_color *, int, int);
931 static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
932 static void combine_alphablend(i_color *, i_color *, int, int);
933 static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
934 static void combine_mult(i_color *, i_color *, int, int);
935 static void combine_multf(i_fcolor *, i_fcolor *, int, int);
936 static void combine_dissolve(i_color *, i_color *, int, int);
937 static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
938 static void combine_add(i_color *, i_color *, int, int);
939 static void combine_addf(i_fcolor *, i_fcolor *, int, int);
940 static void combine_subtract(i_color *, i_color *, int, int);
941 static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
942 static void combine_diff(i_color *, i_color *, int, int);
943 static void combine_difff(i_fcolor *, i_fcolor *, int, int);
944 static void combine_darken(i_color *, i_color *, int, int);
945 static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
946 static void combine_lighten(i_color *, i_color *, int, int);
947 static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
948 static void combine_hue(i_color *, i_color *, int, int);
949 static void combine_huef(i_fcolor *, i_fcolor *, int, int);
950 static void combine_sat(i_color *, i_color *, int, int);
951 static void combine_satf(i_fcolor *, i_fcolor *, int, int);
952 static void combine_value(i_color *, i_color *, int, int);
953 static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
954 static void combine_color(i_color *, i_color *, int, int);
955 static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
957 static struct i_combines {
958 i_fill_combine_f combine;
959 i_fill_combinef_f combinef;
1022 =item i_get_combine(combine, color_func, fcolor_func)
1027 void i_get_combine(int combine, i_fill_combine_f *color_func,
1028 i_fill_combinef_f *fcolor_func) {
1029 if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
1032 *color_func = combines[combine].combine;
1033 *fcolor_func = combines[combine].combinef;
1036 static void combine_replace(i_color *out, i_color *in, int channels, int count) {
1042 static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1048 static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
1050 COMBINE(*out, *in, channels);
1056 static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1058 COMBINEF(*out, *in, channels);
1064 static void combine_mult(i_color *out, i_color *in, int channels, int count) {
1068 double mult[MAXCHANNELS];
1069 mult[3] = in->channel[3];
1070 for (ch = 0; ch < (channels); ++ch) {
1072 mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
1074 COMBINEA(*out, mult, channels);
1080 static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1085 for (ch = 0; ch < channels; ++ch) {
1087 c.channel[ch] = out->channel[ch] * in->channel[ch];
1089 COMBINEF(*out, c, channels);
1095 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
1097 if (in->channel[3] > rand() * (255.0 / RAND_MAX))
1098 COMBINE(*out, *in, channels);
1104 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1106 if (in->channel[3] > rand() * (1.0 / RAND_MAX))
1107 COMBINEF(*out, *in, channels);
1113 static void combine_add(i_color *out, i_color *in, int channels, int count) {
1118 for (ch = 0; ch < (channels); ++ch) {
1120 int total = out->channel[ch] + in->channel[ch];
1123 c.channel[ch] = total;
1126 COMBINE(*out, c, channels);
1132 static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1137 for (ch = 0; ch < (channels); ++ch) {
1139 double total = out->channel[ch] + in->channel[ch];
1142 out->channel[ch] = total;
1145 COMBINEF(*out, c, channels);
1151 static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
1156 for (ch = 0; ch < (channels); ++ch) {
1158 int total = out->channel[ch] - in->channel[ch];
1161 c.channel[ch] = total;
1164 COMBINE(*out, c, channels);
1170 static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1175 for (ch = 0; ch < channels; ++ch) {
1177 double total = out->channel[ch] - in->channel[ch];
1180 c.channel[ch] = total;
1183 COMBINEF(*out, c, channels);
1189 static void combine_diff(i_color *out, i_color *in, int channels, int count) {
1194 for (ch = 0; ch < (channels); ++ch) {
1196 c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
1198 COMBINE(*out, c, channels)
1204 static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
1209 for (ch = 0; ch < (channels); ++ch) {
1211 c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
1213 COMBINEF(*out, c, channels);
1219 static void combine_darken(i_color *out, i_color *in, int channels, int count) {
1223 for (ch = 0; ch < channels; ++ch) {
1224 if (ch != 3 && out->channel[ch] < in->channel[ch])
1225 in->channel[ch] = out->channel[ch];
1227 COMBINE(*out, *in, channels);
1233 static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1237 for (ch = 0; ch < channels; ++ch) {
1238 if (ch != 3 && out->channel[ch] < in->channel[ch])
1239 in->channel[ch] = out->channel[ch];
1241 COMBINEF(*out, *in, channels);
1247 static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
1251 for (ch = 0; ch < channels; ++ch) {
1252 if (ch != 3 && out->channel[ch] > in->channel[ch])
1253 in->channel[ch] = out->channel[ch];
1255 COMBINE(*out, *in, channels);
1261 static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1265 for (ch = 0; ch < channels; ++ch) {
1266 if (ch != 3 && out->channel[ch] > in->channel[ch])
1267 in->channel[ch] = out->channel[ch];
1269 COMBINEF(*out, *in, channels);
1275 static void combine_hue(i_color *out, i_color *in, int channels, int count) {
1280 c.channel[0] = in->channel[0];
1282 c.channel[3] = in->channel[3];
1283 COMBINE(*out, c, channels);
1289 static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1294 c.channel[0] = in->channel[0];
1296 c.channel[3] = in->channel[3];
1297 COMBINEF(*out, c, channels);
1303 static void combine_sat(i_color *out, i_color *in, int channels, int count) {
1308 c.channel[1] = in->channel[1];
1310 c.channel[3] = in->channel[3];
1311 COMBINE(*out, c, channels);
1317 static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1322 c.channel[1] = in->channel[1];
1324 c.channel[3] = in->channel[3];
1325 COMBINEF(*out, c, channels);
1331 static void combine_value(i_color *out, i_color *in, int channels, int count) {
1336 c.channel[2] = in->channel[2];
1338 c.channel[3] = in->channel[3];
1339 COMBINE(*out, c, channels);
1345 static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
1351 c.channel[2] = in->channel[2];
1353 c.channel[3] = in->channel[3];
1354 COMBINEF(*out, c, channels);
1360 static void combine_color(i_color *out, i_color *in, int channels, int count) {
1365 c.channel[0] = in->channel[0];
1366 c.channel[1] = in->channel[1];
1368 c.channel[3] = in->channel[3];
1369 COMBINE(*out, c, channels);
1375 static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
1381 c.channel[0] = in->channel[0];
1382 c.channel[1] = in->channel[1];
1384 c.channel[3] = in->channel[3];
1385 COMBINEF(*out, c, channels);
1397 Tony Cook <tony@develop-help.com>