Switched i_draw to i_line, added endpoint boolean condition,
authorArnar Mar Hrafnkelsson <addi@cpan.org>
Thu, 2 May 2002 20:20:34 +0000 (20:20 +0000)
committerArnar Mar Hrafnkelsson <addi@cpan.org>
Thu, 2 May 2002 20:20:34 +0000 (20:20 +0000)
switched the algorithm to Bresenham from a stupid floating point
implementation.  Updated docs.

Changes
Imager.pm
Imager.xs
draw.c
draw.h
dynaload.c
image.h
lib/Imager/Draw.pod
t/t30t1font.t
t/t35ttfont.t
t/t38ft2font.t

diff --git a/Changes b/Changes
index 8887750..1cde5c9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -659,6 +659,8 @@ Revision history for Perl extension Imager.
        - Compaq C 6.4 (OSF1) claims to be C99 but doesn't provide 
           stdint.h, don't try to use it under OSF
         - fix missing initialization in tags.c
+        - Change i_draw to i_line and have it use Bresenham's line
+         drawing algorithm.
 
 =================================================================
 
index 6369ce7..8e2502f 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -35,7 +35,7 @@ use Imager::Font;
                i_img_setmask
                i_img_getmask
 
-               i_draw
+               i_line
                i_line_aa
                i_box
                i_box_filled
@@ -2015,29 +2015,34 @@ sub arc {
   return $self;
 }
 
-# Draws a line from one point to (but not including) the destination point
+# Draws a line from one point to the other
+# the endpoint is set if the endp parameter is set which it is by default.
+# to turn of the endpoint being set use endp=>0 when calling line.
 
 sub line {
   my $self=shift;
   my $dflcl=i_color_new(0,0,0,0);
-  my %opts=(color=>$dflcl,@_);
+  my %opts=(color=>$dflcl,
+           endp => 1,
+           @_);
   unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
 
   unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
   unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
 
   my $color = _color($opts{'color'});
-  unless ($color) { 
-    $self->{ERRSTR} = $Imager::ERRSTR; 
-    return; 
+  unless ($color) {
+    $self->{ERRSTR} = $Imager::ERRSTR;
+    return;
   }
+
   $opts{antialias} = $opts{aa} if defined $opts{aa};
   if ($opts{antialias}) {
-    i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2}, 
+    i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
               $color);
   } else {
-    i_draw($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2}, 
-           $color);
+    i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
+           $color, $opts{endp});
   }
   return $self;
 }
