Add dashes, collapse stroke_style/fill_style into gstate

This commit is contained in:
Keith Packard 2002-08-15 17:19:28 +00:00
parent ba6c497130
commit 20f631ce22
10 changed files with 172 additions and 68 deletions

3
Xr.h
View file

@ -127,6 +127,9 @@ typedef enum _XrLineJoin { XrLineJoinMiter, XrLineJoinRound, XrLineJoinBevel } X
void
XrSetLineJoin(XrState *xrs, XrLineJoin line_join);
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset);
void
XrSetMiterLimit(XrState *xrs, double limit);

View file

@ -127,6 +127,9 @@ typedef enum _XrLineJoin { XrLineJoinMiter, XrLineJoinRound, XrLineJoinBevel } X
void
XrSetLineJoin(XrState *xrs, XrLineJoin line_join);
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset);
void
XrSetMiterLimit(XrState *xrs, double limit);

View file

@ -107,6 +107,15 @@ XrSetLineJoin(XrState *xrs, XrLineJoin line_join)
XrGStateSetLineJoin(CURRENT_GSTATE(xrs), line_join);
}
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset)
{
XrError err;
err = XrGStateSetDash(CURRENT_GSTATE(xrs), dashes, ndash, offset);
if (err)
xrs->error = err;
}
void
XrSetMiterLimit(XrState *xrs, double limit)
{

View file

@ -49,12 +49,15 @@ XrGStateInit(XrGState *gstate, Display *dpy)
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
gstate->fill_style.winding = XR_GSTATE_WINDING_DEFAULT;
gstate->winding = XR_GSTATE_WINDING_DEFAULT;
gstate->stroke_style.line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
gstate->stroke_style.line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
gstate->stroke_style.line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
gstate->stroke_style.miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
gstate->line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
gstate->line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
gstate->miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
gstate->dashes = 0;
gstate->ndashes = 0;
gstate->dash_offset = 0.0;
gstate->solidFormat = XcFindStandardFormat(dpy, PictStandardARGB32);
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
@ -74,12 +77,27 @@ XrGStateInit(XrGState *gstate, Display *dpy)
XrError
XrGStateInitCopy(XrGState *gstate, XrGState *other)
{
XrError err;
*gstate = *other;
if (other->dashes) {
gstate->dashes = malloc (other->ndashes * sizeof (double));
if (gstate->dashes == NULL)
return XrErrorNoMemory;
memcpy (gstate->dashes, other->dashes, other->ndashes * sizeof (double));
}
XrSurfaceInit(&gstate->src, gstate->dpy);
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
return XrPathInitCopy(&gstate->path, &other->path);
err = XrPathInitCopy(&gstate->path, &other->path);
if (err) {
if (gstate->dashes) {
free (gstate->dashes);
gstate->dashes = 0;
}
}
return err;
}
void
@ -92,6 +110,8 @@ XrGStateDeinit(XrGState *gstate)
XrTransformDeinit(&gstate->ctm_inverse);
XrPathDeinit(&gstate->path);
if (gstate->dashes)
free (gstate->dashes);
}
void
@ -160,25 +180,45 @@ XrGStateSetAlpha(XrGState *gstate, double alpha)
void
XrGStateSetLineWidth(XrGState *gstate, double width)
{
gstate->stroke_style.line_width = width;
gstate->line_width = width;
}
void
XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
{
gstate->stroke_style.line_cap = line_cap;
gstate->line_cap = line_cap;
}
void
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
{
gstate->stroke_style.line_join = line_join;
gstate->line_join = line_join;
}
XrError
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset)
{
double *ndashes;
if (gstate->dashes) {
free (gstate->dashes);
}
gstate->dashes = malloc (ndash * sizeof (double));
if (!gstate->dashes) {
gstate->ndashes = 0;
return XrErrorNoMemory;
}
gstate->ndashes = ndash;
memcpy (gstate->dashes, dashes, ndash * sizeof (double));
gstate->dash_offset = offset;
return XrErrorSuccess;
}
void
XrGStateSetMiterLimit(XrGState *gstate, double limit)
{
gstate->stroke_style.miter_limit = limit;
gstate->miter_limit = limit;
}
void
@ -332,7 +372,7 @@ XrGStateFill(XrGState *gstate)
XrTrapsInit(&traps);
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->fill_style.winding);
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding);
if (err) {
XrTrapsDeinit(&traps);
return err;

View file

@ -154,22 +154,20 @@ typedef struct _XrTraps {
#define XR_GSTATE_LINE_JOIN_DEFAULT XrLineJoinMiter
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
typedef struct _XrStrokeStyle {
double line_width;
XrLineCap line_cap;
XrLineJoin line_join;
double miter_limit;
} XrStrokeStyle;
typedef struct _XrFillStyle {
int winding;
} XrFillStyle;
typedef struct _XrGState {
Display *dpy;
XrStrokeStyle stroke_style;
XrFillStyle fill_style;
/* stroke style */
double line_width;
XrLineCap line_cap;
XrLineJoin line_join;
double *dashes;
int ndashes;
double dash_offset;
double miter_limit;
/* fill style */
int winding;
XrOperator operator;
@ -277,6 +275,9 @@ XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap);
void
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join);
XrError
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset);
void
XrGStateSetMiterLimit(XrGState *gstate, double limit);

