# libart transform stroked path

• From: chrismail gnwy100 wuh wustl edu
• To: gnome-devel-list gnome org
• Subject: libart transform stroked path
• Date: Sat, 8 Apr 2000 12:35:22 -0500

```
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);
}

```