Added toplevel functions for setting surface matrix, filter. Introduced new XrMatrix object. Fixed to properly hint scaled fonts.

This commit is contained in:
Carl Worth 2003-05-14 18:30:57 +00:00
parent 7e1f3f1798
commit b3b306dfd9
13 changed files with 837 additions and 682 deletions

View file

@ -1,3 +1,34 @@
2003-05-14 Carl Worth <cworth@isi.edu>
* 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 <cworth@isi.edu>
* src/Xr.h: Added XrSetPattern. See also XrSurfaceSetRepeat.

56
README
View file

@ -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 <cworth@isi.edu> and Keith Packard
<keithp@keithp.com>. 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

View file

@ -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

125
src/Xr.h
View file

@ -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

107
src/xr.c
View file

@ -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

View file

@ -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];

View file

@ -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;
}

View file

@ -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

377
src/xrmatrix.c Normal file
View file

@ -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 <stdlib.h>
#include <math.h>
#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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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 <stdlib.h>
#include <math.h>
#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;
}