mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-24 14:50:10 +01:00
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:
parent
88237e451e
commit
f07852454c
18 changed files with 314 additions and 64 deletions
16
Xr.h
16
Xr.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
16
src/Xr.h
16
src/Xr.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
37
src/xr.c
37
src/xr.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
src/xrint.h
28
src/xrint.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
37
xr.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
22
xrgstate.c
22
xrgstate.c
|
|
@ -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
28
xrint.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
2
xrpen.c
2
xrpen.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
16
xrstroker.c
16
xrstroker.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue