A segfault bug fixed in polygon.c where it would crash when invalid polygons
authorArnar Mar Hrafnkelsson <addi@cpan.org>
Mon, 12 Nov 2001 08:26:05 +0000 (08:26 +0000)
committerArnar Mar Hrafnkelsson <addi@cpan.org>
Mon, 12 Nov 2001 08:26:05 +0000 (08:26 +0000)
were fed to it.  Docs added to Imager.pm and minor test enhancements to
t/t75polyaa.t.

Imager.pm
polygon.c
t/t75polyaa.t

index 2bbc800..6c75679 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -1791,7 +1791,29 @@ sub polyline {
   return $self;
 }
 
-# this the multipoint bezier curve 
+sub polygon {
+  my $self = shift;
+  my ($pt,$ls,@points);
+  my $dflcl = i_color_new(0,0,0,0);
+  my %opts = (color=>$dflcl, @_);
+
+  unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
+
+  if (exists($opts{points})) {
+    $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
+    $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
+  }
+
+  if (!exists $opts{'x'} or !exists $opts{'y'})  {
+    $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
+  }
+
+  i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'color'});
+  return $self;
+}
+
+
+# this the multipoint bezier curve
 # this is here more for testing that actual usage since
 # this is not a good algorithm.  Usually the curve would be
 # broken into smaller segments and each done individually.
@@ -2936,6 +2958,16 @@ The point set can either be specified as an arrayref to an array of
 array references (where each such array represents a point).  The
 other way is to specify two array references.
 
+Polygon:
+  $img->polygon(points=>[[$x0,$y0],[$x1,$y1],[$x2,$y2]],color=>$red);
+  $img->polyline(x=>[$x0,$x1,$x2], y=>[$y0,$y1,$y2]);
+
+Polygon is used to draw a filled polygon.  Currently the polygon is
+always drawn antialiased, although that will change in the future.
+Like other antialiased drawing functions its coordinates can be
+specified with floating point values.
+
+
 You can fill a region that all has the same color using the
 flood_fill() method, for example:
 
index 27d2980..9a2a64d 100644 (file)
--- a/polygon.c
+++ b/polygon.c
@@ -148,6 +148,15 @@ ss_scanline_init(ss_scanline *ss, int linelen, int linepairs) {
   ss_scanline_reset(ss);
 }
 
+static
+void
+ss_scanline_exorcise(ss_scanline *ss) {
+  myfree(ss->line);
+  myfree(ss->ss_list);
+}
+  
+                    
+
 
 /* returns the number of matches */
 
@@ -180,18 +189,12 @@ mark_updown_slices(p_line *lset, p_slice *tllist, int count) {
   int k;
   for(k=0; k<count; k+=2) {
     l = lset + tllist[k].n;
-    r = lset + tllist[k+1].n;
 
     if (l->y1 == l->y2) {
       mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
       exit(3);
     }
 
-    if (r->y1 == r->y2) {
-      mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
-      exit(3);
-    }
-
     l->updown = (l->x1 == l->x2) ?
       0 :
       (l->x1 > l->x2)
@@ -200,6 +203,21 @@ mark_updown_slices(p_line *lset, p_slice *tllist, int count) {
       : 
       (l->y1 > l->y2) ? 1 : -1;
 
+    POLY_DEB( printf("marking left line %d as %s(%d)\n", l->n,
+                    l->updown ?  l->updown == 1 ? "up" : "down" : "vert", l->updown, l->updown)
+             );
+
+    if (k+1 >= count) {
+      mm_log((1, "Invalid polygon spec, odd number of line crossings.\n"));
+      return;
+    }
+
+    r = lset + tllist[k+1].n;
+    if (r->y1 == r->y2) {
+      mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
+      exit(3);
+    }
+
     r->updown = (r->x1 == r->x2) ?
       0 :
       (r->x1 > r->x2)
@@ -208,10 +226,8 @@ mark_updown_slices(p_line *lset, p_slice *tllist, int count) {
       : 
       (r->y1 > r->y2) ? 1 : -1;
     
-    POLY_DEB( printf("marking left line %d as %s(%d)\n", l->n,
-                    l->updown ?  l->updown == 1 ? "up" : "down" : "vert", l->updown, l->updown);
-             printf("marking right line %d as %s(%d)\n", r->n,
-                    r->updown ?  r->updown == 1 ? "up" : "down" : "vert", r->updown, r->updown);
+    POLY_DEB( printf("marking right line %d as %s(%d)\n", r->n,
+                    r->updown ?  r->updown == 1 ? "up" : "down" : "vert", r->updown, r->updown)
              );
   }
 }
@@ -509,9 +525,17 @@ 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 */
 
-  fflush(stdout);
-  setbuf(stdout, NULL);
-   
+  mm_log((1, "i_poly_aa(im %p, l %d, x %p, y %p, val %p)\n", im, l, x, y, val));
+
+  for(i=0; i<l; i++) {
+    mm_log((2, "(%.2f, %.2f)\n", x[i], y[i]));
+  }
+
+
+  POLY_DEB(
+          fflush(stdout);
+          setbuf(stdout, NULL);
+          );
 
   tllist   = mymalloc(sizeof(p_slice)*l);
   
@@ -590,5 +614,10 @@ 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);
-} /* Function */
 
+  ss_scanline_exorcise(&templine);
+  myfree(pset);
+  myfree(lset);
+  myfree(tllist);
+  
+} /* Function */
index c9444bf..ddae831 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..5\n"; }
+BEGIN { $| = 1; print "1..6\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager qw(:all);
 
@@ -64,10 +64,24 @@ for $n (0..55) {
   i_poly_aa($img->{IMG}, $x, $y, NC(rand(255), rand(255), rand(255)));
 }
 
-$img->write(file=>"testout/t75big.png") or die $img->errstr;
+$img->write(file=>"testout/t75big.ppm") or die $img->errstr;
 
 print "ok 5\n";
 
+$img = Imager->new(xsize => 200, ysize => 200);
+
+$img -> polygon(color=>$blue,
+               points => [
+                          translate(100,100,
+                                    scale(10,10,
+                                          get_polygon('wavycircle', 32*4, sub { 8+0.5*cos(12*$_) })))
+                         ],
+              ) or die $img->errstr();
+
+$img->write(file=>"testout/t75wave.ppm") or die $img->errstr;
+
+print "ok 6\n";
+
 malloc_state();
 
 
@@ -160,7 +174,7 @@ BEGIN {
               my @radians = map { $_*2*PI/$numv } 0..$numv-1;
               my @radius  = map { $radfunc->($_) } @radians;
               map {
-                [ $radius[$_] * cos($_), $radius[$_] * sin($_) ]
+                [ $radius[$_] * cos($radians[$_]), $radius[$_] * sin($radians[$_]) ]
               } 0..$#radians;
             },
             n_gon => sub {