Added XrConcatMatrix, XrGetStatus. Properly clip color, alpha, and tolerance values from the user. Renamed _XrTransformPointWithoutTranslate to _XrTransformDistance. Added new XrIntStatus type for error codes that are not exported.

This commit is contained in:
Carl Worth 2002-10-23 11:58:38 +00:00
parent 88237e451e
commit f07852454c
18 changed files with 314 additions and 64 deletions

16
Xr.h
View file

@ -143,6 +143,12 @@ XrScale(XrState *xrs, double sx, double sy);
void
XrRotate(XrState *xrs, double angle);
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty);
/* Path creation */
void
XrNewPath(XrState *xrs);
@ -181,5 +187,15 @@ XrStroke(XrState *xrs);
void
XrFill(XrState *xrs);
/* Error status queries */
typedef enum _XrStatus {
XrStatusSuccess = 0,
XrStatusNoMemory
} XrStatus;
XrStatus
XrGetStatus(XrState *xrs);
#endif

View file

@ -143,6 +143,12 @@ XrScale(XrState *xrs, double sx, double sy);
void
XrRotate(XrState *xrs, double angle);
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty);
/* Path creation */
void
XrNewPath(XrState *xrs);
@ -181,5 +187,15 @@ XrStroke(XrState *xrs);
void
XrFill(XrState *xrs);
/* Error status queries */
typedef enum _XrStatus {
XrStatusSuccess = 0,
XrStatusNoMemory
} XrStatus;
XrStatus
XrGetStatus(XrState *xrs);
#endif

View file

@ -27,6 +27,11 @@
#define _XR_CURRENT_GSTATE(xrs) (xrs->stack)
#define XR_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static void
_XrClipValue(double *value, double min, double max);
XrState *
XrCreate(Display *dpy)
{
@ -85,18 +90,26 @@ XrSetOperator(XrState *xrs, XrOperator operator)
void
XrSetRGBColor(XrState *xrs, double red, double green, double blue)
{
_XrClipValue(&red, 0.0, 1.0);
_XrClipValue(&green, 0.0, 1.0);
_XrClipValue(&blue, 0.0, 1.0);
_XrGStateSetRGBColor(_XR_CURRENT_GSTATE(xrs), red, green, blue);
}
void
XrSetTolerance(XrState *xrs, double tolerance)
{
_XrClipValue(&tolerance, XR_TOLERANCE_MINIMUM, tolerance);
_XrGStateSetTolerance(_XR_CURRENT_GSTATE(xrs), tolerance);
}
void
XrSetAlpha(XrState *xrs, double alpha)
{
_XrClipValue(&alpha, 0.0, 1.0);
_XrGStateSetAlpha(_XR_CURRENT_GSTATE(xrs), alpha);
}
@ -151,6 +164,15 @@ XrRotate(XrState *xrs, double angle)
_XrGStateRotate(_XR_CURRENT_GSTATE(xrs), angle);
}
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty)
{
_XrGStateConcatMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty);
}
void
XrNewPath(XrState *xrs)
{
@ -269,3 +291,18 @@ XrFill(XrState *xrs)
xrs->status = status;
}
}
XrStatus
XrGetStatus(XrState *xrs)
{
return xrs->status;
}
static void
_XrClipValue(double *value, double min, double max)
{
if (*value < min)
*value = min;
else if (*value > max)
*value = max;
}

View file

@ -60,7 +60,7 @@ _XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrSpline spline;
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrStatusDegenerate)
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
_XrSplineDecompose(&spline, gstate->tolerance);

View file

