mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-19 16:00:46 +02:00
Switched to autotools. Dropped XrPush/PopGroup. Supports non-X Xc rendering.
This commit is contained in:
parent
b61b9ffc23
commit
ee738deaf6
37 changed files with 701 additions and 6625 deletions
19
.cvsignore
19
.cvsignore
|
|
@ -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
1
AUTHORS
Normal file
|
|
@ -0,0 +1 @@
|
|||
Carl D. Worth <cworth@isi.edu>
|
||||
1
BUGS
Normal file
1
BUGS
Normal file
|
|
@ -0,0 +1 @@
|
|||
SEGV if XrSetRGBColor is called before XrSetTargetDrawable
|
||||
21
COPYING
Normal file
21
COPYING
Normal 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.
|
||||
|
||||
17
ChangeLog
17
ChangeLog
|
|
@ -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
9
INSTALL
Normal 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
|
||||
|
||||
63
Imakefile
63
Imakefile
|
|
@ -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
0
NEWS
Normal file
278
Xr.h
278
Xr.h
|
|
@ -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
28
autogen.sh
Executable 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
51
configure.in
Normal 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
|
||||
])
|
||||
53
local.def
53
local.def
|
|
@ -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
7
src/.cvsignore
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.am
|
||||
Makefile.in
|
||||
*.la
|
||||
*.lo
|
||||
91
src/Xr.h
91
src/Xr.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
50
src/xr.c
50
src/xr.c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
240
src/xrgstate.c
240
src/xrgstate.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
123
src/xrint.h
123
src/xrint.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
454
src/xrsurface.c
454
src/xrsurface.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
513
xr.c
|
|
@ -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;
|
||||
}
|
||||
70
xrcolor.c
70
xrcolor.c
|
|
@ -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);
|
||||
}
|
||||
103
xrfiller.c
103
xrfiller.c
|
|
@ -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
170
xrfont.c
|
|
@ -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;
|
||||
}
|
||||
885
xrgstate.c
885
xrgstate.c
|
|
@ -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
794
xrint.h
|
|
@ -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
|
||||
34
xrmisc.c
34
xrmisc.c
|
|
@ -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
432
xrpath.c
|
|
@ -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, ¤t, &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, ¤t, &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, ¤t, &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
389
xrpen.c
|
|
@ -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;
|
||||
}
|
||||
173
xrpolygon.c
173
xrpolygon.c
|
|
@ -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;
|
||||
}
|
||||
269
xrspline.c
269
xrspline.c
|
|
@ -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
109
xrstate.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
643
xrstroker.c
643
xrstroker.c
|
|
@ -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;
|
||||
}
|
||||
323
xrsurface.c
323
xrsurface.c
|
|
@ -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;
|
||||
}
|
||||
301
xrtransform.c
301
xrtransform.c
|
|
@ -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
589
xrtraps.c
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue