move the combining function call outside the general fills (simplifies
authorTony Cook <tony@develop=help.com>
Mon, 19 Nov 2001 12:10:43 +0000 (12:10 +0000)
committerTony Cook <tony@develop=help.com>
Mon, 19 Nov 2001 12:10:43 +0000 (12:10 +0000)
the fills)
implement general fills for anti-aliased polygons

Changes
Imager.pm
Imager.xs
draw.c
fills.c
filters.c
image.h
pnm.c
polygon.c
t/t75polyaa.t

diff --git a/Changes b/Changes
index 95eb293..a6017ab 100644 (file)
--- a/Changes
+++ b/Changes
@@ -546,6 +546,10 @@ Revision history for Perl extension Imager.
 
 0.39    Released: Nov 2 2001.
 
+0.40  pre1
+        - anti-aliased polygon fill
+        - add general fill to polygon fill
+
 =================================================================
 
         For latest versions check the Imager-devel pages:
index 6c75679..d6a9a67 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -44,6 +44,7 @@ use Imager::Font;
 
                i_bezier_multi
                i_poly_aa
+               i_poly_aa_cfill
 
                i_copyto
                i_rubthru
@@ -1808,7 +1809,22 @@ sub polygon {
     $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
   }
 
-  i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'color'});
+  if ($opts{'fill'}) {
+    unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
+      # assume it's a hash ref
+      require 'Imager/Fill.pm';
+      unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
+        $self->{ERRSTR} = $Imager::ERRSTR;
+        return undef;
+      }
+    }
+    i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, 
+                    $opts{'fill'}{'fill'});
+  }
+  else {
+    i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'color'});
+  }
+
   return $self;
 }
 
index 885bfa7..6854792 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -981,6 +981,39 @@ i_poly_aa(im,xc,yc,val)
              myfree(x);
              myfree(y);
 
+void
+i_poly_aa_cfill(im,xc,yc,fill)
+    Imager::ImgRaw     im
+     Imager::FillHandle     fill
+            PREINIT:
+            double   *x,*y;
+            int       len;
+            AV       *av1;
+            AV       *av2;
+            SV       *sv1;
+            SV       *sv2;
+            int i;
+            PPCODE:
+            if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+            if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+            if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+            if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+            av1=(AV*)SvRV(ST(1));
+            av2=(AV*)SvRV(ST(2));
+            if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
+            len=av_len(av1)+1;
+            x=mymalloc( len*sizeof(double) );
+            y=mymalloc( len*sizeof(double) );
+            for(i=0;i<len;i++) {
+              sv1=(*(av_fetch(av1,i,0)));
+              sv2=(*(av_fetch(av2,i,0)));
+              x[i]=(double)SvNV(sv1);
+              y[i]=(double)SvNV(sv2);
+            }
+             i_poly_aa_cfill(im,len,x,y,fill);
+             myfree(x);
+             myfree(y);
+
 
 
 void
diff --git a/draw.c b/draw.c
index 0340c75..68ada4f 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -59,10 +59,14 @@ i_mmarray_render_fill(i_img *im,i_mmarray *ar,i_fill_t *fill) {
         x = ar->data[y].min;
         w = ar->data[y].max-ar->data[y].min;
 
-        if (fill->combine) 
+        if (fill->combine) {
           i_glin(im, x, x+w, y, line);
-        
-        (fill->fill_with_color)(fill, x, y, w, im->channels, line, work);
+          (fill->fill_with_color)(fill, x, y, w, im->channels, work);
+          (fill->combine)(line, work, im->channels, w);
+        }
+        else {
+          (fill->fill_with_color)(fill, x, y, w, im->channels, line);
+        }
         i_plin(im, x, x+w, y, line);
       }
     }
