Switched to autotools. Dropped XrPush/PopGroup. Supports non-X Xc rendering.

This commit is contained in:
Carl Worth 2003-04-17 13:24:29 +00:00
parent b61b9ffc23
commit ee738deaf6
37 changed files with 701 additions and 6625 deletions

View file

@ -1,2 +1,17 @@
unshared
exports
Makefile
Makefile.am
Makefile.in
aclocal.m4
config.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
Xr.pc
libtool
ltmain.sh
stamp-h
stamp-h.in

1
AUTHORS Normal file
View file

@ -0,0 +1 @@
Carl D. Worth <cworth@isi.edu>

1
BUGS Normal file
View file

@ -0,0 +1 @@
SEGV if XrSetRGBColor is called before XrSetTargetDrawable

21
COPYING Normal file
View file

@ -0,0 +1,21 @@
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.

View file

@ -1,3 +1,20 @@
2003-04-17 Carl Worth <cworth@isi.edu>
* Switched from imake to autotools.
* src/xrint.h: XrSurface structure is now greatly simplified,
(details now handled by XcSurface).
* src/Xr.h: Eliminated Display * parameter so Xr can be used for
non-X drawing.
Removed XrPushGroup/XrPopGroup.
Replaced XrSetDrawable/XrSetVisual with XrSetTargetDrawable.
Added XrSetTargetSurface and several new XrSurfaceCreate
functions.
Added XrShowSurface, (functionality overlaps with XrShowImage --
need to fix this)
2003-02-14 Carl Worth <cworth@east.isi.edu>
* xrgstate.c (_XrGStateShowImageTransform): Fixed transformed

9
INSTALL Normal file
View file

@ -0,0 +1,9 @@
This package uses automake, in order to generate the Makefiles use:
$ autogen.sh
After that, standard build procedures apply:
$ make
# make install

View file

@ -1,63 +0,0 @@
XCOMM $XFree86: $
#ifdef UseInstalled
/* building outside the tree, use private defines */
#include "local.def"
#endif
#define DoNormalLib NormalLibXr
#define DoSharedLib SharedLibXr
#define DoDebugLib DebugLibXr
#define DoProfileLib ProfileLibXr
#define LibName Xr
#define SoRev SOXRREV
#define IncSubdir X11
#define IncSubSubdir Xr
#include <Threads.tmpl>
#ifdef SharedXrReqs
REQUIREDLIBS = SharedXrReqs
#endif
INCLUDES = $(XFTINCLUDES)
SRCS = xr.c \
xrcolor.c \
xrfiller.c \
xrfont.c \
xrgstate.c \
xrmisc.c \
xrpath.c \
xrpen.c \
xrpolygon.c \
xrspline.c \
xrstate.c \
xrstroker.c \
xrsurface.c \
xrtransform.c \
xrtraps.c
OBJS = xr.o \
xrcolor.o \
xrfiller.o \
xrfont.o \
xrgstate.o \
xrmisc.o \
xrpath.o \
xrpen.o \
xrpolygon.o \
xrspline.o \
xrstate.o \
xrstroker.o \
xrsurface.o \
xrtransform.o \
xrtraps.o
HEADERS = Xr.h
#include <Library.tmpl>
DependTarget()

0
NEWS Normal file
View file

278
Xr.h
View file

@ -1,278 +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.
*/
#ifndef _XR_H_
#define _XR_H_
#include <X11/Xc/Xc.h>
typedef struct _XrState XrState;
/* Functions for manipulating state objects */
XrState *
XrCreate(Display *dpy);
void
XrDestroy(XrState *xrs);
void
XrSave(XrState *xrs);
void
XrRestore(XrState *xrs);
void
XrPushGroup(XrState *xrs);
void
XrPopGroup(XrState *xrs);
/* Modify state */
void
XrSetDrawable(XrState *xrs, Drawable drawable);
void
XrSetVisual(XrState *xrs, Visual *visual);
typedef enum _XrFormat {
XrFormatARGB32 = PictStandardARGB32,
XrFormatRGB32 = PictStandardRGB24,
XrFormatA8 = PictStandardA8,
XrFormatA1 = PictStandardA1
} XrFormat;
void
XrSetFormat(XrState *xrs, XrFormat format);
typedef enum _XrOperator {
XrOperatorClear = PictOpClear,
XrOperatorSrc = PictOpSrc,
XrOperatorDst = PictOpDst,
XrOperatorOver = PictOpOver,
XrOperatorOverReverse = PictOpOverReverse,
XrOperatorIn = PictOpIn,
XrOperatorInReverse = PictOpInReverse,
XrOperatorOut = PictOpOut,
XrOperatorOutReverse = PictOpOutReverse,
XrOperatorAtop = PictOpAtop,
XrOperatorAtopReverse = PictOpAtopReverse,
XrOperatorXor = PictOpXor,
XrOperatorAdd = PictOpAdd,
XrOperatorSaturate = PictOpSaturate,
XrOperatorDisjointClear = PictOpDisjointClear,
XrOperatorDisjointSrc = PictOpDisjointSrc,
XrOperatorDisjointDst = PictOpDisjointDst,
XrOperatorDisjointOver = PictOpDisjointOver,
XrOperatorDisjointOverReverse = PictOpDisjointOverReverse,
XrOperatorDisjointIn = PictOpDisjointIn,
XrOperatorDisjointInReverse = PictOpDisjointInReverse,
XrOperatorDisjointOut = PictOpDisjointOut,
XrOperatorDisjointOutReverse = PictOpDisjointOutReverse,
XrOperatorDisjointAtop = PictOpDisjointAtop,
XrOperatorDisjointAtopReverse = PictOpDisjointAtopReverse,
XrOperatorDisjointXor = PictOpDisjointXor,
XrOperatorConjointClear = PictOpConjointClear,
XrOperatorConjointSrc = PictOpConjointSrc,
XrOperatorConjointDst = PictOpConjointDst,
XrOperatorConjointOver = PictOpConjointOver,
XrOperatorConjointOverReverse = PictOpConjointOverReverse,
XrOperatorConjointIn = PictOpConjointIn,
XrOperatorConjointInReverse = PictOpConjointInReverse,
XrOperatorConjointOut = PictOpConjointOut,
XrOperatorConjointOutReverse = PictOpConjointOutReverse,
XrOperatorConjointAtop = PictOpConjointAtop,
XrOperatorConjointAtopReverse = PictOpConjointAtopReverse,
XrOperatorConjointXor = PictOpConjointXor
} XrOperator;
void
XrSetOperator(XrState *xrs, XrOperator operator);
void
XrSetRGBColor(XrState *xrs, double red, double green, double blue);
void
XrSetTolerance(XrState *xrs, double tolerance);
void
XrSetAlpha(XrState *xrs, double alpha);
typedef enum _XrFillRule { XrFillRuleWinding, XrFillRuleEvenOdd } XrFillRule;
void
XrSetFillRule(XrState *xrs, XrFillRule fill_rule);
void
XrSetLineWidth(XrState *xrs, double width);
typedef enum _XrLineCap { XrLineCapButt, XrLineCapRound, XrLineCapSquare } XrLineCap;
void
XrSetLineCap(XrState *xrs, XrLineCap line_cap);
typedef enum _XrLineJoin { XrLineJoinMiter, XrLineJoinRound, XrLineJoinBevel } XrLineJoin;
void
XrSetLineJoin(XrState *xrs, XrLineJoin line_join);
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset);
void
XrSetMiterLimit(XrState *xrs, double limit);
void
XrTranslate(XrState *xrs, double tx, double ty);
void
XrScale(XrState *xrs, double sx, double sy);
void
XrRotate(XrState *xrs, double angle);
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty);
void
XrSetMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty);
/* XXX: Postscript has both a defaultmatrix and an identmatrix. But
there, they do different things. Here, where they perform the same
function, we should probably only have one name to avoid
confusion. Any votes? */
void
XrDefaultMatrix(XrState *xrs);
void
XrIdentityMatrix(XrState *xrs);
/* Path creation functions */
void
XrNewPath(XrState *xrs);
void
XrMoveTo(XrState *xrs, double x, double y);
void
XrLineTo(XrState *xrs, double x, double y);
void
XrCurveTo(XrState *xrs,
double x1, double y1,
double x2, double y2,
double x3, double y3);
void
XrRelMoveTo(XrState *xrs, double dx, double dy);
void
XrRelLineTo(XrState *xrs, double dx, double dy);
void
XrRelCurveTo(XrState *xrs,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3);
void
XrClosePath(XrState *xrs);
/* Painting functions */
void
XrStroke(XrState *xrs);
void
XrFill(XrState *xrs);
/* Font/Text functions */
void
XrSelectFont(XrState *xrs, const char *key);
void
XrScaleFont(XrState *xrs, double scale);
void
XrTransformFont(XrState *xrs,
double a, double b,
double c, double d);
void
XrTextExtents(XrState *xrs,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy);
void
XrShowText(XrState *xrs, const unsigned char *utf8);
/* Image functions */
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);
/* Error status queries */
typedef enum _XrStatus {
XrStatusSuccess = 0,
XrStatusNoMemory,
XrStatusInvalidRestore,
XrStatusInvalidPopGroup,
XrStatusNoCurrentPoint,
XrStatusInvalidMatrix
} XrStatus;
XrStatus
XrGetStatus(XrState *xrs);
const char *
XrGetStatusString(XrState *xrs);
#endif

28
autogen.sh Executable file
View file

@ -0,0 +1,28 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
set -e
if test -z "$*"; then
echo "$0: Note: \`./configure' will be run with no arguments."
echo " If you wish to pass any to it, please specify them on the"
echo " \`$0' command line."
echo
fi
do_cmd() {
echo "$0: running \`$@'"
$@
}
do_cmd libtoolize --force --copy
do_cmd aclocal
do_cmd autoheader
do_cmd automake --add-missing
do_cmd autoconf
do_cmd ./configure ${1+"$@"} && echo "Now type \`make' to compile" || exit 1

51
configure.in Normal file
View file

@ -0,0 +1,51 @@
AC_INIT(src/Xr.h)
dnl ===========================================================================
XR_MAJOR_VERSION=0
XR_MINOR_VERSION=1
XR_MICRO_VERSION=0
AC_SUBST(XR_MAJOR_VERSION)
AC_SUBST(XR_MINOR_VERSION)
AC_SUBST(XR_MICRO_VERSION)
XR_VERSION=$XR_MAJOR_VERSION.$XR_MINOR_VERSION.$XR_MICRO_VERSION
VERSION_INFO=`expr $XR_MAJOR_VERSION + $XR_MINOR_VERSION`:$XR_MICRO_VERSION:$XR_MINOR_VERSION
AC_SUBST(VERSION_INFO)
dnl ===========================================================================
XC_REQUIRED=0.1.0
dnl ===========================================================================
AM_INIT_AUTOMAKE(Xr, $XR_VERSION)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_PROG_CC
AC_PROG_CPP
AM_PROG_LIBTOOL
AC_STDC_HEADERS
dnl ===========================================================================
AC_PATH_XTRA
dnl ===========================================================================
PKG_CHECK_MODULES(XR, \
Xc >= $XC_REQUIRED
)
AC_SUBST(XR_CFLAGS)
AC_SUBST(XR_LIBS)
dnl ===========================================================================
AC_OUTPUT([
Xr.pc
Makefile
src/Makefile
])

View file

@ -1,53 +0,0 @@
#ifndef SharedLibXr
#define SharedLibXr HasSharedLibraries
#endif
#ifndef NormalLibXr
#define NormalLibXr (!SharedLibXr | ForceNormalLib)
#endif
#ifndef DebugLibXr
#define DebugLibXr NO
#endif
#ifndef ProfileLibXr
#define ProfileLibXr NO
#endif
#ifndef XrClientDepLibs
#define XrClientDepLibs $(DEPXCLIB) $(DEPXFTLIB) FontconfigClientDepLibs
#endif
#ifndef XrClientLibs
#define XrClientLibs $(XCLIB) $(XFTLIB) FontconfigClientLibs
#endif
XRINCLUDES=$(XCINCLUDES) $(XFTINCLUDES) $(FONTCONFIGINCLUDES)
#if SharedLibXr
#ifndef SharedXrRev
#define SharedXrRev 1.1
#endif
SharedLibReferences(XR,Xr,$(XRLIBSRC),SOXRREV,SharedXrRev)
#else
ProjectUnsharedLibReferences(XR,Xr,$(XRLIBSRC),XBuildLibDir)
#endif
#undef LinkBuildLibrary
#define LinkBuildLibrary(lib) MakeDir($(BUILDLIBDIR)) @@\
RemoveFile($(BUILDLIBDIR)/lib) @@\
cd $(BUILDLIBDIR) && $(LN) $(BUILDLIBTOP)/$(CURRENT_DIR)/lib .
#undef _LinkBuildLibrary
#define _LinkBuildLibrary(lib) LinkBuildLibrary(lib)
#undef LinkBuildLibraryMaybe
#define LinkBuildLibraryMaybe(lib,doit) MakeDir($(BUILDLIBDIR)) @@\
@if doit; then (set -x; \ @@\
RemoveFile($(BUILDLIBDIR)/lib); \ @@\
cd $(BUILDLIBDIR) && $(LN) $(BUILDLIBTOP)/$(CURRENT_DIR)/lib .); fi
#ifdef LdPreLibs
# undef LdPreLibs
#endif
#define LdPreLibs -L$(BUILDLIBDIR) LdPreLib XLdPreLibs
LDPRELIBS=LdPreLibs

7
src/.cvsignore Normal file
View file

@ -0,0 +1,7 @@
.deps
.libs
Makefile
Makefile.am
Makefile.in
*.la
*.lo

View file

@ -26,13 +26,14 @@
#ifndef _XR_H_
#define _XR_H_
#include <X11/Xc/Xc.h>
#include <Xc.h>
typedef struct _XrState XrState;
typedef struct _XrSurface XrSurface;
/* Functions for manipulating state objects */
XrState *
XrCreate(Display *dpy);
XrCreate(void);
void
XrDestroy(XrState *xrs);
@ -43,18 +44,17 @@ XrSave(XrState *xrs);
void
XrRestore(XrState *xrs);
/* XXX: I want to rethink this API
void
XrPushGroup(XrState *xrs);
void
XrPopGroup(XrState *xrs);
*/
/* Modify state */
void
XrSetDrawable(XrState *xrs, Drawable drawable);
void
XrSetVisual(XrState *xrs, Visual *visual);
XrSetTargetSurface (XrState *xrs, XrSurface *surface);
typedef enum _XrFormat {
XrFormatARGB32 = PictStandardARGB32,
@ -62,9 +62,11 @@ typedef enum _XrFormat {
XrFormatA8 = PictStandardA8,
XrFormatA1 = PictStandardA1
} XrFormat;
void
XrSetFormat(XrState *xrs, XrFormat format);
XrSetTargetDrawable (XrState *xrs,
Display *dpy,
Drawable drawable);
typedef enum _XrOperator {
XrOperatorClear = PictOpClear,
@ -238,6 +240,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,
@ -257,6 +262,24 @@ XrShowImageTransform(XrState *xrs,
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);
/* Query functions */
XrSurface *
XrGetTargetSurface (XrState *xrs);
/* Error status queries */
typedef enum _XrStatus {
@ -274,5 +297,57 @@ XrGetStatus(XrState *xrs);
const char *
XrGetStatusString(XrState *xrs);
/* Surface mainpulation */
/* XXX: This is a mess from the user's POV. Should the Visual or the
XrFormat control what render format is used? Maybe I can have
XrSurfaceCreateForWindow with a visual, and
XrSurfaceCreateForPixmap with an XrFormat. Would that work?
*/
XrSurface *
XrSurfaceCreateForDrawable (Display *dpy,
Drawable drawable,
Visual *visual,
XrFormat format,
Colormap colormap);
XrSurface *
XrSurfaceCreateForImage (char *data,
XrFormat format,
int width,
int height,
int stride);
XrSurface *
XrSurfaceCreateNextTo (XrSurface *neighbor,
XrFormat format,
int width,
int height);
/* XXX: One problem with having RGB and A here in one function is that
it introduces the question of pre-multiplied vs. non-pre-multiplied
alpha. Do I want to export an XrColor structure instead? So far, no
other public functions need it. */
XrSurface *
XrSurfaceCreateNextToSolid (XrSurface *neighbor,
XrFormat format,
int width,
int height,
double red,
double green,
double blue,
double alpha);
void
XrSurfaceDestroy(XrSurface *surface);
/* XXX: The Xc version of this function isn't quite working yet
XrStatus
XrSurfaceSetClipRegion (XrSurface *surface, Region region);
*/
XrStatus
XrSurfaceSetRepeat (XrSurface *surface, int repeat);
#endif

View file

@ -33,9 +33,9 @@ static void
_XrClipValue(double *value, double min, double max);
XrState *
XrCreate(Display *dpy)
XrCreate(void)
{
return _XrStateCreate(dpy);
return _XrStateCreate();
}
void
@ -62,6 +62,7 @@ XrRestore(XrState *xrs)
xrs->status = _XrStatePop(xrs);
}
/* XXX: I want to rethink this API
void
XrPushGroup(XrState *xrs)
{
@ -87,32 +88,29 @@ XrPopGroup(XrState *xrs)
xrs->status = _XrStatePop(xrs);
}
*/
void
XrSetDrawable(XrState *xrs, Drawable drawable)
XrSetTargetSurface (XrState *xrs, XrSurface *surface)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetDrawable(_XR_CURRENT_GSTATE(xrs), drawable);
xrs->status = _XrGStateSetTargetSurface (_XR_CURRENT_GSTATE (xrs), surface);
}
void
XrSetVisual(XrState *xrs, Visual *visual)
XrSetTargetDrawable (XrState *xrs,
Display *dpy,
Drawable drawable)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetVisual(_XR_CURRENT_GSTATE(xrs), visual);
}
void
XrSetFormat(XrState *xrs, XrFormat format)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetFormat(_XR_CURRENT_GSTATE(xrs), format);
xrs->status = _XrGStateSetTargetDrawable (_XR_CURRENT_GSTATE (xrs),
dpy, drawable,
DefaultVisual (dpy, DefaultScreen (dpy)),
0);
}
void
@ -475,6 +473,28 @@ XrShowImageTransform(XrState *xrs,
tx, ty);
}
void
XrShowSurface (XrState *xrs,
XrSurface *surface,
int x,
int y,
int width,
int height)
{
if (xrs->status)
return;
xrs->status = _XrGStateShowSurface (_XR_CURRENT_GSTATE (xrs),
surface,
x, y,
width, height);
}
XrSurface *
XrGetTargetSurface (XrState *xrs)
{
return _XrGStateGetTargetSurface (_XR_CURRENT_GSTATE (xrs));
}
XrStatus
XrGetStatus(XrState *xrs)

View file

@ -155,7 +155,9 @@ _XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font)
FcPatternAddMatrix(pattern, "matrix", &fc_matrix);
font->dpy = gstate->dpy;
/* XXX: Need to abandon Xft and use Xc instead */
/* When I do that I can throw away these Display pointers */
font->dpy = gstate->surface->dpy;
match = XftFontMatch (font->dpy, DefaultScreen(font->dpy), pattern, &result);
if (!match)
return 0;

View file

@ -28,30 +28,22 @@
#include "xrint.h"
static Picture
_XrGStateGetPicture(XrGState *gstate);
static Picture
_XrGStateGetSrcPicture(XrGState *gstate);
XrGState *
_XrGStateCreate(Display *dpy)
_XrGStateCreate()
{
XrGState *gstate;
gstate = malloc(sizeof(XrGState));
if (gstate)
_XrGStateInit(gstate, dpy);
_XrGStateInit(gstate);
return gstate;
}
void
_XrGStateInit(XrGState *gstate, Display *dpy)
_XrGStateInit(XrGState *gstate)
{
gstate->dpy = dpy;
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = XR_GSTATE_TOLERANCE_DEFAULT;
@ -67,18 +59,15 @@ _XrGStateInit(XrGState *gstate, Display *dpy)
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
_XrFontInit(&gstate->font);
gstate->parent_surface = NULL;
gstate->surface = _XrSurfaceCreate(dpy);
gstate->src = _XrSurfaceCreate(dpy);
gstate->surface = NULL;
gstate->solid = NULL;
gstate->pattern = NULL;
gstate->mask = NULL;
gstate->alpha = 1.0;
_XrColorInit(&gstate->color);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
_XrTransformInitIdentity(&gstate->ctm);
_XrTransformInitIdentity(&gstate->ctm_inverse);
@ -109,11 +98,10 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other)
if (status)
goto CLEANUP_DASHES;
gstate->parent_surface = NULL;
_XrSurfaceReference(gstate->surface);
_XrSurfaceReference(gstate->src);
if (gstate->mask)
_XrSurfaceReference(gstate->mask);
_XrSurfaceReference(gstate->solid);
_XrSurfaceReference(gstate->pattern);
_XrSurfaceReference(gstate->mask);
status = _XrPathInitCopy(&gstate->path, &other->path);
if (status)
@ -139,15 +127,12 @@ _XrGStateInitCopy(XrGState *gstate, XrGState *other)
void
_XrGStateDeinit(XrGState *gstate)
{
if (gstate->parent_surface)
_XrGStateEndGroup(gstate);
_XrFontDeinit(&gstate->font);
_XrSurfaceDereferenceDestroy(gstate->surface);
_XrSurfaceDereferenceDestroy(gstate->src);
if (gstate->mask)
_XrSurfaceDereferenceDestroy(gstate->mask);
XrSurfaceDestroy(gstate->surface);
XrSurfaceDestroy(gstate->solid);
XrSurfaceDestroy(gstate->pattern);
XrSurfaceDestroy(gstate->mask);
_XrColorDeinit(&gstate->color);
@ -190,6 +175,7 @@ _XrGStateClone(XrGState *gstate)
}
/* Push rendering off to an off-screen group. */
/* XXX: Rethinking this API
XrStatus
_XrGStateBeginGroup(XrGState *gstate)
{
@ -209,7 +195,7 @@ _XrGStateBeginGroup(XrGState *gstate)
if (pix == 0)
return XrStatusNoMemory;
gstate->surface = _XrSurfaceCreate(gstate->dpy);
gstate->surface = XrSurfaceCreate(gstate->dpy);
if (gstate->surface == NULL)
return XrStatusNoMemory;
@ -218,8 +204,7 @@ _XrGStateBeginGroup(XrGState *gstate)
_XrColorInit(&clear);
_XrColorSetAlpha(&clear, 0);
XcFillRectangle(gstate->dpy,
XrOperatorSrc,
XcFillRectangle(XrOperatorSrc,
_XrSurfaceGetXcSurface(gstate->surface),
&clear.xc_color,
0, 0,
@ -228,8 +213,10 @@ _XrGStateBeginGroup(XrGState *gstate)
return XrStatusSuccess;
}
*/
/* Complete the current offscreen group, composing its contents onto the parent surface. */
/* XXX: Rethinking this API
XrStatus
_XrGStateEndGroup(XrGState *gstate)
{
@ -246,10 +233,10 @@ _XrGStateEndGroup(XrGState *gstate)
_XrSurfaceSetSolidColor(&mask, &mask_color);
/* XXX: This could be made much more efficient by using
* XXX: This could be made much more efficient by using
_XrSurfaceGetDamagedWidth/Height if XrSurface actually kept
track of such informaton. */
XcComposite(gstate->dpy, gstate->operator,
track of such informaton. *
XcComposite(gstate->operator,
_XrSurfaceGetXcSurface(gstate->surface),
_XrSurfaceGetXcSurface(&mask),
_XrSurfaceGetXcSurface(gstate->parent_surface),
@ -264,35 +251,58 @@ _XrGStateEndGroup(XrGState *gstate)
pix = _XrSurfaceGetDrawable(gstate->surface);
XFreePixmap(gstate->dpy, pix);
_XrSurfaceDestroy(gstate->surface);
XrSurfaceDestroy(gstate->surface);
gstate->surface = gstate->parent_surface;
gstate->parent_surface = NULL;
return XrStatusSuccess;
}
*/
XrStatus
_XrGStateSetDrawable(XrGState *gstate, Drawable drawable)
_XrGStateSetTargetSurface (XrGState *gstate, XrSurface *surface)
{
_XrSurfaceSetDrawable(gstate->surface, drawable);
XrSurfaceDestroy (gstate->surface);
gstate->surface = surface;
_XrSurfaceReference (surface);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetVisual(XrGState *gstate, Visual *visual)
/* XXX: Need to decide the memory mangement semantics of this
function. Should it reference the surface again? */
XrSurface *
_XrGStateGetTargetSurface (XrGState *gstate)
{
_XrSurfaceSetVisual(gstate->surface, visual);
if (gstate == NULL)
return NULL;
return XrStatusSuccess;
return gstate->surface;
}
XrStatus
_XrGStateSetFormat(XrGState *gstate, XrFormat format)
_XrGStateSetTargetDrawable (XrGState *gstate,
Display *dpy,
Drawable drawable,
Visual *visual,
XrFormat format)
{
_XrSurfaceSetFormat(gstate->surface, format);
XrStatus status;
XrSurface *surface;
return XrStatusSuccess;
surface = XrSurfaceCreateForDrawable (dpy, drawable,
visual,
format,
DefaultColormap (dpy, DefaultScreen (dpy)));
if (surface == NULL)
return XrStatusNoMemory;
status = _XrGStateSetTargetSurface (gstate, surface);
XrSurfaceDestroy (surface);
return status;
}
XrStatus
@ -307,7 +317,13 @@ XrStatus
_XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue)
{
_XrColorSetRGB(&gstate->color, red, green, blue);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
XrSurfaceDestroy(gstate->solid);
gstate->solid = XrSurfaceCreateNextToSolid (gstate->surface, XrFormatARGB32,
1, 1,
red, green, blue,
gstate->alpha);
XrSurfaceSetRepeat (gstate->solid, 1);
return XrStatusSuccess;
}
@ -324,8 +340,18 @@ XrStatus
_XrGStateSetAlpha(XrGState *gstate, double alpha)
{
gstate->alpha = alpha;
_XrColorSetAlpha(&gstate->color, alpha);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
XrSurfaceDestroy (gstate->solid);
gstate->solid = XrSurfaceCreateNextToSolid (gstate->surface,
XrFormatARGB32,
1, 1,
gstate->color.red,
gstate->color.green,
gstate->color.blue,
gstate->color.alpha);
XrSurfaceSetRepeat (gstate->solid, 1);
return XrStatusSuccess;
}
@ -446,7 +472,7 @@ _XrGStateConcatMatrix(XrGState *gstate,
_XrTransformInitMatrix(&tmp, a, b, c, d, tx, ty);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformComputeInverse(&tmp);
_XrTransformInvert(&tmp);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
return XrStatusSuccess;
@ -463,7 +489,7 @@ _XrGStateSetMatrix(XrGState *gstate,
_XrTransformInitMatrix(&gstate->ctm, a, b, c, d, tx, ty);
gstate->ctm_inverse = gstate->ctm;
status = _XrTransformComputeInverse(&gstate->ctm_inverse);
status = _XrTransformInvert (&gstate->ctm_inverse);
if (status)
return status;
@ -660,10 +686,9 @@ _XrGStateStroke(XrGState *gstate)
return status;
}
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(gstate->src),
_XrSurfaceGetXcSurface(gstate->surface),
gstate->alphaFormat,
XcCompositeTrapezoids(gstate->operator,
gstate->pattern ? gstate->pattern->xc_surface : gstate->solid->xc_surface,
gstate->surface->xc_surface,
0, 0,
traps.xtraps,
traps.num_xtraps);
@ -700,10 +725,9 @@ _XrGStateFill(XrGState *gstate)
return status;
}
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(gstate->src),
_XrSurfaceGetXcSurface(gstate->surface),
gstate->alphaFormat,
XcCompositeTrapezoids(gstate->operator,
gstate->pattern ? gstate->pattern->xc_surface : gstate->solid->xc_surface,
gstate->surface->xc_surface,
0, 0,
traps.xtraps,
traps.num_xtraps);
@ -749,7 +773,9 @@ _XrGStateTextExtents(XrGState *gstate,
_XrFontResolveXftFont(&gstate->font, gstate, &xft_font);
XftTextExtentsUtf8(gstate->dpy,
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage XrSurfaces */
XftTextExtentsUtf8(gstate->surface->dpy,
xft_font,
utf8,
strlen((char *) utf8),
@ -778,11 +804,13 @@ _XrGStateShowText(XrGState *gstate, const unsigned char *utf8)
_XrFontResolveXftFont(&gstate->font, gstate, &xft_font);
XftTextRenderUtf8(gstate->dpy,
/* XXX: Need to abandon Xft and use Xc instead */
/* (until I do, this call will croak on IcImage XrSurfaces */
XftTextRenderUtf8(gstate->surface->dpy,
gstate->operator,
_XrGStateGetSrcPicture(gstate),
_XrSurfaceGetPicture (gstate->solid),
xft_font,
_XrGStateGetPicture(gstate),
_XrSurfaceGetPicture (gstate->surface),
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
@ -818,35 +846,38 @@ _XrGStateShowImageTransform(XrGState *gstate,
double c, double d,
double tx, double ty)
{
XrStatus status;
XrColor mask_color;
XrSurface image_surface, mask;
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;
_XrSurfaceInit(&mask, gstate->dpy);
_XrColorInit(&mask_color);
_XrColorSetAlpha(&mask_color, gstate->alpha);
mask = XrSurfaceCreateNextToSolid (gstate->surface,
XrFormatA8,
1, 1,
1.0, 1.0, 1.0,
gstate->alpha);
if (mask == NULL)
return XrStatusNoMemory;
XrSurfaceSetRepeat (mask, 1);
_XrSurfaceSetSolidColor(&mask, &mask_color);
image_surface = XrSurfaceCreateNextTo (gstate->surface, format, width, height);
if (image_surface == NULL) {
XrSurfaceDestroy (mask);
return XrStatusNoMemory;
}
_XrSurfaceInit(&image_surface, gstate->dpy);
_XrSurfaceSetFormat(&image_surface, format);
status = _XrSurfaceSetImage(&image_surface, data,width, height, stride);
if (status)
return status;
/* 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);
_XrSurfaceSetTransform(image_surface, &device_to_image);
image_to_user = user_to_image;
_XrTransformComputeInverse(&image_to_user);
_XrTransformMultiply(&image_to_user, &gstate->ctm, &image_to_device);
_XrTransformInvert (&image_to_user);
_XrTransformMultiply (&image_to_user, &gstate->ctm, &image_to_device);
dst_x = 0;
dst_y = 0;
@ -856,30 +887,53 @@ _XrGStateShowImageTransform(XrGState *gstate,
&dst_x, &dst_y,
&dst_width, &dst_height);
XcComposite(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(&image_surface),
_XrSurfaceGetXcSurface(&mask),
_XrSurfaceGetXcSurface(gstate->surface),
XcComposite(gstate->operator,
image_surface->xc_surface,
mask->xc_surface,
gstate->surface->xc_surface,
dst_x, dst_y,
0, 0,
dst_x, dst_y,
dst_width + 1,
dst_height + 1);
dst_width + 2,
dst_height + 2);
_XrSurfaceDeinit(&image_surface);
_XrSurfaceDeinit(&mask);
XrSurfaceDestroy (image_surface);
XrSurfaceDestroy (mask);
return XrStatusSuccess;
}
static Picture
_XrGStateGetPicture(XrGState *gstate)
XrStatus
_XrGStateShowSurface(XrGState *gstate,
XrSurface *surface,
int x,
int y,
int width,
int height)
{
return _XrSurfaceGetPicture(gstate->surface);
}
XrSurface *mask;
static Picture
_XrGStateGetSrcPicture(XrGState *gstate)
{
return _XrSurfaceGetPicture(gstate->src);
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);
XrSurfaceDestroy (mask);
return XrStatusSuccess;
}

View file

@ -159,27 +159,14 @@ typedef struct _XrPen {
XrPenVertex *vertex;
} XrPen;
typedef struct _XrSurface {
struct _XrSurface {
Display *dpy;
Drawable drawable;
GC gc;
unsigned int width;
unsigned int height;
unsigned int depth;
unsigned long xc_sa_mask;
XcSurfaceAttributes xc_sa;
XrFormat format;
XcFormat *xc_format;
char *image_data;
XcSurface *xc_surface;
int needs_new_xc_surface;
unsigned int ref_count;
} XrSurface;
};
typedef struct _XrColor {
double red;
@ -224,8 +211,6 @@ typedef struct _XrFont {
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
typedef struct _XrGState {
Display *dpy;
XrOperator operator;
double tolerance;
@ -242,13 +227,11 @@ typedef struct _XrGState {
int num_dashes;
double dash_offset;
XcFormat *alphaFormat;
XrFont font;
XrSurface *parent_surface;
XrSurface *surface;
XrSurface *src;
XrSurface *solid;
XrSurface *pattern;
XrSurface *mask;
double alpha;
@ -269,7 +252,6 @@ typedef struct _XrGState {
} XrGState;
struct _XrState {
Display *dpy;
XrGState *stack;
XrStatus status;
};
@ -306,10 +288,10 @@ typedef struct _XrFiller {
/* xrstate.c */
XrState *
_XrStateCreate(Display *dpy);
_XrStateCreate(void);
XrStatus
_XrStateInit(XrState *state, Display *dpy);
_XrStateInit(XrState *state);
void
_XrStateDeinit(XrState *xrs);
@ -325,10 +307,10 @@ _XrStatePop(XrState *xrs);
/* xrgstate.c */
XrGState *
_XrGStateCreate(Display *dpy);
_XrGStateCreate(void);
void
_XrGStateInit(XrGState *gstate, Display *dpy);
_XrGStateInit(XrGState *gstate);
XrStatus
_XrGStateInitCopy(XrGState *gstate, XrGState *other);
@ -357,6 +339,19 @@ _XrGStateSetVisual(XrGState *gstate, Visual *visual);
XrStatus
_XrGStateSetFormat(XrGState *gstate, XrFormat format);
XrStatus
_XrGStateSetTargetSurface (XrGState *gstate, XrSurface *surface);
XrSurface *
_XrGStateGetTargetSurface (XrGState *gstate);
XrStatus
_XrGStateSetTargetDrawable (XrGState *gstate,
Display *dpy,
Drawable drawable,
Visual *visual,
XrFormat format);
XrStatus
_XrGStateSetOperator(XrGState *gstate, XrOperator operator);
@ -487,6 +482,14 @@ _XrGStateShowImageTransform(XrGState *gstate,
double c, double d,
double tx, double ty);
XrStatus
_XrGStateShowSurface(XrGState *gstate,
XrSurface *surface,
int x,
int y,
int width,
int height);
/* xrcolor.c */
void
_XrColorInit(XrColor *color);
@ -554,72 +557,28 @@ XrStatus
_XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure);
/* xrsurface.c */
XrSurface *
_XrSurfaceCreate(Display *dpy);
void
_XrSurfaceInit(XrSurface *surface, Display *dpy);
void
_XrSurfaceDeinit(XrSurface *surface);
void
_XrSurfaceDestroy(XrSurface *surface);
void
_XrSurfaceReference(XrSurface *surface);
void
_XrSurfaceDereference(XrSurface *surface);
void
_XrSurfaceDereferenceDestroy(XrSurface *surface);
void
_XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color);
XrStatus
_XrSurfaceSetImage(XrSurface *surface,
char *data,
unsigned int width,
unsigned int height,
unsigned int stride);
XrStatus
_XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform);
void
_XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable);
void
_XrSurfaceSetDrawableWH(XrSurface *surface,
Drawable drawable,
unsigned int width,
unsigned int height);
void
_XrSurfaceSetVisual(XrSurface *surface, Visual *visual);
void
_XrSurfaceSetFormat(XrSurface *surface, XrFormat format);
XcSurface *
_XrSurfaceGetXcSurface(XrSurface *surface);
/* XXX: This function is going away, right? */
Picture
_XrSurfaceGetPicture(XrSurface *surface);
Drawable
_XrSurfaceGetDrawable(XrSurface *surface);
unsigned int
_XrSurfaceGetWidth(XrSurface *surface);
unsigned int
_XrSurfaceGetHeight(XrSurface *surface);
unsigned int
_XrSurfaceGetDepth(XrSurface *surface);
void
_XrSurfaceFillRectangle (XrSurface *surface,
XrOperator operator,
XrColor *color,
int x,
int y,
int width,
int height);
/* xrpen.c */
XrStatus
@ -762,13 +721,13 @@ _XrTransformBoundingBox(XrTransform *transform,
double *width, double *height);
XrStatus
_XrTransformComputeInverse(XrTransform *transform);
_XrTransformInvert(XrTransform *transform);
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
_XrTransformComputeEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
/* xrtraps.c */
void

View file

@ -27,7 +27,7 @@
#include "xrint.h"
XrState *
_XrStateCreate(Display *dpy)
_XrStateCreate(void)
{
XrStatus status;
XrState *xrs;
@ -35,7 +35,7 @@ _XrStateCreate(Display *dpy)
xrs = malloc(sizeof(XrState));
if (xrs) {
status = _XrStateInit(xrs, dpy);
status = _XrStateInit(xrs);
if (status) {
free(xrs);
return NULL;
@ -46,9 +46,8 @@ _XrStateCreate(Display *dpy)
}
XrStatus
_XrStateInit(XrState *xrs, Display *dpy)
_XrStateInit(XrState *xrs)
{
xrs->dpy = dpy;
xrs->stack = NULL;
xrs->status = XrStatusSuccess;
@ -79,7 +78,7 @@ _XrStatePush(XrState *xrs)
if (xrs->stack) {
top = _XrGStateClone(xrs->stack);
} else {
top = _XrGStateCreate(xrs->dpy);
top = _XrGStateCreate();
}
if (top == NULL)

View file

@ -28,151 +28,238 @@
#include "xrint.h"
XrSurface *
_XrSurfaceCreate(Display *dpy)
XrSurfaceCreateForDrawable (Display *dpy,
Drawable drawable,
Visual *visual,
XrFormat format,
Colormap colormap)
{
XrSurface *surface;
surface = malloc(sizeof(XrSurface));
if (surface == NULL)
return NULL;
if (surface)
_XrSurfaceInit(surface, dpy);
surface->dpy = dpy;
surface->image_data = NULL;
surface->xc_surface = XcSurfaceCreateForDrawable (dpy, drawable, visual, format, colormap);
if (surface->xc_surface == NULL) {
free (surface);
return NULL;
}
surface->ref_count = 1;
return surface;
}
void
_XrSurfaceInit(XrSurface *surface, Display *dpy)
/* XXX: These definitions are 100% bogus. The problem that needs to be
fixed is that Ic needs to export a real API for passing in
formats. */
#define PICT_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \
((type) << 16) | \
((a) << 12) | \
((r) << 8) | \
((g) << 4) | \
((b)))
/*
* gray/color formats use a visual index instead of argb
*/
#define PICT_VISFORMAT(bpp,type,vi) (((bpp) << 24) | \
((type) << 16) | \
((vi)))
#define PICT_TYPE_A 1
#define PICT_TYPE_ARGB 2
#define PICT_FORMAT_COLOR(f) (PICT_FORMAT_TYPE(f) & 2)
/* 32bpp formats */
#define PICT_a8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,8,8,8,8)
#define PICT_x8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,0,8,8,8)
#define PICT_a8 PICT_FORMAT(8,PICT_TYPE_A,8,0,0,0)
#define PICT_a1 PICT_FORMAT(1,PICT_TYPE_A,1,0,0,0)
static int
_XrFormatBPP (XrFormat format)
{
surface->dpy = dpy;
surface->drawable = 0;
surface->gc = 0;
surface->width = 0;
surface->height = 0;
surface->depth = 0;
surface->xc_sa_mask = 0;
_XrSurfaceSetFormat(surface, XrFormatARGB32);
surface->xc_surface = 0;
surface->needs_new_xc_surface = 1;
surface->ref_count = 0;
switch (format) {
case XrFormatA1:
return 1;
break;
case XrFormatA8:
return 8;
break;
case XrFormatARGB32:
case XrFormatRGB32:
default:
return 32;
break;
}
}
void
_XrSurfaceDeinit(XrSurface *surface)
XrSurface *
XrSurfaceCreateForImage (char *data,
XrFormat format,
int width,
int height,
int stride)
{
if (surface->xc_surface)
XcFreeSurface(surface->dpy, surface->xc_surface);
if (surface->gc)
XFreeGC(surface->dpy, surface->gc);
XrSurface *surface;
IcFormat icformat;
IcImage *image;
int bpp;
/* XXX: This all needs to change, (but IcFormatInit interface needs to change first) */
switch (format) {
case XrFormatARGB32:
IcFormatInit (&icformat, PICT_a8r8g8b8);
bpp = 32;
break;
case XrFormatRGB32:
IcFormatInit (&icformat, PICT_x8r8g8b8);
bpp = 32;
break;
case XrFormatA8:
IcFormatInit (&icformat, PICT_a8);
bpp = 8;
break;
case XrFormatA1:
IcFormatInit (&icformat, PICT_a1);
bpp = 1;
break;
default:
return NULL;
}
surface = malloc(sizeof(XrSurface));
if (surface == NULL)
return NULL;
surface->dpy = NULL;
surface->image_data = NULL;
image = IcImageCreateForData ((IcBits *) data, &icformat, width, height, _XrFormatBPP (format), stride);
if (image == NULL) {
free (surface);
return NULL;
}
surface->xc_surface = XcSurfaceCreateForIcImage (image);
if (surface->xc_surface == NULL) {
IcImageDestroy (image);
free (surface);
return NULL;
}
surface->ref_count = 1;
return surface;
}
void
_XrSurfaceDestroy(XrSurface *surface)
XrSurface *
XrSurfaceCreateNextTo (XrSurface *neighbor, XrFormat format, int width, int height)
{
_XrSurfaceDeinit(surface);
free(surface);
return XrSurfaceCreateNextToSolid (neighbor, format, width, height, 0, 0, 0, 0);
}
static int
_XrFormatDepth (XrFormat format)
{
switch (format) {
case XrFormatA1:
return 1;
case XrFormatA8:
return 8;
case XrFormatARGB32:
case XrFormatRGB32:
default:
return 32;
}
}
XrSurface *
XrSurfaceCreateNextToSolid (XrSurface *neighbor,
XrFormat format,
int width,
int height,
double red,
double green,
double blue,
double alpha)
{
XrSurface *surface = NULL;
XrColor color;
/* XXX: CreateNextTo should perhaps move down to Xc, (then we
could drop xrsurface->dpy as well) */
if (neighbor->dpy) {
Display *dpy = neighbor->dpy;
int scr = DefaultScreen (dpy);
Pixmap pix = XCreatePixmap(dpy,
DefaultRootWindow (dpy),
width, height,
_XrFormatDepth (format));
surface = XrSurfaceCreateForDrawable (dpy, pix,
NULL,
format,
DefaultColormap (dpy, scr));
XFreePixmap(surface->dpy, pix);
} else {
char *data;
int stride;
stride = ((width * _XrFormatBPP (format)) + 7) >> 3;
data = malloc (stride * height);
if (data == NULL)
return NULL;
surface = XrSurfaceCreateForImage (data, format,
width, height, stride);
/* lodge data in the surface structure to be freed with the surface */
surface->image_data = data;
}
/* XXX: Initializing the color in this way assumes
non-pre-multiplied alpha. I'm not sure that that's what I want
to do or not. */
_XrColorInit (&color);
_XrColorSetRGB (&color, red, green, blue);
_XrColorSetAlpha (&color, alpha);
_XrSurfaceFillRectangle (surface, XrOperatorSrc, &color, 0, 0, width, height);
return surface;
}
void
_XrSurfaceReference(XrSurface *surface)
{
if (surface == NULL)
return;
surface->ref_count++;
}
void
_XrSurfaceDereference(XrSurface *surface)
XrSurfaceDestroy(XrSurface *surface)
{
if (surface->ref_count == 0)
_XrSurfaceDeinit(surface);
else
surface->ref_count--;
}
if (surface == NULL)
return;
void
_XrSurfaceDereferenceDestroy(XrSurface *surface)
{
if (surface->ref_count == 0)
_XrSurfaceDestroy(surface);
else
_XrSurfaceDereference(surface);
}
surface->ref_count--;
if (surface->ref_count)
return;
void
_XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color)
{
/* XXX: QUESTION: Special handling for depth==1 ala xftdraw.c? */
if (surface->xc_surface == 0) {
Pixmap pix = XCreatePixmap(surface->dpy,
DefaultRootWindow(surface->dpy),
1, 1,
surface->xc_format->depth);
_XrSurfaceSetDrawableWH(surface, pix, 1, 1);
surface->xc_sa_mask |= CPRepeat;
surface->xc_sa.repeat = True;
_XrSurfaceGetXcSurface(surface);
XFreePixmap(surface->dpy, pix);
}
XcFillRectangle(surface->dpy, PictOpSrc,
surface->xc_surface, &color->xc_color,
0, 0, 1, 1);
}
surface->dpy = 0;
XrStatus
_XrSurfaceSetImage(XrSurface *surface,
char *data,
unsigned int width,
unsigned int height,
unsigned int stride)
{
XImage *image;
unsigned int depth, bitmap_pad;
Pixmap pix;
XcSurfaceDestroy (surface->xc_surface);
surface->xc_surface = NULL;
depth = surface->xc_format->depth;
if (depth > 16)
bitmap_pad = 32;
else if (depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
pix = XCreatePixmap(surface->dpy,
DefaultRootWindow(surface->dpy),
width, height,
depth);
_XrSurfaceSetDrawableWH(surface, pix, width, height);
image = XCreateImage(surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
depth, ZPixmap, 0,
data, width, height,
bitmap_pad,
stride);
if (image == NULL)
return XrStatusNoMemory;
XPutImage(surface->dpy, surface->drawable, surface->gc,
image, 0, 0, 0, 0, width, height);
/* I want to free the pixmap, so I have to commit to an xc_surface
to reference the pixmap in the Picture. */
_XrSurfaceGetXcSurface(surface);
XFreePixmap(surface->dpy, pix);
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
image->data = NULL;
XDestroyImage(image);
return XrStatusSuccess;
free(surface);
}
/* XXX: We may want to move to projective matrices at some point. If
@ -195,129 +282,50 @@ _XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform)
xtransform.matrix[2][1] = 0;
xtransform.matrix[2][2] = XDoubleToFixed(1);
XcSetSurfaceTransform(surface->dpy,
_XrSurfaceGetXcSurface(surface),
XcSurfaceSetTransform(surface->xc_surface,
&xtransform);
return XrStatusSuccess;
}
void
_XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable)
/* XXX: The Xc version of this function isn't quite working yet
XrStatus
XrSurfaceSetClipRegion (XrSurface *surface, Region region)
{
Window root;
int x, y;
unsigned int border, depth;
unsigned int width, height;
XcSurfaceSetClipRegion (surface->xc_surface, region);
XGetGeometry (surface->dpy, drawable,
&root, &x, &y,
&width, &height,
&border, &depth);
return XrStatusSuccess;
}
*/
_XrSurfaceSetDrawableWH(surface, drawable, width, height);
}
void
_XrSurfaceSetDrawableWH(XrSurface *surface,
Drawable drawable,
unsigned int width,
unsigned int height)
{
if (surface->gc)
XFreeGC(surface->dpy, surface->gc);
surface->drawable = drawable;
surface->width = width;
surface->height = height;
surface->gc = XCreateGC(surface->dpy, surface->drawable, 0, 0);
surface->needs_new_xc_surface = 1;
}
void
_XrSurfaceSetVisual(XrSurface *surface, Visual *visual)
{
surface->xc_format = XcFindVisualFormat(surface->dpy, visual);
surface->needs_new_xc_surface = 1;
}
void
_XrSurfaceSetFormat(XrSurface *surface, XrFormat format)
{
surface->format = format;
surface->xc_format = XcFindStandardFormat(surface->dpy, format);
switch (surface->format) {
case XrFormatARGB32:
surface->depth = 32;
case XrFormatRGB32:
/* XXX: Is this correct? */
surface->depth = 24;
case XrFormatA8:
surface->depth = 8;
case XrFormatA1:
surface->depth = 1;
default:
surface->depth = 32;
}
surface->needs_new_xc_surface = 1;
}
XcSurface *
_XrSurfaceGetXcSurface(XrSurface *surface)
{
if (surface == NULL)
return NULL;
if (! surface->needs_new_xc_surface)
return surface->xc_surface;
if (surface->xc_surface)
XcFreeSurface(surface->dpy, surface->xc_surface);
if (surface->drawable)
surface->xc_surface = XcCreateDrawableSurface(surface->dpy,
surface->drawable,
surface->xc_format,
surface->xc_sa_mask,
&surface->xc_sa);
else
/* XXX: Is this what we wnat to do here? */
surface->xc_surface = 0;
surface->needs_new_xc_surface = 0;
return surface->xc_surface;
XrStatus
XrSurfaceSetRepeat (XrSurface *surface, int repeat)
{
XcSurfaceSetRepeat (surface->xc_surface, repeat);
return XrStatusSuccess;
}
/* XXX: This function is going away, right? */
Picture
_XrSurfaceGetPicture(XrSurface *surface)
{
return XcSurfaceGetPicture(_XrSurfaceGetXcSurface(surface));
return XcSurfaceGetPicture(surface->xc_surface);
}
Drawable
_XrSurfaceGetDrawable(XrSurface *surface)
void
_XrSurfaceFillRectangle (XrSurface *surface,
XrOperator operator,
XrColor *color,
int x,
int y,
int width,
int height)
{
return surface->drawable;
XcFillRectangle (operator,
surface->xc_surface,
&color->xc_color,
x, y,
width, height);
}
unsigned int
_XrSurfaceGetWidth(XrSurface *surface)
{
return surface->width;
}
unsigned int
_XrSurfaceGetHeight(XrSurface *surface)
{
return surface->height;
}
unsigned int
_XrSurfaceGetDepth(XrSurface *surface)
{
return surface->depth;
}

View file

@ -241,18 +241,18 @@ _XrTransformComputeAdjoint(XrTransform *transform)
}
XrStatus
_XrTransformComputeInverse(XrTransform *transform)
_XrTransformInvert (XrTransform *transform)
{
/* inv(A) = 1/det(A) * adj(A) */
double det;
_XrTransformComputeDeterminant(transform, &det);
_XrTransformComputeDeterminant (transform, &det);
if (det == 0)
return XrStatusInvalidMatrix;
_XrTransformComputeAdjoint(transform);
_XrTransformScalarMultiply(transform, 1 / det);
_XrTransformComputeAdjoint (transform);
_XrTransformScalarMultiply (transform, 1 / det);
return XrStatusSuccess;
}
@ -269,7 +269,7 @@ _XrTransformComputeDeterminant(XrTransform *transform, double *det)
}
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
_XrTransformComputeEigenValues (XrTransform *transform, double *lambda1, double *lambda2)
{
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:

513
xr.c
View file

@ -1,513 +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 "xrint.h"
#define _XR_CURRENT_GSTATE(xrs) (xrs->stack)
#define XR_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static void
_XrClipValue(double *value, double min, double max);
XrState *
XrCreate(Display *dpy)
{
return _XrStateCreate(dpy);
}
void
XrDestroy(XrState *xrs)
{
_XrStateDestroy(xrs);
}
void
XrSave(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrStatePush(xrs);
}
void
XrRestore(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrStatePop(xrs);
}
void
XrPushGroup(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrStatePush(xrs);
if (xrs->status)
return;
xrs->status = _XrGStateBeginGroup(_XR_CURRENT_GSTATE(xrs));
}
void
XrPopGroup(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateEndGroup(_XR_CURRENT_GSTATE(xrs));
if (xrs->status)
return;
xrs->status = _XrStatePop(xrs);
}
void
XrSetDrawable(XrState *xrs, Drawable drawable)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetDrawable(_XR_CURRENT_GSTATE(xrs), drawable);
}
void
XrSetVisual(XrState *xrs, Visual *visual)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetVisual(_XR_CURRENT_GSTATE(xrs), visual);
}
void
XrSetFormat(XrState *xrs, XrFormat format)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetFormat(_XR_CURRENT_GSTATE(xrs), format);
}
void
XrSetOperator(XrState *xrs, XrOperator operator)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetOperator(_XR_CURRENT_GSTATE(xrs), operator);
}
void
XrSetRGBColor(XrState *xrs, double red, double green, double blue)
{
if (xrs->status)
return;
_XrClipValue(&red, 0.0, 1.0);
_XrClipValue(&green, 0.0, 1.0);
_XrClipValue(&blue, 0.0, 1.0);
xrs->status = _XrGStateSetRGBColor(_XR_CURRENT_GSTATE(xrs), red, green, blue);
}
void
XrSetTolerance(XrState *xrs, double tolerance)
{
if (xrs->status)
return;
_XrClipValue(&tolerance, XR_TOLERANCE_MINIMUM, tolerance);
xrs->status = _XrGStateSetTolerance(_XR_CURRENT_GSTATE(xrs), tolerance);
}
void
XrSetAlpha(XrState *xrs, double alpha)
{
if (xrs->status)
return;
_XrClipValue(&alpha, 0.0, 1.0);
xrs->status = _XrGStateSetAlpha(_XR_CURRENT_GSTATE(xrs), alpha);
}
void
XrSetFillRule(XrState *xrs, XrFillRule fill_rule)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetFillRule(_XR_CURRENT_GSTATE(xrs), fill_rule);
}
void
XrSetLineWidth(XrState *xrs, double width)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetLineWidth(_XR_CURRENT_GSTATE(xrs), width);
}
void
XrSetLineCap(XrState *xrs, XrLineCap line_cap)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetLineCap(_XR_CURRENT_GSTATE(xrs), line_cap);
}
void
XrSetLineJoin(XrState *xrs, XrLineJoin line_join)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetLineJoin(_XR_CURRENT_GSTATE(xrs), line_join);
}
void
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetDash(_XR_CURRENT_GSTATE(xrs), dashes, ndash, offset);
}
void
XrSetMiterLimit(XrState *xrs, double limit)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetMiterLimit(_XR_CURRENT_GSTATE(xrs), limit);
}
void
XrTranslate(XrState *xrs, double tx, double ty)
{
if (xrs->status)
return;
xrs->status = _XrGStateTranslate(_XR_CURRENT_GSTATE(xrs), tx, ty);
}
void
XrScale(XrState *xrs, double sx, double sy)
{
if (xrs->status)
return;
xrs->status = _XrGStateScale(_XR_CURRENT_GSTATE(xrs), sx, sy);
}
void
XrRotate(XrState *xrs, double angle)
{
if (xrs->status)
return;
xrs->status = _XrGStateRotate(_XR_CURRENT_GSTATE(xrs), angle);
}
void
XrConcatMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty)
{
if (xrs->status)
return;
xrs->status = _XrGStateConcatMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty);
}
void
XrSetMatrix(XrState *xrs,
double a, double b,
double c, double d,
double tx, double ty)
{
if (xrs->status)
return;
xrs->status = _XrGStateSetMatrix(_XR_CURRENT_GSTATE(xrs), a, b, c, d, tx, ty);
}
void
XrDefaultMatrix(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateIdentityMatrix(_XR_CURRENT_GSTATE(xrs));
}
void
XrIdentityMatrix(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateIdentityMatrix(_XR_CURRENT_GSTATE(xrs));
}
void
XrNewPath(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateNewPath(_XR_CURRENT_GSTATE(xrs));
}
void
XrMoveTo(XrState *xrs, double x, double y)
{
if (xrs->status)
return;
xrs->status = _XrGStateMoveTo(_XR_CURRENT_GSTATE(xrs), x, y);
}
void
XrLineTo(XrState *xrs, double x, double y)
{
if (xrs->status)
return;
xrs->status = _XrGStateLineTo(_XR_CURRENT_GSTATE(xrs), x, y);
}
void
XrCurveTo(XrState *xrs,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
if (xrs->status)
return;
xrs->status = _XrGStateCurveTo(_XR_CURRENT_GSTATE(xrs),
x1, y1,
x2, y2,
x3, y3);
}
void
XrRelMoveTo(XrState *xrs, double dx, double dy)
{
if (xrs->status)
return;
xrs->status = _XrGStateRelMoveTo(_XR_CURRENT_GSTATE(xrs), dx, dy);
}
void
XrRelLineTo(XrState *xrs, double dx, double dy)
{
if (xrs->status)
return;
xrs->status = _XrGStateRelLineTo(_XR_CURRENT_GSTATE(xrs), dx, dy);
}
void
XrRelCurveTo(XrState *xrs,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3)
{
if (xrs->status)
return;
xrs->status = _XrGStateRelCurveTo(_XR_CURRENT_GSTATE(xrs),
dx1, dy1,
dx2, dy2,
dx3, dy3);
}
void
XrClosePath(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateClosePath(_XR_CURRENT_GSTATE(xrs));
}
void
XrStroke(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateStroke(_XR_CURRENT_GSTATE(xrs));
}
void
XrFill(XrState *xrs)
{
if (xrs->status)
return;
xrs->status = _XrGStateFill(_XR_CURRENT_GSTATE(xrs));
}
void
XrSelectFont(XrState *xrs, const char *key)
{
if (xrs->status)
return;
xrs->status = _XrGStateSelectFont(_XR_CURRENT_GSTATE(xrs), key);
}
void
XrScaleFont(XrState *xrs, double scale)
{
if (xrs->status)
return;
xrs->status = _XrGStateScaleFont(_XR_CURRENT_GSTATE(xrs), scale);
}
void
XrTransformFont(XrState *xrs,
double a, double b,
double c, double d)
{
if (xrs->status)
return;
xrs->status = _XrGStateTransformFont(_XR_CURRENT_GSTATE(xrs),
a, b, c, d);
}
void
XrTextExtents(XrState *xrs,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
{
if (xrs->status)
return;
xrs->status = _XrGStateTextExtents(_XR_CURRENT_GSTATE(xrs), utf8,
x, y, width, height, dx, dy);
}
void
XrShowText(XrState *xrs, const unsigned char *utf8)
{
if (xrs->status)
return;
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);
}
XrStatus
XrGetStatus(XrState *xrs)
{
return xrs->status;
}
const char *
XrGetStatusString(XrState *xrs)
{
switch (xrs->status) {
case XrStatusSuccess:
return "success";
case XrStatusNoMemory:
return "out of memory";
case XrStatusInvalidRestore:
return "XrRestore without matching XrSave";
case XrStatusInvalidPopGroup:
return "XrPopGroup without matching XrPushGroup";
case XrStatusNoCurrentPoint:
return "no current point defined";
case XrStatusInvalidMatrix:
return "invalid matrix (not invertible)";
}
return "";
}
static void
_XrClipValue(double *value, double min, double max)
{
if (*value < min)
*value = min;
else if (*value > max)
*value = max;
}

View file

@ -1,70 +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 "xrint.h"
static XrColor XR_COLOR_DEFAULT = { 1.0, 1.0, 1.0, 1.0, {0xffff, 0xffff, 0xffff, 0xffff}};
static void
_XrColorComputeXcColor(XrColor *color);
void
_XrColorInit(XrColor *color)
{
*color = XR_COLOR_DEFAULT;
}
void
_XrColorDeinit(XrColor *color)
{
/* Nothing to do here */
}
static void
_XrColorComputeXcColor(XrColor *color)
{
color->xc_color.red = color->red * color->alpha * 0xffff;
color->xc_color.green = color->green * color->alpha * 0xffff;
color->xc_color.blue = color->blue * color->alpha * 0xffff;
color->xc_color.alpha = color->alpha * 0xffff;
}
void
_XrColorSetRGB(XrColor *color, double red, double green, double blue)
{
color->red = red;
color->green = green;
color->blue = blue;
_XrColorComputeXcColor(color);
}
void
_XrColorSetAlpha(XrColor *color, double alpha)
{
color->alpha = alpha;
_XrColorComputeXcColor(color);
}

View file

@ -1,103 +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 "xrint.h"
void
_XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps)
{
filler->gstate = gstate;
filler->traps = traps;
_XrPolygonInit(&filler->polygon);
}
void
_XrFillerDeinit(XrFiller *filler)
{
_XrPolygonDeinit(&filler->polygon);
}
XrStatus
_XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
{
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
return _XrPolygonAddEdge(polygon, p1, p2);
}
XrStatus
_XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
{
int i;
XrStatus status = XrStatusSuccess;
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
XrGState *gstate = filler->gstate;
XrSpline spline;
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
_XrSplineDecompose(&spline, gstate->tolerance);
if (status)
goto CLEANUP_SPLINE;
for (i = 0; i < spline.num_pts - 1; i++) {
status = _XrPolygonAddEdge(polygon, &spline.pts[i], &spline.pts[i+1]);
if (status)
goto CLEANUP_SPLINE;
}
CLEANUP_SPLINE:
_XrSplineDeinit(&spline);
return status;
}
XrStatus
_XrFillerDoneSubPath (void *closure, XrSubPathDone done)
{
XrStatus status = XrStatusSuccess;
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
_XrPolygonClose(polygon);
return status;
}
XrStatus
_XrFillerDonePath (void *closure)
{
XrFiller *filler = closure;
return _XrTrapsTessellatePolygon(filler->traps,
&filler->polygon,
filler->gstate->fill_rule);
}

170
xrfont.c
View file

