From b3b306dfd91b4126812254380dc3a7ae77f33935 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 14 May 2003 18:30:57 +0000 Subject: [PATCH] Added toplevel functions for setting surface matrix, filter. Introduced new XrMatrix object. Fixed to properly hint scaled fonts. --- ChangeLog | 31 ++++ README | 56 ++++--- src/Makefile.am | 4 +- src/Xr.h | 125 ++++++++++----- src/xr.c | 107 +++++++------ src/xrfont.c | 51 +++--- src/xrgstate.c | 272 ++++++++++++++++---------------- src/xrint.h | 134 ++++++---------- src/xrmatrix.c | 377 +++++++++++++++++++++++++++++++++++++++++++++ src/xrpathstroke.c | 14 +- src/xrpen.c | 8 +- src/xrsurface.c | 39 ++++- src/xrtransform.c | 301 ------------------------------------ 13 files changed, 837 insertions(+), 682 deletions(-) create mode 100644 src/xrmatrix.c delete mode 100644 src/xrtransform.c diff --git a/ChangeLog b/ChangeLog index 611aa2ae6..06f24d86d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2003-05-14 Carl Worth + + * src/xrfont.c (_XrFontResolveXftFont): Fixed fonts to pull + pixelsize out of the transformation matrix. Fonts are now properly + hinted regardless of scaling. + + * src/Xr.h: Three new functions for manipulating surfaces: + XrSurfaceSetMatrix, XrSurfaceGetMatrix, XrSurfaceSetFilter. + + * src/Xr.h: Removed broken XrShowImage* functions. Changed + XrShowSurface to not require X/Y but instead depend on the CTM for + translation, (or the surface transformation matrix). I'd like to + get rid of width/height as well but it turns out an XrSurface is + not aware of its dimensions. + + * src/Xr.h: Added convenience function for building rectangular + paths: XrRectangle. + + * src/Xr.h: Added functions for performing transformations with + the CTM and its inverse: XrTransformPoint, XrTransformDistance, + XrInverseTransformPoint, XrInverseTransformDistance. + + * src/Xr.h: XrConcatMatrix and XrSetMatrix now accept a pointer to + an XrMatrix rather than 6 doubles. + + * src/Xr.h: Now exporting opaque XrMatrix object with several + functions: XrMatrixCreate, XrMatrixDestroy, XrMatrixCopy, + XrMatrixSetIdentity, XrMatrixSetAffine, XrMatrixTranslate, + XrMatrixScale, XrMatrixRotate, XrMatrixInvert, XrMatrixMultiply, + XrMatrixTransformDistance, XrMatrixTransformPoint. + 2003-05-12 Carl Worth * src/Xr.h: Added XrSetPattern. See also XrSurfaceSetRepeat. diff --git a/README b/README index 2296a9130..faeba682e 100644 --- a/README +++ b/README @@ -1,13 +1,29 @@ -Xr - Rendering for X +Xr - Rendering library + +Compiling +--------- +See the INSTALL document for build instructions. Description ----------- Xr provides anti-aliased vector-based rendering for X. Paths consist of line segments and cubic splines and can be rendered at any width with various join and cap styles. All colors may be specified with -optional translucence (opacity/alpha) throught the extended +optional translucence (opacity/alpha) and combined using the extended Porter/Duff compositing algebra as found in the X Render Extension. +Xr exports a stateful rendering API similar in spirit to the path +construction, text, and painting operators of PostScript, (with the +significant addition of translucence in the imaging model). When +complete, the API is intended to support the complete imaging model of +PDF 1.4. + +Xr relies on the Xc library for backend rendering. Xc provides an +abstract interface for rendering to multiple target types. As of this +writing, Xc allows Xr to target X drawables as well as generic image +buffers. Future backends such as PostScript, PDF, and perhaps OpenGL +are currently being planned. + Dependencies ------------ Xr currently requires the following supporting libraries: @@ -15,27 +31,18 @@ Xr currently requires the following supporting libraries: Xc Xft fontconfig - -Usage ------ -Xr exports a stateful rendering API similar in spirit to the path -construction, text, and painting operators of PostScript, (with the -significant addition of translucence in the imaging model). The API -was carefully designed to be easily understood with as little -additional explanation as possible. All functions take a minimal -number of arguments so that the number and order of arguments should -be easy to remember without the need to continually consult reference -documentation while developing with Xr. + libic + libpixregion Documentation ------------- -As mentioned above, we hope that users of Xr will be productive -without having to consult the documentation often. Ideally, a simple -glance at the Xr.h header file will provide enough information for the -programmer. +There's not much documentation yet apart from the Xr.h header +file. We'll be correcting that shortly. -We'll see if we've been successful in our goal, since for the moment -the Xr.h header file is the only documentation that currently exists. +In the meantime, the xrtest module in CVS provides a few example +programs using Xr. These may be helpful to a programmer just beginning +with Xr. Also, familiarity with the PostScript imaging model will +help in understanding Xr. History ------- @@ -43,3 +50,14 @@ Xr was developed by Carl Worth and Keith Packard . Many thanks are due to Lyle Ramshaw without whose patient help our ignorance would be much more apparent. +Mailing List +------------ +If you have trouble with Xr or you have some ideas for how it could be +improved, please feel free to send a message to xr@xwin.org. + +Xr is still under active development and all discussion happens on +that list. So if you want to lurk or, (even better), take part in the +development, take a look. Subscription information and archives are +available: + + http://xwin.org/cgi-bin/mailman/listinfo/xr diff --git a/src/Makefile.am b/src/Makefile.am index 18e1973ca..4cb40d263 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ libXr_la_SOURCES = \ xrcolor.c \ xrfont.c \ xrgstate.c \ + xrmatrix.c \ xrmisc.c \ xrpath.c \ xrpathbounds.c \ @@ -18,11 +19,10 @@ libXr_la_SOURCES = \ xrspline.c \ xrstate.c \ xrsurface.c \ - xrtransform.c \ xrtraps.c libXr_la_LDFLAGS = -version-info @VERSION_INFO@ INCLUDES = $(XR_CFLAGS) $(X_CFLAGS) -libXr_la_LIBADD = $(XR_LIBS) +libXr_la_LIBADD = $(XR_LIBS) -lm diff --git a/src/Xr.h b/src/Xr.h index 1b94a4c48..b59211b45 100644 --- a/src/Xr.h +++ b/src/Xr.h @@ -30,6 +30,7 @@ typedef struct _XrState XrState; typedef struct _XrSurface XrSurface; +typedef struct _XrMatrix XrMatrix; _XFUNCPROTOBEGIN @@ -166,18 +167,11 @@ XrRotate(XrState *xrs, double angle); void XrConcatMatrix(XrState *xrs, - double a, double b, - double c, double d, - double tx, double ty); - -/* XXX: Probably want to expose an XrMatrix object here, with XrMatrixTransformPoint, etc. - That might make it easier to expand to projective transforms later */ + XrMatrix *matrix); void XrSetMatrix(XrState *xrs, - double a, double b, - double c, double d, - double tx, double ty); + XrMatrix *matrix); /* XXX: Postscript has both a defaultmatrix and an identmatrix. But there, they do different things. Here, where they perform the same @@ -189,6 +183,18 @@ XrDefaultMatrix(XrState *xrs); void XrIdentityMatrix(XrState *xrs); +void +XrTransformPoint (XrState *xrs, double *x, double *y); + +void +XrTransformDistance (XrState *xrs, double *dx, double *dy); + +void +XrInverseTransformPoint (XrState *xrs, double *x, double *y); + +void +XrInverseTransformDistance (XrState *xrs, double *dx, double *dy); + /* Path creation functions */ void XrNewPath(XrState *xrs); @@ -217,6 +223,11 @@ XrRelCurveTo(XrState *xrs, double dx2, double dy2, double dx3, double dy3); +void +XrRectangle (XrState *xrs, + double x, double y, + double width, double height); + void XrClosePath(XrState *xrs); @@ -232,12 +243,18 @@ void XrClip(XrState *xrs); /* Font/Text functions */ + +/* XXX: The font support should probably expose an XrFont object with + several functions, (XrFontTransform, etc.) in a parallel manner as + XrMatrix and (eventually) XrColor */ void XrSelectFont(XrState *xrs, const char *key); void XrScaleFont(XrState *xrs, double scale); +/* XXX: Probably want to use an XrMatrix here, (to fix as part of the + big text support rewrite) */ void XrTransformFont(XrState *xrs, double a, double b, @@ -255,38 +272,9 @@ XrShowText(XrState *xrs, const unsigned char *utf8); /* Image functions */ -/* XXX: Is "Show" the right term here? With operators such as - OutReverse we may not actually be showing any part of the - surface. */ -void -XrShowImage(XrState *xrs, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride); - -void -XrShowImageTransform(XrState *xrs, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride, - double a, double b, - double c, double d, - double tx, double ty); - -/* XXX: The ShowImage/ShowSurface APIs definitely need some work. If - we want both then one should be a convenience function for the - other and the interfaces should be consistent in some sense. One - trick is to resolve the interaction with XrSurfaceSetTransform (if - it is to be exposed) */ void XrShowSurface (XrState *xrs, XrSurface *surface, - int x, - int y, int width, int height); @@ -393,11 +381,68 @@ XrStatus XrSurfaceSetClipRegion (XrSurface *surface, Region region); */ +/* XXX: Note: The current Render/Ic implementations don't do the right + thing with repeat when the surface has a non-identity matrix. */ XrStatus XrSurfaceSetRepeat (XrSurface *surface, int repeat); -/* XXX: Need some of the following to make pattern support useful: - XrSurfaceSetTransform, XrSurfaceSetMatrix, XrSurfaceScale, XrSurfaceTranslate */ +XrStatus +XrSurfaceSetMatrix(XrSurface *surface, XrMatrix *matrix); + +XrStatus +XrSurfaceGetMatrix (XrSurface *surface, XrMatrix *matrix); + +typedef enum { + XrFilterFast = XcFilterFast, + XrFilterGood = XcFilterGood, + XrFilterBest = XcFilterBest, + XrFilterNearest = XcFilterNearest, + XrFilterBilinear = XcFilterBilinear +} XrFilter; + +XrStatus +XrSurfaceSetFilter(XrSurface *surface, XrFilter filter); + +/* Matrix functions */ + +XrMatrix * +XrMatrixCreate (void); + +void +XrMatrixDestroy (XrMatrix *matrix); + +XrStatus +XrMatrixCopy(XrMatrix *matrix, const XrMatrix *other); + +XrStatus +XrMatrixSetIdentity (XrMatrix *matrix); + +XrStatus +XrMatrixSetAffine (XrMatrix *xrs, + double a, double b, + double c, double d, + double tx, double ty); + +XrStatus +XrMatrixTranslate (XrMatrix *matrix, double tx, double ty); + +XrStatus +XrMatrixScale (XrMatrix *matrix, double sx, double sy); + +XrStatus +XrMatrixRotate (XrMatrix *matrix, double radians); + +XrStatus +XrMatrixInvert(XrMatrix *matrix); + +XrStatus +XrMatrixMultiply (XrMatrix *result, const XrMatrix *a, const XrMatrix *b); + +XrStatus +XrMatrixTransformDistance (XrMatrix *xr, double *dx, double *dy); + +XrStatus +XrMatrixTransformPoint (XrMatrix *xr, double *x, double *y); _XFUNCPROTOEND diff --git a/src/xr.c b/src/xr.c index a353f61bc..5f4ee9ff9 100644 --- a/src/xr.c +++ b/src/xr.c @@ -291,26 +291,22 @@ XrRotate(XrState *xrs, double angle) void XrConcatMatrix(XrState *xrs, - double a, double b, - double c, double d, - double tx, double ty) + XrMatrix *matrix) { if (xrs->status) return; - xrs->status = _XrGStateConcatMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty); + xrs->status = _XrGStateConcatMatrix(_XR_CURRENT_GSTATE(xrs), matrix); } void XrSetMatrix(XrState *xrs, - double a, double b, - double c, double d, - double tx, double ty) + XrMatrix *matrix) { if (xrs->status) return; - xrs->status = _XrGStateSetMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty); + xrs->status = _XrGStateSetMatrix(_XR_CURRENT_GSTATE(xrs), matrix); } void @@ -331,6 +327,42 @@ XrIdentityMatrix(XrState *xrs) xrs->status = _XrGStateIdentityMatrix(_XR_CURRENT_GSTATE(xrs)); } +void +XrTransformPoint (XrState *xrs, double *x, double *y) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateTransformPoint (_XR_CURRENT_GSTATE (xrs), x, y); +} + +void +XrTransformDistance (XrState *xrs, double *dx, double *dy) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateTransformDistance (_XR_CURRENT_GSTATE (xrs), dx, dy); +} + +void +XrInverseTransformPoint (XrState *xrs, double *x, double *y) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateInverseTransformPoint (_XR_CURRENT_GSTATE (xrs), x, y); +} + +void +XrInverseTransformDistance (XrState *xrs, double *dx, double *dy) +{ + if (xrs->status) + return; + + xrs->status = _XrGStateInverseTransformDistance (_XR_CURRENT_GSTATE (xrs), dx, dy); +} + void XrNewPath(XrState *xrs) { @@ -406,6 +438,21 @@ XrRelCurveTo(XrState *xrs, dx3, dy3); } +void +XrRectangle (XrState *xrs, + double x, double y, + double width, double height) +{ + if (xrs->status) + return; + + XrMoveTo (xrs, x, y); + XrRelLineTo (xrs, width, 0); + XrRelLineTo (xrs, 0, height); + XrRelLineTo (xrs, -width, 0); + XrClosePath (xrs); +} + void XrClosePath(XrState *xrs) { @@ -505,49 +552,9 @@ XrShowText(XrState *xrs, const unsigned char *utf8) xrs->status = _XrGStateShowText(_XR_CURRENT_GSTATE(xrs), utf8); } -void -XrShowImage(XrState *xrs, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride) -{ - if (xrs->status) - return; - - xrs->status = _XrGStateShowImage(_XR_CURRENT_GSTATE(xrs), - data, format, - width, height, stride); -} - -void -XrShowImageTransform(XrState *xrs, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride, - double a, double b, - double c, double d, - double tx, double ty) -{ - if (xrs->status) - return; - - xrs->status = _XrGStateShowImageTransform(_XR_CURRENT_GSTATE(xrs), - data, format, - width, height, stride, - a, b, - c, d, - tx, ty); -} - void XrShowSurface (XrState *xrs, XrSurface *surface, - int x, - int y, int width, int height) { @@ -555,9 +562,7 @@ XrShowSurface (XrState *xrs, return; xrs->status = _XrGStateShowSurface (_XR_CURRENT_GSTATE (xrs), - surface, - x, y, - width, height); + surface, width, height); } XrStatus diff --git a/src/xrfont.c b/src/xrfont.c index 9349cee2a..f57abe3ff 100644 --- a/src/xrfont.c +++ b/src/xrfont.c @@ -32,11 +32,10 @@ _XrFontInit(XrFont *font) { font->key = (unsigned char *) strdup(XR_FONT_KEY_DEFAULT); - font->scale = 1.0; - font->has_transform = 0; - font->dpy = NULL; font->xft_font = NULL; + + XrMatrixSetIdentity(&font->matrix); } XrStatus @@ -66,7 +65,7 @@ _XrFontDeinit(XrFont *font) free(font->key); font->key = NULL; - _XrTransformDeinit(&font->transform); + _XrMatrixFini(&font->matrix); if (font->xft_font) XftFontClose(font->dpy, font->xft_font); @@ -93,14 +92,7 @@ _XrFontSelect(XrFont *font, const char *key) XrStatus _XrFontScale(XrFont *font, double scale) { - if (font->has_transform) { - XrTransform tmp; - - _XrTransformInitScale(&tmp, scale, scale); - _XrTransformMultiplyIntoRight(&tmp, &font->transform); - } else { - font->scale *= scale; - } + XrMatrixScale(&font->matrix, scale, scale); return XrStatusSuccess; } @@ -110,16 +102,10 @@ _XrFontTransform(XrFont *font, double a, double b, double c, double d) { - XrTransform tmp; + XrMatrix m; - if (! font->has_transform) { - _XrTransformInitScale(&tmp, font->scale, font->scale); - } - - _XrTransformInitMatrix(&tmp, a, b, c, d, 0, 0); - _XrTransformMultiplyIntoRight(&tmp, &font->transform); - - font->has_transform = 1; + XrMatrixSetAffine(&m, a, b, c, d, 0, 0); + _XrMatrixMultiplyIntoRight(&m, &font->matrix); return XrStatusSuccess; } @@ -130,8 +116,10 @@ _XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font) FcPattern *pattern; FcPattern *match; FcResult result; - XrTransform matrix; + XrMatrix matrix; FcMatrix fc_matrix; + double expansion; + double font_size; if (font->xft_font) { *xft_font = font->xft_font; @@ -142,11 +130,20 @@ _XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font) matrix = gstate->ctm; - if (!font->has_transform) { - FcPatternAddDouble(pattern, "pixelsize", font->scale); - } else { - _XrTransformMultiplyIntoRight(&font->transform, &matrix); - } + _XrMatrixMultiplyIntoRight(&font->matrix, &matrix); + + /* Pull the scale factor out of the final matrix and use it to set + the direct pixelsize of the font. This enables freetype to + perform proper hinting at any size. */ + + /* XXX: The determinant gives an area expansion factor, so the + math below should be correct for the (common) case of uniform + X/Y scaling. Is there anything different we would want to do + for non-uniform X/Y scaling? */ + _XrMatrixComputeDeterminant (&matrix, &expansion); + font_size = sqrt (expansion); + FcPatternAddDouble (pattern, "pixelsize", font_size); + XrMatrixScale (&matrix, 1.0 / font_size, 1.0 / font_size); fc_matrix.xx = matrix.m[0][0]; fc_matrix.xy = matrix.m[0][1]; diff --git a/src/xrgstate.c b/src/xrgstate.c index 15a443bbc..8a2688276 100644 --- a/src/xrgstate.c +++ b/src/xrgstate.c @@ -74,14 +74,16 @@ _XrGStateInit(XrGState *gstate) gstate->surface = NULL; gstate->solid = NULL; gstate->pattern = NULL; + gstate->pattern_offset.x = 0.0; + gstate->pattern_offset.y = 0.0; gstate->clip.surface = NULL; gstate->alpha = 1.0; _XrColorInit(&gstate->color); - _XrTransformInitIdentity(&gstate->ctm); - _XrTransformInitIdentity(&gstate->ctm_inverse); + XrMatrixSetIdentity(&gstate->ctm); + XrMatrixSetIdentity(&gstate->ctm_inverse); _XrPathInit(&gstate->path); @@ -154,8 +156,8 @@ _XrGStateDeinit(XrGState *gstate) _XrColorDeinit(&gstate->color); - _XrTransformDeinit(&gstate->ctm); - _XrTransformDeinit(&gstate->ctm_inverse); + _XrMatrixFini(&gstate->ctm); + _XrMatrixFini(&gstate->ctm_inverse); _XrPathDeinit(&gstate->path); @@ -331,6 +333,12 @@ _XrGStateSetPattern (XrGState *gstate, XrSurface *pattern) gstate->pattern = pattern; _XrSurfaceReference (gstate->pattern); + gstate->pattern_offset.x = 0; + gstate->pattern_offset.y = 0; + XrMatrixTransformPoint (&gstate->ctm, + &gstate->pattern_offset.x, + &gstate->pattern_offset.y); + return XrStatusSuccess; } @@ -353,6 +361,9 @@ _XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue) { _XrColorSetRGB(&gstate->color, red, green, blue); + XrSurfaceDestroy(gstate->pattern); + gstate->pattern = NULL; + XrSurfaceDestroy(gstate->solid); gstate->solid = XrSurfaceCreateNextToSolid (gstate->surface, XrFormatARGB32, 1, 1, @@ -487,13 +498,13 @@ _XrGStateGetMiterLimit(XrGState *gstate) XrStatus _XrGStateTranslate(XrGState *gstate, double tx, double ty) { - XrTransform tmp; + XrMatrix tmp; - _XrTransformInitTranslate(&tmp, tx, ty); - _XrTransformMultiplyIntoRight(&tmp, &gstate->ctm); + _XrMatrixSetTranslate(&tmp, tx, ty); + _XrMatrixMultiplyIntoRight(&tmp, &gstate->ctm); - _XrTransformInitTranslate(&tmp, -tx, -ty); - _XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); + _XrMatrixSetTranslate(&tmp, -tx, -ty); + _XrMatrixMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); return XrStatusSuccess; } @@ -501,13 +512,13 @@ _XrGStateTranslate(XrGState *gstate, double tx, double ty) XrStatus _XrGStateScale(XrGState *gstate, double sx, double sy) { - XrTransform tmp; + XrMatrix tmp; - _XrTransformInitScale(&tmp, sx, sy); - _XrTransformMultiplyIntoRight(&tmp, &gstate->ctm); + _XrMatrixSetScale(&tmp, sx, sy); + _XrMatrixMultiplyIntoRight(&tmp, &gstate->ctm); - _XrTransformInitScale(&tmp, 1/sx, 1/sy); - _XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); + _XrMatrixSetScale(&tmp, 1/sx, 1/sy); + _XrMatrixMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); return XrStatusSuccess; } @@ -515,46 +526,42 @@ _XrGStateScale(XrGState *gstate, double sx, double sy) XrStatus _XrGStateRotate(XrGState *gstate, double angle) { - XrTransform tmp; + XrMatrix tmp; - _XrTransformInitRotate(&tmp, angle); - _XrTransformMultiplyIntoRight(&tmp, &gstate->ctm); + _XrMatrixSetRotate(&tmp, angle); + _XrMatrixMultiplyIntoRight(&tmp, &gstate->ctm); - _XrTransformInitRotate(&tmp, -angle); - _XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); + _XrMatrixSetRotate(&tmp, -angle); + _XrMatrixMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); return XrStatusSuccess; } XrStatus _XrGStateConcatMatrix(XrGState *gstate, - double a, double b, - double c, double d, - double tx, double ty) + XrMatrix *matrix) { - XrTransform tmp; + XrMatrix tmp; - _XrTransformInitMatrix(&tmp, a, b, c, d, tx, ty); - _XrTransformMultiplyIntoRight(&tmp, &gstate->ctm); + XrMatrixCopy(&tmp, matrix); + _XrMatrixMultiplyIntoRight(&tmp, &gstate->ctm); - _XrTransformInvert(&tmp); - _XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); + XrMatrixInvert(&tmp); + _XrMatrixMultiplyIntoLeft(&gstate->ctm_inverse, &tmp); return XrStatusSuccess; } XrStatus _XrGStateSetMatrix(XrGState *gstate, - double a, double b, - double c, double d, - double tx, double ty) + XrMatrix *matrix) { XrStatus status; - _XrTransformInitMatrix(&gstate->ctm, a, b, c, d, tx, ty); + XrMatrixCopy(&gstate->ctm, matrix); - gstate->ctm_inverse = gstate->ctm; - status = _XrTransformInvert (&gstate->ctm_inverse); + XrMatrixCopy(&gstate->ctm_inverse, matrix); + status = XrMatrixInvert (&gstate->ctm_inverse); if (status) return status; @@ -564,8 +571,40 @@ _XrGStateSetMatrix(XrGState *gstate, XrStatus _XrGStateIdentityMatrix(XrGState *gstate) { - _XrTransformInitIdentity(&gstate->ctm); - _XrTransformInitIdentity(&gstate->ctm_inverse); + XrMatrixSetIdentity(&gstate->ctm); + XrMatrixSetIdentity(&gstate->ctm_inverse); + + return XrStatusSuccess; +} + +XrStatus +_XrGStateTransformPoint (XrGState *gstate, double *x, double *y) +{ + XrMatrixTransformPoint (&gstate->ctm, x, y); + + return XrStatusSuccess; +} + +XrStatus +_XrGStateTransformDistance (XrGState *gstate, double *dx, double *dy) +{ + XrMatrixTransformDistance (&gstate->ctm, dx, dy); + + return XrStatusSuccess; +} + +XrStatus +_XrGStateInverseTransformPoint (XrGState *gstate, double *x, double *y) +{ + XrMatrixTransformPoint (&gstate->ctm_inverse, x, y); + + return XrStatusSuccess; +} + +XrStatus +_XrGStateInverseTransformDistance (XrGState *gstate, double *dx, double *dy) +{ + XrMatrixTransformDistance (&gstate->ctm_inverse, dx, dy); return XrStatusSuccess; } @@ -593,7 +632,7 @@ _XrGStateMoveTo(XrGState *gstate, double x, double y) { XrStatus status; - _XrTransformPoint(&gstate->ctm, &x, &y); + XrMatrixTransformPoint(&gstate->ctm, &x, &y); status = _XrPathMoveTo(&gstate->path, x, y); @@ -609,7 +648,7 @@ _XrGStateLineTo(XrGState *gstate, double x, double y) { XrStatus status; - _XrTransformPoint(&gstate->ctm, &x, &y); + XrMatrixTransformPoint(&gstate->ctm, &x, &y); status = _XrPathLineTo(&gstate->path, x, y); @@ -626,9 +665,9 @@ _XrGStateCurveTo(XrGState *gstate, { XrStatus status; - _XrTransformPoint(&gstate->ctm, &x1, &y1); - _XrTransformPoint(&gstate->ctm, &x2, &y2); - _XrTransformPoint(&gstate->ctm, &x3, &y3); + XrMatrixTransformPoint(&gstate->ctm, &x1, &y1); + XrMatrixTransformPoint(&gstate->ctm, &x2, &y2); + XrMatrixTransformPoint(&gstate->ctm, &x3, &y3); status = _XrPathCurveTo(&gstate->path, x1, y1, @@ -646,7 +685,7 @@ _XrGStateRelMoveTo(XrGState *gstate, double dx, double dy) XrStatus status; double x, y; - _XrTransformDistance(&gstate->ctm, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm, &dx, &dy); x = gstate->current_pt.x + dx; y = gstate->current_pt.y + dy; @@ -666,7 +705,7 @@ _XrGStateRelLineTo(XrGState *gstate, double dx, double dy) XrStatus status; double x, y; - _XrTransformDistance(&gstate->ctm, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm, &dx, &dy); x = gstate->current_pt.x + dx; y = gstate->current_pt.y + dy; @@ -686,9 +725,9 @@ _XrGStateRelCurveTo(XrGState *gstate, { XrStatus status; - _XrTransformDistance(&gstate->ctm, &dx1, &dy1); - _XrTransformDistance(&gstate->ctm, &dx2, &dy2); - _XrTransformDistance(&gstate->ctm, &dx3, &dy3); + XrMatrixTransformDistance(&gstate->ctm, &dx1, &dy1); + XrMatrixTransformDistance(&gstate->ctm, &dx2, &dy2); + XrMatrixTransformDistance(&gstate->ctm, &dx3, &dy3); status = _XrPathCurveTo(&gstate->path, gstate->current_pt.x + dx1, gstate->current_pt.y + dy1, @@ -722,7 +761,7 @@ _XrGStateGetCurrentPoint(XrGState *gstate, double *x, double *y) *x = gstate->current_pt.x; *y = gstate->current_pt.y; - _XrTransformPoint(&gstate->ctm_inverse, x, y); + XrMatrixTransformPoint(&gstate->ctm_inverse, x, y); return XrStatusSuccess; } @@ -764,6 +803,9 @@ _XrGStateClipAndCompositeTrapezoids(XrGState *gstate, XrSurface *dst, XrTraps *traps) { + if (traps->num_xtraps == 0) + return XrStatusSuccess; + if (gstate->clip.surface) { XrSurface *intermediate, *white; @@ -801,10 +843,21 @@ _XrGStateClipAndCompositeTrapezoids(XrGState *gstate, XrSurfaceDestroy (white); } else { + double xoff, yoff; + + if (traps->xtraps[0].left.p1.y < traps->xtraps[0].left.p2.y) { + xoff = traps->xtraps[0].left.p1.x; + yoff = traps->xtraps[0].left.p1.y; + } else { + xoff = traps->xtraps[0].left.p2.x; + yoff = traps->xtraps[0].left.p2.y; + } + XcCompositeTrapezoids(gstate->operator, src->xc_surface, dst->xc_surface, - 0, 0, + XFixedToDouble(xoff) - gstate->pattern_offset.x, + XFixedToDouble(yoff) - gstate->pattern_offset.y, traps->xtraps, traps->num_xtraps); } @@ -967,36 +1020,16 @@ _XrGStateShowText(XrGState *gstate, const unsigned char *utf8) } XrStatus -_XrGStateShowImage(XrGState *gstate, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride) +_XrGStateShowSurface(XrGState *gstate, + XrSurface *surface, + int width, + int height) { - return _XrGStateShowImageTransform(gstate, - data, format, width, height, stride, - width, 0, - 0, height, - 0, 0); -} - -XrStatus -_XrGStateShowImageTransform(XrGState *gstate, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride, - double a, double b, - double c, double d, - double tx, double ty) -{ - XrSurface *image_surface, *mask; - XrTransform user_to_image, image_to_user; - XrTransform image_to_device, device_to_image; - double dst_x, dst_y; - double dst_width, dst_height; + XrSurface *mask; + XrMatrix user_to_image, image_to_user; + XrMatrix image_to_device, device_to_image; + double device_x, device_y; + double device_width, device_height; mask = XrSurfaceCreateNextToSolid (gstate->surface, XrFormatA8, @@ -1005,81 +1038,40 @@ _XrGStateShowImageTransform(XrGState *gstate, gstate->alpha); if (mask == NULL) return XrStatusNoMemory; + XrSurfaceSetRepeat (mask, 1); - image_surface = XrSurfaceCreateNextTo (gstate->surface, format, width, height); - if (image_surface == NULL) { - XrSurfaceDestroy (mask); - return XrStatusNoMemory; - } - - /* XXX: Need a way to transfer bits to an XcSurface - XcPutImage (image_surface->xc_surface, data, width, height, stride); - */ - - _XrTransformInitMatrix(&user_to_image, a, b, c, d, tx, ty); - _XrTransformMultiply(&gstate->ctm_inverse, &user_to_image, &device_to_image); - _XrSurfaceSetTransform(image_surface, &device_to_image); + XrSurfaceGetMatrix (surface, &user_to_image); + XrMatrixMultiply (&device_to_image, &gstate->ctm_inverse, &user_to_image); + XrSurfaceSetMatrix (surface, &device_to_image); image_to_user = user_to_image; - _XrTransformInvert (&image_to_user); - _XrTransformMultiply (&image_to_user, &gstate->ctm, &image_to_device); - - dst_x = 0; - dst_y = 0; - dst_width = width; - dst_height = height; - _XrTransformBoundingBox(&image_to_device, - &dst_x, &dst_y, - &dst_width, &dst_height); + XrMatrixInvert (&image_to_user); + XrMatrixMultiply (&image_to_device, &image_to_user, &gstate->ctm); + device_x = 0; + device_y = 0; + device_width = width; + device_height = height; + _XrMatrixTransformBoundingBox(&image_to_device, + &device_x, &device_y, + &device_width, &device_height); + + /* XXX: The +2 here looks bogus to me */ XcComposite(gstate->operator, - image_surface->xc_surface, + surface->xc_surface, mask->xc_surface, gstate->surface->xc_surface, - dst_x, dst_y, + device_x, device_y, 0, 0, - dst_x, dst_y, - dst_width + 2, - dst_height + 2); - - XrSurfaceDestroy (image_surface); - XrSurfaceDestroy (mask); - - return XrStatusSuccess; -} - -XrStatus -_XrGStateShowSurface(XrGState *gstate, - XrSurface *surface, - int x, - int y, - int width, - int height) -{ - XrSurface *mask; - - mask = XrSurfaceCreateNextToSolid (gstate->surface, - XrFormatARGB32, - 1, 1, - 1.0, 1.0, 1.0, - gstate->alpha); - if (mask == NULL) - return XrStatusNoMemory; - - XrSurfaceSetRepeat (mask, 1); - - XcComposite (gstate->operator, - surface->xc_surface, - mask->xc_surface, - gstate->surface->xc_surface, - x, y, - 0, 0, - x, y, - width, - height); + device_x, device_y, + device_width + 2, + device_height + 2); XrSurfaceDestroy (mask); + /* restore the matrix originally in the surface */ + XrSurfaceSetMatrix (surface, &user_to_image); + return XrStatusSuccess; } diff --git a/src/xrint.h b/src/xrint.h index fbf15ded2..217bf21b6 100644 --- a/src/xrint.h +++ b/src/xrint.h @@ -177,9 +177,9 @@ typedef struct _XrColor { XcColor xc_color; } XrColor; -typedef struct _XrTransform { +struct _XrMatrix { double m[3][2]; -} XrTransform; +}; typedef struct _XrTraps { int num_xtraps; @@ -187,15 +187,13 @@ typedef struct _XrTraps { XTrapezoid *xtraps; } XrTraps; -/* XXX: What should this really be? */ -#define XR_FONT_KEY_DEFAULT "mono" +#define XR_FONT_KEY_DEFAULT "serif" typedef struct _XrFont { unsigned char *key; double scale; - int has_transform; - XrTransform transform; + XrMatrix matrix; Display *dpy; XftFont *xft_font; @@ -241,14 +239,15 @@ typedef struct _XrGState { XrSurface *surface; XrSurface *solid; XrSurface *pattern; + XPointDouble pattern_offset; XrClipRec clip; double alpha; XrColor color; - XrTransform ctm; - XrTransform ctm_inverse; + XrMatrix ctm; + XrMatrix ctm_inverse; XrPath path; @@ -403,19 +402,27 @@ _XrGStateRotate(XrGState *gstate, double angle); XrStatus _XrGStateConcatMatrix(XrGState *gstate, - double a, double b, - double c, double d, - double tx, double ty); + XrMatrix *matrix); XrStatus _XrGStateSetMatrix(XrGState *gstate, - double a, double b, - double c, double d, - double tx, double ty); + XrMatrix *matrix); XrStatus _XrGStateIdentityMatrix(XrGState *xrs); +XrStatus +_XrGStateTransformPoint (XrGState *gstate, double *x, double *y); + +XrStatus +_XrGStateTransformDistance (XrGState *gstate, double *dx, double *dy); + +XrStatus +_XrGStateInverseTransformPoint (XrGState *gstate, double *x, double *y); + +XrStatus +_XrGStateInverseTransformDistance (XrGState *gstate, double *dx, double *dy); + XrStatus _XrGStateNewPath(XrGState *gstate); @@ -479,30 +486,9 @@ _XrGStateTextExtents(XrGState *gstate, XrStatus _XrGStateShowText(XrGState *gstate, const unsigned char *utf8); -XrStatus -_XrGStateShowImage(XrGState *gstate, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride); - -XrStatus -_XrGStateShowImageTransform(XrGState *gstate, - char *data, - XrFormat format, - unsigned int width, - unsigned int height, - unsigned int stride, - double a, double b, - double c, double d, - double tx, double ty); - XrStatus _XrGStateShowSurface(XrGState *gstate, XrSurface *surface, - int x, - int y, int width, int height); @@ -590,9 +576,6 @@ _XrPathStrokeToTraps (XrPath *path, XrGState *gstate, XrTraps *traps); void _XrSurfaceReference(XrSurface *surface); -XrStatus -_XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform); - XcSurface * _XrSurfaceGetXcSurface(XrSurface *surface); @@ -663,59 +646,42 @@ _XrSplineDecompose(XrSpline *spline, double tolerance); void _XrSplineDeinit(XrSpline *spline); -/* xrtransform.c */ +/* xrmatrix.c */ void -_XrTransformInitIdentity(XrTransform *transform); +_XrMatrixInit(XrMatrix *matrix); void -_XrTransformDeinit(XrTransform *transform); - -void -_XrTransformInitMatrix(XrTransform *transform, - double a, double b, - double c, double d, - double tx, double ty); - -void -_XrTransformInitTranslate(XrTransform *transform, - double tx, double ty); - -void -_XrTransformInitScale(XrTransform *transform, - double sx, double sy); - -void -_XrTransformInitRotate(XrTransform *transform, - double angle); - -void -_XrTransformMultiplyIntoLeft(XrTransform *t1, const XrTransform *t2); - -void -_XrTransformMultiplyIntoRight(const XrTransform *t1, XrTransform *t2); - -void -_XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *new); - -void -_XrTransformDistance(XrTransform *transform, double *dx, double *dy); - -void -_XrTransformPoint(XrTransform *transform, double *x, double *y); - -void -_XrTransformBoundingBox(XrTransform *transform, - double *x, double *y, - double *width, double *height); +_XrMatrixFini(XrMatrix *matrix); XrStatus -_XrTransformInvert(XrTransform *transform); +_XrMatrixSetTranslate(XrMatrix *matrix, + double tx, double ty); -void -_XrTransformComputeDeterminant(XrTransform *transform, double *det); +XrStatus +_XrMatrixSetScale(XrMatrix *matrix, + double sx, double sy); -void -_XrTransformComputeEigenValues(XrTransform *transform, double *lambda1, double *lambda2); +XrStatus +_XrMatrixSetRotate(XrMatrix *matrix, + double angle); + +XrStatus +_XrMatrixMultiplyIntoLeft(XrMatrix *t1, const XrMatrix *t2); + +XrStatus +_XrMatrixMultiplyIntoRight(const XrMatrix *t1, XrMatrix *t2); + + +XrStatus +_XrMatrixTransformBoundingBox(XrMatrix *matrix, + double *x, double *y, + double *width, double *height); + +XrStatus +_XrMatrixComputeDeterminant(XrMatrix *matrix, double *det); + +XrStatus +_XrMatrixComputeEigenValues(XrMatrix *matrix, double *lambda1, double *lambda2); /* xrtraps.c */ void diff --git a/src/xrmatrix.c b/src/xrmatrix.c new file mode 100644 index 000000000..7f9b66821 --- /dev/null +++ b/src/xrmatrix.c @@ -0,0 +1,377 @@ +/* + * $XFree86: $ + * + * Copyright © 2002 Carl D. Worth + * + * 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. + * + * 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. + */ + +#include +#include + +#include "xrint.h" + +static XrMatrix XR_MATRIX_IDENTITY = { + { + {1, 0}, + {0, 1}, + {0, 0} + } +}; + +static void +_XrMatrixScalarMultiply(XrMatrix *matrix, double scalar); + +static void +_XrMatrixComputeAdjoint(XrMatrix *matrix); + +XrMatrix * +XrMatrixCreate (void) +{ + XrMatrix *matrix; + + matrix = malloc (sizeof (XrMatrix)); + if (matrix == NULL) + return NULL; + + _XrMatrixInit (matrix); + + return matrix; +} + +void +_XrMatrixInit(XrMatrix *matrix) +{ + XrMatrixSetIdentity (matrix); +} + +void +_XrMatrixFini(XrMatrix *matrix) +{ + /* nothing to do here */ +} + +void +XrMatrixDestroy (XrMatrix *matrix) +{ + _XrMatrixFini (matrix); + free (matrix); +} + +XrStatus +XrMatrixCopy(XrMatrix *matrix, const XrMatrix *other) +{ + *matrix = *other; + + return XrStatusSuccess; +} + +XrStatus +XrMatrixSetIdentity(XrMatrix *matrix) +{ + *matrix = XR_MATRIX_IDENTITY; + + return XrStatusSuccess; +} + +XrStatus +XrMatrixSetAffine (XrMatrix *matrix, + double a, double b, + double c, double d, + double tx, double ty) +{ + matrix->m[0][0] = a; matrix->m[0][1] = b; + matrix->m[1][0] = c; matrix->m[1][1] = d; + matrix->m[2][0] = tx; matrix->m[2][1] = ty; + + return XrStatusSuccess; +} + +XrStatus +_XrMatrixSetTranslate(XrMatrix *matrix, + double tx, double ty) +{ + return XrMatrixSetAffine(matrix, + 1, 0, + 0, 1, + tx, ty); +} + +XrStatus +XrMatrixTranslate (XrMatrix *matrix, double tx, double ty) +{ + XrMatrix tmp; + + _XrMatrixSetTranslate(&tmp, tx, ty); + + return _XrMatrixMultiplyIntoRight(&tmp, matrix); +} + +XrStatus +_XrMatrixSetScale(XrMatrix *matrix, + double sx, double sy) +{ + return XrMatrixSetAffine(matrix, + sx, 0, + 0, sy, + 0, 0); +} + +XrStatus +XrMatrixScale (XrMatrix *matrix, double sx, double sy) +{ + XrMatrix tmp; + + _XrMatrixSetScale (&tmp, sx, sy); + + return _XrMatrixMultiplyIntoRight (&tmp, matrix); +} + +XrStatus +_XrMatrixSetRotate(XrMatrix *matrix, + double radians) +{ + return XrMatrixSetAffine(matrix, + cos(radians), sin(radians), + -sin(radians), cos(radians), + 0, 0); +} + +XrStatus +XrMatrixRotate (XrMatrix *matrix, double radians) +{ + XrMatrix tmp; + + _XrMatrixSetRotate (&tmp, radians); + + return _XrMatrixMultiplyIntoRight (&tmp, matrix); +} + +XrStatus +_XrMatrixMultiplyIntoLeft(XrMatrix *m1, const XrMatrix *m2) +{ + return XrMatrixMultiply(m1, m1, m2); +} + +XrStatus +_XrMatrixMultiplyIntoRight(const XrMatrix *m1, XrMatrix *m2) +{ + return XrMatrixMultiply(m2, m1, m2); +} + +XrStatus +XrMatrixMultiply(XrMatrix *result, const XrMatrix *a, const XrMatrix *b) +{ + XrMatrix r; + int row, col, n; + double t; + + for (row = 0; row < 3; row++) { + for (col = 0; col < 2; col++) { + if (row == 2) + t = b->m[2][col]; + else + t = 0; + for (n = 0; n < 2; n++) { + t += a->m[row][n] * b->m[n][col]; + } + r.m[row][col] = t; + } + } + + *result = r; + + return XrStatusSuccess; +} + +XrStatus +XrMatrixTransformDistance(XrMatrix *matrix, double *dx, double *dy) +{ + double new_x, new_y; + + new_x = (matrix->m[0][0] * *dx + + matrix->m[1][0] * *dy); + new_y = (matrix->m[0][1] * *dx + + matrix->m[1][1] * *dy); + + *dx = new_x; + *dy = new_y; + + return XrStatusSuccess; +} + +XrStatus +XrMatrixTransformPoint(XrMatrix *matrix, double *x, double *y) +{ + XrMatrixTransformDistance(matrix, x, y); + + *x += matrix->m[2][0]; + *y += matrix->m[2][1]; + + return XrStatusSuccess; +} + +XrStatus +_XrMatrixTransformBoundingBox(XrMatrix *matrix, + double *x, double *y, + double *width, double *height) +{ + int i; + double quad_x[4], quad_y[4]; + double dx1, dy1; + double dx2, dy2; + double min_x, max_x; + double min_y, max_y; + + quad_x[0] = *x; + quad_y[0] = *y; + XrMatrixTransformPoint(matrix, &quad_x[0], &quad_y[0]); + + dx1 = *width; + dy1 = 0; + XrMatrixTransformDistance(matrix, &dx1, &dy1); + quad_x[1] = quad_x[0] + dx1; + quad_y[1] = quad_y[0] + dy1; + + dx2 = 0; + dy2 = *height; + XrMatrixTransformDistance(matrix, &dx2, &dy2); + quad_x[2] = quad_x[0] + dx2; + quad_y[2] = quad_y[0] + dy2; + + quad_x[3] = quad_x[0] + dx1 + dx2; + quad_y[3] = quad_y[0] + dy1 + dy2; + + min_x = max_x = quad_x[0]; + min_y = max_y = quad_y[0]; + + for (i=1; i < 4; i++) { + if (quad_x[i] < min_x) + min_x = quad_x[i]; + if (quad_x[i] > max_x) + max_x = quad_x[i]; + + if (quad_y[i] < min_y) + min_y = quad_y[i]; + if (quad_y[i] > max_y) + max_y = quad_y[i]; + } + + *x = min_x; + *y = min_y; + *width = max_x - min_x; + *height = max_y - min_y; + + return XrStatusSuccess; +} + +static void +_XrMatrixScalarMultiply(XrMatrix *matrix, double scalar) +{ + int row, col; + + for (row = 0; row < 3; row++) + for (col = 0; col < 2; col++) + matrix->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 +_XrMatrixComputeAdjoint(XrMatrix *matrix) +{ + /* adj(A) = transpose(C:cofactor(A,i,j)) */ + double a, b, c, d, tx, ty; + + a = matrix->m[0][0]; b = matrix->m[0][1]; + c = matrix->m[1][0]; d = matrix->m[1][1]; + tx = matrix->m[2][0]; ty = matrix->m[2][1]; + + XrMatrixSetAffine(matrix, + d, -b, + -c, a, + c*ty - d*tx, b*tx - a*ty); +} + +XrStatus +XrMatrixInvert (XrMatrix *matrix) +{ + /* inv(A) = 1/det(A) * adj(A) */ + double det; + + _XrMatrixComputeDeterminant (matrix, &det); + + if (det == 0) + return XrStatusInvalidMatrix; + + _XrMatrixComputeAdjoint (matrix); + _XrMatrixScalarMultiply (matrix, 1 / det); + + return XrStatusSuccess; +} + +XrStatus +_XrMatrixComputeDeterminant(XrMatrix *matrix, double *det) +{ + double a, b, c, d; + + a = matrix->m[0][0]; b = matrix->m[0][1]; + c = matrix->m[1][0]; d = matrix->m[1][1]; + + *det = a*d - b*c; + + return XrStatusSuccess; +} + +XrStatus +_XrMatrixComputeEigenValues (XrMatrix *matrix, double *lambda1, double *lambda2) +{ + /* The eigenvalues of an NxN matrix M are found by solving the polynomial: + + det(M - lI) = 0 + + The zeros in our homogeneous 3x3 matrix make this equation equal + to that formed by the sub-matrix: + + M = a b + c d + + by which: + + l^2 - (a+d)l + (ad - bc) = 0 + + l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2; + */ + + double a, b, c, d, rad; + + a = matrix->m[0][0]; + b = matrix->m[0][1]; + c = matrix->m[1][0]; + d = matrix->m[1][1]; + + rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c)); + *lambda1 = (a + d + rad) / 2.0; + *lambda2 = (a + d - rad) / 2.0; + + return XrStatusSuccess; +} diff --git a/src/xrpathstroke.c b/src/xrpathstroke.c index 3d31edf7b..027ec0652 100644 --- a/src/xrpathstroke.c +++ b/src/xrpathstroke.c @@ -223,13 +223,13 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) y1 = XFixedToDouble(inpt->y); dx1 = in->usr_vector.x; dy1 = in->usr_vector.y; - _XrTransformDistance(&gstate->ctm, &dx1, &dy1); + XrMatrixTransformDistance(&gstate->ctm, &dx1, &dy1); x2 = XFixedToDouble(outpt->x); y2 = XFixedToDouble(outpt->y); dx2 = out->usr_vector.x; dy2 = out->usr_vector.y; - _XrTransformDistance(&gstate->ctm, &dx2, &dy2); + XrMatrixTransformDistance(&gstate->ctm, &dx2, &dy2); my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) / (dx1 * dy2 - dx2 * dy1)); @@ -311,7 +311,7 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f) dy = f->usr_vector.y; dx *= gstate->line_width / 2.0; dy *= gstate->line_width / 2.0; - _XrTransformDistance(&gstate->ctm, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm, &dx, &dy); fvector.dx = XDoubleToFixed(dx); fvector.dy = XDoubleToFixed(dy); occw.x = f->ccw.x + fvector.dx; @@ -346,7 +346,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac dx = XFixedToDouble(slope->dx); dy = XFixedToDouble(slope->dy); - _XrTransformDistance(&gstate->ctm_inverse, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm_inverse, &dx, &dy); mag = sqrt(dx * dx + dy * dy); if (mag == 0) { @@ -364,7 +364,7 @@ _ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFac dx = - dy * (gstate->line_width / 2.0); dy = tmp * (gstate->line_width / 2.0); - _XrTransformDistance(&gstate->ctm, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm, &dx, &dy); offset_ccw.x = XDoubleToFixed(dx); offset_ccw.y = XDoubleToFixed(dy); @@ -471,7 +471,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2) dx = XFixedToDouble(p2->x - p1->x); dy = XFixedToDouble(p2->y - p1->y); - _XrTransformDistance(&gstate->ctm_inverse, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm_inverse, &dx, &dy); mag = sqrt(dx *dx + dy * dy); remain = mag; @@ -483,7 +483,7 @@ _XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2) remain -= tmp; dx2 = dx * (mag - remain)/mag; dy2 = dy * (mag - remain)/mag; - _XrTransformDistance (&gstate->ctm, &dx2, &dy2); + XrMatrixTransformDistance (&gstate->ctm, &dx2, &dy2); fd2.x = XDoubleToFixed (dx2); fd2.y = XDoubleToFixed (dy2); fd2.x += p1->x; diff --git a/src/xrpen.c b/src/xrpen.c index f89111f2f..bb7c47d92 100644 --- a/src/xrpen.c +++ b/src/xrpen.c @@ -26,7 +26,7 @@ #include "xrint.h" static int -_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix); +_XrPenVerticesNeeded(double radius, double tolerance, XrMatrix *matrix); static void _XrPenComputeSlopes(XrPen *pen); @@ -89,7 +89,7 @@ _XrPenInit(XrPen *pen, double radius, XrGState *gstate) v->theta = 2 * M_PI * i / (double) pen->num_vertices; dx = radius * cos(v->theta); dy = radius * sin(v->theta); - _XrTransformDistance(&gstate->ctm, &dx, &dy); + XrMatrixTransformDistance(&gstate->ctm, &dx, &dy); v->pt.x = XDoubleToFixed(dx); v->pt.y = XDoubleToFixed(dy); /* Recompute theta in device space */ @@ -186,7 +186,7 @@ _XrPenAddPoints(XrPen *pen, XPointFixed *pt, int num_pts) } static int -_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix) +_XrPenVerticesNeeded(double radius, double tolerance, XrMatrix *matrix) { double expansion, theta; @@ -194,7 +194,7 @@ _XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix) transform. In the worst case, this is entirely in one dimension, which is what we assume here. */ - _XrTransformComputeDeterminant(matrix, &expansion); + _XrMatrixComputeDeterminant(matrix, &expansion); if (tolerance > expansion*radius) { return 4; diff --git a/src/xrsurface.c b/src/xrsurface.c index cc6c7b4a0..9331afba8 100644 --- a/src/xrsurface.c +++ b/src/xrsurface.c @@ -271,17 +271,17 @@ XrSurfaceDestroy(XrSurface *surface) nothing else, that would eliminate the two different transform data structures we have here. */ XrStatus -_XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform) +XrSurfaceSetMatrix(XrSurface *surface, XrMatrix *matrix) { XTransform xtransform; - xtransform.matrix[0][0] = XDoubleToFixed(transform->m[0][0]); - xtransform.matrix[0][1] = XDoubleToFixed(transform->m[1][0]); - xtransform.matrix[0][2] = XDoubleToFixed(transform->m[2][0]); + xtransform.matrix[0][0] = XDoubleToFixed(matrix->m[0][0]); + xtransform.matrix[0][1] = XDoubleToFixed(matrix->m[1][0]); + xtransform.matrix[0][2] = XDoubleToFixed(matrix->m[2][0]); - xtransform.matrix[1][0] = XDoubleToFixed(transform->m[0][1]); - xtransform.matrix[1][1] = XDoubleToFixed(transform->m[1][1]); - xtransform.matrix[1][2] = XDoubleToFixed(transform->m[2][1]); + xtransform.matrix[1][0] = XDoubleToFixed(matrix->m[0][1]); + xtransform.matrix[1][1] = XDoubleToFixed(matrix->m[1][1]); + xtransform.matrix[1][2] = XDoubleToFixed(matrix->m[2][1]); xtransform.matrix[2][0] = 0; xtransform.matrix[2][1] = 0; @@ -293,6 +293,31 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform) return XrStatusSuccess; } +XrStatus +XrSurfaceGetMatrix (XrSurface *surface, XrMatrix *matrix) +{ + XTransform xtransform; + + XcSurfaceGetTransform (surface->xc_surface, &xtransform); + + matrix->m[0][0] = XFixedToDouble (xtransform.matrix[0][0]); + matrix->m[1][0] = XFixedToDouble (xtransform.matrix[0][1]); + matrix->m[2][0] = XFixedToDouble (xtransform.matrix[0][2]); + + matrix->m[0][1] = XFixedToDouble (xtransform.matrix[1][0]); + matrix->m[1][1] = XFixedToDouble (xtransform.matrix[1][1]); + matrix->m[2][1] = XFixedToDouble (xtransform.matrix[1][2]); + + return XrStatusSuccess; +} + +XrStatus +XrSurfaceSetFilter(XrSurface *surface, XrFilter filter) +{ + XcSurfaceSetFilter(surface->xc_surface, filter); + return XrStatusSuccess; +} + /* XXX: The Xc version of this function isn't quite working yet XrStatus XrSurfaceSetClipRegion (XrSurface *surface, Region region) diff --git a/src/xrtransform.c b/src/xrtransform.c deleted file mode 100644 index e8eee7ee1..000000000 --- a/src/xrtransform.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * $XFree86: $ - * - * Copyright © 2002 Carl D. Worth - * - * 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. - * - * 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. - */ - -#include -#include - -#include "xrint.h" - -static XrTransform XR_TRANSFORM_IDENTITY = { - { - {1, 0}, - {0, 1}, - {0, 0} - } -}; - -static void -_XrTransformScalarMultiply(XrTransform *transform, double scalar); - -static void -_XrTransformComputeAdjoint(XrTransform *transform); - -void -_XrTransformInitIdentity(XrTransform *transform) -{ - *transform = XR_TRANSFORM_IDENTITY; -} - -void -_XrTransformDeinit(XrTransform *transform) -{ - /* nothing to do here */ -} - -void -_XrTransformInitMatrix(XrTransform *transform, - double a, double b, - double c, double d, - double tx, double ty) -{ - transform->m[0][0] = a; transform->m[0][1] = b; - transform->m[1][0] = c; transform->m[1][1] = d; - transform->m[2][0] = tx; transform->m[2][1] = ty; -} - -void -_XrTransformInitTranslate(XrTransform *transform, - double tx, double ty) -{ - _XrTransformInitMatrix(transform, - 1, 0, - 0, 1, - tx, ty); -} - -void -_XrTransformInitScale(XrTransform *transform, - double sx, double sy) -{ - _XrTransformInitMatrix(transform, - sx, 0, - 0, sy, - 0, 0); -} - -void -_XrTransformInitRotate(XrTransform *transform, - double angle) -{ - _XrTransformInitMatrix(transform, - cos(angle), sin(angle), - -sin(angle), cos(angle), - 0, 0); -} - -void -_XrTransformMultiplyIntoLeft(XrTransform *t1, const XrTransform *t2) -{ - XrTransform new; - - _XrTransformMultiply(t1, t2, &new); - - *t1 = new; -} - -void -_XrTransformMultiplyIntoRight(const XrTransform *t1, XrTransform *t2) -{ - XrTransform new; - - _XrTransformMultiply(t1, t2, &new); - - *t2 = new; -} - -void -_XrTransformMultiply(const XrTransform *t1, const XrTransform *t2, XrTransform *new) -{ - int row, col, n; - double t; - - for (row = 0; row < 3; row++) { - for (col = 0; col < 2; col++) { - if (row == 2) - t = t2->m[2][col]; - else - t = 0; - for (n = 0; n < 2; n++) { - t += t1->m[row][n] * t2->m[n][col]; - } - new->m[row][col] = t; - } - } -} - -void -_XrTransformDistance(XrTransform *transform, double *dx, double *dy) -{ - double new_x, new_y; - - new_x = (transform->m[0][0] * *dx - + transform->m[1][0] * *dy); - new_y = (transform->m[0][1] * *dx - + transform->m[1][1] * *dy); - - *dx = new_x; - *dy = new_y; -} - -void -_XrTransformPoint(XrTransform *transform, double *x, double *y) -{ - _XrTransformDistance(transform, x, y); - - *x += transform->m[2][0]; - *y += transform->m[2][1]; -} - -void -_XrTransformBoundingBox(XrTransform *transform, - double *x, double *y, - double *width, double *height) -{ - int i; - double quad_x[4], quad_y[4]; - double dx1, dy1; - double dx2, dy2; - double min_x, max_x; - double min_y, max_y; - - quad_x[0] = *x; - quad_y[0] = *y; - _XrTransformPoint(transform, &quad_x[0], &quad_y[0]); - - dx1 = *width; - dy1 = 0; - _XrTransformDistance(transform, &dx1, &dy1); - quad_x[1] = quad_x[0] + dx1; - quad_y[1] = quad_y[0] + dy1; - - dx2 = 0; - dy2 = *height; - _XrTransformDistance(transform, &dx2, &dy2); - quad_x[2] = quad_x[0] + dx2; - quad_y[2] = quad_y[0] + dy2; - - quad_x[3] = quad_x[0] + dx1 + dx2; - quad_y[3] = quad_y[0] + dy1 + dy2; - - min_x = max_x = quad_x[0]; - min_y = max_y = quad_y[0]; - - for (i=1; i < 4; i++) { - if (quad_x[i] < min_x) - min_x = quad_x[i]; - if (quad_x[i] > max_x) - max_x = quad_x[i]; - - if (quad_y[i] < min_y) - min_y = quad_y[i]; - if (quad_y[i] > max_y) - max_y = quad_y[i]; - } - - *x = min_x; - *y = min_y; - *width = max_x - min_x; - *height = max_y - min_y; -} - -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); -} - -XrStatus -_XrTransformInvert (XrTransform *transform) -{ - /* inv(A) = 1/det(A) * adj(A) */ - double det; - - _XrTransformComputeDeterminant (transform, &det); - - if (det == 0) - return XrStatusInvalidMatrix; - - _XrTransformComputeAdjoint (transform); - _XrTransformScalarMultiply (transform, 1 / det); - - return XrStatusSuccess; -} - -void -_XrTransformComputeDeterminant(XrTransform *transform, double *det) -{ - double a, b, c, d; - - 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; -} - -void -_XrTransformComputeEigenValues (XrTransform *transform, double *lambda1, double *lambda2) -{ - /* The eigenvalues of an NxN matrix M are found by solving the polynomial: - - det(M - lI) = 0 - - The zeros in our homogeneous 3x3 matrix make this equation equal - to that formed by the sub-matrix: - - M = a b - c d - - by which: - - l^2 - (a+d)l + (ad - bc) = 0 - - l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2; - */ - - double a, b, c, d, rad; - - a = transform->m[0][0]; - b = transform->m[0][1]; - c = transform->m[1][0]; - d = transform->m[1][1]; - - rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c)); - *lambda1 = (a + d + rad) / 2.0; - *lambda2 = (a + d - rad) / 2.0; -}