@@ -81,10 +85,14 @@ i_mmarray_render_fill(i_img *im,i_mmarray *ar,i_fill_t *fill) {
         x = ar->data[y].min;
         w = ar->data[y].max-ar->data[y].min;
 
-        if (fill->combinef) 
+        if (fill->combinef) {
           i_glinf(im, x, x+w, y, line);
-        
-        (fill->fill_with_fcolor)(fill, x, y, w, im->channels, line, work);
+          (fill->fill_with_fcolor)(fill, x, y, w, im->channels, work);
+          (fill->combinef)(line, work, im->channels, w);
+        }
+        else {
+          (fill->fill_with_fcolor)(fill, x, y, w, im->channels, line);
+        }
         i_plinf(im, x, x+w, y, line);
       }
     }
@@ -375,10 +383,14 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
     if (fill->combine)
       work = mymalloc(sizeof(i_color) * (x2-x1));
     while (y1 <= y2) {
-      if (fill->combine)
+      if (fill->combine) {
         i_glin(im, x1, x2, y1, line);
-
-      (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, line, work);
+        (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, work);
+        (fill->combine)(line, work, im->channels, x2-x1);
+      }
+      else {
+        (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, line);
+      }
       i_plin(im, x1, x2, y1, line);
       ++y1;
     }
@@ -392,12 +404,15 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
     work = mymalloc(sizeof(i_fcolor) * (x2 - x1));
 
     while (y1 <= y2) {
-      if (fill->combinef)
+      if (fill->combine) {
         i_glinf(im, x1, x2, y1, line);
-
-      (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, line, work);
+        (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, work);
+        (fill->combinef)(line, work, im->channels, x2-x1);
+      }
+      else {
+        (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, line);
+      }
       i_plinf(im, x1, x2, y1, line);
-      ++y1;
     }
     myfree(line);
     if (work)
@@ -955,10 +970,16 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
           while (x < bxmax && btm_test(btm, x, y)) {
             ++x;
           }
-          if (fill->combine)
+          if (fill->combine) {
             i_glin(im, start, x, y, line);
-          (fill->fill_with_color)(fill, start, y, x-start, im->channels, 
-                                  line, work);
+            (fill->fill_with_color)(fill, start, y, x-start, im->channels, 
+                                    work);
+            (fill->combine)(line, work, im->channels, x-start);
+          }
+          else {
+            (fill->fill_with_color)(fill, start, y, x-start, im->channels, 
+                                    line);
+          }
           i_plin(im, start, x, y, line);
         }
       }
@@ -984,10 +1005,16 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
           while (x < bxmax && btm_test(btm, x, y)) {
             ++x;
           }
-          if (fill->combinef)
+          if (fill->combinef) {
             i_glinf(im, start, x, y, line);
-          (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels, 
-                                   line, work);
+            (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels, 
+                                    work);
+            (fill->combinef)(line, work, im->channels, x-start);
+          }
+          else {
+            (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels, 
+                                    line);
+          }
           i_plinf(im, start, x, y, line);
         }
       }
diff --git a/fills.c b/fills.c
index 181fca6..bcd0604 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -163,13 +163,13 @@ typedef struct
 } i_fill_solid_t;
 
 static void fill_solid(i_fill_t *, int x, int y, int width, int channels, 
-                       i_color *, i_color *);
+                       i_color *);
 static void fill_solidf(i_fill_t *, int x, int y, int width, int channels, 
-                        i_fcolor *, i_fcolor *);
+                        i_fcolor *);
 static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels, 
-                            i_color *, i_color *);
+                            i_color *);
 static void fill_solidf_comb(i_fill_t *, int x, int y, int width, 
-                             int channels, i_fcolor *, i_fcolor *);
+                             int channels, i_fcolor *);
 
 static i_fill_solid_t base_solid_fill =
 {
@@ -408,9 +408,9 @@ typedef struct
 } i_fill_hatch_t;
 
 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels, 
-                       i_color *data, i_color *work);
+                       i_color *data);
 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels, 