@ -1,170 +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 <string.h>
#include "xrint.h"
void
_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;
}
XrStatus
_XrFontInitCopy(XrFont *font, XrFont *other)
{
*font = *other;
if (other->key) {
font->key = (unsigned char *) strdup((char *) other->key);
if (font->key == NULL)
return XrStatusNoMemory;
}
if (other->xft_font) {
font->xft_font = XftFontCopy(other->dpy, other->xft_font);
if (font->xft_font == NULL)
return XrStatusNoMemory;
}
return XrStatusSuccess;
}
void
_XrFontDeinit(XrFont *font)
{
if (font->key)
free(font->key);
font->key = NULL;
_XrTransformDeinit(&font->transform);
if (font->xft_font)
XftFontClose(font->dpy, font->xft_font);
font->xft_font = NULL;
}
XrStatus
_XrFontSelect(XrFont *font, const char *key)
{
if (font->xft_font)
XftFontClose(font->dpy, font->xft_font);
font->xft_font = NULL;
if (font->key)
free(font->key);
font->key = (unsigned char *) strdup((char *) key);
if (font->key == NULL)
return XrStatusNoMemory;
return XrStatusSuccess;
}
XrStatus
_XrFontScale(XrFont *font, double scale)
{
if (font->has_transform) {
XrTransform tmp;
_XrTransformInitScale(&tmp, scale, scale);
_XrTransformMultiplyIntoRight(&tmp, &font->transform);
} else {
font->scale *= scale;
}
return XrStatusSuccess;
}
XrStatus
_XrFontTransform(XrFont *font,
double a, double b,
double c, double d)
{
XrTransform tmp;
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;
return XrStatusSuccess;
}
XrStatus
_XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font)
{
FcPattern *pattern;
FcPattern *match;
FcResult result;
XrTransform matrix;
FcMatrix fc_matrix;
if (font->xft_font) {
*xft_font = font->xft_font;
return XrStatusSuccess;
}
pattern = FcNameParse(font->key);
matrix = gstate->ctm;
if (!font->has_transform) {
FcPatternAddDouble(pattern, "pixelsize", font->scale);
} else {
_XrTransformMultiplyIntoRight(&font->transform, &matrix);
}
fc_matrix.xx = matrix.m[0][0];
fc_matrix.xy = matrix.m[0][1];
fc_matrix.yx = matrix.m[1][0];
fc_matrix.yy = matrix.m[1][1];
FcPatternAddMatrix(pattern, "matrix", &fc_matrix);
font->dpy = gstate->dpy;
match = XftFontMatch (font->dpy, DefaultScreen(font->dpy), pattern, &result);
if (!match)
return 0;
font->xft_font = XftFontOpenPattern (font->dpy, match);
*xft_font = font->xft_font;
FcPatternDestroy (pattern);
return XrStatusSuccess;
}

View file

@ -1,885 +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 Picture
_XrGStateGetPicture(XrGState *gstate);
static Picture
_XrGStateGetSrcPicture(XrGState *gstate);
XrGState *
_XrGStateCreate(Display *dpy)
{
XrGState *gstate;
gstate = malloc(sizeof(XrGState));
if (gstate)
_XrGStateInit(gstate, dpy);
return gstate;
}
void
_XrGStateInit(XrGState *gstate, Display *dpy)
{
gstate->dpy = dpy;
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = XR_GSTATE_TOLERANCE_DEFAULT;
gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
gstate->line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
gstate->line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
gstate->miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
gstate->fill_rule = XR_GSTATE_FILL_RULE_DEFAULT;
gstate->dash = NULL;
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
_XrFontInit(&gstate->font);
gstate->parent_surface = NULL;
gstate->surface = _XrSurfaceCreate(dpy);
gstate->src = _XrSurfaceCreate(dpy);
gstate->mask = NULL;
gstate->alpha = 1.0;
_XrColorInit(&gstate->color);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
_XrTransformInitIdentity(&gstate->ctm);
_XrTransformInitIdentity(&gstate->ctm_inverse);
_XrPathInit(&gstate->path);
gstate->has_current_pt = 0;
_XrPenInitEmpty(&gstate->pen_regular);
gstate->next = NULL;
}
XrStatus
_XrGStateInitCopy(XrGState *gstate, XrGState *other)
{
XrStatus status;
*gstate = *other;
if (other->dash) {
gstate->dash = malloc (other->num_dashes * sizeof (double));
if (gstate->dash == NULL)
return XrStatusNoMemory;
memcpy(gstate->dash, other->dash, other->num_dashes * sizeof (double));
}
status = _XrFontInitCopy(&gstate->font, &other->font);
if (status)
goto CLEANUP_DASHES;
gstate->parent_surface = NULL;
_XrSurfaceReference(gstate->surface);
_XrSurfaceReference(gstate->src);
if (gstate->mask)
_XrSurfaceReference(gstate->mask);
status = _XrPathInitCopy(&gstate->path, &other->path);
if (status)
goto CLEANUP_FONT;
status = _XrPenInitCopy(&gstate->pen_regular, &other->pen_regular);
if (status)
goto CLEANUP_PATH;
return status;
CLEANUP_PATH:
_XrPathDeinit(&gstate->path);
CLEANUP_FONT:
_XrFontDeinit(&gstate->font);
CLEANUP_DASHES:
free (gstate->dash);
gstate->dash = NULL;
return status;
}
void
_XrGStateDeinit(XrGState *gstate)
{
if (gstate->parent_surface)
_XrGStateEndGroup(gstate);
_XrFontDeinit(&gstate->font);
_XrSurfaceDereferenceDestroy(gstate->surface);
_XrSurfaceDereferenceDestroy(gstate->src);
if (gstate->mask)
_XrSurfaceDereferenceDestroy(gstate->mask);
_XrColorDeinit(&gstate->color);
_XrTransformDeinit(&gstate->ctm);
_XrTransformDeinit(&gstate->ctm_inverse);
_XrPathDeinit(&gstate->path);
_XrPenDeinit(&gstate->pen_regular);
if (gstate->dash) {
free (gstate->dash);
gstate->dash = NULL;
}
}
void
_XrGStateDestroy(XrGState *gstate)
{
_XrGStateDeinit(gstate);
free(gstate);
}
XrGState*
_XrGStateClone(XrGState *gstate)
{
XrStatus status;
XrGState *clone;
clone = malloc(sizeof(XrGState));
if (clone) {
status = _XrGStateInitCopy(clone, gstate);
if (status) {
free(clone);
return NULL;
}
}
return clone;
}
/* Push rendering off to an off-screen group. */
XrStatus
_XrGStateBeginGroup(XrGState *gstate)
{
Pixmap pix;
XrColor clear;
unsigned int width, height;
gstate->parent_surface = gstate->surface;
width = _XrSurfaceGetWidth(gstate->surface);
height = _XrSurfaceGetHeight(gstate->surface);
pix = XCreatePixmap(gstate->dpy,
_XrSurfaceGetDrawable(gstate->surface),
width, height,
_XrSurfaceGetDepth(gstate->surface));
if (pix == 0)
return XrStatusNoMemory;
gstate->surface = _XrSurfaceCreate(gstate->dpy);
if (gstate->surface == NULL)
return XrStatusNoMemory;
_XrSurfaceSetDrawableWH(gstate->surface, pix, width, height);
_XrColorInit(&clear);
_XrColorSetAlpha(&clear, 0);
XcFillRectangle(gstate->dpy,
XrOperatorSrc,
_XrSurfaceGetXcSurface(gstate->surface),
&clear.xc_color,
0, 0,
_XrSurfaceGetWidth(gstate->surface),
_XrSurfaceGetHeight(gstate->surface));
return XrStatusSuccess;
}
/* Complete the current offscreen group, composing its contents onto the parent surface. */
XrStatus
_XrGStateEndGroup(XrGState *gstate)
{
Pixmap pix;
XrColor mask_color;
XrSurface mask;
if (gstate->parent_surface == NULL)
return XrStatusInvalidPopGroup;
_XrSurfaceInit(&mask, gstate->dpy);
_XrColorInit(&mask_color);
_XrColorSetAlpha(&mask_color, gstate->alpha);
_XrSurfaceSetSolidColor(&mask, &mask_color);
/* XXX: This could be made much more efficient by using
_XrSurfaceGetDamagedWidth/Height if XrSurface actually kept
track of such informaton. */
XcComposite(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(gstate->surface),
_XrSurfaceGetXcSurface(&mask),
_XrSurfaceGetXcSurface(gstate->parent_surface),
0, 0,
0, 0,
0, 0,
_XrSurfaceGetWidth(gstate->surface),
_XrSurfaceGetHeight(gstate->surface));
_XrSurfaceDeinit(&mask);
pix = _XrSurfaceGetDrawable(gstate->surface);
XFreePixmap(gstate->dpy, pix);
_XrSurfaceDestroy(gstate->surface);
gstate->surface = gstate->parent_surface;
gstate->parent_surface = NULL;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetDrawable(XrGState *gstate, Drawable drawable)
{
_XrSurfaceSetDrawable(gstate->surface, drawable);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetVisual(XrGState *gstate, Visual *visual)
{
_XrSurfaceSetVisual(gstate->surface, visual);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetFormat(XrGState *gstate, XrFormat format)
{
_XrSurfaceSetFormat(gstate->surface, format);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetOperator(XrGState *gstate, XrOperator operator)
{
gstate->operator = operator;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue)
{
_XrColorSetRGB(&gstate->color, red, green, blue);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetTolerance(XrGState *gstate, double tolerance)
{
gstate->tolerance = tolerance;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetAlpha(XrGState *gstate, double alpha)
{
gstate->alpha = alpha;
_XrColorSetAlpha(&gstate->color, alpha);
_XrSurfaceSetSolidColor(gstate->src, &gstate->color);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetFillRule(XrGState *gstate, XrFillRule fill_rule)
{
gstate->fill_rule = fill_rule;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetLineWidth(XrGState *gstate, double width)
{
gstate->line_width = width;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
{
gstate->line_cap = line_cap;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
{
gstate->line_join = line_join;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetDash(XrGState *gstate, double *dash, int num_dashes, double offset)
{
if (gstate->dash) {
free (gstate->dash);
gstate->dash = NULL;
}
gstate->num_dashes = num_dashes;
if (gstate->num_dashes) {
gstate->dash = malloc (gstate->num_dashes * sizeof (double));
if (gstate->dash == NULL) {
gstate->num_dashes = 0;
return XrStatusNoMemory;
}
}
memcpy (gstate->dash, dash, gstate->num_dashes * sizeof (double));
gstate->dash_offset = offset;
return XrStatusSuccess;
}
XrStatus
_XrGStateSetMiterLimit(XrGState *gstate, double limit)
{
gstate->miter_limit = limit;
return XrStatusSuccess;
}
XrStatus
_XrGStateTranslate(XrGState *gstate, double tx, double ty)
{
XrTransform tmp;
_XrTransformInitTranslate(&tmp, tx, ty);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformInitTranslate(&tmp, -tx, -ty);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
return XrStatusSuccess;
}
XrStatus
_XrGStateScale(XrGState *gstate, double sx, double sy)
{
XrTransform tmp;
_XrTransformInitScale(&tmp, sx, sy);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformInitScale(&tmp, 1/sx, 1/sy);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
return XrStatusSuccess;
}
XrStatus
_XrGStateRotate(XrGState *gstate, double angle)
{
XrTransform tmp;
_XrTransformInitRotate(&tmp, angle);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformInitRotate(&tmp, -angle);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
return XrStatusSuccess;
}
XrStatus
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty)
{
XrTransform tmp;
_XrTransformInitMatrix(&tmp, a, b, c, d, tx, ty);
_XrTransformMultiplyIntoRight(&tmp, &gstate->ctm);
_XrTransformComputeInverse(&tmp);
_XrTransformMultiplyIntoLeft(&gstate->ctm_inverse, &tmp);
return XrStatusSuccess;
}
XrStatus
_XrGStateSetMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty)
{
XrStatus status;
_XrTransformInitMatrix(&gstate->ctm, a, b, c, d, tx, ty);
gstate->ctm_inverse = gstate->ctm;
status = _XrTransformComputeInverse(&gstate->ctm_inverse);
if (status)
return status;
return XrStatusSuccess;
}
XrStatus
_XrGStateIdentityMatrix(XrGState *gstate)
{
_XrTransformInitIdentity(&gstate->ctm);
_XrTransformInitIdentity(&gstate->ctm_inverse);
return XrStatusSuccess;
}
static void
_XrGStateSetCurrentPt(XrGState *gstate, double x, double y)
{
gstate->current_pt.x = x;
gstate->current_pt.y = y;
gstate->has_current_pt = 1;
}
XrStatus
_XrGStateNewPath(XrGState *gstate)
{
_XrPathDeinit(&gstate->path);
gstate->has_current_pt = 0;
return XrStatusSuccess;
}
XrStatus
_XrGStateMoveTo(XrGState *gstate, double x, double y)
{
XrStatus status;
_XrTransformPoint(&gstate->ctm, &x, &y);
status = _XrPathMoveTo(&gstate->path, x, y);
_XrGStateSetCurrentPt(gstate, x, y);
gstate->last_move_pt = gstate->current_pt;
return status;
}
XrStatus
_XrGStateLineTo(XrGState *gstate, double x, double y)
{
XrStatus status;
_XrTransformPoint(&gstate->ctm, &x, &y);
status = _XrPathLineTo(&gstate->path, x, y);
_XrGStateSetCurrentPt(gstate, x, y);
return status;
}
XrStatus
_XrGStateCurveTo(XrGState *gstate,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
XrStatus status;
_XrTransformPoint(&gstate->ctm, &x1, &y1);
_XrTransformPoint(&gstate->ctm, &x2, &y2);
_XrTransformPoint(&gstate->ctm, &x3, &y3);
status = _XrPathCurveTo(&gstate->path,
x1, y1,
x2, y2,
x3, y3);
_XrGStateSetCurrentPt(gstate, x3, y3);
return status;
}
XrStatus
_XrGStateRelMoveTo(XrGState *gstate, double dx, double dy)
{
XrStatus status;
double x, y;
_XrTransformDistance(&gstate->ctm, &dx, &dy);
x = gstate->current_pt.x + dx;
y = gstate->current_pt.y + dy;
status = _XrPathMoveTo(&gstate->path, x, y);
_XrGStateSetCurrentPt(gstate, x, y);
gstate->last_move_pt = gstate->current_pt;
return status;
}
XrStatus
_XrGStateRelLineTo(XrGState *gstate, double dx, double dy)
{
XrStatus status;
double x, y;
_XrTransformDistance(&gstate->ctm, &dx, &dy);
x = gstate->current_pt.x + dx;
y = gstate->current_pt.y + dy;
status = _XrPathLineTo(&gstate->path, x, y);
_XrGStateSetCurrentPt(gstate, x, y);
return status;
}
XrStatus
_XrGStateRelCurveTo(XrGState *gstate,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3)
{
XrStatus status;
_XrTransformDistance(&gstate->ctm, &dx1, &dy1);
_XrTransformDistance(&gstate->ctm, &dx2, &dy2);
_XrTransformDistance(&gstate->ctm, &dx3, &dy3);
status = _XrPathCurveTo(&gstate->path,
gstate->current_pt.x + dx1, gstate->current_pt.y + dy1,
gstate->current_pt.x + dx2, gstate->current_pt.y + dy2,
gstate->current_pt.x + dx3, gstate->current_pt.y + dy3);
_XrGStateSetCurrentPt(gstate,
gstate->current_pt.x + dx3,
gstate->current_pt.y + dy3);
return status;
}
XrStatus
_XrGStateClosePath(XrGState *gstate)
{
XrStatus status;
status = _XrPathClosePath(&gstate->path);
_XrGStateSetCurrentPt(gstate,
gstate->last_move_pt.x,
gstate->last_move_pt.y);
return status;
}
XrStatus
_XrGStateStroke(XrGState *gstate)
{
XrStatus status;
static XrPathCallbacks cb = {
_XrStrokerAddEdge,
_XrStrokerAddSpline,
_XrStrokerDoneSubPath,
_XrStrokerDonePath
};
static XrPathCallbacks cb_dash = {
_XrStrokerAddEdgeDashed,
_XrStrokerAddSpline,
_XrStrokerDoneSubPath,
_XrStrokerDonePath
};
XrPathCallbacks *cbs = gstate->dash ? &cb_dash : &cb;
XrStroker stroker;
XrTraps traps;
_XrPenInit(&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_XrTrapsInit(&traps);
_XrStrokerInit(&stroker, gstate, &traps);
status = _XrPathInterpret(&gstate->path, XrPathDirectionForward, cbs, &stroker);
if (status) {
_XrStrokerDeinit(&stroker);
_XrTrapsDeinit(&traps);
return status;
}
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(gstate->src),
_XrSurfaceGetXcSurface(gstate->surface),
gstate->alphaFormat,
0, 0,
traps.xtraps,
traps.num_xtraps);
_XrStrokerDeinit(&stroker);
_XrTrapsDeinit(&traps);
_XrGStateNewPath(gstate);
return XrStatusSuccess;
}
XrStatus
_XrGStateFill(XrGState *gstate)
{
XrStatus status;
static XrPathCallbacks cb = {
_XrFillerAddEdge,
_XrFillerAddSpline,
_XrFillerDoneSubPath,
_XrFillerDonePath
};
XrFiller filler;
XrTraps traps;
_XrTrapsInit(&traps);
_XrFillerInit(&filler, gstate, &traps);
status = _XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &filler);
if (status) {
_XrFillerDeinit(&filler);
_XrTrapsDeinit(&traps);
return status;
}
XcCompositeTrapezoids(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(gstate->src),
_XrSurfaceGetXcSurface(gstate->surface),
gstate->alphaFormat,
0, 0,
traps.xtraps,
traps.num_xtraps);
_XrFillerDeinit(&filler);
_XrTrapsDeinit(&traps);
_XrGStateNewPath(gstate);
return XrStatusSuccess;
}
XrStatus
_XrGStateSelectFont(XrGState *gstate, const char *key)
{
return _XrFontSelect(&gstate->font, key);
}
XrStatus
_XrGStateScaleFont(XrGState *gstate, double scale)
{
return _XrFontScale(&gstate->font, scale);
}
XrStatus
_XrGStateTransformFont(XrGState *gstate,
double a, double b,
double c, double d)
{
return _XrFontTransform(&gstate->font,
a, b, c, d);
}
XrStatus
_XrGStateTextExtents(XrGState *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy)
{
XftFont *xft_font;
XGlyphInfo extents;
_XrFontResolveXftFont(&gstate->font, gstate, &xft_font);
XftTextExtentsUtf8(gstate->dpy,
xft_font,
utf8,
strlen((char *) utf8),
&extents);
/* XXX: What are the semantics of XftTextExtents? Specifically,
what does it do with x/y? I think we actually need to use the
gstate's current point in here somewhere. */
*x = extents.x;
*y = extents.y;
*width = extents.width;
*height = extents.height;
*dx = extents.xOff;
*dy = extents.yOff;
return XrStatusSuccess;
}
XrStatus
_XrGStateShowText(XrGState *gstate, const unsigned char *utf8)
{
XftFont *xft_font;
if (gstate->has_current_pt == 0)
return XrStatusNoCurrentPoint;
_XrFontResolveXftFont(&gstate->font, gstate, &xft_font);
XftTextRenderUtf8(gstate->dpy,
gstate->operator,
_XrGStateGetSrcPicture(gstate),
xft_font,
_XrGStateGetPicture(gstate),
0, 0,
gstate->current_pt.x,
gstate->current_pt.y,
utf8,
strlen((char *) utf8));
return XrStatusSuccess;
}
XrStatus
_XrGStateShowImage(XrGState *gstate,
char *data,
XrFormat format,
unsigned int width,
unsigned int height,
unsigned int stride)
{
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)
{
XrStatus status;
XrColor mask_color;
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;
_XrSurfaceInit(&mask, gstate->dpy);
_XrColorInit(&mask_color);
_XrColorSetAlpha(&mask_color, gstate->alpha);
_XrSurfaceSetSolidColor(&mask, &mask_color);
_XrSurfaceInit(&image_surface, gstate->dpy);
_XrSurfaceSetFormat(&image_surface, format);
status = _XrSurfaceSetImage(&image_surface, data,width, height, stride);
if (status)
return status;
_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);
image_to_user = user_to_image;
_XrTransformComputeInverse(&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);
XcComposite(gstate->dpy, gstate->operator,
_XrSurfaceGetXcSurface(&image_surface),
_XrSurfaceGetXcSurface(&mask),
_XrSurfaceGetXcSurface(gstate->surface),
dst_x, dst_y,
0, 0,
dst_x, dst_y,
dst_width + 1,
dst_height + 1);
_XrSurfaceDeinit(&image_surface);
_XrSurfaceDeinit(&mask);
return XrStatusSuccess;
}
static Picture
_XrGStateGetPicture(XrGState *gstate)
{
return _XrSurfaceGetPicture(gstate->surface);
}
static Picture
_XrGStateGetSrcPicture(XrGState *gstate)
{
return _XrSurfaceGetPicture(gstate->src);
}

794
xrint.h
View file

@ -1,794 +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.
*/
/*
* These definitions are solely for use by the implementation of Xr
* and constitute no kind of standard. If you need any of these
* functions, please drop me a note. Either the library needs new
* functionality, or there's a way to do what you need using the
* existing published interfaces. cworth@isi.edu
*/
#ifndef _XRINT_H_
#define _XRINT_H_
#include <math.h>
#include <X11/Xlibint.h>
#include <X11/Xft/Xft.h>
#include "Xr.h"
#ifndef __GCC__
#define __attribute__(x)
#endif
/* Sure wish C had a real enum type so that this would be distinct
from XrStatus. Oh well, without that, I'll use this bogus 1000
offset */
typedef enum _XrIntStatus {
XrIntStatusDegenerate = 1000
} XrIntStatus;
typedef enum _XrPathOp {
XrPathOpMoveTo = 0,
XrPathOpLineTo = 1,
XrPathOpCurveTo = 2,
XrPathOpClosePath = 3
} __attribute__ ((packed)) XrPathOp; /* Don't want 32 bits if we can avoid it. */
typedef enum _XrPathDirection {
XrPathDirectionForward,
XrPathDirectionReverse
} XrPathDirection;
typedef enum _XrSubPathDone {
XrSubPathDoneCap,
XrSubPathDoneJoin
} XrSubPathDone;
typedef struct _XrPathCallbacks {
XrStatus (*AddEdge)(void *closure, XPointFixed *p1, XPointFixed *p2);
XrStatus (*AddSpline)(void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus (*DoneSubPath) (void *closure, XrSubPathDone done);
XrStatus (*DonePath) (void *closure);
} XrPathCallbacks;
#define XR_PATH_BUF_SZ 64
typedef struct _XrPathOpBuf {
int num_ops;
XrPathOp op[XR_PATH_BUF_SZ];
struct _XrPathOpBuf *next, *prev;
} XrPathOpBuf;
typedef struct _XrPathArgBuf {
int num_pts;
XPointFixed pt[XR_PATH_BUF_SZ];
struct _XrPathArgBuf *next, *prev;
} XrPathArgBuf;
typedef struct _XrPath {
XrPathOpBuf *op_head;
XrPathOpBuf *op_tail;
XrPathArgBuf *arg_head;
XrPathArgBuf *arg_tail;
} XrPath;
typedef struct _XrEdge {
XLineFixed edge;
Bool clockWise;
XFixed current_x;
struct _XrEdge *next, *prev;
} XrEdge;
typedef struct _XrPolygon {
int num_edges;
int edges_size;
XrEdge *edges;
XPointFixed first_pt;
int first_pt_defined;
XPointFixed last_pt;
int last_pt_defined;
int closed;
} XrPolygon;
typedef struct _XrSlopeFixed
{
XFixed dx;
XFixed dy;
} XrSlopeFixed;
typedef struct _XrSpline {
XPointFixed a, b, c, d;
XrSlopeFixed initial_slope;
XrSlopeFixed final_slope;
int num_pts;
int pts_size;
XPointFixed *pts;
} XrSpline;
/* XXX: This can go away once incremental spline tessellation is working */
typedef enum _XrPenStrokeDirection {
XrPenStrokeDirectionForward,
XrPenStrokeDirectionReverse
} XrPenStrokeDirection;
typedef struct _XrPenVertex {
XPointFixed pt;
double theta;
XrSlopeFixed slope_ccw;
XrSlopeFixed slope_cw;
} XrPenVertex;
typedef struct _XrPen {
double radius;
double tolerance;
int num_vertices;
XrPenVertex *vertex;
} XrPen;
typedef struct _XrSurface {
Display *dpy;
Drawable drawable;
GC gc;
unsigned int width;
unsigned int height;
unsigned int depth;
unsigned long xc_sa_mask;
XcSurfaceAttributes xc_sa;
XrFormat format;
XcFormat *xc_format;
XcSurface *xc_surface;
int needs_new_xc_surface;
unsigned int ref_count;
} XrSurface;
typedef struct _XrColor {
double red;
double green;
double blue;
double alpha;
XcColor xc_color;
} XrColor;
typedef struct _XrTransform {
double m[3][2];
} XrTransform;
typedef struct _XrTraps {
int num_xtraps;
int xtraps_size;
XTrapezoid *xtraps;
} XrTraps;
/* XXX: What should this really be? */
#define XR_FONT_KEY_DEFAULT "mono"
typedef struct _XrFont {
unsigned char *key;
double scale;
int has_transform;
XrTransform transform;
Display *dpy;
XftFont *xft_font;
} XrFont;
#define XR_GSTATE_OPERATOR_DEFAULT XrOperatorOver
#define XR_GSTATE_TOLERANCE_DEFAULT 0.1
#define XR_GSTATE_FILL_RULE_DEFAULT XrFillRuleWinding
#define XR_GSTATE_LINE_WIDTH_DEFAULT 2.0
#define XR_GSTATE_LINE_CAP_DEFAULT XrLineCapButt
#define XR_GSTATE_LINE_JOIN_DEFAULT XrLineJoinMiter
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
typedef struct _XrGState {
Display *dpy;
XrOperator operator;
double tolerance;
/* stroke style */
double line_width;
XrLineCap line_cap;
XrLineJoin line_join;
double miter_limit;
XrFillRule fill_rule;
double *dash;
int num_dashes;
double dash_offset;
XcFormat *alphaFormat;
XrFont font;
XrSurface *parent_surface;
XrSurface *surface;
XrSurface *src;
XrSurface *mask;
double alpha;
XrColor color;
XrTransform ctm;
XrTransform ctm_inverse;
XrPath path;
XPointDouble last_move_pt;
XPointDouble current_pt;
int has_current_pt;
XrPen pen_regular;
struct _XrGState *next;
} XrGState;
struct _XrState {
Display *dpy;
XrGState *stack;
XrStatus status;
};
typedef struct _XrStrokeFace {
XPointFixed ccw;
XPointFixed pt;
XPointFixed cw;
XrSlopeFixed dev_vector;
XPointDouble usr_vector;
} XrStrokeFace;
typedef struct _XrStroker {
XrGState *gstate;
XrTraps *traps;
int have_prev;
int have_first;
int is_first;
XrStrokeFace prev;
XrStrokeFace first;
int dash_index;
int dash_on;
double dash_remain;
} XrStroker;
typedef struct _XrFiller {
XrGState *gstate;
XrTraps *traps;
XrPolygon polygon;
} XrFiller;
/* xrstate.c */
XrState *
_XrStateCreate(Display *dpy);
XrStatus
_XrStateInit(XrState *state, Display *dpy);
void
_XrStateDeinit(XrState *xrs);
void
_XrStateDestroy(XrState *state);
XrStatus
_XrStatePush(XrState *xrs);
XrStatus
_XrStatePop(XrState *xrs);
/* xrgstate.c */
XrGState *
_XrGStateCreate(Display *dpy);
void
_XrGStateInit(XrGState *gstate, Display *dpy);
XrStatus
_XrGStateInitCopy(XrGState *gstate, XrGState *other);
void
_XrGStateDeinit(XrGState *gstate);
void
_XrGStateDestroy(XrGState *gstate);
XrGState *
_XrGStateClone(XrGState *gstate);
XrStatus
_XrGStateBeginGroup(XrGState *gstate);
XrStatus
_XrGStateEndGroup(XrGState *gstate);
XrStatus
_XrGStateSetDrawable(XrGState *gstate, Drawable drawable);
XrStatus
_XrGStateSetVisual(XrGState *gstate, Visual *visual);
XrStatus
_XrGStateSetFormat(XrGState *gstate, XrFormat format);
XrStatus
_XrGStateSetOperator(XrGState *gstate, XrOperator operator);
XrStatus
_XrGStateSetRGBColor(XrGState *gstate, double red, double green, double blue);
XrStatus
_XrGStateSetTolerance(XrGState *gstate, double tolerance);
XrStatus
_XrGStateSetAlpha(XrGState *gstate, double alpha);
XrStatus
_XrGStateSetFillRule(XrGState *gstate, XrFillRule fill_rule);
XrStatus
_XrGStateSetLineWidth(XrGState *gstate, double width);
XrStatus
_XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap);
XrStatus
_XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join);
XrStatus
_XrGStateSetDash(XrGState *gstate, double *dash, int num_dashes, double offset);
XrStatus
_XrGStateSetMiterLimit(XrGState *gstate, double limit);
XrStatus
_XrGStateTranslate(XrGState *gstate, double tx, double ty);
XrStatus
_XrGStateScale(XrGState *gstate, double sx, double sy);
XrStatus
_XrGStateRotate(XrGState *gstate, double angle);
XrStatus
_XrGStateConcatMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty);
XrStatus
_XrGStateSetMatrix(XrGState *gstate,
double a, double b,
double c, double d,
double tx, double ty);
XrStatus
_XrGStateIdentityMatrix(XrGState *xrs);
XrStatus
_XrGStateNewPath(XrGState *gstate);
XrStatus
_XrGStateMoveTo(XrGState *gstate, double x, double y);
XrStatus
_XrGStateLineTo(XrGState *gstate, double x, double y);
XrStatus
_XrGStateCurveTo(XrGState *gstate,
double x1, double y1,
double x2, double y2,
double x3, double y3);
XrStatus
_XrGStateRelMoveTo(XrGState *gstate, double dx, double dy);
XrStatus
_XrGStateRelLineTo(XrGState *gstate, double dx, double dy);
XrStatus
_XrGStateRelCurveTo(XrGState *gstate,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3);
XrStatus
_XrGStateClosePath(XrGState *gstate);
XrStatus
_XrGStateStroke(XrGState *gstate);
XrStatus
_XrGStateFill(XrGState *fill);
XrStatus
_XrGStateSelectFont(XrGState *gstate, const char *key);
XrStatus
_XrGStateScaleFont(XrGState *gstate, double scale);
XrStatus
_XrGStateTransformFont(XrGState *gstate,
double a, double b,
double c, double d);
XrStatus
_XrGStateTextExtents(XrGState *gstate,
const unsigned char *utf8,
double *x, double *y,
double *width, double *height,
double *dx, double *dy);
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);
/* xrcolor.c */
void
_XrColorInit(XrColor *color);
void
_XrColorDeinit(XrColor *color);
void
_XrColorSetRGB(XrColor *color, double red, double green, double blue);
void
_XrColorSetAlpha(XrColor *color, double alpha);
/* xrfont.c */
void
_XrFontInit(XrFont *font);
XrStatus
_XrFontInitCopy(XrFont *font, XrFont *other);
void
_XrFontDeinit(XrFont *font);
XrStatus
_XrFontSelect(XrFont *font, const char *key);
XrStatus
_XrFontScale(XrFont *font, double scale);
XrStatus
_XrFontTransform(XrFont *font,
double a, double b,
double c, double d);
XrStatus
_XrFontResolveXftFont(XrFont *font, XrGState *gstate, XftFont **xft_font);
/* xrpath.c */
void
_XrPathInit(XrPath *path);
XrStatus
_XrPathInitCopy(XrPath *path, XrPath *other);
void
_XrPathDeinit(XrPath *path);
XrStatus
_XrPathMoveTo(XrPath *path, double x, double y);
XrStatus
_XrPathLineTo(XrPath *path, double x, double y);
XrStatus
_XrPathCurveTo(XrPath *path,
double x1, double y1,
double x2, double y2,
double x3, double y3);
XrStatus
_XrPathClosePath(XrPath *path);
XrStatus
_XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure);
/* xrsurface.c */
XrSurface *
_XrSurfaceCreate(Display *dpy);
void
_XrSurfaceInit(XrSurface *surface, Display *dpy);
void
_XrSurfaceDeinit(XrSurface *surface);
void
_XrSurfaceDestroy(XrSurface *surface);
void
_XrSurfaceReference(XrSurface *surface);
void
_XrSurfaceDereference(XrSurface *surface);
void
_XrSurfaceDereferenceDestroy(XrSurface *surface);
void
_XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color);
XrStatus
_XrSurfaceSetImage(XrSurface *surface,
char *data,
unsigned int width,
unsigned int height,
unsigned int stride);
XrStatus
_XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform);
void
_XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable);
void
_XrSurfaceSetDrawableWH(XrSurface *surface,
Drawable drawable,
unsigned int width,
unsigned int height);
void
_XrSurfaceSetVisual(XrSurface *surface, Visual *visual);
void
_XrSurfaceSetFormat(XrSurface *surface, XrFormat format);
XcSurface *
_XrSurfaceGetXcSurface(XrSurface *surface);
Picture
_XrSurfaceGetPicture(XrSurface *surface);
Drawable
_XrSurfaceGetDrawable(XrSurface *surface);
unsigned int
_XrSurfaceGetWidth(XrSurface *surface);
unsigned int
_XrSurfaceGetHeight(XrSurface *surface);
unsigned int
_XrSurfaceGetDepth(XrSurface *surface);
/* xrpen.c */
XrStatus
_XrPenInit(XrPen *pen, double radius, XrGState *gstate);
XrStatus
_XrPenInitEmpty(XrPen *pen);
XrStatus
_XrPenInitCopy(XrPen *pen, XrPen *other);
void
_XrPenDeinit(XrPen *pen);
XrStatus
_XrPenAddPoints(XrPen *pen, XPointFixed *pt, int num_pts);
XrStatus
_XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
_XrPenFindActiveCWVertexIndex(XrPen *pen, XrSlopeFixed *slope, int *active);
XrStatus
_XrPenFindActiveCCWVertexIndex(XrPen *pen, XrSlopeFixed *slope, int *active);
XrStatus
_XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrTraps *traps);
/* xrpolygon.c */
void
_XrPolygonInit(XrPolygon *polygon);
void
_XrPolygonDeinit(XrPolygon *polygon);
XrStatus
_XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2);
XrStatus
_XrPolygonAddPoint(XrPolygon *polygon, XPointFixed *pt);
XrStatus
_XrPolygonClose(XrPolygon *polygon);
/* xrspline.c */
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
_XrSplineDecompose(XrSpline *spline, double tolerance);
void
_XrSplineDeinit(XrSpline *spline);
/* xrstroker.c */
void
_XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps);
void
_XrStrokerDeinit(XrStroker *stroker);
XrStatus
_XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2);
XrStatus
_XrStrokerAddEdgeDashed(void *closure, XPointFixed *p1, XPointFixed *p2);
XrStatus
_XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
_XrStrokerDoneSubPath (void *closure, XrSubPathDone done);
XrStatus
_XrStrokerDonePath (void *closure);
/* xrfiller.c */
void
_XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps);
void
_XrFillerDeinit(XrFiller *filler);
XrStatus
_XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2);
XrStatus
_XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrStatus
_XrFillerDoneSubPath (void *closure, XrSubPathDone done);
XrStatus
_XrFillerDonePath (void *closure);
/* xrtransform.c */
void
_XrTransformInitIdentity(XrTransform *transform);
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);
XrStatus
_XrTransformComputeInverse(XrTransform *transform);
void
_XrTransformComputeDeterminant(XrTransform *transform, double *det);
void
_XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
/* xrtraps.c */
void
_XrTrapsInit(XrTraps *traps);
void
_XrTrapsDeinit(XrTraps *traps);
XrStatus
_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3]);
XrStatus
_XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4]);
XrStatus
_XrTrapsTessellatePolygon (XrTraps *traps, XrPolygon *poly, XrFillRule fill_rule);
/* xrmisc.c */
void
_ComputeSlope(XPointFixed *a, XPointFixed *b, XrSlopeFixed *slope);
#endif