@ -76,6 +76,8 @@ _XrGStateInit(XrGState *gstate, Display *dpy)
_XrPathInit(&gstate->path);
_XrPenInitEmpty(&gstate->pen_regular);
gstate->next = NULL;
}
XrStatus
@ -192,8 +194,6 @@ void
_XrGStateSetTolerance(XrGState *gstate, double tolerance)
{
gstate->tolerance = tolerance;
if (gstate->tolerance < XR_GSTATE_TOLERANCE_MINIMUM)
gstate->tolerance = XR_GSTATE_TOLERANCE_MINIMUM;
}
void
@ -281,6 +281,21 @@ _XrGStateRotate(XrGState *gstate, double angle)
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
}
void
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty)
{
XrTransform tmp;
_XrTransformInitMatrix(&tmp, a, b, c, d, tx, ty);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformComputeInverse(&tmp);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
}
void
_XrGStateNewPath(XrGState *gstate)
{
@ -306,7 +321,7 @@ _XrGStateAddPathOp(XrGState *gstate, XrPathOp op, XPointDouble *pt, int num_pts)
case XrPathOpRelLineTo:
case XrPathOpRelCurveTo:
for (i=0; i < num_pts; i++) {
_XrTransformPointWithoutTranslate(&gstate->ctm, &pt[i]);
_XrTransformDistance(&gstate->ctm, &pt[i]);
}
break;
case XrPathOpClosePath:
@ -435,4 +450,3 @@ _XrGStateFill(XrGState *gstate)
return XrStatusSuccess;
}

View file

@ -42,11 +42,12 @@
#define __attribute__(x)
#endif
typedef enum _XrStatus {
XrStatusSuccess = 0,
XrStatusNoMemory,
XrStatusDegenerate
} XrStatus;
/* Sure wish C had a real enum type so that this would be distinct
from XrStatus. Oh well, without that, I'll use this bogus 1000
offset */
typedef enum _XrIntStatus {
XrIntStatusDegenerate = 1000
} XrIntStatus;
typedef enum _XrPathOp {
XrPathOpMoveTo = 0,
@ -201,7 +202,6 @@ typedef struct _XrTraps {
#define XR_GSTATE_OPERATOR_DEFAULT XrOperatorOver
#define XR_GSTATE_TOLERANCE_DEFAULT 0.1
#define XR_GSTATE_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
#define XR_GSTATE_WINDING_DEFAULT 1
#define XR_GSTATE_LINE_WIDTH_DEFAULT 2.0
#define XR_GSTATE_LINE_CAP_DEFAULT XrLineCapButt
@ -362,6 +362,12 @@ _XrGStateScale(XrGState *gstate, double sx, double sy);
void
_XrGStateRotate(XrGState *gstate, double angle);
void
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty);
void
_XrGStateNewPath(XrGState *gstate);
@ -467,7 +473,7 @@ XrStatus
_XrPolygonClose(XrPolygon *polygon);
/* xrspline.c */
XrStatus
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
@ -552,14 +558,14 @@ void
_XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *new);
void
_XrTransformPointScaleOnly(XrTransform *transform, XPointDouble *pt);
void
_XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
_XrTransformDistance(XrTransform *transform, XPointDouble *pt);
void
_XrTransformPoint(XrTransform *transform, XPointDouble *pt);
void
_XrTransformComputeInverse(XrTransform *transform);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);

View file

@ -90,7 +90,7 @@ _XrPenInit(XrPen *pen, double radius, XrGState *gstate)
v->theta = 2 * M_PI * i / (double) pen->num_vertices;
pt.x = radius * cos(v->theta);
pt.y = radius * sin(v->theta);
_XrTransformPointWithoutTranslate(&gstate->ctm, &pt);
_XrTransformDistance(&gstate->ctm, &pt);
v->pt.x = XDoubleToFixed(pt.x);
v->pt.y = XDoubleToFixed(pt.y);
v->flag = XrPenVertexFlagNone;

View file