-                        i_fcolor *data, i_fcolor *work);
+                        i_fcolor *data);
 static
 i_fill_t *
 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg, 
@@ -464,9 +464,9 @@ i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
 }
 
 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
-                       i_color *data, i_color *work);
+                       i_color *data);
 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
-                       i_fcolor *data, i_fcolor *work);
+                       i_fcolor *data);
 struct i_fill_image_t {
   i_fill_t base;
   i_img *src;
@@ -532,7 +532,7 @@ The 8-bit sample fill function for non-combining solid fills.
 */
 static void
 fill_solid(i_fill_t *fill, int x, int y, int width, int channels, 
-           i_color *data, i_color *work) {
+           i_color *data) {
   while (width-- > 0) {
     *data++ = T_SOLID_FILL(fill)->c;
   }
@@ -547,7 +547,7 @@ The floating sample fill function for non-combining solid fills.
 */
 static void
 fill_solidf(i_fill_t *fill, int x, int y, int width, int channels, 
-           i_fcolor *data, i_fcolor *work) {
+           i_fcolor *data) {
   while (width-- > 0) {
     *data++ = T_SOLID_FILL(fill)->fc;
   }
@@ -562,15 +562,12 @@ The 8-bit sample fill function for combining solid fills.
 */
 static void
 fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels, 
-                i_color *data, i_color *work) {
+                i_color *data) {
   i_color c = T_SOLID_FILL(fill)->c;
-  int count = width;
-  i_color *wstart = work;
 
   while (width-- > 0) {
-    *work++ = c;
+    *data++ = c;
   }
-  (fill->combine)(data, wstart, channels, count);
 }
 
 /*
@@ -582,15 +579,12 @@ The floating sample fill function for combining solid fills.
 */
 static void
 fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels, 
-           i_fcolor *data, i_fcolor *work) {
+           i_fcolor *data) {
   i_fcolor c = T_SOLID_FILL(fill)->fc;
-  int count = width;
-  i_fcolor *wstart = work;
 
   while (width-- > 0) {
-    *work++ = c;
+    *data++ = c;
   }
-  (fill->combinef)(data, wstart, channels, count);
 }
 
 /*
@@ -643,31 +637,17 @@ The 8-bit sample fill function for hatched fills.
 =cut
 */
 static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels, 
-                       i_color *data, i_color *work) {
+                       i_color *data) {
   i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
   int byte = f->hatch[(y + f->dy) & 7];
   int xpos = (x + f->dx) & 7;
   int mask = 128 >> xpos;
 
-  if (fill->combine) {
-    int count = width;
-    i_color *wstart = work;
-
-    while (count-- > 0) {
-      *work++ = (byte & mask) ? f->fg : f->bg;
-      
-      if ((mask >>= 1) == 0)
-        mask = 128;
-    }
-    (fill->combine)(data, wstart, channels, width);
-  }
-  else {
-    while (width-- > 0) {
-      *data++ = (byte & mask) ? f->fg : f->bg;
-
-      if ((mask >>= 1) == 0)
-        mask = 128;
-    }
+  while (width-- > 0) {
+    *data++ = (byte & mask) ? f->fg : f->bg;
+    
+    if ((mask >>= 1) == 0)
+      mask = 128;
   }
 }
 
@@ -679,31 +659,17 @@ The floating sample fill function for hatched fills.
 =back
 */
 static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels, 
-                        i_fcolor *data, i_fcolor *work) {
+                        i_fcolor *data) {
   i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
   int byte = f->hatch[(y + f->dy) & 7];
   int xpos = (x + f->dx) & 7;
   int mask = 128 >> xpos;
   
-  if (fill->combinef) {
-    int count = width;
-    i_fcolor *wstart = work;
-
-    while (count-- > 0) {
-      *work++ = (byte & mask) ? f->ffg : f->fbg;
-      
-      if ((mask >>= 1) == 0)
-        mask = 128;
-    }
-    (fill->combinef)(data, wstart, channels, width);
-  }
-  else {
-    while (width-- > 0) {
-      *data++ = (byte & mask) ? f->ffg : f->fbg;
-
-      if ((mask >>= 1) == 0)
-        mask = 128;
-    }
+  while (width-- > 0) {
+    *data++ = (byte & mask) ? f->ffg : f->fbg;
+    
+    if ((mask >>= 1) == 0)
+      mask = 128;
   }
 }
 
@@ -757,9 +723,8 @@ static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos,
 =cut
 */
 static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
-                       i_color *data, i_color *work) {
+                       i_color *data) {
   struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
-  i_color *out = fill->combine ? work : data;
   int i = 0;
   i_color c;
   
@@ -796,7 +761,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
         }
         c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
       }