View file

@ -1,34 +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 "xrint.h"
void
_ComputeSlope(XPointFixed *a, XPointFixed *b, XrSlopeFixed *slope)
{
slope->dx = b->x - a->x;
slope->dy = b->y - a->y;
}

432
xrpath.c
View file

@ -1,432 +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 "xrint.h"
/* private functions */
static XrStatus
_XrPathAdd(XrPath *path, XrPathOp op, XPointFixed *pts, int num_pts);
static void
_XrPathAddOpBuf(XrPath *path, XrPathOpBuf *op);
static XrStatus
_XrPathNewOpBuf(XrPath *path);
static void
_XrPathAddArgBuf(XrPath *path, XrPathArgBuf *arg);
static XrStatus
_XrPathNewArgBuf(XrPath *path);
static XrPathOpBuf *
_XrPathOpBufCreate(void);
static void
_XrPathOpBufDestroy(XrPathOpBuf *buf);
static void
_XrPathOpBufAdd(XrPathOpBuf *op_buf, XrPathOp op);
static XrPathArgBuf *
_XrPathArgBufCreate(void);
static void
_XrPathArgBufDestroy(XrPathArgBuf *buf);
static void
_XrPathArgBufAdd(XrPathArgBuf *arg, XPointFixed *pts, int num_pts);
void
_XrPathInit(XrPath *path)
{
path->op_head = NULL;
path->op_tail = NULL;
path->arg_head = NULL;
path->arg_tail = NULL;
}
XrStatus
_XrPathInitCopy(XrPath *path, XrPath *other)
{
XrPathOpBuf *op, *other_op;
XrPathArgBuf *arg, *other_arg;
_XrPathInit(path);
for (other_op = other->op_head; other_op; other_op = other_op->next) {
op = _XrPathOpBufCreate();
if (op == NULL) {
return XrStatusNoMemory;
}
*op = *other_op;
_XrPathAddOpBuf(path, op);
}
for (other_arg = other->arg_head; other_arg; other_arg = other_arg->next) {
arg = _XrPathArgBufCreate();
if (arg == NULL) {
return XrStatusNoMemory;
}
*arg = *other_arg;
_XrPathAddArgBuf(path, arg);
}
return XrStatusSuccess;
}
void
_XrPathDeinit(XrPath *path)
{
XrPathOpBuf *op;
XrPathArgBuf *arg;
while (path->op_head) {
op = path->op_head;
path->op_head = op->next;
_XrPathOpBufDestroy(op);
}
path->op_tail = NULL;
while (path->arg_head) {
arg = path->arg_head;
path->arg_head = arg->next;
_XrPathArgBufDestroy(arg);
}
path->arg_tail = NULL;
}
XrStatus
_XrPathMoveTo(XrPath *path, double x, double y)
{
XPointFixed pt;
pt.x = XDoubleToFixed(x);
pt.y = XDoubleToFixed(y);
return _XrPathAdd(path, XrPathOpMoveTo, &pt, 1);
}
XrStatus
_XrPathLineTo(XrPath *path, double x, double y)
{
XPointFixed pt;
pt.x = XDoubleToFixed(x);
pt.y = XDoubleToFixed(y);
return _XrPathAdd(path, XrPathOpLineTo, &pt, 1);
}
XrStatus
_XrPathCurveTo(XrPath *path,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
XPointFixed pt[3];
pt[0].x = XDoubleToFixed(x1);
pt[0].y = XDoubleToFixed(y1);
pt[1].x = XDoubleToFixed(x2);
pt[1].y = XDoubleToFixed(y2);
pt[2].x = XDoubleToFixed(x3);
pt[2].y = XDoubleToFixed(y3);
return _XrPathAdd(path, XrPathOpCurveTo, pt, 3);
}
XrStatus
_XrPathClosePath(XrPath *path)
{
return _XrPathAdd(path, XrPathOpClosePath, NULL, 0);
}
static XrStatus
_XrPathAdd(XrPath *path, XrPathOp op, XPointFixed *pts, int num_pts)
{
XrStatus status;
if (path->op_tail == NULL || path->op_tail->num_ops + 1 > XR_PATH_BUF_SZ) {
status = _XrPathNewOpBuf(path);
if (status)
return status;
}
_XrPathOpBufAdd(path->op_tail, op);
if (path->arg_tail == NULL || path->arg_tail->num_pts + num_pts > XR_PATH_BUF_SZ) {
status = _XrPathNewArgBuf(path);
if (status)
return status;
}
_XrPathArgBufAdd(path->arg_tail, pts, num_pts);
return XrStatusSuccess;
}
static void
_XrPathAddOpBuf(XrPath *path, XrPathOpBuf *op)
{
op->next = NULL;
op->prev = path->op_tail;
if (path->op_tail) {
path->op_tail->next = op;
} else {
path->op_head = op;
}
path->op_tail = op;
}
static XrStatus
_XrPathNewOpBuf(XrPath *path)
{
XrPathOpBuf *op;
op = _XrPathOpBufCreate();
if (op == NULL)
return XrStatusNoMemory;
_XrPathAddOpBuf(path, op);
return XrStatusSuccess;
}
static void
_XrPathAddArgBuf(XrPath *path, XrPathArgBuf *arg)
{
arg->next = NULL;
arg->prev = path->arg_tail;
if (path->arg_tail) {
path->arg_tail->next = arg;
} else {
path->arg_head = arg;
}
path->arg_tail = arg;
}
static XrStatus
_XrPathNewArgBuf(XrPath *path)
{
XrPathArgBuf *arg;
arg = _XrPathArgBufCreate();
if (arg == NULL)
return XrStatusNoMemory;
_XrPathAddArgBuf(path, arg);
return XrStatusSuccess;
}
static XrPathOpBuf *
_XrPathOpBufCreate(void)
{
XrPathOpBuf *op;
op = malloc(sizeof(XrPathOpBuf));
if (op) {
op->num_ops = 0;
op->next = NULL;
}
return op;
}
static void
_XrPathOpBufDestroy(XrPathOpBuf *op)
{
free(op);
}
static void
_XrPathOpBufAdd(XrPathOpBuf *op_buf, XrPathOp op)
{
op_buf->op[op_buf->num_ops++] = op;
}
static XrPathArgBuf *
_XrPathArgBufCreate(void)
{
XrPathArgBuf *arg;
arg = malloc(sizeof(XrPathArgBuf));
if (arg) {
arg->num_pts = 0;
arg->next = NULL;
}
return arg;
}
static void
_XrPathArgBufDestroy(XrPathArgBuf *arg)
{
free(arg);
}
static void
_XrPathArgBufAdd(XrPathArgBuf *arg, XPointFixed *pts, int num_pts)
{
int i;
for (i=0; i < num_pts; i++) {
arg->pt[arg->num_pts++] = pts[i];
}
}
#define XR_PATH_OP_MAX_ARGS 3
static int num_args[] =
{
1, /* XrPathMoveTo */
1, /* XrPathOpLineTo */
3, /* XrPathOpCurveTo */
0, /* XrPathOpClosePath */
};
XrStatus
_XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure)
{
XrStatus status;
int i, arg;
XrPathOpBuf *op_buf;
XrPathOp op;
XrPathArgBuf *arg_buf = path->arg_head;
int buf_i = 0;
XPointFixed pt[XR_PATH_OP_MAX_ARGS];
XPointFixed current = {0, 0};
XPointFixed first = {0, 0};
int has_current = 0;
int has_edge = 0;
int step = (dir == XrPathDirectionForward) ? 1 : -1;
for (op_buf = (dir == XrPathDirectionForward) ? path->op_head : path->op_tail;
op_buf;
op_buf = (dir == XrPathDirectionForward) ? op_buf->next : op_buf->prev)
{
int start, stop;
if (dir == XrPathDirectionForward) {
start = 0;
stop = op_buf->num_ops;
} else {
start = op_buf->num_ops - 1;
stop = -1;
}
for (i=start; i != stop; i += step) {
op = op_buf->op[i];
if (dir == XrPathDirectionReverse) {
if (buf_i == 0) {
arg_buf = arg_buf->prev;
buf_i = arg_buf->num_pts;
}
buf_i -= num_args[op];
}
for (arg = 0; arg < num_args[op]; arg++) {
pt[arg] = arg_buf->pt[buf_i];
buf_i++;
if (buf_i >= arg_buf->num_pts) {
arg_buf = arg_buf->next;
buf_i = 0;
}
}
if (dir == XrPathDirectionReverse) {
buf_i -= num_args[op];
}
switch (op) {
case XrPathOpMoveTo:
if (has_edge) {
status = (*cb->DoneSubPath) (closure, XrSubPathDoneCap);
if (status)
return status;
}
first = pt[0];
current = pt[0];
has_current = 1;
has_edge = 0;
break;
case XrPathOpLineTo:
if (has_current) {
status = (*cb->AddEdge)(closure, &current, &pt[0]);
if (status)
return status;
current = pt[0];
has_edge = 1;
} else {
first = pt[0];
current = pt[0];
has_current = 1;
has_edge = 0;
}
break;
case XrPathOpCurveTo:
if (has_current) {
status = (*cb->AddSpline)(closure, &current, &pt[0], &pt[1], &pt[2]);
if (status)
return status;
current = pt[2];
has_edge = 1;
} else {
first = pt[2];
current = pt[2];
has_current = 1;
has_edge = 0;
}
break;
case XrPathOpClosePath:
if (has_edge) {
(*cb->AddEdge)(closure, &current, &first);
(*cb->DoneSubPath) (closure, XrSubPathDoneJoin);
}
current.x = 0;
current.y = 0;
first.x = 0;
first.y = 0;
has_current = 0;
has_edge = 0;
break;
}
}
}
if (has_edge)
(*cb->DoneSubPath) (closure, XrSubPathDoneCap);
return (*cb->DonePath)(closure);
}