View file

@ -89,12 +89,12 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
outpt = &out->ccw;
}
XrPolygonInit (&polygon);
switch (gstate->stroke_style.line_join) {
switch (gstate->line_join) {
case XrLineJoinRound: {
}
case XrLineJoinMiter: {
XDouble c = in->vector.x * out->vector.x + in->vector.y * out->vector.y;
double ml = gstate->stroke_style.miter_limit;
double ml = gstate->miter_limit;
if (2 <= ml * ml * (1 - c))
{
XDouble x1, y1, x2, y2;
@ -155,11 +155,11 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XrGState *gstate = stroker->gstate;
XrPolygon polygon;
if (gstate->stroke_style.line_cap == XrLineCapButt)
if (gstate->line_cap == XrLineCapButt)
return XrErrorSuccess;
XrPolygonInit (&polygon);
switch (gstate->stroke_style.line_cap) {
switch (gstate->line_cap) {
case XrLineCapRound: {
break;
}
@ -167,8 +167,8 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XPointDouble vector = f->vector;
XPointFixed fvector;
XPointFixed outer, occw, ocw;
vector.x *= gstate->stroke_style.line_width / 2.0;
vector.y *= gstate->stroke_style.line_width / 2.0;
vector.x *= gstate->line_width / 2.0;
vector.y *= gstate->line_width / 2.0;
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
fvector.x = XDoubleToFixed(vector.x);
fvector.y = XDoubleToFixed(vector.y);
@ -200,14 +200,13 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
XrError err;
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
XrStrokeStyle *style = &gstate->stroke_style;
XrTraps *traps = stroker->traps;
double mag, tmp;
XPointDouble vector;
XPointDouble user_vector;
XPointFixed offset_ccw, offset_cw;
XPointFixed quad[4];
XrStrokeFace face;
XrStrokeFace face;
vector.x = XFixedToDouble(p2->x - p1->x);
vector.y = XFixedToDouble(p2->y - p1->y);
@ -225,8 +224,8 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
user_vector = vector;
tmp = vector.x;
vector.x = - vector.y * (style->line_width / 2.0);
vector.y = tmp * (style->line_width / 2.0);
vector.x = - vector.y * (gstate->line_width / 2.0);
vector.y = tmp * (gstate->line_width / 2.0);
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);

9
xr.c
View file

@ -107,6 +107,15 @@ XrSetLineJoin(XrState *xrs, XrLineJoin line_join)
XrGStateSetLineJoin(CURRENT_GSTATE(xrs), line_join);
}
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset)
{
XrError err;
err = XrGStateSetDash(CURRENT_GSTATE(xrs), dashes, ndash, offset);
if (err)
xrs->error = err;
}
void
XrSetMiterLimit(XrState *xrs, double limit)
{

View file

@ -49,12 +49,15 @@ XrGStateInit(XrGState *gstate, Display *dpy)
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
gstate->fill_style.winding = XR_GSTATE_WINDING_DEFAULT;
gstate->winding = XR_GSTATE_WINDING_DEFAULT;
gstate->stroke_style.line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
gstate->stroke_style.line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
gstate->stroke_style.line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
gstate->stroke_style.miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
gstate->line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
gstate->line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
gstate->miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
gstate->dashes = 0;
gstate->ndashes = 0;
gstate->dash_offset = 0.0;
gstate->solidFormat = XcFindStandardFormat(dpy, PictStandardARGB32);
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
@ -74,12 +77,27 @@ XrGStateInit(XrGState *gstate, Display *dpy)
XrError
XrGStateInitCopy(XrGState *gstate, XrGState *other)
{
XrError err;
*gstate = *other;
if (other->dashes) {
gstate->dashes = malloc (other->ndashes * sizeof (double));
if (gstate->dashes == NULL)
return XrErrorNoMemory;
memcpy (gstate->dashes, other->dashes, other->ndashes * sizeof (double));
}
XrSurfaceInit(&gstate->src, gstate->dpy);
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
return XrPathInitCopy(&gstate->path, &other->path);
err = XrPathInitCopy(&gstate->path, &other->path);
if (err) {
if (gstate->dashes) {
free (gstate->dashes);
gstate->dashes = 0;
}
}
return err;
}
void
@ -92,6 +110,8 @@ XrGStateDeinit(XrGState *gstate)
XrTransformDeinit(&gstate->ctm_inverse);
XrPathDeinit(&gstate->path);
if (gstate->dashes)
free (gstate->dashes);
}
void
@ -160,25 +180,45 @@ XrGStateSetAlpha(XrGState *gstate, double alpha)
void
XrGStateSetLineWidth(XrGState *gstate, double width)
{
gstate->stroke_style.line_width = width;
gstate->line_width = width;
}
void
XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
{
gstate->stroke_style.line_cap = line_cap;
gstate->line_cap = line_cap;
}
void
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
{
gstate->stroke_style.line_join = line_join;
gstate->line_join = line_join;
}
XrError
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset)
{
double *ndashes;
if (gstate->dashes) {
free (gstate->dashes);
}
gstate->dashes = malloc (ndash * sizeof (double));
if (!gstate->dashes) {
gstate->ndashes = 0;
return XrErrorNoMemory;
}
gstate->ndashes = ndash;
memcpy (gstate->dashes, dashes, ndash * sizeof (double));
gstate->dash_offset = offset;
return XrErrorSuccess;
}
void
XrGStateSetMiterLimit(XrGState *gstate, double limit)
{
gstate->stroke_style.miter_limit = limit;
gstate->miter_limit = limit;
}
void
@ -332,7 +372,7 @@ XrGStateFill(XrGState *gstate)
XrTrapsInit(&traps);
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->fill_style.winding);
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding);
if (err) {
XrTrapsDeinit(&traps);
return err;

27
xrint.h
View file

@ -154,22 +154,20 @@ typedef struct _XrTraps {
#define XR_GSTATE_LINE_JOIN_DEFAULT XrLineJoinMiter
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
typedef struct _XrStrokeStyle {
double line_width;
XrLineCap line_cap;
XrLineJoin line_join;
double miter_limit;
} XrStrokeStyle;
typedef struct _XrFillStyle {
int winding;
} XrFillStyle;
typedef struct _XrGState {
Display *dpy;
XrStrokeStyle stroke_style;
XrFillStyle fill_style;
/* stroke style */
double line_width;
XrLineCap line_cap;
XrLineJoin line_join;
double *dashes;
int ndashes;
double dash_offset;
double miter_limit;
/* fill style */
int winding;
XrOperator operator;
@ -277,6 +275,9 @@ XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap);
void
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join);
XrError
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset);
void
XrGStateSetMiterLimit(XrGState *gstate, double limit);