-      *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
+      *data++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
       ++i;
     }
   }
@@ -819,15 +784,11 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
       }
       rx -= ix * f->src->xsize;
       ry -= iy * f->src->ysize;
-      i_gpix(f->src, rx, ry, out);
-      ++out;
+      i_gpix(f->src, rx, ry, data);
+      ++data;
       ++i;
     }
   }
-
-  if (fill->combine) {
-    (fill->combine)(data, work, channels, width);
-  }
 }
 
 /*
@@ -836,9 +797,8 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
 =cut
 */
 static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
-                       i_fcolor *data, i_fcolor *work) {
+                       i_fcolor *data) {
   struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
-  i_fcolor *out = fill->combine ? work : data;
   int i = 0;
   i_fcolor c;
   
@@ -875,7 +835,7 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
         }
         c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
       }
-      *out++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
+      *data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
       ++i;
     }
   }
@@ -898,15 +858,11 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
       }
       rx -= ix * f->src->xsize;
       ry -= iy * f->src->ysize;
-      i_gpixf(f->src, rx, ry, out);
-      ++out;
+      i_gpixf(f->src, rx, ry, data);
+      ++data;
       ++i;
     }
   }
-
-  if (fill->combinef) {
-    (fill->combinef)(data, work, channels, width);
-  }
 }
 
 static void combine_replace(i_color *, i_color *, int, int);
index ef5f63a..51993c7 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1468,7 +1468,7 @@ typedef struct {
 
 static void
 fill_fountf(i_fill_t *fill, int x, int y, int width, int channels, 
-            i_fcolor *data, i_fcolor *work);
+            i_fcolor *data);
 static void
 fount_fill_destroy(i_fill_t *fill);
 
@@ -2079,42 +2079,21 @@ The fill function for fountain fills.
 */
 static void
 fill_fountf(i_fill_t *fill, int x, int y, int width, int channels, 
-            i_fcolor *data, i_fcolor *work) {
+            i_fcolor *data) {
   i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
   
-  if (fill->combinef) {
-    i_fcolor *wstart = work;
-    int count = width;
-
-    while (width--) {
-      i_fcolor c;
-      int got_one;
-
-      if (f->state.ssfunc)
-        got_one = f->state.ssfunc(&c, x, y, &f->state);
-      else
-        got_one = fount_getat(&c, x, y, &f->state);
-      
-      *work++ = c;
-      
-      ++x;
-    }
-    (fill->combinef)(data, wstart, channels, count);
-  }
-  else {
-    while (width--) {
-      i_fcolor c;
-      int got_one;
-
-      if (f->state.ssfunc)
-        got_one = f->state.ssfunc(&c, x, y, &f->state);
-      else
-        got_one = fount_getat(&c, x, y, &f->state);
-      
-      *data++ = c;
-      
-      ++x;
-    }
+  while (width--) {
+    i_fcolor c;
+    int got_one;
+    
+    if (f->state.ssfunc)
+      got_one = f->state.ssfunc(&c, x, y, &f->state);
+    else
+      got_one = fount_getat(&c, x, y, &f->state);
+    
+    *data++ = c;
+    
+    ++x;
   }
 }
 
diff --git a/image.h b/image.h
index 9bdd3ff..62ea289 100644 (file)
--- a/image.h
+++ b/image.h
@@ -127,10 +127,10 @@ struct i_fill_tag;
 
 typedef void (*i_fill_with_color_f)
      (struct i_fill_tag *fill, int x, int y, int width, int channels, 
-      i_color *data, i_color *work);
+      i_color *data);
 typedef void (*i_fill_with_fcolor_f)
      (struct i_fill_tag *fill, int x, int y, int width, int channels,
-      i_fcolor *data, i_fcolor *work);
+      i_fcolor *data);
 typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill);
 typedef void (*i_fill_combine_f)(i_color *out, i_color *in, int channels, 
                                  int count);
