diff --git a/ChangeLog b/ChangeLog index 4f43fad92..2284c90db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2002-11-04 Carl Worth + + * xrsurface.c (_XrSurfaceDereference): + (_XrSurfaceDereferenceDestroy): Fixed bug in reference counting + logic. + (_XrSurfaceSetDrawableWH): XrSurface now keeps track of its width/height. + (_XrSurfaceGetDrawable): + (_XrSurfaceGetWidth): + (_XrSurfaceGetHeight): + (_XrSurfaceGetDepth): New accessor functions. + + * xrgstate.c (_XrGStateBeginGroup): + (_XrGStateEndGroup): Preliminary group support. Not too efficient + since it always composite's a full-size picture from child group + to parent picture, (even if only a small portion has + non-transparent pixels). + (_XrGStateShowImageTransform): Fixed show image to use current + alpha value. + + * xrfont.c (_XrFontResolveXftFont): Fixed memory leak + (FcPatternDestroy). There's still some meory + leaking/left-reachable in Xft/fontconfig that I need to track + down. + + * xr.c (XrPushGroup): + (XrPopGroup): Added preliminary group support. I think I like + having this in the API as it takes several burdens away from the + user, (plus it matches the PDF model). Things to do still: think + about the names of these functions. Re-read the PDF semantics to + see if we're missing anything. + 2002-11-02 Carl Worth * xrsurface.c (_XrSurfaceSetImage): Fixed leak of the image diff --git a/Xr.h b/Xr.h index 160eeb8b4..69df4a0a8 100644 --- a/Xr.h +++ b/Xr.h @@ -43,6 +43,12 @@ XrSave(XrState *xrs); void XrRestore(XrState *xrs); +void +XrPushGroup(XrState *xrs); + +void +XrPopGroup(XrState *xrs); + /* Modify state */ void XrSetDrawable(XrState *xrs, Drawable drawable); @@ -241,6 +247,7 @@ typedef enum _XrStatus { XrStatusSuccess = 0, XrStatusNoMemory, XrStatusInvalidRestore, + XrStatusInvalidPopGroup, XrStatusNoCurrentPoint } XrStatus; diff --git a/src/Xr.h b/src/Xr.h index 160eeb8b4..69df4a0a8 100644 --- a/src/Xr.h +++ b/src/Xr.h @@ -43,6 +43,12 @@ XrSave(XrState *xrs); void XrRestore(XrState *xrs); +void +XrPushGroup(XrState *xrs); + +void +XrPopGroup(XrState *xrs); + /* Modify state */ void XrSetDrawable(XrState *xrs, Drawable drawable); @@ -241,6 +247,7 @@ typedef enum _XrStatus { XrStatusSuccess = 0, XrStatusNoMemory, XrStatusInvalidRestore, + XrStatusInvalidPopGroup, XrStatusNoCurrentPoint } XrStatus; diff --git a/src/xr.c b/src/xr.c index 6869689ae..d9193d0e7 100644 --- a/src/xr.c +++ b/src/xr.c @@ -62,6 +62,32 @@ XrRestore(XrState *xrs) xrs->status = _XrStatePop(xrs); } +void +XrPushGroup(XrState *xrs) +{ + if (xrs->status) + return; + + xrs->status = _XrStatePush(xrs); + if (xrs->status) + return; + + xrs->status = _XrGStateBeginGroup(_XR_CURRENT_GSTATE(xrs)); +} + +void +XrPopGroup(XrState *xrs) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateEndGroup(_XR_CURRENT_GSTATE(xrs)); + if (xrs->status) + return; + + xrs->status = _XrStatePop(xrs); +} + void XrSetDrawable(XrState *xrs, Drawable drawable) { @@ -435,7 +461,9 @@ XrGetStatusString(XrState *xrs) case XrStatusNoMemory: return "out of memory"; case XrStatusInvalidRestore: - return "XrRestore without matchin XrSave"; + return "XrRestore without matching XrSave"; + case XrStatusInvalidPopGroup: + return "XrPopGroup without matching XrPushGroup"; case XrStatusNoCurrentPoint: return "no current point defined"; } diff --git a/src/xrfont.c b/src/xrfont.c index c0f70e1de..d1416bce8 100644 --- a/src/xrfont.c +++ b/src/xrfont.c @@ -28,7 +28,7 @@ #include "xrint.h" void -_XrFontInit(XrFont *font, XrGState *gstate) +_XrFontInit(XrFont *font) { font->key = (unsigned char *) strdup(XR_FONT_KEY_DEFAULT); @@ -164,5 +164,7 @@ _XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font) *xft_font = font->xft_font; + FcPatternDestroy (pattern); + return XrStatusSuccess; } diff --git a/src/xrgstate.c b/src/xrgstate.c index 5397690ed..e57264c13 100644 --- a/src/xrgstate.c +++ b/src/xrgstate.c @@ -41,9 +41,8 @@ _XrGStateCreate(Display *dpy) gstate = malloc(sizeof(XrGState)); - if (gstate) { + if (gstate) _XrGStateInit(gstate, dpy); - } return gstate; } @@ -70,14 +69,16 @@ _XrGStateInit(XrGState *gstate, Display *dpy) gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8); - _XrFontInit(&gstate->font, gstate); + _XrFontInit(&gstate->font); - _XrSurfaceInit(&gstate->surface, dpy); - _XrSurfaceInit(&gstate->src, dpy); + gstate->parent_surface = NULL; + gstate->surface = _XrSurfaceCreate(dpy); + gstate->src = _XrSurfaceCreate(dpy); gstate->mask = NULL; + gstate->alpha = 1.0; _XrColorInit(&gstate->color); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); _XrTransformInit(&gstate->ctm); _XrTransformInit(&gstate->ctm_inverse); @@ -107,9 +108,10 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other) status = _XrFontInitCopy(&gstate->font, &other->font); if (status) goto CLEANUP_DASHES; - - _XrSurfaceReference(&gstate->surface); - _XrSurfaceReference(&gstate->src); + + gstate->parent_surface = NULL; + _XrSurfaceReference(gstate->surface); + _XrSurfaceReference(gstate->src); if (gstate->mask) _XrSurfaceReference(gstate->mask); @@ -137,10 +139,13 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other) void _XrGStateDeinit(XrGState *gstate) { + if (gstate->parent_surface) + _XrGStateEndGroup(gstate); + _XrFontDeinit(&gstate->font); - _XrSurfaceDereference(&gstate->src); - _XrSurfaceDereference(&gstate->surface); + _XrSurfaceDereferenceDestroy(gstate->surface); + _XrSurfaceDereferenceDestroy(gstate->src); if (gstate->mask) _XrSurfaceDereferenceDestroy(gstate->mask); @@ -184,10 +189,92 @@ _XrGStateClone(XrGState *gstate) return clone; } +/* Push rendering off to an off-screen group. */ +XrStatus +_XrGStateBeginGroup(XrGState *gstate) +{ + Pixmap pix; + XrColor clear; + unsigned int width, height; + + gstate->parent_surface = gstate->surface; + + width = _XrSurfaceGetWidth(gstate->surface); + height = _XrSurfaceGetHeight(gstate->surface); + + pix = XCreatePixmap(gstate->dpy, + _XrSurfaceGetDrawable(gstate->surface), + width, height, + _XrSurfaceGetDepth(gstate->surface)); + if (pix == 0) + return XrStatusNoMemory; + + gstate->surface = _XrSurfaceCreate(gstate->dpy); + if (gstate->surface == NULL) + return XrStatusNoMemory; + + _XrSurfaceSetDrawableWH(gstate->surface, pix, width, height); + + _XrColorInit(&clear); + _XrColorSetAlpha(&clear, 0); + + XcFillRectangle(gstate->dpy, + XrOperatorSrc, + _XrSurfaceGetXcSurface(gstate->surface), + &clear.xc_color, + 0, 0, + _XrSurfaceGetWidth(gstate->surface), + _XrSurfaceGetHeight(gstate->surface)); + + return XrStatusSuccess; +} + +/* Complete the current offscreen group, composing its contents onto the parent surface. */ +XrStatus +_XrGStateEndGroup(XrGState *gstate) +{ + Pixmap pix; + XrColor mask_color; + XrSurface mask; + + if (gstate->parent_surface == NULL) + return XrStatusInvalidPopGroup; + + _XrSurfaceInit(&mask, gstate->dpy); + _XrColorInit(&mask_color); + _XrColorSetAlpha(&mask_color, gstate->alpha); + + _XrSurfaceSetSolidColor(&mask, &mask_color); + + /* XXX: This could be made much more efficient by using + _XrSurfaceGetDamagedWidth/Height if XrSurface actually kept + track of such informaton. */ + XcComposite(gstate->dpy, gstate->operator, + _XrSurfaceGetXcSurface(gstate->surface), + _XrSurfaceGetXcSurface(&mask), + _XrSurfaceGetXcSurface(gstate->parent_surface), + 0, 0, + 0, 0, + 0, 0, + _XrSurfaceGetWidth(gstate->surface), + _XrSurfaceGetHeight(gstate->surface)); + + _XrSurfaceDeinit(&mask); + + pix = _XrSurfaceGetDrawable(gstate->surface); + XFreePixmap(gstate->dpy, pix); + + _XrSurfaceDestroy(gstate->surface); + gstate->surface = gstate->parent_surface; + gstate->parent_surface = NULL; + + return XrStatusSuccess; +} + XrStatus _XrGStateSetDrawable(XrGState *gstate, Drawable drawable) { - _XrSurfaceSetDrawable(&gstate->surface, drawable); + _XrSurfaceSetDrawable(gstate->surface, drawable); return XrStatusSuccess; } @@ -195,7 +282,7 @@ _XrGStateSetDrawable(XrGState *gstate, Drawable drawable) XrStatus _XrGStateSetVisual(XrGState *gstate, Visual *visual) { - _XrSurfaceSetVisual(&gstate->surface, visual); + _XrSurfaceSetVisual(gstate->surface, visual); return XrStatusSuccess; } @@ -203,7 +290,7 @@ _XrGStateSetVisual(XrGState *gstate, Visual *visual) XrStatus _XrGStateSetFormat(XrGState *gstate, XrFormat format) { - _XrSurfaceSetFormat(&gstate->surface, format); + _XrSurfaceSetFormat(gstate->surface, format); return XrStatusSuccess; } @@ -220,7 +307,7 @@ XrStatus _XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue) { _XrColorSetRGB(&gstate->color, red, green, blue); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); return XrStatusSuccess; } @@ -236,8 +323,9 @@ _XrGStateSetTolerance(XrGState *gstate, double tolerance) XrStatus _XrGStateSetAlpha(XrGState *gstate, double alpha) { + gstate->alpha = alpha; _XrColorSetAlpha(&gstate->color, alpha); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); return XrStatusSuccess; } @@ -542,8 +630,8 @@ _XrGStateStroke(XrGState *gstate) } XcCompositeTrapezoids(gstate->dpy, gstate->operator, - _XrSurfaceGetXcSurface(&gstate->src), - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(gstate->src), + _XrSurfaceGetXcSurface(gstate->surface), gstate->alphaFormat, 0, 0, traps.xtraps, @@ -582,8 +670,8 @@ _XrGStateFill(XrGState *gstate) } XcCompositeTrapezoids(gstate->dpy, gstate->operator, - _XrSurfaceGetXcSurface(&gstate->src), - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(gstate->src), + _XrSurfaceGetXcSurface(gstate->surface), gstate->alphaFormat, 0, 0, traps.xtraps, @@ -701,14 +789,21 @@ _XrGStateShowImageTransform(XrGState *gstate, double tx, double ty) { XrStatus status; - XrSurface image_surface; + XrColor mask_color; + XrSurface image_surface, mask; double dst_width, dst_height; + _XrSurfaceInit(&mask, gstate->dpy); + _XrColorInit(&mask_color); + _XrColorSetAlpha(&mask_color, gstate->alpha); + + _XrSurfaceSetSolidColor(&mask, &mask_color); + _XrSurfaceInit(&image_surface, gstate->dpy); _XrSurfaceSetFormat(&image_surface, format); - status = _XrSurfaceSetImage(&image_surface, data, width, height, stride); + status = _XrSurfaceSetImage(&image_surface, data,width, height, stride); if (status) return status; @@ -720,8 +815,8 @@ _XrGStateShowImageTransform(XrGState *gstate, XcComposite(gstate->dpy, gstate->operator, _XrSurfaceGetXcSurface(&image_surface), - 0, - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(&mask), + _XrSurfaceGetXcSurface(gstate->surface), 0, 0, 0, 0, gstate->current_pt.x, @@ -730,6 +825,7 @@ _XrGStateShowImageTransform(XrGState *gstate, dst_height); _XrSurfaceDeinit(&image_surface); + _XrSurfaceDeinit(&mask); return XrStatusSuccess; } @@ -737,11 +833,11 @@ _XrGStateShowImageTransform(XrGState *gstate, static Picture _XrGStateGetPicture(XrGState *gstate) { - return _XrSurfaceGetPicture(&gstate->surface); + return _XrSurfaceGetPicture(gstate->surface); } static Picture _XrGStateGetSrcPicture(XrGState *gstate) { - return _XrSurfaceGetPicture(&gstate->src); + return _XrSurfaceGetPicture(gstate->src); } diff --git a/src/xrint.h b/src/xrint.h index 35ed6b1d0..5b96e7c0e 100644 --- a/src/xrint.h +++ b/src/xrint.h @@ -171,10 +171,14 @@ typedef struct _XrSurface { Drawable drawable; GC gc; + unsigned int width; + unsigned int height; unsigned int depth; unsigned long xc_sa_mask; XcSurfaceAttributes xc_sa; + + XrFormat format; XcFormat *xc_format; XcSurface *xc_surface; @@ -248,10 +252,12 @@ typedef struct _XrGState { XrFont font; - XrSurface src; - XrSurface surface; + XrSurface *parent_surface; + XrSurface *surface; + XrSurface *src; XrSurface *mask; + double alpha; XrColor color; XrTransform ctm; @@ -341,6 +347,12 @@ _XrGStateDestroy(XrGState *gstate); XrGState * _XrGStateClone(XrGState *gstate); +XrStatus +_XrGStateBeginGroup(XrGState *gstate); + +XrStatus +_XrGStateEndGroup(XrGState *gstate); + XrStatus _XrGStateSetDrawable(XrGState *gstate, Drawable drawable); @@ -487,7 +499,7 @@ _XrColorSetAlpha(XrColor *color, double alpha); /* xrfont.c */ void -_XrFontInit(XrFont *font, XrGState *gstate); +_XrFontInit(XrFont *font); XrStatus _XrFontInitCopy(XrFont *font, XrFont *other); @@ -538,9 +550,18 @@ XrStatus _XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure); /* xrsurface.c */ +XrSurface * +_XrSurfaceCreate(Display *dpy); + void _XrSurfaceInit(XrSurface *surface, Display *dpy); +void +_XrSurfaceDeinit(XrSurface *surface); + +void +_XrSurfaceDestroy(XrSurface *surface); + void _XrSurfaceReference(XrSurface *surface); @@ -550,9 +571,6 @@ _XrSurfaceDereference(XrSurface *surface); void _XrSurfaceDereferenceDestroy(XrSurface *surface); -void -_XrSurfaceDeinit(XrSurface *surface); - void _XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color); @@ -569,6 +587,12 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform); void _XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable); +void +_XrSurfaceSetDrawableWH(XrSurface *surface, + Drawable drawable, + unsigned int width, + unsigned int height); + void _XrSurfaceSetVisual(XrSurface *surface, Visual *visual); @@ -581,6 +605,18 @@ _XrSurfaceGetXcSurface(XrSurface *surface); Picture _XrSurfaceGetPicture(XrSurface *surface); +Drawable +_XrSurfaceGetDrawable(XrSurface *surface); + +unsigned int +_XrSurfaceGetWidth(XrSurface *surface); + +unsigned int +_XrSurfaceGetHeight(XrSurface *surface); + +unsigned int +_XrSurfaceGetDepth(XrSurface *surface); + /* xrpen.c */ XrStatus _XrPenInit(XrPen *pen, double radius, XrGState *gstate); diff --git a/src/xrstate.c b/src/xrstate.c index 26b9f6e62..720f33705 100644 --- a/src/xrstate.c +++ b/src/xrstate.c @@ -50,6 +50,7 @@ _XrStateInit(XrState *xrs, Display *dpy) { xrs->dpy = dpy; xrs->stack = NULL; + xrs->status = XrStatusSuccess; return _XrStatePush(xrs); diff --git a/src/xrsurface.c b/src/xrsurface.c index b1dbdf2aa..88a750855 100644 --- a/src/xrsurface.c +++ b/src/xrsurface.c @@ -23,8 +23,23 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include "xrint.h" +XrSurface * +_XrSurfaceCreate(Display *dpy) +{ + XrSurface *surface; + + surface = malloc(sizeof(XrSurface)); + + if (surface) + _XrSurfaceInit(surface, dpy); + + return surface; +} + void _XrSurfaceInit(XrSurface *surface, Display *dpy) { @@ -33,11 +48,13 @@ _XrSurfaceInit(XrSurface *surface, Display *dpy) surface->drawable = 0; surface->gc = 0; + surface->width = 0; + surface->height = 0; surface->depth = 0; surface->xc_sa_mask = 0; - surface->xc_format = XcFindStandardFormat(dpy, PictStandardARGB32); + _XrSurfaceSetFormat(surface, XrFormatARGB32); surface->xc_surface = 0; surface->needs_new_xc_surface = 1; @@ -45,6 +62,22 @@ _XrSurfaceInit(XrSurface *surface, Display *dpy) surface->ref_count = 0; } +void +_XrSurfaceDeinit(XrSurface *surface) +{ + if (surface->xc_surface) + XcFreeSurface(surface->dpy, surface->xc_surface); + if (surface->gc) + XFreeGC(surface->dpy, surface->gc); +} + +void +_XrSurfaceDestroy(XrSurface *surface) +{ + _XrSurfaceDeinit(surface); + free(surface); +} + void _XrSurfaceReference(XrSurface *surface) { @@ -63,17 +96,10 @@ _XrSurfaceDereference(XrSurface *surface) void _XrSurfaceDereferenceDestroy(XrSurface *surface) { - _XrSurfaceDereference(surface); - if (surface->ref_count == 0) - free(surface); -} - -void -_XrSurfaceDeinit(XrSurface *surface) -{ - if (surface->xc_surface) - XcFreeSurface(surface->dpy, surface->xc_surface); + _XrSurfaceDestroy(surface); + else + _XrSurfaceDereference(surface); } void @@ -85,7 +111,7 @@ _XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color) DefaultRootWindow(surface->dpy), 1, 1, surface->xc_format->depth); - _XrSurfaceSetDrawable(surface, pix); + _XrSurfaceSetDrawableWH(surface, pix, 1, 1); surface->xc_sa_mask |= CPRepeat; surface->xc_sa.repeat = True; _XrSurfaceGetXcSurface(surface); @@ -121,7 +147,7 @@ _XrSurfaceSetImage(XrSurface *surface, DefaultRootWindow(surface->dpy), width, height, depth); - _XrSurfaceSetDrawable(surface, pix); + _XrSurfaceSetDrawableWH(surface, pix, width, height); image = XCreateImage(surface->dpy, DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)), @@ -178,11 +204,32 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform) void _XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable) +{ + Window root; + int x, y; + unsigned int border, depth; + unsigned int width, height; + + XGetGeometry (surface->dpy, drawable, + &root, &x, &y, + &width, &height, + &border, &depth); + + _XrSurfaceSetDrawableWH(surface, drawable, width, height); +} + +void +_XrSurfaceSetDrawableWH(XrSurface *surface, + Drawable drawable, + unsigned int width, + unsigned int height) { if (surface->gc) XFreeGC(surface->dpy, surface->gc); surface->drawable = drawable; + surface->width = width; + surface->height = height; surface->gc = XCreateGC(surface->dpy, surface->drawable, 0, 0); surface->needs_new_xc_surface = 1; @@ -198,7 +245,23 @@ _XrSurfaceSetVisual(XrSurface *surface, Visual *visual) void _XrSurfaceSetFormat(XrSurface *surface, XrFormat format) { + surface->format = format; surface->xc_format = XcFindStandardFormat(surface->dpy, format); + + switch (surface->format) { + case XrFormatARGB32: + surface->depth = 32; + case XrFormatRGB32: + /* XXX: Is this correct? */ + surface->depth = 24; + case XrFormatA8: + surface->depth = 8; + case XrFormatA1: + surface->depth = 1; + default: + surface->depth = 32; + } + surface->needs_new_xc_surface = 1; } @@ -234,3 +297,27 @@ _XrSurfaceGetPicture(XrSurface *surface) { return XcSurfaceGetPicture(_XrSurfaceGetXcSurface(surface)); } + +Drawable +_XrSurfaceGetDrawable(XrSurface *surface) +{ + return surface->drawable; +} + +unsigned int +_XrSurfaceGetWidth(XrSurface *surface) +{ + return surface->width; +} + +unsigned int +_XrSurfaceGetHeight(XrSurface *surface) +{ + return surface->height; +} + +unsigned int +_XrSurfaceGetDepth(XrSurface *surface) +{ + return surface->depth; +} diff --git a/xr.c b/xr.c index 6869689ae..d9193d0e7 100644 --- a/xr.c +++ b/xr.c @@ -62,6 +62,32 @@ XrRestore(XrState *xrs) xrs->status = _XrStatePop(xrs); } +void +XrPushGroup(XrState *xrs) +{ + if (xrs->status) + return; + + xrs->status = _XrStatePush(xrs); + if (xrs->status) + return; + + xrs->status = _XrGStateBeginGroup(_XR_CURRENT_GSTATE(xrs)); +} + +void +XrPopGroup(XrState *xrs) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateEndGroup(_XR_CURRENT_GSTATE(xrs)); + if (xrs->status) + return; + + xrs->status = _XrStatePop(xrs); +} + void XrSetDrawable(XrState *xrs, Drawable drawable) { @@ -435,7 +461,9 @@ XrGetStatusString(XrState *xrs) case XrStatusNoMemory: return "out of memory"; case XrStatusInvalidRestore: - return "XrRestore without matchin XrSave"; + return "XrRestore without matching XrSave"; + case XrStatusInvalidPopGroup: + return "XrPopGroup without matching XrPushGroup"; case XrStatusNoCurrentPoint: return "no current point defined"; } diff --git a/xrfont.c b/xrfont.c index c0f70e1de..d1416bce8 100644 --- a/xrfont.c +++ b/xrfont.c @@ -28,7 +28,7 @@ #include "xrint.h" void -_XrFontInit(XrFont *font, XrGState *gstate) +_XrFontInit(XrFont *font) { font->key = (unsigned char *) strdup(XR_FONT_KEY_DEFAULT); @@ -164,5 +164,7 @@ _XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font) *xft_font = font->xft_font; + FcPatternDestroy (pattern); + return XrStatusSuccess; } diff --git a/xrgstate.c b/xrgstate.c index 5397690ed..e57264c13 100644 --- a/xrgstate.c +++ b/xrgstate.c @@ -41,9 +41,8 @@ _XrGStateCreate(Display *dpy) gstate = malloc(sizeof(XrGState)); - if (gstate) { + if (gstate) _XrGStateInit(gstate, dpy); - } return gstate; } @@ -70,14 +69,16 @@ _XrGStateInit(XrGState *gstate, Display *dpy) gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8); - _XrFontInit(&gstate->font, gstate); + _XrFontInit(&gstate->font); - _XrSurfaceInit(&gstate->surface, dpy); - _XrSurfaceInit(&gstate->src, dpy); + gstate->parent_surface = NULL; + gstate->surface = _XrSurfaceCreate(dpy); + gstate->src = _XrSurfaceCreate(dpy); gstate->mask = NULL; + gstate->alpha = 1.0; _XrColorInit(&gstate->color); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); _XrTransformInit(&gstate->ctm); _XrTransformInit(&gstate->ctm_inverse); @@ -107,9 +108,10 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other) status = _XrFontInitCopy(&gstate->font, &other->font); if (status) goto CLEANUP_DASHES; - - _XrSurfaceReference(&gstate->surface); - _XrSurfaceReference(&gstate->src); + + gstate->parent_surface = NULL; + _XrSurfaceReference(gstate->surface); + _XrSurfaceReference(gstate->src); if (gstate->mask) _XrSurfaceReference(gstate->mask); @@ -137,10 +139,13 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other) void _XrGStateDeinit(XrGState *gstate) { + if (gstate->parent_surface) + _XrGStateEndGroup(gstate); + _XrFontDeinit(&gstate->font); - _XrSurfaceDereference(&gstate->src); - _XrSurfaceDereference(&gstate->surface); + _XrSurfaceDereferenceDestroy(gstate->surface); + _XrSurfaceDereferenceDestroy(gstate->src); if (gstate->mask) _XrSurfaceDereferenceDestroy(gstate->mask); @@ -184,10 +189,92 @@ _XrGStateClone(XrGState *gstate) return clone; } +/* Push rendering off to an off-screen group. */ +XrStatus +_XrGStateBeginGroup(XrGState *gstate) +{ + Pixmap pix; + XrColor clear; + unsigned int width, height; + + gstate->parent_surface = gstate->surface; + + width = _XrSurfaceGetWidth(gstate->surface); + height = _XrSurfaceGetHeight(gstate->surface); + + pix = XCreatePixmap(gstate->dpy, + _XrSurfaceGetDrawable(gstate->surface), + width, height, + _XrSurfaceGetDepth(gstate->surface)); + if (pix == 0) + return XrStatusNoMemory; + + gstate->surface = _XrSurfaceCreate(gstate->dpy); + if (gstate->surface == NULL) + return XrStatusNoMemory; + + _XrSurfaceSetDrawableWH(gstate->surface, pix, width, height); + + _XrColorInit(&clear); + _XrColorSetAlpha(&clear, 0); + + XcFillRectangle(gstate->dpy, + XrOperatorSrc, + _XrSurfaceGetXcSurface(gstate->surface), + &clear.xc_color, + 0, 0, + _XrSurfaceGetWidth(gstate->surface), + _XrSurfaceGetHeight(gstate->surface)); + + return XrStatusSuccess; +} + +/* Complete the current offscreen group, composing its contents onto the parent surface. */ +XrStatus +_XrGStateEndGroup(XrGState *gstate) +{ + Pixmap pix; + XrColor mask_color; + XrSurface mask; + + if (gstate->parent_surface == NULL) + return XrStatusInvalidPopGroup; + + _XrSurfaceInit(&mask, gstate->dpy); + _XrColorInit(&mask_color); + _XrColorSetAlpha(&mask_color, gstate->alpha); + + _XrSurfaceSetSolidColor(&mask, &mask_color); + + /* XXX: This could be made much more efficient by using + _XrSurfaceGetDamagedWidth/Height if XrSurface actually kept + track of such informaton. */ + XcComposite(gstate->dpy, gstate->operator, + _XrSurfaceGetXcSurface(gstate->surface), + _XrSurfaceGetXcSurface(&mask), + _XrSurfaceGetXcSurface(gstate->parent_surface), + 0, 0, + 0, 0, + 0, 0, + _XrSurfaceGetWidth(gstate->surface), + _XrSurfaceGetHeight(gstate->surface)); + + _XrSurfaceDeinit(&mask); + + pix = _XrSurfaceGetDrawable(gstate->surface); + XFreePixmap(gstate->dpy, pix); + + _XrSurfaceDestroy(gstate->surface); + gstate->surface = gstate->parent_surface; + gstate->parent_surface = NULL; + + return XrStatusSuccess; +} + XrStatus _XrGStateSetDrawable(XrGState *gstate, Drawable drawable) { - _XrSurfaceSetDrawable(&gstate->surface, drawable); + _XrSurfaceSetDrawable(gstate->surface, drawable); return XrStatusSuccess; } @@ -195,7 +282,7 @@ _XrGStateSetDrawable(XrGState *gstate, Drawable drawable) XrStatus _XrGStateSetVisual(XrGState *gstate, Visual *visual) { - _XrSurfaceSetVisual(&gstate->surface, visual); + _XrSurfaceSetVisual(gstate->surface, visual); return XrStatusSuccess; } @@ -203,7 +290,7 @@ _XrGStateSetVisual(XrGState *gstate, Visual *visual) XrStatus _XrGStateSetFormat(XrGState *gstate, XrFormat format) { - _XrSurfaceSetFormat(&gstate->surface, format); + _XrSurfaceSetFormat(gstate->surface, format); return XrStatusSuccess; } @@ -220,7 +307,7 @@ XrStatus _XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue) { _XrColorSetRGB(&gstate->color, red, green, blue); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); return XrStatusSuccess; } @@ -236,8 +323,9 @@ _XrGStateSetTolerance(XrGState *gstate, double tolerance) XrStatus _XrGStateSetAlpha(XrGState *gstate, double alpha) { + gstate->alpha = alpha; _XrColorSetAlpha(&gstate->color, alpha); - _XrSurfaceSetSolidColor(&gstate->src, &gstate->color); + _XrSurfaceSetSolidColor(gstate->src, &gstate->color); return XrStatusSuccess; } @@ -542,8 +630,8 @@ _XrGStateStroke(XrGState *gstate) } XcCompositeTrapezoids(gstate->dpy, gstate->operator, - _XrSurfaceGetXcSurface(&gstate->src), - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(gstate->src), + _XrSurfaceGetXcSurface(gstate->surface), gstate->alphaFormat, 0, 0, traps.xtraps, @@ -582,8 +670,8 @@ _XrGStateFill(XrGState *gstate) } XcCompositeTrapezoids(gstate->dpy, gstate->operator, - _XrSurfaceGetXcSurface(&gstate->src), - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(gstate->src), + _XrSurfaceGetXcSurface(gstate->surface), gstate->alphaFormat, 0, 0, traps.xtraps, @@ -701,14 +789,21 @@ _XrGStateShowImageTransform(XrGState *gstate, double tx, double ty) { XrStatus status; - XrSurface image_surface; + XrColor mask_color; + XrSurface image_surface, mask; double dst_width, dst_height; + _XrSurfaceInit(&mask, gstate->dpy); + _XrColorInit(&mask_color); + _XrColorSetAlpha(&mask_color, gstate->alpha); + + _XrSurfaceSetSolidColor(&mask, &mask_color); + _XrSurfaceInit(&image_surface, gstate->dpy); _XrSurfaceSetFormat(&image_surface, format); - status = _XrSurfaceSetImage(&image_surface, data, width, height, stride); + status = _XrSurfaceSetImage(&image_surface, data,width, height, stride); if (status) return status; @@ -720,8 +815,8 @@ _XrGStateShowImageTransform(XrGState *gstate, XcComposite(gstate->dpy, gstate->operator, _XrSurfaceGetXcSurface(&image_surface), - 0, - _XrSurfaceGetXcSurface(&gstate->surface), + _XrSurfaceGetXcSurface(&mask), + _XrSurfaceGetXcSurface(gstate->surface), 0, 0, 0, 0, gstate->current_pt.x, @@ -730,6 +825,7 @@ _XrGStateShowImageTransform(XrGState *gstate, dst_height); _XrSurfaceDeinit(&image_surface); + _XrSurfaceDeinit(&mask); return XrStatusSuccess; } @@ -737,11 +833,11 @@ _XrGStateShowImageTransform(XrGState *gstate, static Picture _XrGStateGetPicture(XrGState *gstate) { - return _XrSurfaceGetPicture(&gstate->surface); + return _XrSurfaceGetPicture(gstate->surface); } static Picture _XrGStateGetSrcPicture(XrGState *gstate) { - return _XrSurfaceGetPicture(&gstate->src); + return _XrSurfaceGetPicture(gstate->src); } diff --git a/xrint.h b/xrint.h index 35ed6b1d0..5b96e7c0e 100644 --- a/xrint.h +++ b/xrint.h @@ -171,10 +171,14 @@ typedef struct _XrSurface { Drawable drawable; GC gc; + unsigned int width; + unsigned int height; unsigned int depth; unsigned long xc_sa_mask; XcSurfaceAttributes xc_sa; + + XrFormat format; XcFormat *xc_format; XcSurface *xc_surface; @@ -248,10 +252,12 @@ typedef struct _XrGState { XrFont font; - XrSurface src; - XrSurface surface; + XrSurface *parent_surface; + XrSurface *surface; + XrSurface *src; XrSurface *mask; + double alpha; XrColor color; XrTransform ctm; @@ -341,6 +347,12 @@ _XrGStateDestroy(XrGState *gstate); XrGState * _XrGStateClone(XrGState *gstate); +XrStatus +_XrGStateBeginGroup(XrGState *gstate); + +XrStatus +_XrGStateEndGroup(XrGState *gstate); + XrStatus _XrGStateSetDrawable(XrGState *gstate, Drawable drawable); @@ -487,7 +499,7 @@ _XrColorSetAlpha(XrColor *color, double alpha); /* xrfont.c */ void -_XrFontInit(XrFont *font, XrGState *gstate); +_XrFontInit(XrFont *font); XrStatus _XrFontInitCopy(XrFont *font, XrFont *other); @@ -538,9 +550,18 @@ XrStatus _XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure); /* xrsurface.c */ +XrSurface * +_XrSurfaceCreate(Display *dpy); + void _XrSurfaceInit(XrSurface *surface, Display *dpy); +void +_XrSurfaceDeinit(XrSurface *surface); + +void +_XrSurfaceDestroy(XrSurface *surface); + void _XrSurfaceReference(XrSurface *surface); @@ -550,9 +571,6 @@ _XrSurfaceDereference(XrSurface *surface); void _XrSurfaceDereferenceDestroy(XrSurface *surface); -void -_XrSurfaceDeinit(XrSurface *surface); - void _XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color); @@ -569,6 +587,12 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform); void _XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable); +void +_XrSurfaceSetDrawableWH(XrSurface *surface, + Drawable drawable, + unsigned int width, + unsigned int height); + void _XrSurfaceSetVisual(XrSurface *surface, Visual *visual); @@ -581,6 +605,18 @@ _XrSurfaceGetXcSurface(XrSurface *surface); Picture _XrSurfaceGetPicture(XrSurface *surface); +Drawable +_XrSurfaceGetDrawable(XrSurface *surface); + +unsigned int +_XrSurfaceGetWidth(XrSurface *surface); + +unsigned int +_XrSurfaceGetHeight(XrSurface *surface); + +unsigned int +_XrSurfaceGetDepth(XrSurface *surface); + /* xrpen.c */ XrStatus _XrPenInit(XrPen *pen, double radius, XrGState *gstate); diff --git a/xrstate.c b/xrstate.c index 26b9f6e62..720f33705 100644 --- a/xrstate.c +++ b/xrstate.c @@ -50,6 +50,7 @@ _XrStateInit(XrState *xrs, Display *dpy) { xrs->dpy = dpy; xrs->stack = NULL; + xrs->status = XrStatusSuccess; return _XrStatePush(xrs); diff --git a/xrsurface.c b/xrsurface.c index b1dbdf2aa..88a750855 100644 --- a/xrsurface.c +++ b/xrsurface.c @@ -23,8 +23,23 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include "xrint.h" +XrSurface * +_XrSurfaceCreate(Display *dpy) +{ + XrSurface *surface; + + surface = malloc(sizeof(XrSurface)); + + if (surface) + _XrSurfaceInit(surface, dpy); + + return surface; +} + void _XrSurfaceInit(XrSurface *surface, Display *dpy) { @@ -33,11 +48,13 @@ _XrSurfaceInit(XrSurface *surface, Display *dpy) surface->drawable = 0; surface->gc = 0; + surface->width = 0; + surface->height = 0; surface->depth = 0; surface->xc_sa_mask = 0; - surface->xc_format = XcFindStandardFormat(dpy, PictStandardARGB32); + _XrSurfaceSetFormat(surface, XrFormatARGB32); surface->xc_surface = 0; surface->needs_new_xc_surface = 1; @@ -45,6 +62,22 @@ _XrSurfaceInit(XrSurface *surface, Display *dpy) surface->ref_count = 0; } +void +_XrSurfaceDeinit(XrSurface *surface) +{ + if (surface->xc_surface) + XcFreeSurface(surface->dpy, surface->xc_surface); + if (surface->gc) + XFreeGC(surface->dpy, surface->gc); +} + +void +_XrSurfaceDestroy(XrSurface *surface) +{ + _XrSurfaceDeinit(surface); + free(surface); +} + void _XrSurfaceReference(XrSurface *surface) { @@ -63,17 +96,10 @@ _XrSurfaceDereference(XrSurface *surface) void _XrSurfaceDereferenceDestroy(XrSurface *surface) { - _XrSurfaceDereference(surface); - if (surface->ref_count == 0) - free(surface); -} - -void -_XrSurfaceDeinit(XrSurface *surface) -{ - if (surface->xc_surface) - XcFreeSurface(surface->dpy, surface->xc_surface); + _XrSurfaceDestroy(surface); + else + _XrSurfaceDereference(surface); } void @@ -85,7 +111,7 @@ _XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color) DefaultRootWindow(surface->dpy), 1, 1, surface->xc_format->depth); - _XrSurfaceSetDrawable(surface, pix); + _XrSurfaceSetDrawableWH(surface, pix, 1, 1); surface->xc_sa_mask |= CPRepeat; surface->xc_sa.repeat = True; _XrSurfaceGetXcSurface(surface); @@ -121,7 +147,7 @@ _XrSurfaceSetImage(XrSurface *surface, DefaultRootWindow(surface->dpy), width, height, depth); - _XrSurfaceSetDrawable(surface, pix); + _XrSurfaceSetDrawableWH(surface, pix, width, height); image = XCreateImage(surface->dpy, DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)), @@ -178,11 +204,32 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform) void _XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable) +{ + Window root; + int x, y; + unsigned int border, depth; + unsigned int width, height; + + XGetGeometry (surface->dpy, drawable, + &root, &x, &y, + &width, &height, + &border, &depth); + + _XrSurfaceSetDrawableWH(surface, drawable, width, height); +} + +void +_XrSurfaceSetDrawableWH(XrSurface *surface, + Drawable drawable, + unsigned int width, + unsigned int height) { if (surface->gc) XFreeGC(surface->dpy, surface->gc); surface->drawable = drawable; + surface->width = width; + surface->height = height; surface->gc = XCreateGC(surface->dpy, surface->drawable, 0, 0); surface->needs_new_xc_surface = 1; @@ -198,7 +245,23 @@ _XrSurfaceSetVisual(XrSurface *surface, Visual *visual) void _XrSurfaceSetFormat(XrSurface *surface, XrFormat format) { + surface->format = format; surface->xc_format = XcFindStandardFormat(surface->dpy, format); + + switch (surface->format) { + case XrFormatARGB32: + surface->depth = 32; + case XrFormatRGB32: + /* XXX: Is this correct? */ + surface->depth = 24; + case XrFormatA8: + surface->depth = 8; + case XrFormatA1: + surface->depth = 1; + default: + surface->depth = 32; + } + surface->needs_new_xc_surface = 1; } @@ -234,3 +297,27 @@ _XrSurfaceGetPicture(XrSurface *surface) { return XcSurfaceGetPicture(_XrSurfaceGetXcSurface(surface)); } + +Drawable +_XrSurfaceGetDrawable(XrSurface *surface) +{ + return surface->drawable; +} + +unsigned int +_XrSurfaceGetWidth(XrSurface *surface) +{ + return surface->width; +} + +unsigned int +_XrSurfaceGetHeight(XrSurface *surface) +{ + return surface->height; +} + +unsigned int +_XrSurfaceGetDepth(XrSurface *surface) +{ + return surface->depth; +}