View file

@ -89,12 +89,12 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
outpt = &out->ccw;
}
XrPolygonInit (&polygon);
switch (gstate->stroke_style.line_join) {
switch (gstate->line_join) {
case XrLineJoinRound: {
}
case XrLineJoinMiter: {
XDouble c = in->vector.x * out->vector.x + in->vector.y * out->vector.y;
double ml = gstate->stroke_style.miter_limit;
double ml = gstate->miter_limit;
if (2 <= ml * ml * (1 - c))
{
XDouble x1, y1, x2, y2;
@ -155,11 +155,11 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XrGState *gstate = stroker->gstate;
XrPolygon polygon;
if (gstate->stroke_style.line_cap == XrLineCapButt)
if (gstate->line_cap == XrLineCapButt)
return XrErrorSuccess;
XrPolygonInit (&polygon);
switch (gstate->stroke_style.line_cap) {
switch (gstate->line_cap) {
case XrLineCapRound: {
break;
}
@ -167,8 +167,8 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
XPointDouble vector = f->vector;
XPointFixed fvector;
XPointFixed outer, occw, ocw;
vector.x *= gstate->stroke_style.line_width / 2.0;
vector.y *= gstate->stroke_style.line_width / 2.0;
vector.x *= gstate->line_width / 2.0;
vector.y *= gstate->line_width / 2.0;
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
fvector.x = XDoubleToFixed(vector.x);
fvector.y = XDoubleToFixed(vector.y);
@ -200,14 +200,13 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
XrError err;
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
XrStrokeStyle *style = &gstate->stroke_style;
XrTraps *traps = stroker->traps;
double mag, tmp;
XPointDouble vector;
XPointDouble user_vector;
XPointFixed offset_ccw, offset_cw;
XPointFixed quad[4];
XrStrokeFace face;
XrStrokeFace face;
vector.x = XFixedToDouble(p2->x - p1->x);
vector.y = XFixedToDouble(p2->y - p1->y);
@ -225,8 +224,8 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
user_vector = vector;
tmp = vector.x;
vector.x = - vector.y * (style->line_width / 2.0);
vector.y = tmp * (style->line_width / 2.0);
vector.x = - vector.y * (gstate->line_width / 2.0);
vector.y = tmp * (gstate->line_width / 2.0);
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);