@ -45,7 +45,7 @@ _XrSplineDecomposeInto(XrSpline *spline, double tolerance_squared, XrSpline *res
#define XR_SPLINE_GROWTH_INC 100
XrStatus
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
{
spline->a = *a;
@ -60,7 +60,7 @@ _XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c
} else if (a->x != d->x || a->y != d->y) {
_ComputeSlope(&spline->a, &spline->d, &spline->initial_slope);
} else {
return XrStatusDegenerate;
return XrIntStatusDegenerate;
}
if (c->x != d->x || c->y != d->y) {

View file

@ -150,14 +150,14 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
x1 = XFixedToDouble(inpt->x);
y1 = XFixedToDouble(inpt->y);
v1 = in->vector;
_XrTransformPointWithoutTranslate(&gstate->ctm, &v1);
_XrTransformDistance(&gstate->ctm, &v1);
dx1 = v1.x;
dy1 = v1.y;
x2 = XFixedToDouble(outpt->x);
y2 = XFixedToDouble(outpt->y);
v2 = out->vector;
_XrTransformPointWithoutTranslate(&gstate->ctm, &v2);
_XrTransformDistance(&gstate->ctm, &v2);
dx2 = v2.x;
dy2 = v2.y;
@ -213,7 +213,7 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XPointFixed occw, ocw;
vector.x *= gstate->line_width / 2.0;
vector.y *= gstate->line_width / 2.0;
_XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
_XrTransformDistance(&gstate->ctm, &vector);
fvector.x = XDoubleToFixed(vector.x);
fvector.y = XDoubleToFixed(vector.y);
occw.x = f->ccw.x + fvector.x;
@ -249,7 +249,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac
vector.x = XFixedToDouble(slope->dx);
vector.y = XFixedToDouble(slope->dy);
_XrTransformPointWithoutTranslate(&gstate->ctm_inverse, &vector);
_XrTransformDistance(&gstate->ctm_inverse, &vector);
mag = sqrt(vector.x * vector.x + vector.y * vector.y);
if (mag == 0) {
@ -266,7 +266,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac
vector.x = - vector.y * (gstate->line_width / 2.0);
vector.y = tmp * (gstate->line_width / 2.0);
_XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
_XrTransformDistance(&gstate->ctm, &vector);
offset_ccw.x = XDoubleToFixed(vector.x);
offset_ccw.y = XDoubleToFixed(vector.y);
@ -370,7 +370,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2)
vector.x = XFixedToDouble(p2->x - p1->x);
vector.y = XFixedToDouble(p2->y - p1->y);
_XrTransformPointWithoutTranslate(&gstate->ctm_inverse, &vector);
_XrTransformDistance(&gstate->ctm_inverse, &vector);
mag = sqrt(vector.x * vector.x + vector.y * vector.y);
remain = mag;
@ -382,7 +382,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2)
remain -= tmp;
d2.x = vector.x * (mag - remain)/mag;
d2.y = vector.y * (mag - remain)/mag;
_XrTransformPointWithoutTranslate (&gstate->ctm, &d2);
_XrTransformDistance (&gstate->ctm, &d2);
fd2.x = XDoubleToFixed (d2.x);
fd2.y = XDoubleToFixed (d2.y);
fd2.x += p1->x;
@ -472,7 +472,7 @@ _XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed
XrPenFlaggedPoint extra_points[4];
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrStatusDegenerate)
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
status = _XrPenInitCopy(&pen, &gstate->pen_regular);

View file

@ -36,6 +36,12 @@ static XrTransform XR_TRANSFORM_DEFAULT = {
}
};
static void
_XrTransformScalarMultiply(XrTransform *transform, double scalar);
static void
_XrTransformComputeAdjoint(XrTransform *transform);
void
_XrTransformInit(XrTransform *transform)
{
@ -130,7 +136,7 @@ _XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *
}
void
_XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt)
_XrTransformDistance(XrTransform *transform, XPointDouble *pt)
{
double new_x, new_y;
@ -146,12 +152,58 @@ _XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt)
void
_XrTransformPoint(XrTransform *transform, XPointDouble *pt)
{
_XrTransformPointWithoutTranslate(transform, pt);
_XrTransformDistance(transform, pt);
pt->x += transform->m[2][0];
pt->y += transform->m[2][1];
}
static void
_XrTransformScalarMultiply(XrTransform *transform, double scalar)
{
int row, col;
for (row = 0; row < 3; row++)
for (col = 0; col < 2; col++)
transform->m[row][col] *= scalar;
}
/* This function isn't a correct adjoint in that the implicit 1 in the
homogeneous result should actually be ad-bc instead. But, since this
adjoint is only used in the computation of the inverse, which
divides by det(A)=ad-bc anyway, everything works out in the end. */
static void
_XrTransformComputeAdjoint(XrTransform *transform)
{
/* adj(A) = transpose(C:cofactor(A,i,j)) */
double a, b, c, d, tx, ty;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
tx = transform->m[2][0]; ty = transform->m[2][1];
_XrTransformInitMatrix(transform,
d, -b,
-c, a,
c*ty - d*tx, b*tx - a*ty);
}
void
_XrTransformComputeInverse(XrTransform *transform)
{
/* inv(A) = 1/det(A) * adj(A) */
double a, b, c, d, det;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
det = a*d - b*c;
_XrTransformComputeAdjoint(transform);
_XrTransformScalarMultiply(transform, 1 / det);
}
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{
@ -159,12 +211,13 @@ _XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2
det(M - lI) = 0
which for our 2x2 matrix:
The zeros in our homogeneous 3x3 matrix make this equation equal
to that formed by the sub-matrix:
M = a b
c d
gives:
by which:
l^2 - (a+d)l + (ad - bc) = 0
@ -182,4 +235,3 @@ _XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2
*lambda1 = (a + d + rad) / 2.0;
*lambda2 = (a + d - rad) / 2.0;
}

37
xr.c
View file

@ -27,6 +27,11 @@
#define _XR_CURRENT_GSTATE(xrs) (xrs->stack)
#define XR_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static void
_XrClipValue(double *value, double min, double max);
XrState *
XrCreate(Display *dpy)
{
@ -85,18 +90,26 @@ XrSetOperator(XrState *xrs, XrOperator operator)
void
XrSetRGBColor(XrState *xrs, double red, double green, double blue)
{
_XrClipValue(&red, 0.0, 1.0);
_XrClipValue(&green, 0.0, 1.0);
_XrClipValue(&blue, 0.0, 1.0);
_XrGStateSetRGBColor(_XR_CURRENT_GSTATE(xrs), red, green, blue);
}
void
XrSetTolerance(XrState *xrs, double tolerance)
{
_XrClipValue(&tolerance, XR_TOLERANCE_MINIMUM, tolerance);
_XrGStateSetTolerance(_XR_CURRENT_GSTATE(xrs), tolerance);
}
void
XrSetAlpha(XrState *xrs, double alpha)
{
_XrClipValue(&alpha, 0.0, 1.0);
_XrGStateSetAlpha(_XR_CURRENT_GSTATE(xrs), alpha);
}
@ -151,6 +164,15 @@ XrRotate(XrState *xrs, double angle)
_XrGStateRotate(_XR_CURRENT_GSTATE(xrs), angle);
}
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty)
{
_XrGStateConcatMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty);
}
void
XrNewPath(XrState *xrs)
{
@ -269,3 +291,18 @@ XrFill(XrState *xrs)
xrs->status = status;
}
}
XrStatus
XrGetStatus(XrState *xrs)
{
return xrs->status;
}
static void
_XrClipValue(double *value, double min, double max)
{
if (*value < min)
*value = min;
else if (*value > max)
*value = max;
}

View file

@ -60,7 +60,7 @@ _XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrSpline spline;
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrStatusDegenerate)
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
_XrSplineDecompose(&spline, gstate->tolerance);

View file

@ -76,6 +76,8 @@ _XrGStateInit(XrGState *gstate, Display *dpy)
_XrPathInit(&gstate->path);
_XrPenInitEmpty(&gstate->pen_regular);
gstate->next = NULL;
}
XrStatus
@ -192,8 +194,6 @@ void
_XrGStateSetTolerance(XrGState *gstate, double tolerance)
{
gstate->tolerance = tolerance;
if (gstate->tolerance < XR_GSTATE_TOLERANCE_MINIMUM)
gstate->tolerance = XR_GSTATE_TOLERANCE_MINIMUM;
}
void
@ -281,6 +281,21 @@ _XrGStateRotate(XrGState *gstate, double angle)
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
}
void
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty)
{
XrTransform tmp;
_XrTransformInitMatrix(&tmp, a, b, c, d, tx, ty);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformComputeInverse(&tmp);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
}
void
_XrGStateNewPath(XrGState *gstate)
{
@ -306,7 +321,7 @@ _XrGStateAddPathOp(XrGState *gstate, XrPathOp op, XPointDouble *pt, int num_pts)
case XrPathOpRelLineTo:
case XrPathOpRelCurveTo:
for (i=0; i < num_pts; i++) {
_XrTransformPointWithoutTranslate(&gstate->ctm, &pt[i]);
_XrTransformDistance(&gstate->ctm, &pt[i]);
}
break;
case XrPathOpClosePath:
@ -435,4 +450,3 @@ _XrGStateFill(XrGState *gstate)
return XrStatusSuccess;
}

