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]);
114 static i_fcolor color_to_fcolor(i_color *c) {
118 for (ch = 0; ch < MAXCHANNELS; ++ch)
119 out.channel[ch] = Sample8ToF(c->channel[ch]);
122 /* alpha combine in with out */
123 #define COMBINE(out, in, channels) \
126 for (ch = 0; ch < (channels); ++ch) { \
127 (out).channel[ch] = ((out).channel[ch] * (255 - (in).channel[3]) \
128 + (in).channel[ch] * (in).channel[3]) / 255; \
132 /* alpha combine in with out, in this case in is a simple array of
133 samples, potentially not integers - the mult combiner uses doubles
135 #define COMBINEA(out, in, channels) \
138 for (ch = 0; ch < (channels); ++ch) { \
139 (out).channel[ch] = ((out).channel[ch] * (255 - (in)[3]) \
140 + (in)[ch] * (in)[3]) / 255; \
144 #define COMBINEF(out, in, channels) \
147 for (ch = 0; ch < (channels); ++ch) { \
148 (out).channel[ch] = (out).channel[ch] * (1.0 - (in).channel[3]) \
149 + (in).channel[ch] * (in).channel[3]; \
160 static void fill_solid(i_fill_t *, int x, int y, int width, int channels,
161 i_color *, i_color *);
162 static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
163 i_fcolor *, i_fcolor *);
164 static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
165 i_color *, i_color *);
166 static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
167 int channels, i_fcolor *, i_fcolor *);
169 static i_fill_solid_t base_solid_fill =
179 static i_fill_solid_t base_solid_fill_comb =
191 =item i_fill_destroy(fill)
193 Call to destroy any fill object.
199 i_fill_destroy(i_fill_t *fill) {
201 (fill->destroy)(fill);
206 =item i_new_fill_solidf(color, combine)
208 Create a solid fill based on a float color.
210 If combine is non-zero then alpha values will be combined.
216 i_new_fill_solidf(i_fcolor *c, int combine) {
218 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
220 if (combine && c->channel[3] < 1.0) {
221 *fill = base_solid_fill_comb;
222 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
225 *fill = base_solid_fill;
227 for (ch = 0; ch < MAXCHANNELS; ++ch) {
228 fill->c.channel[ch] = SampleFTo8(c->channel[ch]);
235 =item i_new_fill_solid(color, combine)
237 Create a solid fill based.
239 If combine is non-zero then alpha values will be combined.
245 i_new_fill_solid(i_color *c, int combine) {
247 i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
249 if (combine && c->channel[3] < 255) {
250 *fill = base_solid_fill_comb;
251 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
254 *fill = base_solid_fill;
256 for (ch = 0; ch < MAXCHANNELS; ++ch) {
257 fill->fc.channel[ch] = Sample8ToF(c->channel[ch]);
264 builtin_hatches[][8] =
267 /* 1x1 checkerboard */
268 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
271 /* 2x2 checkerboard */
272 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33,
275 /* 4 x 4 checkerboard */
276 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
279 /* single vertical lines */
280 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
283 /* double vertical lines */
284 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
287 /* quad vertical lines */
288 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
292 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
300 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
304 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
308 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
312 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88,
316 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11,
320 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
324 0xFF, 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88,
328 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA,
332 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
340 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
344 0x48, 0x84, 0x00, 0x00, 0x84, 0x48, 0x00, 0x00,
348 0x55, 0xFD, 0x05, 0xFD, 0x55, 0xDF, 0x50, 0xDF,
351 /* single cross hatch */
352 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x01,
355 /* double cross hatch */
356 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11,
359 /* vertical lozenge */
360 0x11, 0x11, 0x11, 0xAA, 0x44, 0x44, 0x44, 0xAA,
363 /* horizontal lozenge */
364 0x88, 0x70, 0x88, 0x07, 0x88, 0x70, 0x88, 0x07,
367 /* scales overlapping downwards */
368 0x80, 0x80, 0x41, 0x3E, 0x08, 0x08, 0x14, 0xE3,
371 /* scales overlapping upwards */
372 0xC7, 0x28, 0x10, 0x10, 0x7C, 0x82, 0x01, 0x01,
375 /* scales overlapping leftwards */
376 0x83, 0x84, 0x88, 0x48, 0x38, 0x48, 0x88, 0x84,
379 /* scales overlapping rightwards */
380 0x21, 0x11, 0x12, 0x1C, 0x12, 0x11, 0x21, 0xC1,
384 0x44, 0x88, 0x22, 0x11, 0x44, 0x88, 0x22, 0x11,
388 0xFF, 0x84, 0x84, 0x9C, 0x94, 0x9C, 0x90, 0x90,
392 0x80, 0x40, 0x20, 0x00, 0x02, 0x04, 0x08, 0x00,
401 unsigned char hatch[8];
405 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
406 i_color *data, i_color *work);
407 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
408 i_fcolor *data, i_fcolor *work);
411 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
412 int combine, int hatch, unsigned char *cust_hatch,
416 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
418 Creates a new hatched fill with the fg color used for the 1 bits in
419 the hatch and bg for the 0 bits. If combine is non-zero alpha values
422 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
423 hash definition, with the high-bits to the left.
425 If cust_hatch is NULL then one of the standard hatches is used.
427 (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.
432 i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
433 unsigned char *cust_hatch, int dx, int dy) {
434 return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch,
439 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
441 Creates a new hatched fill with the fg color used for the 1 bits in
442 the hatch and bg for the 0 bits. If combine is non-zero alpha values
445 If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
446 hash definition, with the high-bits to the left.
448 If cust_hatch is NULL then one of the standard hatches is used.
450 (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.
455 i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
456 unsigned char *cust_hatch, int dx, int dy) {
457 return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch,
461 #define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
466 =head1 INTERNAL FUNCTIONS
470 =item fill_solid(fill, x, y, width, channels, data)
472 The 8-bit sample fill function for non-combining solid fills.
477 fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
478 i_color *data, i_color *work) {
479 while (width-- > 0) {
480 *data++ = T_SOLID_FILL(fill)->c;
485 =item fill_solid(fill, x, y, width, channels, data)
487 The floating sample fill function for non-combining solid fills.
492 fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
493 i_fcolor *data, i_fcolor *work) {
494 while (width-- > 0) {
495 *data++ = T_SOLID_FILL(fill)->fc;
500 =item fill_solid_comb(fill, x, y, width, channels, data)
502 The 8-bit sample fill function for combining solid fills.
507 fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
508 i_color *data, i_color *work) {
509 i_color c = T_SOLID_FILL(fill)->c;
511 i_color *wstart = work;
513 while (width-- > 0) {
516 (fill->combine)(data, wstart, channels, count);
520 =item fill_solidf_comb(fill, x, y, width, channels, data)
522 The floating sample fill function for combining solid fills.
527 fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
528 i_fcolor *data, i_fcolor *work) {
529 i_fcolor c = T_SOLID_FILL(fill)->fc;
531 i_fcolor *wstart = work;
533 while (width-- > 0) {
536 (fill->combinef)(data, wstart, channels, count);
540 =item i_new_hatch_low(fg, bg, ffg, fbg, combine, hatch, cust_hatch, dx, dy)
542 Implements creation of hatch fill objects.
548 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
549 int combine, int hatch, unsigned char *cust_hatch,
551 i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t));
553 fill->base.fill_with_color = fill_hatch;
554 fill->base.fill_with_fcolor = fill_hatchf;
555 fill->base.destroy = NULL;
556 fill->fg = fg ? *fg : fcolor_to_color(ffg);
557 fill->bg = bg ? *bg : fcolor_to_color(fbg);
558 fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
559 fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
560 if (combine && (fill->ffg.channel[0] < 1 || fill->fbg.channel[0] < 1)) {
561 i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
564 fill->base.combine = NULL;
565 fill->base.combinef = NULL;
568 memcpy(fill->hatch, cust_hatch, 8);
571 if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
573 memcpy(fill->hatch, builtin_hatches[hatch], 8);
582 =item fill_hatch(fill, x, y, width, channels, data)
584 The 8-bit sample fill function for hatched fills.
588 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
589 i_color *data, i_color *work) {
590 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
591 int byte = f->hatch[(y + f->dy) & 7];
592 int xpos = (x + f->dx) & 7;
593 int mask = 128 >> xpos;
597 i_color *wstart = work;
599 while (count-- > 0) {
600 *work++ = (byte & mask) ? f->fg : f->bg;
602 if ((mask >>= 1) == 0)
605 (fill->combine)(data, wstart, channels, width);
608 while (width-- > 0) {
609 *data++ = (byte & mask) ? f->fg : f->bg;
611 if ((mask >>= 1) == 0)
618 =item fill_hatchf(fill, x, y, width, channels, data)
620 The floating sample fill function for hatched fills.
624 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
625 i_fcolor *data, i_fcolor *work) {
626 i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
627 int byte = f->hatch[(y + f->dy) & 7];
628 int xpos = (x + f->dx) & 7;
629 int mask = 128 >> xpos;
631 if (fill->combinef) {
633 i_fcolor *wstart = work;
635 while (count-- > 0) {
636 *work++ = (byte & mask) ? f->ffg : f->fbg;
638 if ((mask >>= 1) == 0)
641 (fill->combinef)(data, wstart, channels, width);
644 while (width-- > 0) {
645 *data++ = (byte & mask) ? f->ffg : f->fbg;
647 if ((mask >>= 1) == 0)
653 static void combine_replace(i_color *, i_color *, int, int);
654 static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
655 static void combine_alphablend(i_color *, i_color *, int, int);
656 static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
657 static void combine_mult(i_color *, i_color *, int, int);
658 static void combine_multf(i_fcolor *, i_fcolor *, int, int);
659 static void combine_dissolve(i_color *, i_color *, int, int);
660 static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
661 static void combine_add(i_color *, i_color *, int, int);
662 static void combine_addf(i_fcolor *, i_fcolor *, int, int);
663 static void combine_subtract(i_color *, i_color *, int, int);
664 static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
665 static void combine_diff(i_color *, i_color *, int, int);
666 static void combine_difff(i_fcolor *, i_fcolor *, int, int);
667 static void combine_darken(i_color *, i_color *, int, int);
668 static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
669 static void combine_lighten(i_color *, i_color *, int, int);
670 static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
671 static void combine_hue(i_color *, i_color *, int, int);
672 static void combine_huef(i_fcolor *, i_fcolor *, int, int);
673 static void combine_sat(i_color *, i_color *, int, int);
674 static void combine_satf(i_fcolor *, i_fcolor *, int, int);
675 static void combine_value(i_color *, i_color *, int, int);
676 static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
677 static void combine_color(i_color *, i_color *, int, int);
678 static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
681 i_fill_combine_f combine;
682 i_fill_combinef_f combinef;
745 =item i_get_combine(combine, color_func, fcolor_func)
750 void i_get_combine(int combine, i_fill_combine_f *color_func,
751 i_fill_combinef_f *fcolor_func) {
752 if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
755 *color_func = combines[combine].combine;
756 *fcolor_func = combines[combine].combinef;
759 static void combine_replace(i_color *out, i_color *in, int channels, int count) {
765 static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
771 static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
773 COMBINE(*out, *in, channels);
779 static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
781 COMBINEF(*out, *in, channels);
787 static void combine_mult(i_color *out, i_color *in, int channels, int count) {
792 double mult[MAXCHANNELS];
793 mult[3] = in->channel[3];
794 for (ch = 0; ch < (channels); ++ch) {
796 mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
798 COMBINEA(*out, mult, channels);
804 static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
809 for (ch = 0; ch < channels; ++ch) {
811 c.channel[ch] = out->channel[ch] * in->channel[ch];
813 COMBINEF(*out, c, channels);
819 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
823 if (in->channel[3] > rand() * (255.0 / RAND_MAX))
824 COMBINE(*out, *in, channels);
830 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
834 if (in->channel[3] > rand() * (1.0 / RAND_MAX))
835 COMBINEF(*out, *in, channels);
841 static void combine_add(i_color *out, i_color *in, int channels, int count) {
846 for (ch = 0; ch < (channels); ++ch) {
848 int total = out->channel[ch] + in->channel[ch];
851 c.channel[ch] = total;
854 COMBINE(*out, c, channels);
860 static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
865 for (ch = 0; ch < (channels); ++ch) {
867 double total = out->channel[ch] + in->channel[ch];
870 out->channel[ch] = total;
873 COMBINEF(*out, c, channels);
879 static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
884 for (ch = 0; ch < (channels); ++ch) {
886 int total = out->channel[ch] - in->channel[ch];
889 c.channel[ch] = total;
892 COMBINE(*out, c, channels);
898 static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
903 for (ch = 0; ch < channels; ++ch) {
905 double total = out->channel[ch] - in->channel[ch];
908 c.channel[ch] = total;
911 COMBINEF(*out, c, channels);
917 static void combine_diff(i_color *out, i_color *in, int channels, int count) {
922 for (ch = 0; ch < (channels); ++ch) {
924 c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
926 COMBINE(*out, c, channels)
932 static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
937 for (ch = 0; ch < (channels); ++ch) {
939 c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
941 COMBINEF(*out, c, channels);
947 static void combine_darken(i_color *out, i_color *in, int channels, int count) {
951 for (ch = 0; ch < channels; ++ch) {
952 if (ch != 3 && out->channel[ch] < in->channel[ch])
953 in->channel[ch] = out->channel[ch];
955 COMBINE(*out, *in, channels);
961 static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
965 for (ch = 0; ch < channels; ++ch) {
966 if (ch != 3 && out->channel[ch] < in->channel[ch])
967 in->channel[ch] = out->channel[ch];
969 COMBINEF(*out, *in, channels);
975 static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
979 for (ch = 0; ch < channels; ++ch) {
980 if (ch != 3 && out->channel[ch] > in->channel[ch])
981 in->channel[ch] = out->channel[ch];
983 COMBINE(*out, *in, channels);
989 static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
993 for (ch = 0; ch < channels; ++ch) {
994 if (ch != 3 && out->channel[ch] > in->channel[ch])
995 in->channel[ch] = out->channel[ch];
997 COMBINEF(*out, *in, channels);
1003 static void combine_hue(i_color *out, i_color *in, int channels, int count) {
1008 c.channel[0] = in->channel[0];
1010 COMBINE(*out, c, channels);
1016 static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
1021 c.channel[0] = in->channel[0];
1023 c.channel[3] = in->channel[3];
1024 COMBINEF(*out, c, channels);
1030 static void combine_sat(i_color *out, i_color *in, int channels, int count) {
1035 c.channel[1] = in->channel[1];
1037 c.channel[3] = in->channel[3];
1038 COMBINE(*out, c, channels);
1044 static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
1049 c.channel[1] = in->channel[1];
1051 c.channel[3] = in->channel[3];
1052 COMBINEF(*out, c, channels);
1058 static void combine_value(i_color *out, i_color *in, int channels, int count) {
1063 c.channel[2] = in->channel[2];
1065 c.channel[3] = in->channel[3];
1066 COMBINE(*out, c, channels);
1072 static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
1078 c.channel[2] = in->channel[2];
1080 c.channel[3] = in->channel[3];
1081 COMBINEF(*out, c, channels);
1087 static void combine_color(i_color *out, i_color *in, int channels, int count) {
1092 c.channel[0] = in->channel[0];
1093 c.channel[1] = in->channel[1];
1095 c.channel[3] = in->channel[3];
1096 COMBINE(*out, c, channels);
1102 static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
1108 c.channel[0] = in->channel[0];
1109 c.channel[1] = in->channel[1];
1111 c.channel[3] = in->channel[3];
1112 COMBINEF(*out, c, channels);
1124 Tony Cook <tony@develop-help.com>