389
xrpen.c
View file

@ -1,389 +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 "xrint.h"
static int
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix);
static void
_XrPenComputeSlopes(XrPen *pen);
static int
_SlopeClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static int
_XrPenVertexCompareByTheta(const void *a, const void *b);
static XrStatus
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenStrokeDirection dir, XrPolygon *polygon);
XrStatus
_XrPenInitEmpty(XrPen *pen)
{
pen->radius = 0;
pen->tolerance = 0;
pen->vertex = NULL;
pen->num_vertices = 0;
return XrStatusSuccess;
}
XrStatus
_XrPenInit(XrPen *pen, double radius, XrGState *gstate)
{
int i;
XrPenVertex *v;
double dx, dy;
if (pen->num_vertices) {
/* XXX: It would be nice to notice that the pen is already properly constructed.
However, this test would also have to account for possible changes in the transformation
matrix.
if (pen->radius == radius && pen->tolerance == tolerance)
return XrStatusSuccess;
*/
_XrPenDeinit(pen);
}
pen->radius = radius;
pen->tolerance = gstate->tolerance;
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
/* number of vertices must be even */
if (pen->num_vertices % 2)
pen->num_vertices++;
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
return XrStatusNoMemory;
}
for (i=0; i < pen->num_vertices; i++) {
v = &pen->vertex[i];
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);
v->pt.x = XDoubleToFixed(dx);
v->pt.y = XDoubleToFixed(dy);
/* Recompute theta in device space */
v->theta = atan2(v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
_XrPenComputeSlopes(pen);
return XrStatusSuccess;
}
void
_XrPenDeinit(XrPen *pen)
{
free(pen->vertex);
_XrPenInitEmpty(pen);
}
XrStatus
_XrPenInitCopy(XrPen *pen, XrPen *other)
{
*pen = *other;
if (pen->num_vertices) {
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
return XrStatusNoMemory;
}
memcpy(pen->vertex, other->vertex, pen->num_vertices * sizeof(XrPenVertex));
}
return XrStatusSuccess;
}
static int
_XrPenVertexCompareByTheta(const void *a, const void *b)
{
double diff;
const XrPenVertex *va = a;
const XrPenVertex *vb = b;
diff = va->theta - vb->theta;
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else
return 0;
}
XrStatus
_XrPenAddPoints(XrPen *pen, XPointFixed *pt, int num_pts)
{
int i, j;
XrPenVertex *v, *v_next, *new_vertex;
pen->num_vertices += num_pts;
new_vertex = realloc(pen->vertex, pen->num_vertices * sizeof(XrPenVertex));
if (new_vertex == NULL) {
pen->num_vertices -= num_pts;
return XrStatusNoMemory;
}
pen->vertex = new_vertex;
/* initialize new vertices */
for (i=0; i < num_pts; i++) {
v = &pen->vertex[pen->num_vertices-(i+1)];
v->pt = pt[i];
v->theta = atan2(v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
qsort(pen->vertex, pen->num_vertices, sizeof(XrPenVertex), _XrPenVertexCompareByTheta);
/* eliminate any duplicate vertices */
for (i=0; i < pen->num_vertices - 1; i++ ) {
v = &pen->vertex[i];
v_next = &pen->vertex[i+1];
if (v->pt.x == v_next->pt.x && v->pt.y == v_next->pt.y) {
for (j=i+1; j < pen->num_vertices - 1; j++)
pen->vertex[j] = pen->vertex[j+1];
pen->num_vertices--;
/* There may be more of the same duplicate, check again */
i--;
}
}
_XrPenComputeSlopes(pen);
return XrStatusSuccess;
}
static int
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
{
double expansion, theta;
/* The determinant represents the area expansion factor of the
transform. In the worst case, this is entirely in one
dimension, which is what we assume here. */
_XrTransformComputeDeterminant(matrix, &expansion);
if (tolerance > expansion*radius) {
return 4;
}
theta = acos(1 - tolerance/(expansion * radius));
return ceil(M_PI / theta);
}
static void
_XrPenComputeSlopes(XrPen *pen)
{
int i, i_prev;
XrPenVertex *prev, *v, *next;
for (i=0, i_prev = pen->num_vertices - 1;
i < pen->num_vertices;
i_prev = i++) {
prev = &pen->vertex[i_prev];
v = &pen->vertex[i];
next = &pen->vertex[(i + 1) % pen->num_vertices];
_ComputeSlope(&prev->pt, &v->pt, &v->slope_cw);
_ComputeSlope(&v->pt, &next->pt, &v->slope_ccw);
}
}
/* Is a clockwise of b?
*
* NOTE: The strict equality here is not significant in and of itself,
* but there are functions up above that are sensitive to it,
* (cf. _XrPenFindActiveCWVertexIndex).
*/
static int
_SlopeClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
{
double a_dx = XFixedToDouble(a->dx);
double a_dy = XFixedToDouble(a->dy);
double b_dx = XFixedToDouble(b->dx);
double b_dy = XFixedToDouble(b->dy);
return b_dy * a_dx > a_dy * b_dx;
}
static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
{
return ! _SlopeClockwise(a, b);
}
/* Find active pen vertex for clockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _SlopeClockwise/_SlopeCounterClockwise.
*
* The issue is that the slope_ccw member of one pen vertex will be
* equivalent to the slope_cw member of the next pen vertex in a
* counterclockwise order. However, for this function, we care
* strongly about which vertex is returned.
*/
XrStatus
_XrPenFindActiveCWVertexIndex(XrPen *pen, XrSlopeFixed *slope, int *active)
{
int i;
for (i=0; i < pen->num_vertices; i++) {
if (_SlopeClockwise(slope, &pen->vertex[i].slope_ccw)
&& _SlopeCounterClockwise(slope, &pen->vertex[i].slope_cw))
break;
}
*active = i;
return XrStatusSuccess;
}
/* Find active pen vertex for counterclockwise edge of stroke at the given slope.
*
* NOTE: The behavior of this function is sensitive to the sense of
* the inequality within _SlopeClockwise/_SlopeCounterClockwise.
*/
XrStatus
_XrPenFindActiveCCWVertexIndex(XrPen *pen, XrSlopeFixed *slope, int *active)
{
int i;
XrSlopeFixed slope_reverse;
slope_reverse = *slope;
slope_reverse.dx = -slope_reverse.dx;
slope_reverse.dy = -slope_reverse.dy;
for (i=pen->num_vertices-1; i >= 0; i--) {
if (_SlopeCounterClockwise(&pen->vertex[i].slope_ccw, &slope_reverse)
&& _SlopeClockwise(&pen->vertex[i].slope_cw, &slope_reverse))
break;
}
*active = i;
return XrStatusSuccess;
}
static XrStatus
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenStrokeDirection dir, XrPolygon *polygon)
{
int i;
XrStatus status;
int start, stop, step;
int active = 0;
XPointFixed hull_pt;
XrSlopeFixed slope, initial_slope, final_slope;
XPointFixed *pt = spline->pts;
int num_pts = spline->num_pts;
if (dir == XrPenStrokeDirectionForward) {
start = 0;
stop = num_pts;
step = 1;
initial_slope = spline->initial_slope;
final_slope = spline->final_slope;
} else {
start = num_pts - 1;
stop = -1;
step = -1;
initial_slope = spline->final_slope;
initial_slope.dx = -initial_slope.dx;
initial_slope.dy = -initial_slope.dy;
final_slope = spline->initial_slope;
final_slope.dx = -final_slope.dx;
final_slope.dy = -final_slope.dy;
}
_XrPenFindActiveCWVertexIndex(pen, &initial_slope, &active);
i = start;
while (i != stop) {
hull_pt.x = pt[i].x + pen->vertex[active].pt.x;
hull_pt.y = pt[i].y + pen->vertex[active].pt.y;
status = _XrPolygonAddPoint(polygon, &hull_pt);
if (status)
return status;
if (i + step == stop)
slope = final_slope;
else
_ComputeSlope(&pt[i], &pt[i+step], &slope);
if (_SlopeCounterClockwise(&slope, &pen->vertex[active].slope_ccw)) {
if (++active == pen->num_vertices)
active = 0;
} else if (_SlopeClockwise(&slope, &pen->vertex[active].slope_cw)) {
if (--active == -1)
active = pen->num_vertices - 1;
} else {
i += step;
}
}
return XrStatusSuccess;
}
/* Compute outline of a given spline using the pen.
The trapezoids needed to fill that outline will be added to traps
*/
XrStatus
_XrPenStrokeSpline(XrPen *pen,
XrSpline *spline,
double tolerance,
XrTraps *traps)
{
XrStatus status;
XrPolygon polygon;
_XrPolygonInit(&polygon);
status = _XrSplineDecompose(spline, tolerance);
if (status)
return status;
status = _XrPenStrokeSplineHalf(pen, spline, XrPenStrokeDirectionForward, &polygon);
if (status)
return status;
status = _XrPenStrokeSplineHalf(pen, spline, XrPenStrokeDirectionReverse, &polygon);
if (status)
return status;
_XrPolygonClose(&polygon);
_XrTrapsTessellatePolygon(traps, &polygon, XrFillRuleWinding);
_XrPolygonDeinit(&polygon);
return XrStatusSuccess;
}

View file

@ -1,173 +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 "xrint.h"
#define XR_POLYGON_GROWTH_INC 10
/* private functions */
static XrStatus
_XrPolygonGrowBy(XrPolygon *polygon, int additional);
static void
_XrPolygonSetLastPoint(XrPolygon *polygon, XPointFixed *pt);
void
_XrPolygonInit(XrPolygon *polygon)
{
polygon->num_edges = 0;
polygon->edges_size = 0;
polygon->edges = NULL;
polygon->first_pt_defined = 0;
polygon->last_pt_defined = 0;
polygon->closed = 0;
}
void
_XrPolygonDeinit(XrPolygon *polygon)
{
if (polygon->edges_size) {
free(polygon->edges);
polygon->edges = NULL;
polygon->edges_size = 0;
polygon->num_edges = 0;
}
polygon->first_pt_defined = 0;
polygon->last_pt_defined = 0;
polygon->closed = 0;
}
static XrStatus
_XrPolygonGrowBy(XrPolygon *polygon, int additional)
{
XrEdge *new_edges;
int old_size = polygon->edges_size;
int new_size = polygon->num_edges + additional;
if (new_size <= polygon->edges_size) {
return XrStatusSuccess;
}
polygon->edges_size = new_size;
new_edges = realloc(polygon->edges, polygon->edges_size * sizeof(XrEdge));
if (new_edges == NULL) {
polygon->edges_size = old_size;
return XrStatusNoMemory;
}
polygon->edges = new_edges;
return XrStatusSuccess;
}
static void
_XrPolygonSetLastPoint(XrPolygon *polygon, XPointFixed *pt)
{
polygon->last_pt = *pt;
polygon->last_pt_defined = 1;
}
XrStatus
_XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2)
{
XrStatus status;
XrEdge *edge;
if (! polygon->first_pt_defined) {
polygon->first_pt = *p1;
polygon->first_pt_defined = 1;
polygon->closed = 0;
}
/* drop horizontal edges */
if (p1->y == p2->y) {
goto DONE;
}
if (polygon->num_edges >= polygon->edges_size) {
status = _XrPolygonGrowBy(polygon, XR_POLYGON_GROWTH_INC);
if (status) {
return status;
}
}
edge = &polygon->edges[polygon->num_edges];
if (p1->y < p2->y) {
edge->edge.p1 = *p1;
edge->edge.p2 = *p2;
edge->clockWise = True;
} else {
edge->edge.p1 = *p2;
edge->edge.p2 = *p1;
edge->clockWise = False;
}
polygon->num_edges++;
DONE:
_XrPolygonSetLastPoint(polygon, p2);
return XrStatusSuccess;
}
XrStatus
_XrPolygonAddPoint(XrPolygon *polygon, XPointFixed *pt)
{
XrStatus status = XrStatusSuccess;
if (polygon->last_pt_defined) {
status = _XrPolygonAddEdge(polygon, &polygon->last_pt, pt);
} else {
_XrPolygonSetLastPoint(polygon, pt);
}
return status;
}
XrStatus
_XrPolygonClose(XrPolygon *polygon)
{
XrStatus status;
if (polygon->closed == 0 && polygon->last_pt_defined) {
status = _XrPolygonAddEdge(polygon, &polygon->last_pt, &polygon->first_pt);
if (status)
return status;
polygon->closed = 1;
polygon->first_pt_defined = 0;
}
return XrStatusSuccess;
}

View file

@ -1,269 +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 "xrint.h"
static XrStatus
_XrSplineGrowBy(XrSpline *spline, int additional);
static XrStatus
_XrSplineAddPoint(XrSpline *spline, XPointFixed *pt);
static void
_LerpHalf(XPointFixed *a, XPointFixed *b, XPointFixed *result);
static void
_DeCastlejau(XrSpline *spline, XrSpline *s1, XrSpline *s2);
static double
_XrSplineErrorSquared(XrSpline *spline);
static XrStatus
_XrSplineDecomposeInto(XrSpline *spline, double tolerance_squared, XrSpline *result);
#define XR_SPLINE_GROWTH_INC 100
XrIntStatus
_XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
{
spline->a = *a;
spline->b = *b;
spline->c = *c;
spline->d = *d;
if (a->x != b->x || a->y != b->y) {
_ComputeSlope(&spline->a, &spline->b, &spline->initial_slope);
} else if (a->x != c->x || a->y != c->y) {
_ComputeSlope(&spline->a, &spline->c, &spline->initial_slope);
} else if (a->x != d->x || a->y != d->y) {
_ComputeSlope(&spline->a, &spline->d, &spline->initial_slope);
} else {
return XrIntStatusDegenerate;
}
if (c->x != d->x || c->y != d->y) {
_ComputeSlope(&spline->c, &spline->d, &spline->final_slope);
} else if (b->x != d->x || b->y != d->y) {
_ComputeSlope(&spline->b, &spline->d, &spline->final_slope);
} else {
_ComputeSlope(&spline->a, &spline->d, &spline->final_slope);
}
spline->num_pts = 0;
spline->pts_size = 0;
spline->pts = NULL;
return XrStatusSuccess;
}
void
_XrSplineDeinit(XrSpline *spline)
{
spline->num_pts = 0;
spline->pts_size = 0;
free(spline->pts);
spline->pts = NULL;
}
static XrStatus
_XrSplineGrowBy(XrSpline *spline, int additional)
{
XPointFixed *new_pts;
int old_size = spline->pts_size;
int new_size = spline->num_pts + additional;
if (new_size <= spline->pts_size)
return XrStatusSuccess;
spline->pts_size = new_size;
new_pts = realloc(spline->pts, spline->pts_size * sizeof(XPointFixed));
if (new_pts == NULL) {
spline->pts_size = old_size;
return XrStatusNoMemory;
}
spline->pts = new_pts;
return XrStatusSuccess;
}
static XrStatus
_XrSplineAddPoint(XrSpline *spline, XPointFixed *pt)
{
XrStatus status;
if (spline->num_pts >= spline->pts_size) {
status = _XrSplineGrowBy(spline, XR_SPLINE_GROWTH_INC);
if (status)
return status;
}
spline->pts[spline->num_pts] = *pt;
spline->num_pts++;
return XrStatusSuccess;
}
static void
_LerpHalf(XPointFixed *a, XPointFixed *b, XPointFixed *result)
{
result->x = a->x + ((b->x - a->x) >> 1);
result->y = a->y + ((b->y - a->y) >> 1);
}
static void
_DeCastlejau(XrSpline *spline, XrSpline *s1, XrSpline *s2)
{
XPointFixed ab, bc, cd;
XPointFixed abbc, bccd;
XPointFixed final;
_LerpHalf(&spline->a, &spline->b, &ab);
_LerpHalf(&spline->b, &spline->c, &bc);
_LerpHalf(&spline->c, &spline->d, &cd);
_LerpHalf(&ab, &bc, &abbc);
_LerpHalf(&bc, &cd, &bccd);
_LerpHalf(&abbc, &bccd, &final);
s1->a = spline->a;
s1->b = ab;
s1->c = abbc;
s1->d = final;
s2->a = final;
s2->b = bccd;
s2->c = cd;
s2->d = spline->d;
}
static double
_PointDistanceSquaredToPoint(XPointFixed *a, XPointFixed *b)
{
double dx = XFixedToDouble(b->x - a->x);
double dy = XFixedToDouble(b->y - a->y);
return dx*dx + dy*dy;
}
static double
_PointDistanceSquaredToSegment(XPointFixed *p, XPointFixed *p1, XPointFixed *p2)
{
double u;
double dx, dy;
double pdx, pdy;
XPointFixed px;
/* intersection point (px):
px = p1 + u(p2 - p1)
(p - px) . (p2 - p1) = 0
Thus:
u = ((p - p1) . (p2 - p1)) / (||(p2 - p1)|| ^ 2);
*/
dx = XFixedToDouble(p2->x - p1->x);
dy = XFixedToDouble(p2->y - p1->y);
if (dx == 0 && dy == 0)
return _PointDistanceSquaredToPoint(p, p1);
pdx = XFixedToDouble(p->x - p1->x);
pdy = XFixedToDouble(p->y - p1->y);
u = (pdx * dx + pdy * dy) / (dx*dx + dy*dy);
if (u <= 0)
return _PointDistanceSquaredToPoint(p, p1);
else if (u >= 1)
return _PointDistanceSquaredToPoint(p, p2);
px.x = p1->x + u * (p2->x - p1->x);
px.y = p1->y + u * (p2->y - p1->y);
return _PointDistanceSquaredToPoint(p, &px);
}
/* Return an upper bound on the error (squared) that could result from approximating
a spline as a line segment connecting the two endpoints */
static double
_XrSplineErrorSquared(XrSpline *spline)
{
double berr, cerr;
berr = _PointDistanceSquaredToSegment(&spline->b, &spline->a, &spline->d);
cerr = _PointDistanceSquaredToSegment(&spline->c, &spline->a, &spline->d);
if (berr > cerr)
return berr;
else
return cerr;
}
static XrStatus
_XrSplineDecomposeInto(XrSpline *spline, double tolerance_squared, XrSpline *result)
{
XrStatus status;
XrSpline s1, s2;
if (_XrSplineErrorSquared(spline) < tolerance_squared) {
return _XrSplineAddPoint(result, &spline->a);
}
_DeCastlejau(spline, &s1, &s2);
status = _XrSplineDecomposeInto(&s1, tolerance_squared, result);
if (status)
return status;
status = _XrSplineDecomposeInto(&s2, tolerance_squared, result);
if (status)
return status;
return XrStatusSuccess;
}
XrStatus
_XrSplineDecompose(XrSpline *spline, double tolerance)
{
XrStatus status;
if (spline->pts_size) {
_XrSplineDeinit(spline);
}
status = _XrSplineDecomposeInto(spline, tolerance * tolerance, spline);
if (status)
return status;
status = _XrSplineAddPoint(spline, &spline->d);
if (status)
return status;
return XrStatusSuccess;
}