28
xrint.h
View file

@ -42,11 +42,12 @@
#define __attribute__(x)
#endif
typedef enum _XrStatus {
XrStatusSuccess = 0,
XrStatusNoMemory,
XrStatusDegenerate
} XrStatus;
/* Sure wish C had a real enum type so that this would be distinct
from XrStatus. Oh well, without that, I'll use this bogus 1000
offset */
typedef enum _XrIntStatus {
XrIntStatusDegenerate = 1000
} XrIntStatus;
typedef enum _XrPathOp {
XrPathOpMoveTo = 0,
@ -201,7 +202,6 @@ typedef struct _XrTraps {
#define XR_GSTATE_OPERATOR_DEFAULT XrOperatorOver
#define XR_GSTATE_TOLERANCE_DEFAULT 0.1
#define XR_GSTATE_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
#define XR_GSTATE_WINDING_DEFAULT 1
#define XR_GSTATE_LINE_WIDTH_DEFAULT 2.0
#define XR_GSTATE_LINE_CAP_DEFAULT XrLineCapButt
@ -362,6 +362,12 @@ _XrGStateScale(XrGState *gstate, double sx, double sy);
void
_XrGStateRotate(XrGState *gstate, double angle);
void
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty);
void
_XrGStateNewPath(XrGState *gstate);
@ -467,7 +473,7 @@ XrStatus
_XrPolygonClose(XrPolygon *polygon);
/* xrspline.c */
XrStatus
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
@ -552,14 +558,14 @@ void
_XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *new);
void
_XrTransformPointScaleOnly(XrTransform *transform, XPointDouble *pt);
void
_XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
_XrTransformDistance(XrTransform *transform, XPointDouble *pt);
void
_XrTransformPoint(XrTransform *transform, XPointDouble *pt);
void
_XrTransformComputeInverse(XrTransform *transform);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);

View file

@ -90,7 +90,7 @@ _XrPenInit(XrPen *pen, double radius, XrGState *gstate)
v->theta = 2 * M_PI * i / (double) pen->num_vertices;
pt.x = radius * cos(v->theta);
pt.y = radius * sin(v->theta);
_XrTransformPointWithoutTranslate(&gstate->ctm, &pt);
_XrTransformDistance(&gstate->ctm, &pt);
v->pt.x = XDoubleToFixed(pt.x);
v->pt.y = XDoubleToFixed(pt.y);
v->flag = XrPenVertexFlagNone;

View file

@ -45,7 +45,7 @@ _XrSplineDecomposeInto(XrSpline *spline, double tolerance_squared, XrSpline *res
#define XR_SPLINE_GROWTH_INC 100
XrStatus
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
{
spline->a = *a;
@ -60,7 +60,7 @@ _XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c
} else if (a->x != d->x || a->y != d->y) {
_ComputeSlope(&spline->a, &spline->d, &spline->initial_slope);
} else {
return XrStatusDegenerate;
return XrIntStatusDegenerate;
}
if (c->x != d->x || c->y != d->y) {

View file

@ -150,14 +150,14 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
x1 = XFixedToDouble(inpt->x);
y1 = XFixedToDouble(inpt->y);
v1 = in->vector;
_XrTransformPointWithoutTranslate(&gstate->ctm, &v1);
_XrTransformDistance(&gstate->ctm, &v1);
dx1 = v1.x;
dy1 = v1.y;
x2 = XFixedToDouble(outpt->x);
y2 = XFixedToDouble(outpt->y);
v2 = out->vector;
_XrTransformPointWithoutTranslate(&gstate->ctm, &v2);
_XrTransformDistance(&gstate->ctm, &v2);
dx2 = v2.x;
dy2 = v2.y;
@ -213,7 +213,7 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XPointFixed occw, ocw;
vector.x *= gstate->line_width / 2.0;
vector.y *= gstate->line_width / 2.0;
_XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
_XrTransformDistance(&gstate->ctm, &vector);
fvector.x = XDoubleToFixed(vector.x);
fvector.y = XDoubleToFixed(vector.y);
occw.x = f->ccw.x + fvector.x;
@ -249,7 +249,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac
vector.x = XFixedToDouble(slope->dx);
vector.y = XFixedToDouble(slope->dy);
_XrTransformPointWithoutTranslate(&gstate->ctm_inverse, &vector);
_XrTransformDistance(&gstate->ctm_inverse, &vector);
mag = sqrt(vector.x * vector.x + vector.y * vector.y);
if (mag == 0) {
@ -266,7 +266,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac
vector.x = - vector.y * (gstate->line_width / 2.0);
vector.y = tmp * (gstate->line_width / 2.0);
_XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
_XrTransformDistance(&gstate->ctm, &vector);
offset_ccw.x = XDoubleToFixed(vector.x);
offset_ccw.y = XDoubleToFixed(vector.y);
@ -370,7 +370,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2)
vector.x = XFixedToDouble(p2->x - p1->x);
vector.y = XFixedToDouble(p2->y - p1->y);
_XrTransformPointWithoutTranslate(&gstate->ctm_inverse, &vector);
_XrTransformDistance(&gstate->ctm_inverse, &vector);
mag = sqrt(vector.x * vector.x + vector.y * vector.y);
remain = mag;
@ -382,7 +382,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2)
remain -= tmp;
d2.x = vector.x * (mag - remain)/mag;
d2.y = vector.y * (mag - remain)/mag;
_XrTransformPointWithoutTranslate (&gstate->ctm, &d2);
_XrTransformDistance (&gstate->ctm, &d2);
fd2.x = XDoubleToFixed (d2.x);
fd2.y = XDoubleToFixed (d2.y);
fd2.x += p1->x;
@ -472,7 +472,7 @@ _XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed
XrPenFlaggedPoint extra_points[4];
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrStatusDegenerate)
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
status = _XrPenInitCopy(&pen, &gstate->pen_regular);

