cairo/xrgstate.c

413 lines
9 KiB
C
Raw Normal View History

2002-06-11 04:02:23 +00:00
/*
* $XFree86: $
*
* Copyright <EFBFBD> 2002 Carl D. Worth
2002-06-11 04:02:23 +00:00
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of Carl
* D. Worth not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Carl D. Worth makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
2002-06-11 04:02:23 +00:00
*
* CARL D. WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL CARL D. WORTH BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
2002-06-11 04:02:23 +00:00
#include <stdlib.h>
#include <math.h>
#include "xrint.h"
XrGState *
XrGStateCreate(Display *dpy)
{
XrGState *gstate;
gstate = malloc(sizeof(XrGState));
if (gstate) {
XrGStateInit(gstate, dpy);
}
2002-06-11 04:02:23 +00:00
return gstate;
}
void
XrGStateInit(XrGState *gstate, Display *dpy)
{
gstate->dpy = dpy;
2002-07-23 07:22:23 +00:00
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = XR_GSTATE_TOLERANCE_DEFAULT;
gstate->winding = XR_GSTATE_WINDING_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;
2002-06-11 04:02:23 +00:00
2002-07-23 07:22:23 +00:00
gstate->solidFormat = XcFindStandardFormat(dpy, PictStandardARGB32);
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
2002-06-11 04:02:23 +00:00
2002-07-23 07:22:23 +00:00
XrSurfaceInit(&gstate->surface, dpy);
2002-06-11 04:02:23 +00:00
2002-07-23 07:22:23 +00:00
XrSurfaceInit(&gstate->src, dpy);
2002-06-11 04:02:23 +00:00
XrColorInit(&gstate->color);
2002-07-23 07:22:23 +00:00
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
2002-06-11 04:02:23 +00:00
XrTransformInit(&gstate->ctm);
XrTransformInit(&gstate->ctm_inverse);
2002-06-11 04:02:23 +00:00
XrPathInit(&gstate->path);
}
XrError
2002-06-11 04:02:23 +00:00
XrGStateInitCopy(XrGState *gstate, XrGState *other)
{
XrError err;
2002-06-11 04:02:23 +00:00
*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));
}
2002-06-11 04:02:23 +00:00
2002-07-23 07:22:23 +00:00
XrSurfaceInit(&gstate->src, gstate->dpy);
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
err = XrPathInitCopy(&gstate->path, &other->path);
if (err) {
if (gstate->dashes) {
free (gstate->dashes);
gstate->dashes = 0;
}
}
return err;
2002-06-11 04:02:23 +00:00
}
void
XrGStateDeinit(XrGState *gstate)
{
XrColorDeinit(&gstate->color);
2002-07-23 07:22:23 +00:00
XrSurfaceDeinit(&gstate->src);
XrSurfaceDeinit(&gstate->surface);
XrTransformDeinit(&gstate->ctm);
XrTransformDeinit(&gstate->ctm_inverse);
2002-06-11 04:02:23 +00:00
XrPathDeinit(&gstate->path);
if (gstate->dashes)
free (gstate->dashes);
2002-06-11 04:02:23 +00:00
}
void
XrGStateDestroy(XrGState *gstate)
{
XrGStateDeinit(gstate);
free(gstate);
}
XrGState*
2002-06-11 04:02:23 +00:00
XrGStateClone(XrGState *gstate)
{
XrError err;
2002-06-11 04:02:23 +00:00
XrGState *clone;
clone = malloc(sizeof(XrGState));
if (clone) {
err = XrGStateInitCopy(clone, gstate);
if (err) {
free(clone);
return NULL;
}
}
2002-06-11 04:02:23 +00:00
return clone;
}
void
XrGStateSetDrawable(XrGState *gstate, Drawable drawable)
2002-06-11 04:02:23 +00:00
{
2002-07-23 07:22:23 +00:00
XrSurfaceSetDrawable(&gstate->surface, drawable);
}
void
XrGStateSetVisual(XrGState *gstate, Visual *visual)
{
2002-07-23 07:22:23 +00:00
XrSurfaceSetVisual(&gstate->surface, visual);
}
void
XrGStateSetFormat(XrGState *gstate, XrFormat format)
{
2002-07-23 07:22:23 +00:00
XrSurfaceSetFormat(&gstate->surface, format);
}
void
XrGStateSetOperator(XrGState *gstate, XrOperator operator)
{
gstate->operator = operator;
2002-06-11 04:02:23 +00:00
}
void
2002-07-23 07:22:23 +00:00
XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue)
2002-06-11 04:02:23 +00:00
{
XrColorSetRGB(&gstate->color, red, green, blue);
2002-07-23 07:22:23 +00:00
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
2002-06-11 04:02:23 +00:00
}
void
XrGStateSetAlpha(XrGState *gstate, double alpha)
{
XrColorSetAlpha(&gstate->color, alpha);
2002-07-23 07:22:23 +00:00
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
2002-06-11 04:02:23 +00:00
}
void
XrGStateSetLineWidth(XrGState *gstate, double width)
{
gstate->line_width = width;
2002-06-11 04:02:23 +00:00
}
2002-07-23 07:22:23 +00:00
void
XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
{
gstate->line_cap = line_cap;
2002-07-23 07:22:23 +00:00
}
void
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
{
gstate->line_join = line_join;
}
XrError
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset)
{
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;
2002-07-23 07:22:23 +00:00
}
void
XrGStateSetMiterLimit(XrGState *gstate, double limit)
{
gstate->miter_limit = limit;
2002-07-23 07:22:23 +00:00
}
2002-06-11 04:02:23 +00:00
void
XrGStateTranslate(XrGState *gstate, double tx, double ty)
{
XrTransform tmp;
XrTransformInitTranslate(&tmp, tx, ty);
XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
2002-06-11 04:02:23 +00:00
XrTransformInitTranslate(&tmp, -tx, -ty);
XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
2002-06-11 04:02:23 +00:00
}
void
XrGStateScale(XrGState *gstate, double sx, double sy)
{
XrTransform tmp;
2002-06-11 04:02:23 +00:00
XrTransformInitScale(&tmp, sx, sy);
XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
XrTransformInitScale(&tmp, 1/sx, 1/sy);
XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
2002-06-11 04:02:23 +00:00
}
void
XrGStateRotate(XrGState *gstate, double angle)
{
XrTransform tmp;
XrTransformInitRotate(&tmp, angle);
XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
2002-06-11 04:02:23 +00:00
XrTransformInitRotate(&tmp, -angle);
XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
2002-06-11 04:02:23 +00:00
}
void
XrGStateNewPath(XrGState *gstate)
{
XrPathDeinit(&gstate->path);
}
XrError
XrGStateAddPathOp(XrGState *gstate, XrPathOp op, XPointDouble *pt, int num_pts)
2002-06-11 04:02:23 +00:00
{
int i;
XrError err;
XPointFixed *pt_fixed;
2002-06-11 04:02:23 +00:00
switch (op) {
case XrPathOpMoveTo:
case XrPathOpLineTo:
case XrPathOpCurveTo:
for (i=0; i < num_pts; i++) {
XrTransformPoint(&gstate->ctm, &pt[i]);
}
break;
case XrPathOpRelMoveTo:
case XrPathOpRelLineTo:
case XrPathOpRelCurveTo:
for (i=0; i < num_pts; i++) {
XrTransformPointWithoutTranslate(&gstate->ctm, &pt[i]);
}
break;
case XrPathOpClosePath:
break;
}
2002-06-11 04:02:23 +00:00
pt_fixed = malloc(num_pts * sizeof(XPointFixed));
if (pt_fixed == NULL) {
return XrErrorNoMemory;
}
for (i=0; i < num_pts; i++) {
pt_fixed[i].x = XDoubleToFixed(pt[i].x);
pt_fixed[i].y = XDoubleToFixed(pt[i].y);
}
err = XrPathAdd(&gstate->path, op, pt_fixed, num_pts);
free(pt_fixed);
2002-06-11 04:02:23 +00:00
return err;
2002-06-11 04:02:23 +00:00
}
XrError
XrGStateAddUnaryPathOp(XrGState *gstate, XrPathOp op, double x, double y)
{
XPointDouble pt;
pt.x = x;
pt.y = y;
return XrGStateAddPathOp(gstate, op, &pt, 1);
}
XrError
2002-06-11 04:02:23 +00:00
XrGStateClosePath(XrGState *gstate)
{
return XrPathAdd(&gstate->path, XrPathOpClosePath, NULL, 0);
2002-06-11 04:02:23 +00:00
}
XrError
2002-06-11 04:02:23 +00:00
XrGStateStroke(XrGState *gstate)
{
XrError err;
static XrPathCallbacks cb = {
XrStrokerAddEdge,
XrStrokerAddSpline,
XrStrokerDoneSubPath,
XrStrokerDonePath
};
static XrPathCallbacks cb_dash = {
XrStrokerAddEdgeDashed,
XrStrokerAddSpline,
XrStrokerDoneSubPath,
XrStrokerDonePath
};
XrPathCallbacks *cbs = gstate->dashes ? &cb_dash : &cb;
XrStroker stroker;
2002-07-23 07:22:23 +00:00
XrTraps traps;
XrTrapsInit(&traps);
XrStrokerInit(&stroker, gstate, &traps);
2002-07-23 07:22:23 +00:00
err = XrPathInterpret(&gstate->path, XrPathDirectionForward, cbs, &stroker);
if (err) {
XrStrokerDeinit(&stroker);
XrTrapsDeinit(&traps);
return err;
}
2002-07-23 07:22:23 +00:00
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
gstate->src.xcsurface, gstate->surface.xcsurface,
gstate->alphaFormat,
0, 0,
traps.xtraps,
traps.num_xtraps);
2002-06-11 04:02:23 +00:00
XrStrokerDeinit(&stroker);
XrTrapsDeinit(&traps);
2002-07-23 07:22:23 +00:00
XrGStateNewPath(gstate);
return XrErrorSuccess;
2002-06-11 04:02:23 +00:00
}
XrError
2002-06-11 04:02:23 +00:00
XrGStateFill(XrGState *gstate)
{
XrError err;
static XrPathCallbacks cb = {
XrFillerAddEdge,
XrFillerAddSpline,
XrFillerDoneSubPath,
XrFillerDonePath
};
XrFiller filler;
2002-07-23 07:22:23 +00:00
XrTraps traps;
2002-06-11 04:02:23 +00:00
2002-07-23 07:22:23 +00:00
XrTrapsInit(&traps);
XrFillerInit(&filler, gstate, &traps);
2002-06-11 04:02:23 +00:00
err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &filler);
if (err) {
XrFillerDeinit(&filler);
XrTrapsDeinit(&traps);
return err;
}
2002-07-23 07:22:23 +00:00
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
gstate->src.xcsurface, gstate->surface.xcsurface,
gstate->alphaFormat,
0, 0,
traps.xtraps,
traps.num_xtraps);
2002-06-11 04:02:23 +00:00
XrFillerDeinit(&filler);
2002-07-23 07:22:23 +00:00
XrTrapsDeinit(&traps);
XrGStateNewPath(gstate);
return XrErrorSuccess;
}
2002-07-23 07:22:23 +00:00