109
xrstate.c
View file

@ -1,109 +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 "xrint.h"
XrState *
_XrStateCreate(Display *dpy)
{
XrStatus status;
XrState *xrs;
xrs = malloc(sizeof(XrState));
if (xrs) {
status = _XrStateInit(xrs, dpy);
if (status) {
free(xrs);
return NULL;
}
}
return xrs;
}
XrStatus
_XrStateInit(XrState *xrs, Display *dpy)
{
xrs->dpy = dpy;
xrs->stack = NULL;
xrs->status = XrStatusSuccess;
return _XrStatePush(xrs);
}
void
_XrStateDeinit(XrState *xrs)
{
while (xrs->stack) {
_XrStatePop(xrs);
}
}
void
_XrStateDestroy(XrState *xrs)
{
_XrStateDeinit(xrs);
free(xrs);
}
XrStatus
_XrStatePush(XrState *xrs)
{
XrGState *top;
if (xrs->stack) {
top = _XrGStateClone(xrs->stack);
} else {
top = _XrGStateCreate(xrs->dpy);
}
if (top == NULL)
return XrStatusNoMemory;
top->next = xrs->stack;
xrs->stack = top;
return XrStatusSuccess;
}
XrStatus
_XrStatePop(XrState *xrs)
{
XrGState *top;
if (xrs->stack == NULL)
return XrStatusInvalidRestore;
top = xrs->stack;
xrs->stack = top->next;
_XrGStateDestroy(top);
return XrStatusSuccess;
}

View file

@ -1,643 +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 "xrint.h"
/* private functions */
static void
_TranslatePoint(XPointFixed *pt, XPointFixed *offset);
static int
_XrStrokerFaceClockwise(XrStrokeFace *in, XrStrokeFace *out);
static XrStatus
_XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out);
static void
_XrStrokerStartDash (XrStroker *stroker)
{
XrGState *gstate = stroker->gstate;
double offset;
int on = 1;
int i = 0;
offset = gstate->dash_offset;
while (offset >= gstate->dash[i]) {
offset -= gstate->dash[i];
on = 1-on;
if (++i == gstate->num_dashes)
i = 0;
}
stroker->dash_index = i;
stroker->dash_on = on;
stroker->dash_remain = gstate->dash[i] - offset;
}
static void
_XrStrokerStepDash (XrStroker *stroker, double step)
{
XrGState *gstate = stroker->gstate;
stroker->dash_remain -= step;
if (stroker->dash_remain <= 0) {
stroker->dash_index++;
if (stroker->dash_index == gstate->num_dashes)
stroker->dash_index = 0;
stroker->dash_on = 1-stroker->dash_on;
stroker->dash_remain = gstate->dash[stroker->dash_index];
}
}
void
_XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps)
{
stroker->gstate = gstate;
stroker->traps = traps;
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
if (gstate->dash)
_XrStrokerStartDash (stroker);
}
void
_XrStrokerDeinit(XrStroker *stroker)
{
/* nothing to do here */
}
static void
_TranslatePoint(XPointFixed *pt, XPointFixed *offset)
{
pt->x += offset->x;
pt->y += offset->y;
}
static int
_XrStrokerFaceClockwise(XrStrokeFace *in, XrStrokeFace *out)
{
XPointDouble d_in, d_out;
d_in.x = XFixedToDouble(in->cw.x - in->pt.x);
d_in.y = XFixedToDouble(in->cw.y - in->pt.y);
d_out.x = XFixedToDouble(out->cw.x - out->pt.x);
d_out.y = XFixedToDouble(out->cw.y - out->pt.y);
return d_out.y * d_in.x > d_in.y * d_out.x;
}
static XrStatus
_XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
{
XrStatus status;
XrGState *gstate = stroker->gstate;
int clockwise = _XrStrokerFaceClockwise (out, in);
XPointFixed *inpt, *outpt;
if (in->cw.x == out->cw.x
&& in->cw.y == out->cw.y
&& in->ccw.x == out->ccw.x
&& in->ccw.y == out->ccw.y) {
return XrStatusSuccess;
}
if (clockwise) {
inpt = &in->ccw;
outpt = &out->ccw;
} else {
inpt = &in->cw;
outpt = &out->cw;
}
switch (gstate->line_join) {
case XrLineJoinRound: {
int i;
int start, step, stop;
XPointFixed tri[3], initial, final;
XrPen *pen = &gstate->pen_regular;
tri[0] = in->pt;
if (clockwise) {
initial = in->ccw;
_XrPenFindActiveCCWVertexIndex(pen, &in->dev_vector, &start);
step = -1;
_XrPenFindActiveCCWVertexIndex(pen, &out->dev_vector, &stop);
final = out->ccw;
} else {
initial = in->cw;
_XrPenFindActiveCWVertexIndex(pen, &in->dev_vector, &start);
step = +1;
_XrPenFindActiveCWVertexIndex(pen, &out->dev_vector, &stop);
final = out->cw;
}
i = start;
tri[1] = initial;
while (i != stop) {
tri[2] = in->pt;
_TranslatePoint(&tri[2], &pen->vertex[i].pt);
_XrTrapsTessellateTriangle(stroker->traps, tri);
tri[1] = tri[2];
i += step;
if (i < 0)
i = pen->num_vertices - 1;
if (i >= pen->num_vertices)
i = 0;
}
tri[2] = final;
return _XrTrapsTessellateTriangle(stroker->traps, tri);
}
case XrLineJoinMiter:
default: {
XrPolygon polygon;
XDouble c = (-in->usr_vector.x * out->usr_vector.x)+(-in->usr_vector.y * out->usr_vector.y);
XDouble ml = gstate->miter_limit;
_XrPolygonInit (&polygon);
if (2 <= ml * ml * (1 - c)) {
XDouble x1, y1, x2, y2;
XDouble mx, my;
XDouble dx1, dx2, dy1, dy2;
XPointFixed outer;
x1 = XFixedToDouble(inpt->x);
y1 = XFixedToDouble(inpt->y);
dx1 = in->usr_vector.x;
dy1 = in->usr_vector.y;
_XrTransformDistance(&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);
my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
(dx1 * dy2 - dx2 * dy1));
if (dy1)
mx = (my - y1) * dx1 / dy1 + x1;
else
mx = (my - y2) * dx2 / dy2 + x2;
outer.x = XDoubleToFixed(mx);
outer.y = XDoubleToFixed(my);
_XrPolygonAddEdge (&polygon, &in->pt, inpt);
_XrPolygonAddEdge (&polygon, inpt, &outer);
_XrPolygonAddEdge (&polygon, &outer, outpt);
_XrPolygonAddEdge (&polygon, outpt, &in->pt);
status = _XrTrapsTessellatePolygon (stroker->traps,
&polygon,
XrFillRuleWinding);
_XrPolygonDeinit (&polygon);
return status;
}
/* fall through ... */
}
case XrLineJoinBevel: {
XPointFixed tri[3];
tri[0] = in->pt;
tri[1] = *inpt;
tri[2] = *outpt;
return _XrTrapsTessellateTriangle (stroker->traps, tri);
}
}
}
static XrStatus
_XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
{
XrStatus status;
XrGState *gstate = stroker->gstate;
if (gstate->line_cap == XrLineCapButt)
return XrStatusSuccess;
switch (gstate->line_cap) {
case XrLineCapRound: {
int i;
int start, stop;
XrSlopeFixed slope;
XPointFixed tri[3];
XrPen *pen = &gstate->pen_regular;
slope = f->dev_vector;
_XrPenFindActiveCWVertexIndex(pen, &slope, &start);
slope.dx = -slope.dx;
slope.dy = -slope.dy;
_XrPenFindActiveCWVertexIndex(pen, &slope, &stop);
tri[0] = f->pt;
tri[1] = f->cw;
for (i=start; i != stop; i = (i+1) % pen->num_vertices) {
tri[2] = f->pt;
_TranslatePoint(&tri[2], &pen->vertex[i].pt);
_XrTrapsTessellateTriangle(stroker->traps, tri);
tri[1] = tri[2];
}
tri[2] = f->ccw;
return _XrTrapsTessellateTriangle(stroker->traps, tri);
}
case XrLineCapSquare: {
double dx, dy;
XrSlopeFixed fvector;
XPointFixed occw, ocw;
XrPolygon polygon;
_XrPolygonInit (&polygon);
dx = f->usr_vector.x;
dy = f->usr_vector.y;
dx *= gstate->line_width / 2.0;
dy *= gstate->line_width / 2.0;
_XrTransformDistance(&gstate->ctm, &dx, &dy);
fvector.dx = XDoubleToFixed(dx);
fvector.dy = XDoubleToFixed(dy);
occw.x = f->ccw.x + fvector.dx;
occw.y = f->ccw.y + fvector.dy;
ocw.x = f->cw.x + fvector.dx;
ocw.y = f->cw.y + fvector.dy;
_XrPolygonAddEdge (&polygon, &f->cw, &ocw);
_XrPolygonAddEdge (&polygon, &ocw, &occw);
_XrPolygonAddEdge (&polygon, &occw, &f->ccw);
_XrPolygonAddEdge (&polygon, &f->ccw, &f->cw);
status = _XrTrapsTessellatePolygon (stroker->traps, &polygon, XrFillRuleWinding);
_XrPolygonDeinit (&polygon);
return status;
}
case XrLineCapButt:
default:
return XrStatusSuccess;
}
}
static void
_ComputeFace(XPointFixed *pt, XrSlopeFixed *slope, XrGState *gstate, XrStrokeFace *face)
{
double mag, tmp;
double dx, dy;
XPointDouble usr_vector;
XPointFixed offset_ccw, offset_cw;
dx = XFixedToDouble(slope->dx);
dy = XFixedToDouble(slope->dy);
_XrTransformDistance(&gstate->ctm_inverse, &dx, &dy);
mag = sqrt(dx * dx + dy * dy);
if (mag == 0) {
/* XXX: Can't compute other face points. Do we want a tag in the face for this case? */
return;
}
dx /= mag;
dy /= mag;
usr_vector.x = dx;
usr_vector.y = dy;
tmp = dx;
dx = - dy * (gstate->line_width / 2.0);
dy = tmp * (gstate->line_width / 2.0);
_XrTransformDistance(&gstate->ctm, &dx, &dy);
offset_ccw.x = XDoubleToFixed(dx);
offset_ccw.y = XDoubleToFixed(dy);
offset_cw.x = -offset_ccw.x;
offset_cw.y = -offset_ccw.y;
face->ccw = *pt;
_TranslatePoint(&face->ccw, &offset_ccw);
face->pt = *pt;
face->cw = *pt;
_TranslatePoint(&face->cw, &offset_cw);
face->usr_vector.x = usr_vector.x;
face->usr_vector.y = usr_vector.y;
face->dev_vector = *slope;
}
static XrStatus
_XrStrokerAddSubEdge (XrStroker *stroker, XPointFixed *p1, XPointFixed *p2,
XrStrokeFace *start, XrStrokeFace *end)
{
XrGState *gstate = stroker->gstate;
XPointFixed quad[4];
XrSlopeFixed slope;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in _ComputeFace). The key behavior is that
degenerate paths should draw as much as possible. */
return XrStatusSuccess;
}
_ComputeSlope(p1, p2, &slope);
_ComputeFace(p1, &slope, gstate, start);
/* XXX: This could be optimized slightly by not calling
_ComputeFace again but rather translating the relevant
fields from start. */
_ComputeFace(p2, &slope, gstate, end);
quad[0] = start->cw;
quad[1] = start->ccw;
quad[2] = end->ccw;
quad[3] = end->cw;
return _XrTrapsTessellateRectangle(stroker->traps, quad);
}
XrStatus
_XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
{
XrStatus status;
XrStroker *stroker = closure;
XrStrokeFace start, end;
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in XrStrokerAddSubEdge and in _ComputeFace). The
key behavior is that degenerate paths should draw as much
as possible. */
return XrStatusSuccess;
}
status = _XrStrokerAddSubEdge (stroker, p1, p2, &start, &end);
if (status)
return status;
if (stroker->have_prev) {
status = _XrStrokerJoin (stroker, &stroker->prev, &start);
if (status)
return status;
} else {
stroker->have_prev = 1;
if (stroker->is_first) {
stroker->have_first = 1;
stroker->first = start;
}
}
stroker->prev = end;
stroker->is_first = 0;
return XrStatusSuccess;
}
/*
* Dashed lines. Cap each dash end, join around turns when on
*/
XrStatus
_XrStrokerAddEdgeDashed (void *closure, XPointFixed *p1, XPointFixed *p2)
{
XrStatus status = XrStatusSuccess;
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
double mag, remain, tmp;
double dx, dy;
double dx2, dy2;
XPointFixed fd1, fd2;
int first = 1;
XrStrokeFace sub_start, sub_end;
dx = XFixedToDouble(p2->x - p1->x);
dy = XFixedToDouble(p2->y - p1->y);
_XrTransformDistance(&gstate->ctm_inverse, &dx, &dy);
mag = sqrt(dx *dx + dy * dy);
remain = mag;
fd1 = *p1;
while (remain) {
tmp = stroker->dash_remain;
if (tmp > remain)
tmp = remain;
remain -= tmp;
dx2 = dx * (mag - remain)/mag;
dy2 = dy * (mag - remain)/mag;
_XrTransformDistance (&gstate->ctm, &dx2, &dy2);
fd2.x = XDoubleToFixed (dx2);
fd2.y = XDoubleToFixed (dy2);
fd2.x += p1->x;
fd2.y += p1->y;
/*
* XXX simplify this case analysis
*/
if (stroker->dash_on) {
status = _XrStrokerAddSubEdge (stroker, &fd1, &fd2, &sub_start, &sub_end);
if (status)
return status;
if (!first) {
/*
* Not first dash in this segment, cap start
*/
status = _XrStrokerCap (stroker, &sub_start);
if (status)
return status;
} else {
/*
* First in this segment, join to any prev, else
* if at start of sub-path, mark position, else
* cap
*/
if (stroker->have_prev) {
status = _XrStrokerJoin (stroker, &stroker->prev, &sub_start);
if (status)
return status;
} else {
if (stroker->is_first) {
stroker->have_first = 1;
stroker->first = sub_start;
} else {
status = _XrStrokerCap (stroker, &sub_start);
if (status)
return status;
}
}
}
if (remain) {
/*
* Cap if not at end of segment
*/
status = _XrStrokerCap (stroker, &sub_end);
if (status)
return status;
} else {
/*
* Mark previous line face and fix up next time
* through
*/
stroker->prev = sub_end;
stroker->have_prev = 1;
}
} else {
/*
* If starting with off dash, check previous face
* and cap if necessary
*/
if (first) {
if (stroker->have_prev) {
status = _XrStrokerCap (stroker, &stroker->prev);
if (status)
return status;
}
}
if (!remain)
stroker->have_prev = 0;
}
_XrStrokerStepDash (stroker, tmp);
fd1 = fd2;
first = 0;
}
stroker->is_first = 0;
return status;
}
XrStatus
_XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d)
{
XrStatus status = XrStatusSuccess;
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
XrSpline spline;
XrPen pen;
XrStrokeFace start, end;
XPointFixed extra_points[4];
status = _XrSplineInit(&spline, a, b, c, d);
if (status == XrIntStatusDegenerate)
return XrStatusSuccess;
status = _XrPenInitCopy(&pen, &gstate->pen_regular);
if (status)
goto CLEANUP_SPLINE;
_ComputeFace(a, &spline.initial_slope, gstate, &start);
_ComputeFace(d, &spline.final_slope, gstate, &end);
if (stroker->have_prev) {
status = _XrStrokerJoin (stroker, &stroker->prev, &start);
if (status)
return status;
} else {
stroker->have_prev = 1;
if (stroker->is_first) {
stroker->have_first = 1;
stroker->first = start;
}
}
stroker->prev = end;
stroker->is_first = 0;
extra_points[0] = start.cw;
extra_points[0].x -= start.pt.x;
extra_points[0].y -= start.pt.y;
extra_points[1] = start.ccw;
extra_points[1].x -= start.pt.x;
extra_points[1].y -= start.pt.y;
extra_points[2] = end.cw;
extra_points[2].x -= end.pt.x;
extra_points[2].y -= end.pt.y;
extra_points[3] = end.ccw;
extra_points[3].x -= end.pt.x;
extra_points[3].y -= end.pt.y;
status = _XrPenAddPoints(&pen, extra_points, 4);
if (status)
goto CLEANUP_PEN;
status = _XrPenStrokeSpline(&pen, &spline, gstate->tolerance, stroker->traps);
if (status)
goto CLEANUP_PEN;
CLEANUP_PEN:
_XrPenDeinit(&pen);
CLEANUP_SPLINE:
_XrSplineDeinit(&spline);
return status;
}
XrStatus
_XrStrokerDoneSubPath (void *closure, XrSubPathDone done)
{
XrStatus status;
XrStroker *stroker = closure;
switch (done) {
case XrSubPathDoneJoin:
if (stroker->have_first && stroker->have_prev) {
status = _XrStrokerJoin (stroker, &stroker->prev, &stroker->first);
if (status)
return status;
break;
}
/* fall through... */
case XrSubPathDoneCap:
if (stroker->have_first) {
XPointFixed t;
/* The initial cap needs an outward facing vector. Reverse everything */
stroker->first.usr_vector.x = -stroker->first.usr_vector.x;
stroker->first.usr_vector.y = -stroker->first.usr_vector.y;
stroker->first.dev_vector.dx = -stroker->first.dev_vector.dx;
stroker->first.dev_vector.dy = -stroker->first.dev_vector.dy;
t = stroker->first.cw;
stroker->first.cw = stroker->first.ccw;
stroker->first.ccw = t;
status = _XrStrokerCap (stroker, &stroker->first);
if (status)
return status;
}
if (stroker->have_prev) {
status = _XrStrokerCap (stroker, &stroker->prev);
if (status)
return status;
}
break;
}
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
return XrStatusSuccess;
}
XrStatus
_XrStrokerDonePath (void *closure)
{
return XrStatusSuccess;
}