View file

@ -36,6 +36,12 @@ static XrTransform XR_TRANSFORM_DEFAULT = {
}
};
static void
_XrTransformScalarMultiply(XrTransform *transform, double scalar);
static void
_XrTransformComputeAdjoint(XrTransform *transform);
void
_XrTransformInit(XrTransform *transform)
{
@ -130,7 +136,7 @@ _XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *
}
void
_XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt)
_XrTransformDistance(XrTransform *transform, XPointDouble *pt)
{
double new_x, new_y;
@ -146,12 +152,58 @@ _XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt)
void
_XrTransformPoint(XrTransform *transform, XPointDouble *pt)
{
_XrTransformPointWithoutTranslate(transform, pt);
_XrTransformDistance(transform, pt);
pt->x += transform->m[2][0];
pt->y += transform->m[2][1];
}
static void
_XrTransformScalarMultiply(XrTransform *transform, double scalar)
{
int row, col;
for (row = 0; row < 3; row++)
for (col = 0; col < 2; col++)
transform->m[row][col] *= scalar;
}
/* This function isn't a correct adjoint in that the implicit 1 in the
homogeneous result should actually be ad-bc instead. But, since this
adjoint is only used in the computation of the inverse, which
divides by det(A)=ad-bc anyway, everything works out in the end. */
static void
_XrTransformComputeAdjoint(XrTransform *transform)
{
/* adj(A) = transpose(C:cofactor(A,i,j)) */
double a, b, c, d, tx, ty;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
tx = transform->m[2][0]; ty = transform->m[2][1];
_XrTransformInitMatrix(transform,
d, -b,
-c, a,
c*ty - d*tx, b*tx - a*ty);
}
void
_XrTransformComputeInverse(XrTransform *transform)
{
/* inv(A) = 1/det(A) * adj(A) */
double a, b, c, d, det;
a = transform->m[0][0]; b = transform->m[0][1];
c = transform->m[1][0]; d = transform->m[1][1];
det = a*d - b*c;
_XrTransformComputeAdjoint(transform);
_XrTransformScalarMultiply(transform, 1 / det);
}
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
{
@ -159,12 +211,13 @@ _XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2
det(M - lI) = 0
which for our 2x2 matrix:
The zeros in our homogeneous 3x3 matrix make this equation equal
to that formed by the sub-matrix:
M = a b
c d
gives:
by which:
l^2 - (a+d)l + (ad - bc) = 0
@ -182,4 +235,3 @@ _XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2
*lambda1 = (a + d + rad) / 2.0;
*lambda2 = (a + d - rad) / 2.0;
}