@@ -209,6 +209,7 @@ extern i_img *i_matrix_transform(i_img *im, int xsize, int ysize, double *matrix
 
 void i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val);
 void i_poly_aa     (i_img *im,int l,double *x,double *y,i_color *val);
+void i_poly_aa_cfill(i_img *im,int l,double *x,double *y,i_fill_t *fill);
 
 void i_flood_fill  (i_img *im,int seedx,int seedy,i_color *dcol);
 
diff --git a/pnm.c b/pnm.c
index 3083eef..5073a8c 100644 (file)
--- a/pnm.c
+++ b/pnm.c
@@ -439,6 +439,7 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
         while (y < im->ysize && rc >= 0) {
           i_gsamp(im, 0, im->xsize, y, data, rgb_chan, 3);
           rc = ig->writecb(ig, data, im->xsize * 3);
+          ++y;
         }
         myfree(data);
       }
@@ -477,6 +478,7 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
         while (y < im->ysize && rc >= 0) {
           i_gsamp(im, 0, im->xsize, y, data, &chan, 1);
           rc = ig->writecb(ig, data, im->xsize);
+          ++y;
         }
         myfree(data);
       }
index b633890..2715132 100644 (file)
--- a/polygon.c
+++ b/polygon.c
@@ -261,13 +261,15 @@ saturate(int in) {
   return 0;
 }
 
+typedef void (*scanline_flusher)(i_img *im, ss_scanline *ss, int y, void *ctx);
 
 /* This function must be modified later to do proper blending */
 
 void
