mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-14 23:50:32 +01:00
Added toplevel functions for setting surface matrix, filter. Introduced new XrMatrix object. Fixed to properly hint scaled fonts.
This commit is contained in:
parent
7e1f3f1798
commit
b3b306dfd9
13 changed files with 837 additions and 682 deletions
31
ChangeLog
31
ChangeLog
|
|
@ -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
56
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 <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
|
||||
|
|
|
|||
|
|
@ -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
125
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
|
||||
|
||||
|
|
|
|||
107
src/xr.c
107
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
|
||||
|
|
|
|||
51
src/xrfont.c
51
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];
|
||||
|
|
|
|||
272
src/xrgstate.c
272
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;
|
||||
}
|
||||
|
|
|
|||
134
src/xrint.h
134
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
|
||||
|
|
|
|||
377
src/xrmatrix.c
Normal file
377
src/xrmatrix.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue