transforming stroked paths (was libart transforming svp's)




I've got an isolated example of the problem I'm having transforming stroked
paths.  I'm following the previous advice of stroking a vpath to an svp, then
using vpath_from_svp to return it to vpath land and transforming it there.

When I do this and invert the y-axis in my transform, the output looks very
ugly: no antialiasing, the line is much thicker.  My guess is that it has
something to do with the orientations of the paths getting inverted and
therefore the wrong regions are getting filled.  I would hypothesize that
orientatio preserving affine transformations would be fine.

Has anyone worked around this problem before?  Am I doing something wrong?  Or,
shoudl I go ahead and invest the effort into writing an
svp_transform_stroke_vpath(..) or something which does the transform together
with the stroke operation so that creating the SVP can be the last step before
rendering.

Thanks for all the help I've gotten so far.

-chris

p.s. I will include an demonstration code (hopefully, this time with fewer
     memory leaks :).

--- begin code snippet ---
/*
  Draws two stroked paths. The top one is a standard untransformed path.  The 
  second is a stroked path that is transformed via the methods suggested on the
  gnome-devel-list.

  Contrast running the code with "version A" of the negMatrix or commenting that
  out and using "version B" of the transformation matrix instead.  This dumps the
  output to an image format that electric eyes can read and that Raph uses in
  testart.c.   On my machine, version B looks really ugly. -cwl
*/

void testDraw5(void)
{
  void srand48(long int);
  /* long int mrand48(void);*/
  art_u8* rawbuf; /* holds my own pixbuf */
  unsigned int yvals[NUMY];
  unsigned ii, w,h,nchan;
  double dx;
  double negMatrix[] = { 1.0, 0.0, 0.0, 1.0, 25.0,150.0}; /* version A looks fine*/
  /* double negMatrix[] = { 1.0, 0.0, 0.0, -1.0, 25.0,250.0};*/ /* version B looks terrible*/
  ArtVpath vpath[NUMY+2];
  ArtVpath negVpath[NUMY+2];
  ArtSVP* svp;
  ArtSVP* neg_stroked_svp;
  ArtVpath* strokedVpath;
  ArtVpath* transNegVpath;

  srand48(234888); /* set seed */

  for (ii=0; ii<NUMY; ++ii) {
    yvals[ii] = (drand48() * 99 );
    /* printf("yval=%u\n",  yvals[ii]);*/
  }

  /* create a squiggly path */
  vpath[0].code = ART_MOVETO_OPEN;
  negVpath[0].code = ART_MOVETO_OPEN;

  vpath[0].x = 0 +25;
  negVpath[0].x = 0;

  vpath[0].y = 0;
  negVpath[0].y = 0;

  for(ii=1, dx=4.0; ii<NUMY; ++ii) {
    vpath[ii].code = ART_LINETO;
    vpath[ii].x = 25+ dx * ii;
    vpath[ii].y = yvals[ii];

    negVpath[ii].code = ART_LINETO;
    negVpath[ii].x = dx * ii;
    negVpath[ii].y = yvals[ii];
    
  }
  vpath[NUMY].code = ART_END;
  negVpath[NUMY].code = ART_END;
  
  /* create buffer to draw into */
  h = 256;
  w = 256;
  nchan = 3;
  rawbuf = calloc(w*h*nchan,1);

  /* now draw the first path */

  svp = art_svp_vpath_stroke(vpath,
                             ART_PATH_STROKE_JOIN_MITER /*join*/,
                             ART_PATH_STROKE_CAP_BUTT /*cap*/,
                             2.0,
                             4, /*miter_limit */
                             0.25/*flatness */);
  art_rgb_svp_alpha(svp,
                    0,0,
                    w, h,
                    0xFFFFFFFF,
                    rawbuf,
                    w*nchan/*rowstride*/,
                    NULL);

  art_svp_free(svp);

  /* now draw transformed version of path */
  neg_stroked_svp = art_svp_vpath_stroke(negVpath,
                             ART_PATH_STROKE_JOIN_MITER /*join*/,
                             ART_PATH_STROKE_CAP_BUTT /*cap*/,
                             2.0,
                             4, /*miter_limit */
                             0.25/*flatness */);

  strokedVpath = art_vpath_from_svp(neg_stroked_svp);

  transNegVpath = art_vpath_affine_transform(strokedVpath, negMatrix);

  svp = art_svp_from_vpath(transNegVpath);
  art_rgb_svp_alpha(svp,
                    0,0,
                    w, h,
                    0xFFFFFFFF,
                    rawbuf,
                    w*nchan/*rowstride*/,
                    NULL);
  art_svp_free(svp);
  art_free(transNegVpath);
  art_free(strokedVpath);
  art_svp_free(neg_stroked_svp);


  dumpRawBufferRGB(rawbuf, w,h,nchan,"testDraw5.img");
  free(rawbuf);
}

void dumpRawBufferRGB(art_u8* buf, int w, int h, int numChan, char*filename)
{
  FILE* fp = fopen(filename, "wb");  
  fprintf (fp, "P6\n%d %d\n255\n", w, h );  /* unknown format (but it works for ee) */
  fwrite(buf, 1, w*h*numChan,fp);
  fclose(fp);
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]