-scanline_flush(i_img *im, ss_scanline *ss, int y, i_color *val) {
+scanline_flush(i_img *im, ss_scanline *ss, int y, void *ctx) {
   int x, ch, tv;
   i_color t;
+  i_color *val = (i_color *)ctx;
   for(x=0; x<im->xsize; x++) {
     tv = saturate(ss->line[x]);
     i_gpix(im, x, y, &t);
@@ -532,7 +534,7 @@ render_slice_scanline_old(ss_scanline *ss, int y, p_line *l, p_line *r) {
 
 
 void
-i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
+i_poly_aa_low(i_img *im, int l, double *x, double *y, void *ctx, scanline_flusher flusher) {
   int i ,k;                    /* Index variables */
   int clc;                     /* Lines inside current interval */
   pcord miny ,maxy;            /* Min and max values of the current slice in the subcord system */
@@ -544,7 +546,7 @@ i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
   p_line  *lset;               /* List of lines in polygon */
   p_slice *tllist;             /* List of slices */
 
-  mm_log((1, "i_poly_aa(im %p, l %d, x %p, y %p, val %p)\n", im, l, x, y, val));
+  mm_log((1, "i_poly_aa(im %p, l %d, x %p, y %p, ctx %p, flusher %p)\n", im, l, x, y, ctx, flusher));
 
   for(i=0; i<l; i++) {
     mm_log((2, "(%.2f, %.2f)\n", x[i], y[i]));
@@ -621,7 +623,7 @@ i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
       }
       if (16*coarse(tempy) == tempy) {
        POLY_DEB( printf("flushing scan line %d\n", cscl) );
-       scanline_flush(im, &templine, cscl, val);
+       flusher(im, &templine, cscl, ctx);
        ss_scanline_reset(&templine);
       }
       /*
@@ -634,7 +636,7 @@ i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
     }
   } /* Intervals */
   if (16*coarse(tempy) != tempy) 
-    scanline_flush(im, &templine, cscl-1, val);
+    flusher(im, &templine, cscl-1, ctx);
 
   ss_scanline_exorcise(&templine);
   myfree(pset);
@@ -642,3 +644,157 @@ i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
   myfree(tllist);
   
 } /* Function */
+
+void
+i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
+  i_poly_aa_low(im, l, x, y, val, scanline_flush);
+}
+
+struct poly_cfill_state {
+  i_color *fillbuf;
+  i_color *linebuf;
+  int *cover;
+  i_fill_t *fill;
+};
+
+void
+scanline_flush_cfill(i_img *im, ss_scanline *ss, int y, void *ctx) {
+  int x, ch, tv;
+  i_color t;
+  int pos;
+  int left, right;
+  struct poly_cfill_state *state = (struct poly_cfill_state *)ctx;
+  i_color *fillbuf = state->fillbuf;
+  i_color *line = state->linebuf;
+
+  left = 0;
+  while (left < im->xsize && ss->line[left] <= 0)
+    ++left;
+  if (left < im->xsize) {
+    right = im->xsize;
+    /* since going from the left found something, moving from the 
+       right should */
+    while (/* right > left && */ ss->line[right-1] <= 0) 
+      --right;
+    
+    (state->fill->fill_with_color)(state->fill, left, y, right-left, 
+                                   im->channels, fillbuf);
+    i_glin(im, left, right, y, line);
+    pos = 0;
+    if (state->fill->combine) {
+      for (x = left; x < right; ++x) {
+        tv = saturate(ss->line[x]);
+        fillbuf[pos].channel[3] = 
+          fillbuf[pos].channel[3] * tv / 255;
+      }
+      (state->fill->combine)(line, fillbuf, im->channels, right-left);
+      pos++;
+    }
+    else {
+      for (x = left; x < right; ++x) {
+        tv = saturate(ss->line[x]);
+        if (tv) { 
+          if (tv == 255) {
+            line[pos] = fillbuf[pos];
+          }
+          else {
+            i_color *to = line + pos;
+            i_color *from = fillbuf + pos;
+            for (ch = 0; ch < im->channels; ++ch) {
+              to->channel[ch] = (tv * from->channel[ch] + 
+                                 (255 - tv) * to->channel[ch]) / 255;
+            }
+          }
+        }
+        pos++;
+      }
+    }
+    i_plin(im, left, right, y, line);
+  }
+}
+
+struct poly_cfill_state_f {
+  i_fcolor *fillbuf;
+  i_fcolor *linebuf;
+  int *cover;
+  i_fill_t *fill;
+};
+
+void
+scanline_flush_cfill_f(i_img *im, ss_scanline *ss, int y, void *ctx) {
+  int x, ch, tv;
+  int pos;
+  int left, right;
+  struct poly_cfill_state_f *state = (struct poly_cfill_state_f *)ctx;
+  i_fcolor *fillbuf = state->fillbuf;
+  i_fcolor *line = state->linebuf;
+
+  left = 0;
+  while (left < im->xsize && ss->line[left] <= 0)
+    ++left;
+  if (left < im->xsize) {
+    right = im->xsize;
+    /* since going from the left found something, moving from the 
+       right should */
+    while (/* right > left && */ ss->line[right-1] <= 0) 
+      --right;
+    
+    (state->fill->fill_with_fcolor)(state->fill, left, y, right-left, 
+                                    im->channels, fillbuf);
+    i_glinf(im, left, right, y, line);
+    pos = 0;
+    if (state->fill->combinef) {
+      for (x = left; x < right; ++x) {
+        tv = saturate(ss->line[x]);
+        fillbuf[pos].channel[3] = 
+          fillbuf[pos].channel[3] * tv / 255;
+      }
+      (state->fill->combinef)(line, fillbuf, im->channels, right-left);
+      pos++;
+    }
+    else {
+      for (x = left; x < right; ++x) {
+        tv = saturate(ss->line[x]);
+        if (tv) { 
+          if (tv == 255) {
+            line[pos] = fillbuf[pos];
+          }
+          else {
+            i_fcolor *to = line + pos;
+            i_fcolor *from = fillbuf + pos;
+            for (ch = 0; ch < im->channels; ++ch) {
+              to->channel[ch] = (tv * from->channel[ch] + 
+                                 (255 - tv) * to->channel[ch]) / 255;
+            }
+          }
+        }
+        pos++;
+      }
+    }
+    i_plinf(im, left, right, y, line);
+  }
+}
+
+void
+i_poly_aa_cfill(i_img *im, int l, double *x, double *y, i_fill_t *fill) {
+  if (im->bits == i_8_bits && fill->fill_with_color) {
+    struct poly_cfill_state ctx;
+    ctx.fillbuf = mymalloc(sizeof(i_color) * im->xsize * 2);
+    ctx.linebuf = ctx.fillbuf + im->xsize;
+    ctx.cover = mymalloc(sizeof(int) * im->xsize);
+    ctx.fill = fill;
+    i_poly_aa_low(im, l, x, y, &ctx, scanline_flush_cfill);
+    myfree(ctx.fillbuf);
+    myfree(ctx.cover);
+  }
+  else {
+    struct poly_cfill_state_f ctx;
+    ctx.fillbuf = mymalloc(sizeof(i_fcolor) * im->xsize * 2);
+    ctx.linebuf = ctx.fillbuf + im->xsize;
+    ctx.cover = mymalloc(sizeof(int) * im->xsize);
+    ctx.fill = fill;
+    i_poly_aa_low(im, l, x, y, &ctx, scanline_flush_cfill_f);
+    myfree(ctx.fillbuf);
+    myfree(ctx.cover);
+  }
+}
index 6c18052..f8af081 100644 (file)
@@ -6,7 +6,7 @@
 # Change 1..1 below to 1..last_test_to_print .
 # (It may become useful if the test is moved to ./t subdirectory.)
 
-BEGIN { $| = 1; print "1..7\n"; }
+BEGIN { $| = 1; print "1..9\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager qw(:all);
 
@@ -102,18 +102,31 @@ make_zoom($img,20,\@data, $blue)->write(file=>"testout/t75wavebug.ppm") or die $
 
 print "ok 7\n";
 
-malloc_state();
-
-
-
-
-
-
-
-
-
-
+$img = Imager->new(xsize=>300, ysize=>300);
+$img->polygon(fill=>{ hatch=>'cross1', fg=>'00FF00', bg=>'0000FF', dx=>3 },
+              points => [
+                         translate(150,150,
+                                   scale(70,70,
+                                         get_polygon('wavycircle', 32*8, sub { 1+1*cos(4*$_) })))
+                        ],
+             ) or die $img->errstr();
+$img->write(file=>"testout/t75wave_fill.ppm") or die $img->errstr;
+
+print "ok 8\n";
+
+$img = Imager->new(xsize=>300, ysize=>300, bits=>16);
+$img->polygon(fill=>{ hatch=>'cross1', fg=>'00FF00', bg=>'0000FF' },
+              points => [
+                         translate(150,150,
+                                   scale(70,70,
+                                         get_polygon('wavycircle', 32*8, sub { 1+1*cos(5*$_) })))
+                        ],
+             ) or die $img->errstr();
+$img->write(file=>"testout/t75wave_fill16.ppm") or die $img->errstr;
+
+print "ok 9\n";
 
+malloc_state();