libart transform stroked path




Here's my first crack at a solution to the problem of stroking a vpath and
transforming the result.  It allows you to specify the line_width and vpath in "user
coodinates" which are defined by an affine transformation matrix.

It gets around the problem with orientation reversing transformations, and seems
to do the right thing.  (I've only done basic testing.)

-chris

----- code snippet -----
ArtSVP* art_svp_stroke_vpath_transform(ArtVpath *vpath,
                               const double affine[6],
                               ArtPathStrokeJoinType join,
                               ArtPathStrokeCapType cap,
                               double line_width /*in user coordinates*/,
                               double miter_limit,
                               double flatness)
/*
  Strokes a vpath and transforms it according to the transformation in affine

  decomposes affine transformation into proper and improper portions so that the
  improper portion can be done on the vpath before stroking.  I think this is what
  you would usually want to happen.  For example, the line_width can now be
  considered to be in "user coordinates". -chris lee

  Could be sped up by doing the flip transformation in a loop w/o calling
  general affine transform code

  N.B. proper affine transformation = orientation preserving transformation

*/
{
  ArtSVP *preTransSvp;
  ArtVpath* backVpath;
  ArtVpath* transVpath;
  ArtSVP* resultSvp;
  double properAffine[6]; /* P matrix (proper affine matrix) */
  ArtVpath* invVpath;
  static double flipAffine[] = {1.0, 0,0,-1.0,0,0}; /* R matrix */
  double det;

  det = affine[0]*affine[3] - affine[1]*affine[2]; /* find determinant, is it proper or improper*/

  if(det > 0) {
    preTransSvp = art_svp_vpath_stroke(vpath,
                                       join,
                                       cap,
                                       line_width,
                                       miter_limit,
                                       flatness);

    backVpath = art_vpath_from_svp(preTransSvp);
    transVpath = art_vpath_affine_transform(backVpath, affine);
    resultSvp = art_svp_from_vpath(transVpath);

    /*clean up this branch */
    art_free(transVpath);
    art_free(backVpath);
    art_svp_free(preTransSvp);

  } else {  /* det is not allowed to be zero, could check here */
    /*
      A = [ a c ]    R = [ 1  0]  and P is the proper affine transform
          [ b d ]        [ 0 -1]

        A = R P ; P = R^-1 ; P = R A
        
     */
    /* need to check if in right order */
    properAffine[0] = affine[0];
    properAffine[1] = -affine[1];
    properAffine[2] = affine[2];
    properAffine[3] = -affine[3];
    properAffine[4] = affine[4];
    properAffine[5] = affine[5];
    
    /* do this the slow way, won't meddle w/ vpath structure yet */
    invVpath = art_vpath_affine_transform(vpath, flipAffine);
    preTransSvp = art_svp_vpath_stroke(invVpath,
                                       join,
                                       cap,
                                       line_width,
                                       miter_limit,
                                       flatness);
    backVpath = art_vpath_from_svp(preTransSvp);
    transVpath = art_vpath_affine_transform(backVpath, properAffine);
    resultSvp = art_svp_from_vpath(transVpath);

    /* clean up this branch*/
    art_free(transVpath);
    art_free(backVpath);
    art_svp_free(preTransSvp);
    art_free(invVpath);
  }

  return(resultSvp);
}



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