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);
23 Implements the basic general fills, which can be used for filling some
24 shapes and for flood fills.
26 Each fill can implement up to 3 functions:
32 called for fills on 8-bit images. This can be NULL in which case the
33 fill_with_colorf function is called.
35 =item fill_with_fcolor
37 called for fills on non-8-bit images or when fill_with_color is NULL.
41 called by i_fill_destroy() if non-NULL, to release any extra resources
42 that the fill may need.
46 fill_with_color and fill_with_fcolor are basically the same function
47 except that the first works with lines of i_color and the second with
50 If the combines member if non-zero the line data is populated from the
51 target image before calling fill_with_*color.
53 fill_with_color needs to fill the I<data> parameter with the fill
54 pixels. If combines is non-zero it the fill pixels should be combined
55 with the existing data.
57 The current fills are:
75 Fountain fill is implemented by L<filters.c>.
77 Other fills that could be implemented include:
83 image - an image tiled over the fill area, with an offset either
84 horizontally or vertically.
88 checkerboard - combine 2 fills in a checkerboard
92 combine - combine the levels of 2 other fills based in the levels of
97 regmach - use the register machine to generate colors
106 static i_color fcolor_to_color(i_fcolor *c) {
110 for (ch = 0; ch < MAXCHANNELS; ++ch)
111 out.channel[ch] = SampleFTo8(c->channel[ch]);
116 static i_fcolor color_to_fcolor(i_color *c) {
120 for (ch = 0; ch < MAXCHANNELS; ++ch)
121 out.channel[ch] = Sample8ToF(c->channel[ch]);
126 /* alpha combine in with out */
127 #define COMBINE(out, in, channels) \
130 for (ch = 0; ch < (channels); ++ch) { \
131 (out).channel[ch] = ((out).channel[ch] * (255 - (in).channel[3]) \
132 + (in).channel[ch] * (in).channel[3]) / 255; \
136 /* alpha combine in with out, in this case in is a simple array of
137 samples, potentially not integers - the mult combiner uses doubles
139 #define COMBINEA(out, in, channels) \
142 for (ch = 0; ch < (channels); ++ch) { \
143 (out).channel[ch] = ((out).channel[ch] * (255 - (in)[3]) \
144 + (in)[ch] * (in)[3]) / 255; \
148 #define COMBINEF(out, in, channels) \
151 for (ch = 0; ch < (channels); ++ch) { \
152 (out).channel[ch] = (out).channel[ch] * (1.0 - (in).channel[3]) \
153 + (in).channel[ch] * (in).channel[3]; \
164 static void fill_solid(i_fill_t *, int x, int y, int width, int channels,
165 i_color *, i_color *);
166 static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
167 i_fcolor *, i_fcolor *);
168 static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
169 i_color *, i_color *);
170 static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
171 int channels, i_fcolor *, i_fcolor *);
173 static i_fill_solid_t base_solid_fill =
183 static i_fill_solid_t base_solid_fill_comb =
195 =item i_fill_destroy(fill)
197 Call to destroy any fill object.
203 i_fill_destroy(i_fill_t *fill) {
205 (fill->destroy)(fill);
210 =item i_new_fill_solidf(color, combine)
212 Create a solid fill based on a float color.
214 If combine is non-zero then alpha values will be combined.
220 i_new_fill_solidf(i_fcolor *c, int combine) {
222 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
225 *fill = base_solid_fill_comb;
226 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
229 *fill = base_solid_fill;
231 for (ch = 0; ch < MAXCHANNELS; ++ch) {
232 fill->c.channel[ch] = SampleFTo8(c->channel[ch]);
239 =item i_new_fill_solid(color, combine)
241 Create a solid fill based.
243 If combine is non-zero then alpha values will be combined.
249 i_new_fill_solid(i_color *c, int combine) {
251 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
254 *fill = base_solid_fill_comb;
255 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
258 *fill = base_solid_fill;
260 for (ch = 0; ch < MAXCHANNELS; ++ch) {
261 fill->fc.channel[ch] = Sample8ToF(c->channel[ch]);
268 builtin_hatches[][8] =
271 /* 1x1 checkerboard */
272 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
275 /* 2x2 checkerboard */
276 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33,
279 /* 4 x 4 checkerboard */
280 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
283 /* single vertical lines */
284 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
287 /* double vertical lines */
288 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
291 /* quad vertical lines */
292 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
296 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
304 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
308 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
312 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
316 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88,
320 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11,
324 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
328 0xFF, 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88,
332 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA,
336 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
344 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
348 0x48, 0x84, 0x00, 0x00, 0x84, 0x48, 0x00, 0x00,
352 0x55, 0xFD, 0x05, 0xFD, 0x55, 0xDF, 0x50, 0xDF,
355 /* single cross hatch */
356 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x01,
359 /* double cross hatch */
360 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11,
363 /* vertical lozenge */
364 0x11, 0x11, 0x11, 0xAA, 0x44, 0x44, 0x44, 0xAA,
367 /* horizontal lozenge */
368 0x88, 0x70, 0x88, 0x07, 0x88, 0x70, 0x88, 0x07,
371 /* scales overlapping downwards */
372 0x80, 0x80, 0x41, 0x3E, 0x08, 0x08, 0x14, 0xE3,
375 /* scales overlapping upwards */
376 0xC7, 0x28, 0x10, 0x10, 0x7C, 0x82, 0x01, 0x01,
379 /* scales overlapping leftwards */
380 0x83, 0x84, 0x88, 0x48, 0x38, 0x48, 0x88, 0x84,
383 /* scales overlapping rightwards */
384 0x21, 0x11, 0x12, 0x1C, 0x12, 0x11, 0x21, 0xC1,
388 0x44, 0x88, 0x22, 0x11, 0x44, 0x88, 0x22, 0x11,
392 0xFF, 0x84, 0x84, 0x9C, 0x94, 0x9C, 0x90, 0x90,
396 0x80, 0x40, 0x20, 0x00, 0x02, 0x04, 0x08, 0x00,
405 unsigned char hatch[8];
409 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
410 i_color *data, i_color *work);
411 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
412 i_fcolor *data, i_fcolor *work);
415 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
416 int combine, int hatch, unsigned char *cust_hatch,
420 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
422 Creates a new hatched fill with the fg color used for the 1 bits in
423 the hatch and bg for the 0 bits. If combine is non-zero alpha values
426 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
427 hash definition, with the high-bits to the left.
429 If cust_hatch is NULL then one of the standard hatches is used.
431 (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.
436 i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
437 unsigned char *cust_hatch, int dx, int dy) {
438 return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch,
443 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
445 Creates a new hatched fill with the fg color used for the 1 bits in
446 the hatch and bg for the 0 bits. If combine is non-zero alpha values
449 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
450 hash definition, with the high-bits to the left.
452 If cust_hatch is NULL then one of the standard hatches is used.
454 (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.
459 i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
460 unsigned char *cust_hatch, int dx, int dy) {
461 return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch,
465 #define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
470 =head1 INTERNAL FUNCTIONS
474 =item fill_solid(fill, x, y, width, channels, data)
476 The 8-bit sample fill function for non-combining solid fills.
481 fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
482 i_color *data, i_color *work) {
483 while (width-- > 0) {
484 *data++ = T_SOLID_FILL(fill)->c;
489 =item fill_solid(fill, x, y, width, channels, data)
491 The floating sample fill function for non-combining solid fills.
496 fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
497 i_fcolor *data, i_fcolor *work) {
498 while (width-- > 0) {
499 *data++ = T_SOLID_FILL(fill)->fc;
504 =item fill_solid_comb(fill, x, y, width, channels, data)
506 The 8-bit sample fill function for combining solid fills.
511 fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
512 i_color *data, i_color *work) {
513 i_color c = T_SOLID_FILL(fill)->c;
515 i_color *wstart = work;
517 while (width-- > 0) {
520 (fill->combine)(data, wstart, channels, count);
524 =item fill_solidf_comb(fill, x, y, width, channels, data)
526 The floating sample fill function for combining solid fills.
531 fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
532 i_fcolor *data, i_fcolor *work) {
533 i_fcolor c = T_SOLID_FILL(fill)->fc;
535 i_fcolor *wstart = work;
537 while (width-- > 0) {
540 (fill->combinef)(data, wstart, channels, count);
544 =item i_new_hatch_low(fg, bg, ffg, fbg, combine, hatch, cust_hatch, dx, dy)
546 Implements creation of hatch fill objects.
552 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
553 int combine, int hatch, unsigned char *cust_hatch,
555 i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t));
557 fill->base.fill_with_color = fill_hatch;
558 fill->base.fill_with_fcolor = fill_hatchf;
559 fill->base.destroy = NULL;
560 fill->fg = fg ? *fg : fcolor_to_color(ffg);
561 fill->bg = bg ? *bg : fcolor_to_color(fbg);
562 fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
563 fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
565 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
568 fill->base.combine = NULL;
569 fill->base.combinef = NULL;
572 memcpy(fill->hatch, cust_hatch, 8);
575 if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
577 memcpy(fill->hatch, builtin_hatches[hatch], 8);
586 =item fill_hatch(fill, x, y, width, channels, data)
588 The 8-bit sample fill function for hatched fills.
592 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
593 i_color *data, i_color *work) {
594 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
595 int byte = f->hatch[(y + f->dy) & 7];
596 int xpos = (x + f->dx) & 7;
597 int mask = 128 >> xpos;
601 i_color *wstart = work;
603 while (count-- > 0) {
604 *work++ = (byte & mask) ? f->fg : f->bg;
606 if ((mask >>= 1) == 0)
609 (fill->combine)(data, wstart, channels, width);
612 while (width-- > 0) {
613 *data++ = (byte & mask) ? f->fg : f->bg;
615 if ((mask >>= 1) == 0)
622 =item fill_hatchf(fill, x, y, width, channels, data)
624 The floating sample fill function for hatched fills.
628 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
629 i_fcolor *data, i_fcolor *work) {
630 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
631 int byte = f->hatch[(y + f->dy) & 7];
632 int xpos = (x + f->dx) & 7;
633 int mask = 128 >> xpos;
635 if (fill->combinef) {
637 i_fcolor *wstart = work;
639 while (count-- > 0) {
640 *work++ = (byte & mask) ? f->ffg : f->fbg;
642 if ((mask >>= 1) == 0)
645 (fill->combinef)(data, wstart, channels, width);
648 while (width-- > 0) {
649 *data++ = (byte & mask) ? f->ffg : f->fbg;
651 if ((mask >>= 1) == 0)
657 static void combine_replace(i_color *, i_color *, int, int);
658 static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
659 static void combine_alphablend(i_color *, i_color *, int, int);
660 static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
661 static void combine_mult(i_color *, i_color *, int, int);
662 static void combine_multf(i_fcolor *, i_fcolor *, int, int);
663 static void combine_dissolve(i_color *, i_color *, int, int);
664 static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
665 static void combine_add(i_color *, i_color *, int, int);
666 static void combine_addf(i_fcolor *, i_fcolor *, int, int);
667 static void combine_subtract(i_color *, i_color *, int, int);
668 static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
669 static void combine_diff(i_color *, i_color *, int, int);
670 static void combine_difff(i_fcolor *, i_fcolor *, int, int);
671 static void combine_darken(i_color *, i_color *, int, int);
672 static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
673 static void combine_lighten(i_color *, i_color *, int, int);
674 static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
675 static void combine_hue(i_color *, i_color *, int, int);
676 static void combine_huef(i_fcolor *, i_fcolor *, int, int);
677 static void combine_sat(i_color *, i_color *, int, int);
678 static void combine_satf(i_fcolor *, i_fcolor *, int, int);
679 static void combine_value(i_color *, i_color *, int, int);
680 static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
681 static void combine_color(i_color *, i_color *, int, int);
682 static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
685 i_fill_combine_f combine;
686 i_fill_combinef_f combinef;
749 =item i_get_combine(combine, color_func, fcolor_func)
754 void i_get_combine(int combine, i_fill_combine_f *color_func,
755 i_fill_combinef_f *fcolor_func) {
756 if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
759 *color_func = combines[combine].combine;
760 *fcolor_func = combines[combine].combinef;
763 static void combine_replace(i_color *out, i_color *in, int channels, int count) {
769 static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
775 static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
777 COMBINE(*out, *in, channels);
783 static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
785 COMBINEF(*out, *in, channels);
791 static void combine_mult(i_color *out, i_color *in, int channels, int count) {
796 double mult[MAXCHANNELS];
797 mult[3] = in->channel[3];
798 for (ch = 0; ch < (channels); ++ch) {
800 mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
802 COMBINEA(*out, mult, channels);
808 static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
813 for (ch = 0; ch < channels; ++ch) {
815 c.channel[ch] = out->channel[ch] * in->channel[ch];
817 COMBINEF(*out, c, channels);
823 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
827 if (in->channel[3] > rand() * (255.0 / RAND_MAX))
828 COMBINE(*out, *in, channels);
834 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
838 if (in->channel[3] > rand() * (1.0 / RAND_MAX))
839 COMBINEF(*out, *in, channels);
845 static void combine_add(i_color *out, i_color *in, int channels, int count) {
850 for (ch = 0; ch < (channels); ++ch) {
852 int total = out->channel[ch] + in->channel[ch];
855 c.channel[ch] = total;
858 COMBINE(*out, c, channels);
864 static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
869 for (ch = 0; ch < (channels); ++ch) {
871 double total = out->channel[ch] + in->channel[ch];
874 out->channel[ch] = total;
877 COMBINEF(*out, c, channels);
883 static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
888 for (ch = 0; ch < (channels); ++ch) {
890 int total = out->channel[ch] - in->channel[ch];
893 c.channel[ch] = total;
896 COMBINE(*out, c, channels);
902 static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
907 for (ch = 0; ch < channels; ++ch) {
909 double total = out->channel[ch] - in->channel[ch];
912 c.channel[ch] = total;
915 COMBINEF(*out, c, channels);
921 static void combine_diff(i_color *out, i_color *in, int channels, int count) {
926 for (ch = 0; ch < (channels); ++ch) {
928 c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
930 COMBINE(*out, c, channels)
936 static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
941 for (ch = 0; ch < (channels); ++ch) {
943 c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
945 COMBINEF(*out, c, channels);
951 static void combine_darken(i_color *out, i_color *in, int channels, int count) {
955 for (ch = 0; ch < channels; ++ch) {
956 if (ch != 3 && out->channel[ch] < in->channel[ch])
957 in->channel[ch] = out->channel[ch];
959 COMBINE(*out, *in, channels);
965 static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
969 for (ch = 0; ch < channels; ++ch) {
970 if (ch != 3 && out->channel[ch] < in->channel[ch])
971 in->channel[ch] = out->channel[ch];
973 COMBINEF(*out, *in, channels);
979 static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
983 for (ch = 0; ch < channels; ++ch) {
984 if (ch != 3 && out->channel[ch] > in->channel[ch])
985 in->channel[ch] = out->channel[ch];
987 COMBINE(*out, *in, channels);
993 static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
997 for (ch = 0; ch < channels; ++ch) {
998 if (ch != 3 && out->channel[ch] > in->channel[ch])
999 in->channel[ch] = out->channel[ch];
1001 COMBINEF(*out, *in, channels);
1007 static void combine_hue(i_color *out, i_color *in, int channels, int count) {
1012 c.channel[0] = in->channel[0];
1014 c.channel[3] = in->channel[3];
1015 COMBINE(*out, c, channels);
1021 static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1026 c.channel[0] = in->channel[0];
1028 c.channel[3] = in->channel[3];
1029 COMBINEF(*out, c, channels);
1035 static void combine_sat(i_color *out, i_color *in, int channels, int count) {
1040 c.channel[1] = in->channel[1];
1042 c.channel[3] = in->channel[3];
1043 COMBINE(*out, c, channels);
1049 static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1054 c.channel[1] = in->channel[1];
1056 c.channel[3] = in->channel[3];
1057 COMBINEF(*out, c, channels);
1063 static void combine_value(i_color *out, i_color *in, int channels, int count) {
1068 c.channel[2] = in->channel[2];
1070 c.channel[3] = in->channel[3];
1071 COMBINE(*out, c, channels);
1077 static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
1083 c.channel[2] = in->channel[2];
1085 c.channel[3] = in->channel[3];
1086 COMBINEF(*out, c, channels);
1092 static void combine_color(i_color *out, i_color *in, int channels, int count) {
1097 c.channel[0] = in->channel[0];
1098 c.channel[1] = in->channel[1];
1100 c.channel[3] = in->channel[3];
1101 COMBINE(*out, c, channels);
1107 static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
1113 c.channel[0] = in->channel[0];
1114 c.channel[1] = in->channel[1];
1116 c.channel[3] = in->channel[3];
1117 COMBINEF(*out, c, channels);
1129 Tony Cook <tony@develop-help.com>