@@ -2076,7 +2081,7 @@ sub polyline {
   } else {
     for $pt(@points) {
       if (defined($ls)) { 
-        i_draw($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color);
+        i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
       }
       $ls=$pt;
     }
@@ -2161,7 +2166,8 @@ sub polybezier {
 sub flood_fill {
   my $self = shift;
   my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
-       my $rc;
+  my $rc;
+
   unless (exists $opts{'x'} && exists $opts{'y'}) {
     $self->{ERRSTR} = "missing seed x and y parameters";
     return undef;
@@ -2180,13 +2186,13 @@ sub flood_fill {
   }
   else {
     my $color = _color($opts{'color'});
-    unless ($color) { 
-      $self->{ERRSTR} = $Imager::ERRSTR; 
-      return; 
+    unless ($color) {
+      $self->{ERRSTR} = $Imager::ERRSTR;
+      return;
     }
     $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
   }
-       if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
+  if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
 }
 
 sub setpixel {
index c3f6272..cae5ce1 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -1250,13 +1250,14 @@ i_img_getdata(im)
 
 
 void
-i_draw(im,x1,y1,x2,y2,val)
+i_line(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
               int     x1
               int     y1
               int     x2
               int     y2
      Imager::Color     val
+              int     endp
 
 void
 i_line_aa(im,x1,y1,x2,y2,val)
diff --git a/draw.c b/draw.c
index 7562515..9906f48 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -421,41 +421,114 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
   }
 }
 
+
+/* 
+=item i_line(im, x1, y1, x2, y2, val, endp)
+
+Draw a line to image using bresenhams linedrawing algorithm
+
+   im   - image to draw to
+   x1   - starting x coordinate
+   y1   - starting x coordinate
+   x2   - starting x coordinate
+   y2   - starting x coordinate
+   val  - color to write to image
+   endp - endpoint flag (boolean)
+
+=cut
+*/
+
 void
-i_draw(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
-  double alpha;
-  double dsec;
-  int temp;
+i_line(i_img *im, int x1, int y1, int x2, int y2, i_color *val, int endp) {
+  int x, y;
+  int dx, dy;
+  int p;
+  unsigned char *cp;
 
-  mm_log((1,"i_draw(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
+  dx = x2 - x1;
+  dy = y2 - y1;
 
-  alpha=(double)(y2-y1)/(double)(x2-x1);
-  if (fabs(alpha)<1) 
-    {
-      if (x2<x1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
-      dsec=y1;
-      while(x1<x2)
-       {
-         dsec+=alpha;
-         i_ppix(im,x1,(int)(dsec+0.5),val);
-         x1++;
-       }
+
+  /* choose variable to iterate on */
+  if (abs(dx)>abs(dy)) {
+    int dx2, dy2, cpy;
+
+    /* sort by x */
+    if (x1 > x2) {
+      int t;
+      t = x1; x1 = x2; x2 = t;
+      t = y1; y1 = y2; y2 = t;
     }
-  else
-    {
-      alpha=1/alpha;
-      if (y2<y1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
-      dsec=x1;
-      while(y1<y2)
-       {
-         dsec+=alpha;
-         i_ppix(im,(int)(dsec+0.5),y1,val);
-         y1++;
-       }
+    
+    dx = abs(dx);
+    dx2 = dx*2;
+    dy = y2 - y1;
+
+    if (dy<0) {
+      dy = -dy;
+      cpy = -1;
+    } else {
+      cpy = 1;
+    }
+    dy2 = dy*2;
+    p = dy2 - dx;
+
+    
+    y = y1;
+    for(x=x1; x<x2-1; x++) {
+      if (p<0) {
+        p += dy2;
+      } else {
+        y += cpy;
+        p += dy2-dx2;
+      }
+      i_ppix(im, x+1, y, val);
     }
-  mm_log((1,"i_draw: alpha=%f.\n",alpha));
+  } else {
+    int dy2, dx2, cpx;
+
+    /* sort bx y */
+    if (y1 > y2) {
+      int t;
+      t = x1; x1 = x2; x2 = t;
+      t = y1; y1 = y2; y2 = t;
+    }
+    
+    dy = abs(dy);
+    dx = x2 - x1;
+    dy2 = dy*2;
+
+    if (dx<0) {
+      dx = -dx;
+      cpx = -1;
+    } else {
+      cpx = 1;
+    }
+    dx2 = dx*2;
+    p = dx2 - dy;
+
+    x = x1;
+    
+    for(y=y1; y<y2-1; y++) {
+      if (p<0) {
+        p  += dx2;
+      } else {
+        x += cpx;
+        p += dx2-dy2;
+      }
+      i_ppix(im, x, y+1, val);
+    }
+  }
+  if (endp) {
+    i_ppix(im, x1, y1, val);
+    i_ppix(im, x2, y2, val);
+  } else {
+    if (x1 != x2 || y1 != y2) 
+      i_ppix(im, x1, y1, val);
+  }
 }
 
+
 void
 i_line_aa(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
   i_color tval;
@@ -707,18 +780,23 @@ i_rspan(i_img *im, int seedx, int seedy, i_color *val) {
 /* INSIDE returns true if pixel is correct color and we haven't set it before. */
 #define INSIDE(x,y) ((!btm_test(btm,x,y) && ( i_gpix(im,x,y,&cval),i_ccomp(&val,&cval,channels)  ) ))
 
-undef_int
-i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
 
-  int lx,rx;
-  int y;
-  int direction;
-  int dadLx,dadRx;
 
-  int wasIn=0;
-  int x=0;
+/* The function that does all the real work */
+
+static struct i_bitmap *
+i_flood_fill_low(i_img *im,int seedx,int seedy,
+                 int *bxminp, int *bxmaxp, int *byminp, int *bymaxp) {
 
-  /*  int tx,ty; */
+  /*
+    int lx,rx;
+    int y;
+    int direction;
+    int dadLx,dadRx;
+    int wasIn=0;
+  */
+  int ltx, rtx;
+  int tx = 0;
 
   int bxmin = seedx;
   int bxmax = seedx;
@@ -729,18 +807,12 @@ i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
   struct i_bitmap *btm;
 
   int channels,xsize,ysize;
-  i_color cval, val;
+  i_color cval,val;
 
   channels = im->channels;
   xsize    = im->xsize;
   ysize    = im->ysize;
 
-  if (seedx < 0 || seedx >= xsize ||
-      seedy < 0 || seedy >= ysize) {
-    i_push_error(0, "i_flood_fill: Seed pixel outside of image");
-    return 0;
-  }
-
   btm = btm_new(xsize, ysize);
   st  = llist_new(100, sizeof(struct stack_element*));
 
@@ -748,80 +820,64 @@ i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
   i_gpix(im, seedx, seedy, &val);
 
   /* Find the starting span and fill it */
-  lx = i_lspan(im, seedx, seedy, &val);
-  rx = i_rspan(im, seedx, seedy, &val);
-  
-  printf("span: %d %d \n",lx,rx);
+  ltx = i_lspan(im, seedx, seedy, &val);
+  rtx = i_rspan(im, seedx, seedy, &val);
+  for(tx=ltx; tx<=rtx; tx++) SET(tx, seedy);
 
-  for(x=lx; x<=rx; x++) SET(x,seedy);
-
-  ST_PUSH(lx, rx, lx, rx, seedy+1, 1);
-  ST_PUSH(lx, rx, lx, rx, seedy-1,-1);
+  ST_PUSH(ltx, rtx, ltx, rtx, seedy+1,  1);
+  ST_PUSH(ltx, rtx, ltx, rtx, seedy-1, -1);
 
   while(st->count) {
-    ST_POP();
-    
-    if (y<0 || y>ysize-1) continue;
+    /* Stack variables */
+    int lx,rx;
+    int dadLx,dadRx;
+    int y;
+    int direction;
 
+    int x;
+    int wasIn=0;
 
+    ST_POP(); /* sets lx, rx, dadLx, dadRx, y, direction */
+
+
+    if (y<0 || y>ysize-1) continue;
     if (bymin > y) bymin=y; /* in the worst case an extra line */
     if (bymax < y) bymax=y; 
 
-    /*
-      {
-      int tx, ty;
-      printf("start of scan - on stack : %d \n",st->count); 
-      printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction); 
-      
-      
-      printf(" ");
-      for(tx=0;tx<xsize;tx++) printf("%d",tx%10);
-      printf("\n");
-      for(ty=0;ty<ysize;ty++) {
-      printf("%d",ty%10);
-      for(tx=0;tx<xsize;tx++) printf("%d",!!btm_test(btm,tx,ty));
-      printf("\n");
-      }
-      printf("y=%d\n",y);
-      }
-    */
-
 
     x = lx+1;
-    if ( lx>=0 && (wasIn = INSIDE(lx,y)) ) {
-      SET(lx,y);
+    if ( lx >= 0 && (wasIn = INSIDE(lx, y)) ) {
+      SET(lx, y);
       lx--;
-      while(lx>0 && INSIDE(lx,y)) {
+      while(INSIDE(lx, y) && lx > 0) {
        SET(lx,y);
        lx--;
       }
     }
 
     if (bxmin > lx) bxmin = lx;
-    
     while(x <= xsize-1) {
       /*  printf("x=%d\n",x); */
       if (wasIn) {
        
-       if (INSIDE(x,y)) {
+       if (INSIDE(x, y)) {
          /* case 1: was inside, am still inside */
          SET(x,y);
        } else {
          /* case 2: was inside, am no longer inside: just found the
             right edge of a span */
-         ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
-
-         if (bxmax < x) bxmax=x;
+         ST_STACK(direction, dadLx, dadRx, lx, (x-1), y);
 
+         if (bxmax < x) bxmax = x;
          wasIn=0;
        }
       } else {
-       if (x>rx) goto EXT;
-       if (INSIDE(x,y)) {
-         SET(x,y);
+       if (x > rx) goto EXT;
+       if (INSIDE(x, y)) {
+         SET(x, y);
          /* case 3: Wasn't inside, am now: just found the start of a new run */
-         wasIn=1;
-         lx=x;
+         wasIn = 1;
+           lx = x;
        } else {
          /* case 4: Wasn't inside, still isn't */
        }
@@ -831,153 +887,49 @@ i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
   EXT: /* out of loop */
     if (wasIn) {
       /* hit an edge of the frame buffer while inside a run */
-      ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
-      if (bxmax < x) bxmax=x;
+      ST_STACK(direction, dadLx, dadRx, lx, (x-1), y);
+      if (bxmax < x) bxmax = x;
     }
   }
-  
-  /*   printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction); 
-       printf("bounding box: [%d,%d] - [%d,%d]\n",bxmin,bymin,bxmax,bymax); */
-
-  for(y=bymin;y<=bymax;y++) for(x=bxmin;x<=bxmax;x++) if (btm_test(btm,x,y)) i_ppix(im,x,y,dcol);
 
-  btm_destroy(btm);
-  mm_log((1, "DESTROY\n"));
   llist_destroy(st);
-  return 1;
-}
-
-static struct i_bitmap *
-i_flood_fill_low(i_img *im,int seedx,int seedy,
-                 int *bxminp, int *bxmaxp, int *byminp, int *bymaxp) {
-  int lx,rx;
-  int y;
-  int direction;
-  int dadLx,dadRx;
-
-  int wasIn=0;
-  int x=0;
-
-  /*  int tx,ty; */
-
-  int bxmin=seedx,bxmax=seedx,bymin=seedy,bymax=seedy;
-
-  struct llist *st;
-  struct i_bitmap *btm;
-
-  int channels,xsize,ysize;
-  i_color cval,val;
-
-  channels=im->channels;
-  xsize=im->xsize;
-  ysize=im->ysize;
-
-  btm=btm_new(xsize,ysize);
-  st=llist_new(100,sizeof(struct stack_element*));
-
-  /* Get the reference color */
-  i_gpix(im,seedx,seedy,&val);
-
-  /* Find the starting span and fill it */
-  lx = i_lspan(im, seedx, seedy, &val);
-  rx = i_rspan(im, seedx, seedy, &val);
-  
-  /* printf("span: %d %d \n",lx,rx); */
-
-  for(x=lx; x<=rx; x++) SET(x, seedy);
-
-  ST_PUSH(lx, rx, lx, rx, seedy+1,  1);
-  ST_PUSH(lx, rx, lx, rx, seedy-1, -1);
-
-  while(st->count) {
-    ST_POP();
-    
-    if (y<0 || y>ysize-1) continue;
-
-    if (bymin > y) bymin=y; /* in the worst case an extra line */
-    if (bymax < y) bymax=y; 
 
-    /*     printf("start of scan - on stack : %d \n",st->count); */
+  *bxminp = bxmin;
+  *bxmaxp = bxmax;
+  *byminp = bymin;
+  *bymaxp = bymax;
 
-    
-    /*     printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction); */
-    
-    /*
-    printf(" ");
-    for(tx=0;tx<xsize;tx++) printf("%d",tx%10);
-    printf("\n");
-    for(ty=0;ty<ysize;ty++) {
-      printf("%d",ty%10);
-      for(tx=0;tx<xsize;tx++) printf("%d",!!btm_test(btm,tx,ty));
-      printf("\n");
-    }
+  return btm;
+}
 
-    printf("y=%d\n",y);
-    */
 
 
-    x=lx+1;
-    if ( (wasIn = INSIDE(lx,y)) ) {
-      SET(lx,y);
-      lx--;
-      while(INSIDE(lx,y) && lx > 0) {
-       SET(lx,y);
-       lx--;
-      }
-    }
 
-    if (bxmin > lx) bxmin=lx;
-    
-    while(x <= xsize-1) {
-      /*  printf("x=%d\n",x); */
-      if (wasIn) {
-       
-       if (INSIDE(x,y)) {
-         /* case 1: was inside, am still inside */
-         SET(x,y);
-       } else {
-         /* case 2: was inside, am no longer inside: just found the
-            right edge of a span */
-         ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
-
-         if (bxmax < x) bxmax=x;
+undef_int
+i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
+  int bxmin, bxmax, bymin, bymax;
+  struct i_bitmap *btm;
+  int x, y;
 
-         wasIn=0;
-       }
-      } else {
-       if (x>rx) goto EXT;
-       if (INSIDE(x,y)) {
-         SET(x,y);
-         /* case 3: Wasn't inside, am now: just found the start of a new run */
-         wasIn=1;
-           lx=x;
-       } else {
-         /* case 4: Wasn't inside, still isn't */
-       }
-      }
-      x++;
-    }
-  EXT: /* out of loop */
-    if (wasIn) {
-      /* hit an edge of the frame buffer while inside a run */
-      ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
-      if (bxmax < x) bxmax=x;
-    }
+  i_clear_error();
+  if (seedx < 0 || seedx >= im->xsize ||
+      seedy < 0 || seedy >= im->ysize) {
+    i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
+    return 0;
   }
-  
-  /*   printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction); 
-       printf("bounding box: [%d,%d] - [%d,%d]\n",bxmin,bymin,bxmax,bymax); */
 
-  llist_destroy(st);
-
-  *bxminp = bxmin;
-  *bxmaxp = bxmax;
-  *byminp = bymin;
-  *bymaxp = bymax;
+  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax);
 
-  return btm;
+  for(y=bymin;y<=bymax;y++)
+    for(x=bxmin;x<=bxmax;x++)
+      if (btm_test(btm,x,y)) 
+       i_ppix(im,x,y,dcol);
+  btm_destroy(btm);
+  return 1;
 }
 
+
+
 undef_int
 i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
   int bxmin, bxmax, bymin, bymax;
@@ -985,6 +937,7 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
   int x, y;
   int start;
 
+  i_clear_error();
   
   if (seedx < 0 || seedx >= im->xsize ||
       seedy < 0 || seedy >= im->ysize) {
@@ -992,7 +945,6 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
     return 0;
   }
 
-
   btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax);
 
   if (im->bits == i_8_bits && fill->fill_with_color) {
@@ -1001,7 +953,7 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
     if (fill->combine)
       work = mymalloc(sizeof(i_color) * (bxmax - bxmin));
 
-    for(y=bymin;y<=bymax;y++) {
+    for(y=bymin; y<=bymax; y++) {
       x = bxmin;
       while (x < bxmax) {
         while (x < bxmax && !btm_test(btm, x, y)) {
diff --git a/draw.h b/draw.h
index 3856733..5c1f894 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -21,4 +21,5 @@ static void i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar);
 void i_mmarray_info(i_mmarray *ar);
 void i_arc(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
 void i_box(i_img *im,int x0,int y0,int x1,int y1,i_color *val);
-void i_draw(i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+void i_line(i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
+
index a058b05..8a6af06 100644 (file)
@@ -5,7 +5,7 @@
 static symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
                             i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
                             i_img_info,i_img_setmask,i_img_getmask,
-                            i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
+                            i_box,i_line,i_arc,i_copyto,i_copyto_trans,i_rubthru};
 
 
 /*
diff --git a/image.h b/image.h
index a02f5fa..3d9143b 100644 (file)
--- a/image.h
+++ b/image.h
@@ -203,7 +203,7 @@ float i_gpix_pch(i_img *im,int x,int y,int ch);
 void i_box         (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
 void i_box_filled  (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
 void i_box_cfill(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill);
-void i_draw        (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+void i_line        (i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
 void i_line_aa     (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
 void i_arc         (i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
 void i_arc_cfill(i_img *im,int x,int y,float rad,float d1,float d2,i_fill_t *fill);
@@ -673,7 +673,7 @@ typedef struct {
   int (*i_gpix)(i_img *im,int x,int y,i_color *val);
   */
   void(*i_box)(i_img *im,int x1,int y1,int x2,int y2,i_color *val);
-  void(*i_draw)(i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+  void(*i_line)(i_img *im,int x1,int y1,int x2,int y2,i_color *val,int endp);
   void(*i_arc)(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
   void(*i_copyto)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty);
   void(*i_copyto_trans)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans);
index 40e5864..00b0a63 100644 (file)
@@ -12,7 +12,7 @@ Imager::Draw - Draw primitives to images
   $fill = Imager::Fill->new(hatch=>'stipple');
 
   $img->line(color=>$blue, x1=>10, x2=>100,
-                           y1=>20, y2=>50, aa=>1 );
+                           y1=>20, y2=>50, aa=>1, endp=>1 );
 
   $img->polyline(points=>[[$x0,$y0], [$x1,$y1], [$x2,$y2]],
                  color=>$blue);
@@ -78,10 +78,12 @@ L<Imager::Fill> for more information.
 =item line
 
   $img->line(color=>$green, x1=>10, x2=>100,
-                            y1=>20, y2=>50, aa=>1 );
+                            y1=>20, y2=>50, aa=>1, endp=>1 );
 
-That draws an antialiased line from (10,100) to (20,50).
-The I<antialias> parameter is still available for backwards compatibility.
+Draws a line from (x1,y1) to (x2,y2).  The endpoint (x2,y2) is drawn
+by default.  If endp of 0 is specified then the endpoint will not be
+drawn.  If C<aa> is set then the line will be drawn antialiased.  The
+I<antialias> parameter is still available for backwards compatibility.
 
 =item polyline
 
index 331a40b..090856b 100644 (file)
@@ -52,7 +52,7 @@ if (!(i_has_format("t1")) ) {
     or print "not ";
   print "ok 2\n";
 
-  i_draw($overlay,0,50,100,50,$bgcolor);
+  i_line($overlay,0,50,100,50,$bgcolor,1);
 
   @bbox=i_t1_bbox(0,50.0,'XMCLH',5);
   print "bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
index 5e68b3e..65b6941 100644 (file)
@@ -49,7 +49,7 @@ okx(@bbox == 6, "bounding box");
 print "#bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
 okx(i_tt_cp($ttraw,$overlay,5,50,1,50.0,'XMCLH',5,1,0), "cp output");
-i_draw($overlay,0,50,100,50,$bgcolor);
+i_line($overlay,0,50,100,50,$bgcolor,1);
 
 open(FH,">testout/t35ttfont.ppm") || die "cannot open testout/t35ttfont.ppm\n";
 binmode(FH);
@@ -72,7 +72,7 @@ okx(i_tt_text($ugly, $backgr,100, 80, $bgcolor, 14, 'g%g', 3, 1, 0),
     "draw g%g");
 okx(i_tt_text($ugly, $backgr,150, 80, $bgcolor, 14, 'delta', 5, 1, 0),
    "draw delta");
-i_draw($backgr,0,20,499,20,i_color_new(0,127,0,0));
+i_line($backgr,0,20,499,20,i_color_new(0,127,0,0),1);
 okx(i_tt_text($ttraw, $backgr, 20, 20, $bgcolor, 14, 'abcdefghijklmnopqrstuvwxyz{|}', 29, 1, 0), "alphabet");
 okx(i_tt_text($ttraw, $backgr, 20, 50, $bgcolor, 14, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 26, 1, 0), "ALPHABET");
 
index 6b04ed2..e78187d 100644 (file)
@@ -49,7 +49,7 @@ $ttraw or print Imager::_error_as_msg(),"\n";
 print "#bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
 Imager::Font::FreeType2::i_ft2_cp($ttraw,$overlay,5,50,1,50.0,50, 'XMCLH',1,1, 0, 0);
-i_draw($overlay,0,50,100,50,$bgcolor);
+i_line($overlay,0,50,100,50,$bgcolor,1);
 
 open(FH,">testout/t38ft2font.ppm") || die "cannot open testout/t38ft2font.ppm\n";
 binmode(FH);
@@ -68,7 +68,7 @@ $backgr=Imager::ImgRaw::new(500,300,3);
 Imager::Font::FreeType2::i_ft2_text($ttraw,$backgr,100,150,NC(255, 64, 64),200.0,50, 'MAW',1,1,0, 0);
 Imager::Font::FreeType2::i_ft2_settransform($ttraw, [0.9659, 0.2588, 0, -0.2588, 0.9659, 0 ]);
 Imager::Font::FreeType2::i_ft2_text($ttraw,$backgr,100,150,NC(0, 128, 0),200.0,50, 'MAW',0,1, 0, 0);
-i_draw($backgr, 0,150, 499, 150, NC(0, 0, 255));
+i_line($backgr, 0,150, 499, 150, NC(0, 0, 255),1);
 
 open(FH,">testout/t38ft2font2.ppm") || die "cannot open testout/t38ft2font.ppm\n";
 binmode(FH);