View file

@ -1,323 +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 "xrint.h"
XrSurface *
_XrSurfaceCreate(Display *dpy)
{
XrSurface *surface;
surface = malloc(sizeof(XrSurface));
if (surface)
_XrSurfaceInit(surface, dpy);
return surface;
}
void
_XrSurfaceInit(XrSurface *surface, Display *dpy)
{
surface->dpy = dpy;
surface->drawable = 0;
surface->gc = 0;
surface->width = 0;
surface->height = 0;
surface->depth = 0;
surface->xc_sa_mask = 0;
_XrSurfaceSetFormat(surface, XrFormatARGB32);
surface->xc_surface = 0;
surface->needs_new_xc_surface = 1;
surface->ref_count = 0;
}
void
_XrSurfaceDeinit(XrSurface *surface)
{
if (surface->xc_surface)
XcFreeSurface(surface->dpy, surface->xc_surface);
if (surface->gc)
XFreeGC(surface->dpy, surface->gc);
}
void
_XrSurfaceDestroy(XrSurface *surface)
{
_XrSurfaceDeinit(surface);
free(surface);
}
void
_XrSurfaceReference(XrSurface *surface)
{
surface->ref_count++;
}
void
_XrSurfaceDereference(XrSurface *surface)
{
if (surface->ref_count == 0)
_XrSurfaceDeinit(surface);
else
surface->ref_count--;
}
void
_XrSurfaceDereferenceDestroy(XrSurface *surface)
{
if (surface->ref_count == 0)
_XrSurfaceDestroy(surface);
else
_XrSurfaceDereference(surface);
}
void
_XrSurfaceSetSolidColor(XrSurface *surface, XrColor *color)
{
/* XXX: QUESTION: Special handling for depth==1 ala xftdraw.c? */
if (surface->xc_surface == 0) {
Pixmap pix = XCreatePixmap(surface->dpy,
DefaultRootWindow(surface->dpy),
1, 1,
surface->xc_format->depth);
_XrSurfaceSetDrawableWH(surface, pix, 1, 1);
surface->xc_sa_mask |= CPRepeat;
surface->xc_sa.repeat = True;
_XrSurfaceGetXcSurface(surface);
XFreePixmap(surface->dpy, pix);
}
XcFillRectangle(surface->dpy, PictOpSrc,
surface->xc_surface, &color->xc_color,
0, 0, 1, 1);
}
XrStatus
_XrSurfaceSetImage(XrSurface *surface,
char *data,
unsigned int width,
unsigned int height,
unsigned int stride)
{
XImage *image;
unsigned int depth, bitmap_pad;
Pixmap pix;
depth = surface->xc_format->depth;
if (depth > 16)
bitmap_pad = 32;
else if (depth > 8)
bitmap_pad = 16;
else
bitmap_pad = 8;
pix = XCreatePixmap(surface->dpy,
DefaultRootWindow(surface->dpy),
width, height,
depth);
_XrSurfaceSetDrawableWH(surface, pix, width, height);
image = XCreateImage(surface->dpy,
DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)),
depth, ZPixmap, 0,
data, width, height,
bitmap_pad,
stride);
if (image == NULL)
return XrStatusNoMemory;
XPutImage(surface->dpy, surface->drawable, surface->gc,
image, 0, 0, 0, 0, width, height);
/* I want to free the pixmap, so I have to commit to an xc_surface
to reference the pixmap in the Picture. */
_XrSurfaceGetXcSurface(surface);
XFreePixmap(surface->dpy, pix);
/* Foolish XDestroyImage thinks it can free my data, but I won't
stand for it. */
image->data = NULL;
XDestroyImage(image);
return XrStatusSuccess;
}
/* XXX: We may want to move to projective matrices at some point. If
nothing else, that would eliminate the two different transform data
structures we have here. */
XrStatus
_XrSurfaceSetTransform(XrSurface *surface, XrTransform *transform)
{
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[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[2][0] = 0;
xtransform.matrix[2][1] = 0;
xtransform.matrix[2][2] = XDoubleToFixed(1);
XcSetSurfaceTransform(surface->dpy,
_XrSurfaceGetXcSurface(surface),
&xtransform);
return XrStatusSuccess;
}
void
_XrSurfaceSetDrawable(XrSurface *surface, Drawable drawable)
{
Window root;
int x, y;
unsigned int border, depth;
unsigned int width, height;
XGetGeometry (surface->dpy, drawable,
&root, &x, &y,
&width, &height,
&border, &depth);
_XrSurfaceSetDrawableWH(surface, drawable, width, height);
}
void
_XrSurfaceSetDrawableWH(XrSurface *surface,
Drawable drawable,
unsigned int width,
unsigned int height)
{
if (surface->gc)
XFreeGC(surface->dpy, surface->gc);
surface->drawable = drawable;
surface->width = width;
surface->height = height;
surface->gc = XCreateGC(surface->dpy, surface->drawable, 0, 0);
surface->needs_new_xc_surface = 1;
}
void
_XrSurfaceSetVisual(XrSurface *surface, Visual *visual)
{
surface->xc_format = XcFindVisualFormat(surface->dpy, visual);
surface->needs_new_xc_surface = 1;
}
void
_XrSurfaceSetFormat(XrSurface *surface, XrFormat format)
{
surface->format = format;
surface->xc_format = XcFindStandardFormat(surface->dpy, format);
switch (surface->format) {
case XrFormatARGB32:
surface->depth = 32;
case XrFormatRGB32:
/* XXX: Is this correct? */
surface->depth = 24;
case XrFormatA8:
surface->depth = 8;
case XrFormatA1:
surface->depth = 1;
default:
surface->depth = 32;
}
surface->needs_new_xc_surface = 1;
}
XcSurface *
_XrSurfaceGetXcSurface(XrSurface *surface)
{
if (surface == NULL)
return NULL;
if (! surface->needs_new_xc_surface)
return surface->xc_surface;
if (surface->xc_surface)
XcFreeSurface(surface->dpy, surface->xc_surface);
if (surface->drawable)
surface->xc_surface = XcCreateDrawableSurface(surface->dpy,
surface->drawable,
surface->xc_format,
surface->xc_sa_mask,
&surface->xc_sa);
else
/* XXX: Is this what we wnat to do here? */
surface->xc_surface = 0;
surface->needs_new_xc_surface = 0;
return surface->xc_surface;
}
Picture
_XrSurfaceGetPicture(XrSurface *surface)
{
return XcSurfaceGetPicture(_XrSurfaceGetXcSurface(surface));
}
Drawable
_XrSurfaceGetDrawable(XrSurface *surface)
{
return surface->drawable;
}
unsigned int
_XrSurfaceGetWidth(XrSurface *surface)
{
return surface->width;
}
unsigned int
_XrSurfaceGetHeight(XrSurface *surface)
{
return surface->height;
}
unsigned int
_XrSurfaceGetDepth(XrSurface *surface)
{
return surface->depth;
}

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
_XrTransformComputeInverse(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
_XrTransformEigenValues(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;
}

589
xrtraps.c
View file

@ -1,589 +0,0 @@
/*
* $XFree86: $
*
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
*
* 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 Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* 2002-07-15: Converted from XRenderCompositeDoublePoly to XrTrap. Carl D. Worth
*/
#include "xrint.h"
#define XR_TRAPS_GROWTH_INC 10
/* private functions */
static XrStatus
_XrTrapsGrowBy(XrTraps *traps, int additional);
XrStatus
_XrTrapsAddTrap(XrTraps *traps, XFixed top, XFixed bottom,
XLineFixed left, XLineFixed right);
XrStatus
_XrTrapsAddTrapFromPoints(XrTraps *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2);
static int
_ComparePointFixedByY (const void *av, const void *bv);
static int
_CompareXrEdgeByTop (const void *av, const void *bv);
static XFixed
_ComputeX (XLineFixed *line, XFixed y);
static double
_ComputeInverseSlope (XLineFixed *l);
static double
_ComputeXIntercept (XLineFixed *l, double inverse_slope);
static XFixed
_LinesIntersect (XLineFixed *l1, XLineFixed *l2, XFixed *intersection);
void
_XrTrapsInit(XrTraps *traps)
{
traps->num_xtraps = 0;
traps->xtraps_size = 0;
traps->xtraps = NULL;
}
void
_XrTrapsDeinit(XrTraps *traps)
{
if (traps->xtraps_size) {
free(traps->xtraps);
traps->xtraps = NULL;
traps->xtraps_size = 0;
traps->num_xtraps = 0;
}
}
XrStatus
_XrTrapsAddTrap(XrTraps *traps, XFixed top, XFixed bottom,
XLineFixed left, XLineFixed right)
{
XrStatus status;
XTrapezoid *trap;
if (top == bottom) {
return XrStatusSuccess;
}
if (traps->num_xtraps >= traps->xtraps_size) {
status = _XrTrapsGrowBy(traps, XR_TRAPS_GROWTH_INC);
if (status)
return status;
}
trap = &traps->xtraps[traps->num_xtraps];
trap->top = top;
trap->bottom = bottom;
trap->left = left;
trap->right = right;
traps->num_xtraps++;
return XrStatusSuccess;
}
XrStatus
_XrTrapsAddTrapFromPoints(XrTraps *traps, XFixed top, XFixed bottom,
XPointFixed left_p1, XPointFixed left_p2,
XPointFixed right_p1, XPointFixed right_p2)
{
XLineFixed left;
XLineFixed right;
left.p1 = left_p1;
left.p2 = left_p2;
right.p1 = right_p1;
right.p2 = right_p2;
return _XrTrapsAddTrap(traps, top, bottom, left, right);
}
static XrStatus
_XrTrapsGrowBy(XrTraps *traps, int additional)
{
XTrapezoid *new_xtraps;
int old_size = traps->xtraps_size;
int new_size = traps->num_xtraps + additional;
if (new_size <= traps->xtraps_size) {
return XrStatusSuccess;
}
traps->xtraps_size = new_size;
new_xtraps = realloc(traps->xtraps, traps->xtraps_size * sizeof(XTrapezoid));
if (new_xtraps == NULL) {
traps->xtraps_size = old_size;
return XrStatusNoMemory;
}
traps->xtraps = new_xtraps;
return XrStatusSuccess;
}
static int
_ComparePointFixedByY (const void *av, const void *bv)
{
const XPointFixed *a = av, *b = bv;
int ret = a->y - b->y;
if (ret == 0) {
ret = a->x - b->x;
}
return ret;
}
XrStatus
_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3])
{
XrStatus status;
XLineFixed line;
double intersect;
XPointFixed tsort[3];
memcpy(tsort, t, 3 * sizeof(XPointFixed));
qsort(tsort, 3, sizeof(XPointFixed), _ComparePointFixedByY);
/* horizontal top edge requires special handling */
if (tsort[0].y == tsort[1].y) {
if (tsort[0].x < tsort[1].x)
status = _XrTrapsAddTrapFromPoints (traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
else
status = _XrTrapsAddTrapFromPoints (traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
return status;
}
line.p1 = tsort[0];
line.p2 = tsort[1];
intersect = _ComputeX (&line, tsort[2].y);
if (intersect < tsort[2].x) {
status = _XrTrapsAddTrapFromPoints(traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[1],
tsort[0], tsort[2]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps,
tsort[1].y, tsort[2].y,
tsort[1], tsort[2],
tsort[0], tsort[2]);
if (status)
return status;
} else {
status = _XrTrapsAddTrapFromPoints(traps,
tsort[0].y, tsort[1].y,
tsort[0], tsort[2],
tsort[0], tsort[1]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps,
tsort[1].y, tsort[2].y,
tsort[0], tsort[2],
tsort[1], tsort[2]);
if (status)
return status;
}
return XrStatusSuccess;
}
/* Warning: This function reorderd the elements of the array provided. */
XrStatus
_XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4])
{
XrStatus status;
qsort(q, 4, sizeof(XPointFixed), _ComparePointFixedByY);
if (q[1].x > q[2].x) {
status = _XrTrapsAddTrapFromPoints(traps, q[0].y, q[1].y, q[0], q[2], q[0], q[1]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps, q[1].y, q[2].y, q[0], q[2], q[1], q[3]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps, q[2].y, q[3].y, q[2], q[3], q[1], q[3]);
if (status)
return status;
} else {
status = _XrTrapsAddTrapFromPoints(traps, q[0].y, q[1].y, q[0], q[1], q[0], q[2]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps, q[1].y, q[2].y, q[1], q[3], q[0], q[2]);
if (status)
return status;
status = _XrTrapsAddTrapFromPoints(traps, q[2].y, q[3].y, q[1], q[3], q[2], q[3]);
if (status)
return status;
}
return XrStatusSuccess;
}
static int
_CompareXrEdgeByTop (const void *av, const void *bv)
{
const XrEdge *a = av, *b = bv;
int ret;
ret = a->edge.p1.y - b->edge.p1.y;
if (ret == 0)
ret = a->edge.p1.x - b->edge.p1.x;
return ret;
}
/* Return value is:
> 0 if a is "clockwise" from b, (in a mathematical, not a graphical sense)
== 0 if slope(a) == slope(b)
< 0 if a is "counter-clockwise" from b
*/
static int
_CompareXrEdgeBySlope (const void *av, const void *bv)
{
const XrEdge *a = av, *b = bv;
double a_dx = XFixedToDouble(a->edge.p2.x - a->edge.p1.x);
double a_dy = XFixedToDouble(a->edge.p2.y - a->edge.p1.y);
double b_dx = XFixedToDouble(b->edge.p2.x - b->edge.p1.x);
double b_dy = XFixedToDouble(b->edge.p2.y - b->edge.p1.y);
return b_dy * a_dx - a_dy * b_dx;
}
static int
_CompareXrEdgeByCurrentXThenSlope (const void *av, const void *bv)
{
const XrEdge *a = av, *b = bv;
int ret;
ret = a->current_x - b->current_x;
if (ret == 0)
ret = _CompareXrEdgeBySlope(a, b);
return ret;
}
/* XXX: Both _ComputeX and _ComputeInverseSlope will divide by zero
for horizontal lines. Now, we "know" that when we are tessellating
polygons that the polygon data structure discards all horizontal
edges, but there's nothing here to guarantee that. I suggest the
following:
A) Move all of the polygon tessellation code out of xrtraps.c and
into xrpoly.c, (in order to be in the same module as the code
discarding horizontal lines).
OR
B) Re-implement the line intersection in a way that avoids all
division by zero. Here's one approach. The only disadvantage
might be that that there are not meaningful names for all of the
sub-computations -- just a bunch of determinants. I haven't
looked at complexity, (both are probably similar and it probably
doesn't matter much anyway).
static double
_det (double a, double b, double c, double d)
{
return a * d - b * c;
}
static int
_LinesIntersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
{
double dx1 = XFixedToDouble(l1->p1.x - l1->p2.x);
double dy1 = XFixedToDouble(l1->p1.y - l1->p2.y);
double dx2 = XFixedToDouble(l2->p1.x - l2->p2.x);
double dy2 = XFixedToDouble(l2->p1.y - l2->p2.y);
double l1_det, l2_det;
double den_det = _det(dx1, dy1, dx2, dy2);
if (den_det == 0)
return 0;
l1_det = _det(l1->p1.x, l1->p1.y,
l1->p2.x, l1->p2.y);
l2_det = _det(l2->p1.x, l2->p1.y,
l2->p2.x, l2->p2.y);
*y_intersection = _det(l1_det, dy1,
l2_det, dy2) / den_det;
return 1;
}
*/
static XFixed
_ComputeX (XLineFixed *line, XFixed y)
{
XFixed dx = line->p2.x - line->p1.x;
double ex = (double) (y - line->p1.y) * (double) dx;
XFixed dy = line->p2.y - line->p1.y;
return line->p1.x + (ex / dy);
}
static double
_ComputeInverseSlope (XLineFixed *l)
{
return (XFixedToDouble (l->p2.x - l->p1.x) /
XFixedToDouble (l->p2.y - l->p1.y));
}
static double
_ComputeXIntercept (XLineFixed *l, double inverse_slope)
{
return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
}
static int
_LinesIntersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
{
/*
* x = m1y + b1
* x = m2y + b2
* m1y + b1 = m2y + b2
* y * (m1 - m2) = b2 - b1
* y = (b2 - b1) / (m1 - m2)
*/
double m1 = _ComputeInverseSlope (l1);
double b1 = _ComputeXIntercept (l1, m1);
double m2 = _ComputeInverseSlope (l2);
double b2 = _ComputeXIntercept (l2, m2);
if (m1 == m2)
return 0;
*y_intersection = XDoubleToFixed ((b2 - b1) / (m1 - m2));
return 1;
}
static void
_SortEdgeList(XrEdge **active)
{
XrEdge *e, *en, *next;
/* sort active list */
for (e = *active; e; e = next)
{
next = e->next;
/*
* Find one later in the list that belongs before the
* current one
*/
for (en = next; en; en = en->next)
{
if (_CompareXrEdgeByCurrentXThenSlope(e, en) > 0)
{
/*
* insert en before e
*
* extract en
*/
en->prev->next = en->next;
if (en->next)
en->next->prev = en->prev;
/*
* insert en
*/
if (e->prev)
e->prev->next = en;
else
*active = en;
en->prev = e->prev;
e->prev = en;
en->next = e;
/*
* start over at en
*/
next = en;
break;
}
}
}
}
/* The algorithm here is pretty simple:
inactive = [edges]
y = min_p1_y(inactive)
while (num_active || num_inactive) {
active = all edges containing y
next_y = min( min_p2_y(active), min_p1_y(inactive), min_intersection(active) )
fill_traps(active, y, next_y, fill_rule)
y = next_y
}
The invariants that hold during fill_traps are:
All edges in active contain both y and next_y
No edges in active intersect within y and next_y
These invariants mean that fill_traps is as simple as sorting the
active edges, forming a trapezoid between each adjacent pair. Then,
either the even-odd or winding rule is used to determine whether to
emit each of these trapezoids.
Warning: This function reorders the edges of the polygon provided.
*/
XrStatus
_XrTrapsTessellatePolygon (XrTraps *traps,
XrPolygon *poly,
XrFillRule fill_rule)
{
XrStatus status;
int inactive;
XrEdge *active;
XrEdge *e, *en, *next;
XFixed y, next_y, intersect;
int in_out, num_edges = poly->num_edges;
XrEdge *edges = poly->edges;
if (num_edges == 0)
return XrStatusSuccess;
qsort (edges, num_edges, sizeof (XrEdge), _CompareXrEdgeByTop);
y = edges[0].edge.p1.y;
active = 0;
inactive = 0;
while (active || inactive < num_edges)
{
for (e = active; e; e = e->next) {
e->current_x = _ComputeX (&e->edge, y);
}
/* insert new active edges into list */
while (inactive < num_edges)
{
e = &edges[inactive];
if (e->edge.p1.y > y)
break;
/* move this edge into the active list */
inactive++;
e->current_x = _ComputeX (&e->edge, y);
/* insert e at head of list */
e->next = active;
e->prev = NULL;
if (active)
active->prev = e;
active = e;
}
_SortEdgeList(&active);
/* find next inflection point */
if (active)
next_y = active->edge.p2.y;
else
next_y = edges[inactive].edge.p1.y;
for (e = active; e; e = en)
{
en = e->next;
if (e->edge.p2.y < next_y)
next_y = e->edge.p2.y;
/* check intersect */
if (en && e->current_x != en->current_x)
{
if (_LinesIntersect (&e->edge, &en->edge, &intersect))
if (intersect > y) {
/* Need to guarantee that we get all the way past
the intersection point so that the edges sort
properly next time through the loop. */
if (_ComputeX(&e->edge, intersect) < _ComputeX(&en->edge, intersect))
intersect++;
if (intersect < next_y)
next_y = intersect;
}
}
}
/* check next inactive point */
if (inactive < num_edges && edges[inactive].edge.p1.y < next_y)
next_y = edges[inactive].edge.p1.y;
/* walk the list generating trapezoids */
in_out = 0;
for (e = active; e && (en = e->next); e = e->next)
{
if (fill_rule == XrFillRuleWinding) {
if (e->clockWise) {
in_out++;
} else {
in_out--;
}
if (in_out == 0) {
continue;
}
} else {
in_out++;
if (in_out % 2 == 0) {
continue;
}
}
status = _XrTrapsAddTrap(traps, y, next_y, e->edge, en->edge);
if (status)
return status;
}
/* delete inactive edges from list */
for (e = active; e; e = next)
{
next = e->next;
if (e->edge.p2.y <= next_y)
{
if (e->prev)
e->prev->next = e->next;
else
active = e->next;
if (e->next)
e->next->prev = e->prev;
}
}
y = next_y;
}
return XrStatusSuccess;
}