--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/X11GraphicsContext.st Tue May 08 12:47:31 2018 +0200
@@ -0,0 +1,840 @@
+"{ Encoding: utf8 }"
+
+"
+COPYRIGHT (c) 1989 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libview' }"
+
+"{ NameSpace: Smalltalk }"
+
+DeviceGraphicsContext subclass:#X11GraphicsContext
+ instanceVariableNames:'depth xftDrawId'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Graphics'
+!
+
+!X11GraphicsContext primitiveDefinitions!
+%{
+
+#define SUPPORT_MOTIF_WM_HINTS
+
+#ifdef LINUX
+# ifndef __arm__
+# define SHM
+# endif
+#endif
+
+/*
+ * x does a typedef Time - I need Object Time ...
+ */
+#undef Time
+#define Time XTime
+
+/*
+ * x does a #define True / False
+ * we are lucky - the ST/X True/False are not needed
+ */
+#undef True
+#undef False
+
+#include <stdio.h>
+
+#if defined(__osx__)
+# include <malloc/malloc.h>
+extern void *malloc();
+#else
+# ifndef FREEBSD
+# include <malloc.h>
+# endif
+#endif
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#define XK_MISCELLANY
+#include <X11/keysymdef.h>
+
+#include <X11/cursorfont.h>
+
+#ifdef LINUX
+# include <sys/socket.h>
+#endif
+
+extern OBJ __GLOBAL_GET_BY_NAME(char *);
+
+# define __HANDLE_VAL(type, externalAddress) \
+ ((type)__externalAddressVal(externalAddress))
+
+# define __HANDLE_NEW(ptr, __cls) \
+ ({ \
+ OBJ handle = __MKEXTERNALADDRESS(ptr); \
+ OBJ clsObj = __GLOBAL_GET_BY_NAME(__cls);\
+ __InstPtr(handle)->o_class = clsObj; \
+ __STORE(handle, clsObj); \
+ handle; \
+ })
+
+/*
+ * this define suppresses XAllocColor/XFreeColor on
+ * TrueColor systems - I am not certain, if this is
+ * always legal to do (it works with XFree servers).
+ */
+#define QUICK_TRUE_COLORS
+
+/*
+ * shape support works; enabled by -DSHAPE in makefile
+ * see RoundClock and RoundGlobe examples
+ */
+#ifdef SHAPE
+# include <X11/extensions/shape.h>
+#endif
+
+/*
+ * shared memory extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef SHM
+# include <X11/extensions/XShm.h>
+#endif
+
+/*
+ * multiBuffer extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef MBUF
+# include <X11/extensions/multibuf.h>
+#endif
+
+/*
+ * XVideo extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef XVIDEO
+# include <X11/extensions/Xv.h>
+#endif
+
+/*
+ * PEX extension - if available
+ */
+#ifdef PEX5
+# include <PEX5/PEX.h>
+#endif
+
+/*
+ * XImage extension - if available
+ */
+#ifdef XIE
+# include <X11/extensions/XIE.h>
+#endif
+
+/*
+ * multiscreen extension - if available
+ */
+#ifdef XINERAMA
+# include <X11/extensions/Xinerama.h>
+#endif
+
+/*
+ * XCURSOR extension - if available
+ */
+#ifdef XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+#endif
+
+/*
+ * xft library (based on RENDER extension) - if available
+ */
+#ifdef XFT
+# include <X11/Xft/Xft.h>
+# include <X11/extensions/Xrender.h>
+# include <X11/extensions/render.h>
+
+# define XFT_FONT(x) __HANDLE_VAL(XftFont*, x)
+# define XFT_FONT_HANDLE_NEW(x) __HANDLE_NEW(x, "XftFontDescription::XftFontHandle")
+
+# define XFT_DRAW(x) __HANDLE_VAL(XftDraw*, x)
+# define XFT_DRAW_HANDLE_NEW(x) __HANDLE_NEW(x, "XftFontDescription::XftDrawHandle")
+#endif // XFT
+
+/*
+ * when I have more time to check it out, I will support display-PS
+ */
+#ifdef DPS
+# ifdef sgi
+# include <X11/extensions/XDPS.h>
+# include <X11/extensions/XDPSlib.h>
+# include <X11/extensions/dpsXclient.h>
+# else
+# include <DPS/XDPS.h>
+# include <DPS/XDPSlib.h>
+# include <DPS/dpsXclient.h>
+# endif
+#endif
+
+#if defined(someMachine)
+/*
+ * if nformats cannot be found in the Display structure ...
+ */
+# define NO_PRIVATE_DISPLAY_ACCESS
+#endif
+
+#if defined(IRIX5) || defined(__VMS) || (XlibSpecificationRelease == 6)
+ /*
+ * accessing private data in Display ... sorry
+ */
+# define DISPLAYACCESS(d) ((_XPrivDisplay)d)
+#else
+# define DISPLAYACCESS(d) d
+#endif
+
+# define DISPLAY(x) __HANDLE_VAL(Display*, x)
+# define SCREEN(x) ((int)(__intVal(x)))
+# define DRAWABLE(x) __HANDLE_VAL(Drawable, x)
+# define GC(x) __HANDLE_VAL(GC, x)
+# define VISUAL(x) __HANDLE_VAL(Visual*, x)
+# define COLORMAP(x) __HANDLE_VAL(Colormap, x)
+
+
+/*
+ * some defines - tired of typing ...
+ */
+#define __DisplayVal(o) (Display *)(__externalAddressVal(o))
+#define __DrawableVal(o) (Drawable)(__externalAddressVal(o))
+#define __WindowVal(o) (Window)(__externalAddressVal(o))
+#define __PixmapVal(o) (Pixmap)(__externalAddressVal(o))
+#define __GCVal(o) (GC)(__externalAddressVal(o))
+#define __CursorVal(o) (Cursor)(__externalAddressVal(o))
+#define __FontVal(o) (XFontStruct *)(__externalAddressVal(o))
+#define __DPSContextVal(o) (DPSContext)(__externalAddressVal(o))
+
+#define __MKATOMOBJ(a) __MKSMALLINT(a) /* add STORE macro if ever changed */
+#define __AtomVal(o) __intVal(o)
+#define __isAtomID(o) __isSmallInteger(o)
+
+#define myDpy __DisplayVal(__INST(displayId))
+#define ISCONNECTED ((__INST(displayId) != nil) && (__INST(hasConnectionBroken) != nil))
+
+#ifdef __VMS__
+# include "vms_Xnames.h"
+#endif
+
+void __XTimeoutErrorHandler();
+int __XErrorHandler__();
+int __XIOErrorHandler__();
+
+/*
+ * these two macros should be placed around X-lib calls,
+ * which may block due to a broken connection.
+ * They setup/remove a VM-timeout which raises an exception
+ * after xlibTimeout seconds.
+ * This exception will shutDown the connection.
+ * Q: is this a good idea for the local display ?
+ */
+#define __ENTER_XLIB(whichTimeout) \
+ { \
+ __blockingPrimitiveTimoutHandler__ = (voidFUNC)__XTimeoutErrorHandler; \
+ __blockingPrimitiveTimeoutArg__ = self; \
+ __blockingPrimitiveTimeout__ = whichTimeout; \
+ } {
+
+#define LEAVE_XLIB() \
+ { \
+ __blockingPrimitiveTimoutHandler__ = (voidFUNC)0; \
+ __blockingPrimitiveTimeoutArg__ = nil; \
+ __blockingPrimitiveTimeout__ = 0; \
+ } }
+
+#define ENTER_XLIB() __ENTER_XLIB(__intVal(__INST(xlibTimeout)) * 1000)
+#define ENTER_XLIB2() __ENTER_XLIB(__intVal(__INST(xlibTimeoutForWindowCreation)) * 1000)
+
+#ifdef SUPPORT_MOTIF_WM_HINTS
+# ifdef SOME_MACHINE
+# include <anIncludeFileWhichDefinesTheStuffBelow>
+# endif
+
+# ifndef MWM_HINTS_FUNCTIONS
+# define MWM_HINTS_FUNCTIONS (1L << 0)
+# define MWM_HINTS_DECORATIONS (1L << 1)
+# define MWM_HINTS_INPUT_MODE (1L << 2)
+# define MWM_HINTS_STATUS (1L << 3)
+
+# define MWM_FUNC_ALL (1L << 0)
+# define MWM_FUNC_RESIZE (1L << 1)
+# define MWM_FUNC_MOVE (1L << 2)
+# define MWM_FUNC_MINIMIZE (1L << 3)
+# define MWM_FUNC_MAXIMIZE (1L << 4)
+# define MWM_FUNC_CLOSE (1L << 5)
+
+# define MWM_INPUT_MODELESS 0
+# define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
+# define MWM_INPUT_SYSTEM_MODAL 2
+# define MWM_INPUT_FULL_APPLICATION_MODAL 3
+
+# define MWM_DECOR_NONE 0
+# define MWM_DECOR_ALL (1L << 0)
+# define MWM_DECOR_BORDER (1L << 1)
+# define MWM_DECOR_RESIZEH (1L << 2)
+# define MWM_DECOR_TITLE (1L << 3)
+# define MWM_DECOR_MENU (1L << 4)
+# define MWM_DECOR_MINIMIZE (1L << 5)
+# define MWM_DECOR_MAXIMIZE (1L << 6)
+# endif
+#endif /* SUPPORT_MOTIF_WM_HINTS */
+
+/*
+ * openlook hints are not supported yet
+ * - noone needs them anymore ;-(
+ */
+#ifdef SUPPORT_OPENLOOCK_WM_HINTS
+# ifdef SOME_MACHINE
+# include <anIncludeFileWhichDefinesTheStuffBelow>
+# endif
+
+# ifndef OL_DECOR_CLOSE
+# define OL_DECOR_CLOSE (1L << 0)
+# define OL_DECOR_RESIZEH (1L << 1)
+# define OL_DECOR_HEADER (1L << 2)
+# define OL_DECOR_ICON_NAME (1L << 3)
+# define OL_DECOR_ALL (OL_DECOR_CLOSE | OL_DECOR_RESIZEH | OL_DECOR_HEADER | OL_DECOR_ICON_NAME)
+# define OL_ANY_HINTS (1L << 7)
+# endif
+#endif /* SUPPORT_OPENLOOCK_WM_HINTS */
+
+
+%}
+! !
+
+!X11GraphicsContext methodsFor:'accessing'!
+
+depth
+ ^ depth
+!
+
+xftDrawId
+ ^ xftDrawId
+! !
+
+!X11GraphicsContext methodsFor:'destroying'!
+
+destroy
+ xftDrawId notNil ifTrue:[
+ self destroyXftDrawId.
+ ].
+ super destroy.
+!
+
+destroyXftDrawId
+ |id|
+
+ id := xftDrawId.
+ xftDrawId := nil.
+%{
+#ifdef XFT
+ if (__isExternalAddress(id)) {
+ XftDraw *address = (XftDraw *)__externalAddressVal(id);
+ if (address) {
+ XftDrawDestroy(address);
+ __externalAddressVal(id) = 0;
+ }
+ }
+#endif
+%}.
+! !
+
+!X11GraphicsContext methodsFor:'displaying'!
+
+displayDeviceString:aString from:index1 to:index2 x:x y:y opaque:opaque
+ "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+ foreground and background characters.
+ If the coordinates are not integers, an error is triggered."
+
+ <context: #return>
+
+ |displayId|
+
+ font isXftFont ifTrue:[
+ self displayDeviceXftString:aString from:index1 to:index2 x:x y:y opaque:opaque.
+ ^ self.
+ ].
+
+ device flushIfAppropriate.
+ displayId := device displayIdOrErrorIfBroken.
+
+%{
+ GC gc;
+ Window win;
+ char *cp;
+ int i1, i2, l, n;
+# define NLOCALBUFFER 200
+ XChar2b xlatebuffer[NLOCALBUFFER];
+ int nInstBytes;
+
+ if (__isExternalAddress(displayId)
+ && __isExternalAddress(__INST(gcId))
+ && __isExternalAddress(__INST(drawableId))
+ && __isNonNilObject(aString)
+ && __bothSmallInteger(index1, index2)
+ && __bothSmallInteger(x, y)) {
+ int lMax = __intVal(@global(XWorkstation:MaxStringLength));
+ Display *dpy = __DisplayVal(displayId);
+ gc = __GCVal(__INST(gcId));
+ win = __WindowVal(__INST(drawableId));
+
+ i1 = __intVal(index1) - 1;
+ if (i1 >= 0) {
+ OBJ cls;
+
+ i2 = __intVal(index2) - 1;
+ if (i2 < i1) {
+ RETURN (self);
+ }
+ cp = (char *) __stringVal(aString);
+ l = i2 - i1 + 1;
+
+ if (__isStringLike(aString)) {
+ n = __stringSize(aString);
+ if (i2 < n) {
+ cp += i1;
+ if (l > lMax) l = lMax;
+ __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+ if (opaque == true)
+ XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+ else
+ XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+ LEAVE_XLIB();
+ RETURN ( self );
+ }
+ }
+
+ cls = __qClass(aString);
+ nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ cp += nInstBytes;
+
+ if (__isBytes(aString)) {
+ n = __byteArraySize(aString) - nInstBytes - 1;
+
+ if (i2 < n) {
+ cp += i1;
+ if (l > lMax) l = lMax;
+ __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+ if (opaque == true)
+ XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+ else
+ XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+ LEAVE_XLIB();
+ RETURN ( self );
+ }
+ }
+
+ /* TWOBYTESTRINGS */
+ if (__isWords(aString)) {
+ n = (__byteArraySize(aString) - nInstBytes) / 2;
+ if (i2 < n) {
+ union {
+ char b[2];
+ unsigned short s;
+ } u;
+ int i;
+ XChar2b *cp2 = (XChar2b *)0;
+ int mustFree = 0;
+
+ cp += (i1 * 2);
+ if (l > lMax) l = lMax;
+
+#if defined(MSBFIRST) || defined(__MSBFIRST)
+ /*
+ * chars already in correct order
+ */
+#else
+# if ! (defined(LSBFIRST) || defined(__LSBFIRST))
+ /*
+ * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+ * X expects them MSB first
+ * convert as required
+ */
+ u.s = 0x1234;
+ if (u.b[0] != 0x12)
+# endif // ! (defined(LSBFIRST) || defined(__LSBFIRST))
+ {
+ if (l <= NLOCALBUFFER) {
+ cp2 = xlatebuffer;
+ } else {
+ cp2 = (XChar2b *)(malloc(l * 2));
+ mustFree = 1;
+ }
+ for (i=0; i<l; i++) {
+ cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+ cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+ }
+ cp = (char *) cp2;
+ }
+#endif // ! (defined(MSBFIRST) || defined(__MSBFIRST))
+ __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+ if (opaque == true)
+ XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+ else
+ XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+ LEAVE_XLIB();
+
+ if (mustFree) {
+ free(cp2);
+ }
+
+ RETURN ( self );
+ }
+ }
+
+ /* FOURBYTESTRINGS */
+ if (__isLongs(aString)) {
+ n = (__byteArraySize(aString) - nInstBytes) / 4;
+ if (i2 < n) {
+ union {
+ char b[2];
+ unsigned short s;
+ } u;
+ int i;
+ XChar2b *cp2 = (XChar2b *)0;
+ int32 *ip;
+ int mustFree = 0;
+
+ cp += (i1 * 4);
+ if (l > lMax) l = lMax;
+
+ /*
+ * all codePoints <= 16rFFFF are draw; above 16bit range are drawn as 16rFFFF.
+ */
+ if (l <= NLOCALBUFFER) {
+ cp2 = xlatebuffer;
+ } else {
+ cp2 = (XChar2b *)(malloc(l * 2));
+ mustFree = 1;
+ }
+ for (i=0; i<l; i++) {
+ int32 codePoint = ((int32 *)cp)[i];
+
+ if (codePoint > 0xFFFF) {
+ codePoint = 0xFFFF;
+ }
+ cp2[i].byte1 = (codePoint >> 8) & 0xFF;
+ cp2[i].byte2 = codePoint & 0xFF;
+ }
+
+ __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+ if (opaque == true)
+ XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp2, l);
+ else
+ XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp2, l);
+ LEAVE_XLIB();
+
+ if (mustFree) {
+ free(cp2);
+ }
+
+ RETURN ( self );
+ }
+ }
+ }
+ }
+#undef NLOCALBUFFER
+%}.
+
+ "x/y not integer, badGC or drawable, or not a string"
+ device primitiveFailedOrClosedConnection
+!
+
+displayDeviceXftString:aString from:index1 to:index2Arg x:drawX y:drawY opaque:opaque
+ "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+ foreground and background characters.
+ If the coordinates are not integers, an error is triggered."
+
+ <context: #return>
+
+ |index2 bytesPerCharacter
+ clipX clipY clipW clipH
+ fgR fgG fgB fgA fgPixel bgR bgG bgB bgA bgPixel
+ displayId screen error stringLen
+ newXftDrawId pixmapDepth fontId|
+
+"/ device flushIfAppropriate.
+ displayId := device displayIdOrErrorIfBroken.
+
+ "limit the string len, otherwise bad output is generated"
+ stringLen := index2Arg - index1 + 1.
+ stringLen > 1000 "8000" ifTrue:[
+ index2 := index1 + 1000 "8000" - 1.
+ ] ifFalse:[
+ stringLen <= 0 ifTrue:[^ self].
+ index2 := index2Arg.
+ ].
+ bytesPerCharacter := aString bytesPerCharacter.
+
+ clipRect notNil ifTrue:[
+ clipX := clipRect left.
+ clipY := clipRect top.
+ clipW := clipRect width.
+ clipH := clipRect height.
+"/clipW > 32767 ifTrue:['clipW > 32767: ' errorPrint. clipW errorPrintCR. clipW := 32767].
+"/(clipX > 16384 or:[clipX < -16384]) ifTrue:['clipX > 16384: ' errorPrint. clipX errorPrintCR.].
+ "/ YES YES YES: this MUST be transformed!!
+ "/ (see htmlView) fix the notebook, please.
+ ].
+
+ fgR := paint scaledRed.
+ fgR notNil ifTrue:[
+ fgG := paint scaledGreen.
+ fgB := paint scaledBlue.
+ fgA := paint scaledAlpha.
+ ] ifFalse:[
+ "/ when drawing into a pixmap...
+ fgPixel := paint colorId.
+ fgPixel == 0 ifTrue:[
+ fgR := fgG := fgB := 0.
+ ] ifFalse:[
+ fgR := fgG := fgB := 16rFFFF.
+ ].
+ fgA := 16rFFFF.
+ ].
+
+ opaque ifTrue:[
+ bgPaint isColor ifTrue:[
+ bgR := bgPaint scaledRed.
+ bgR notNil ifTrue:[
+ bgG := bgPaint scaledGreen.
+ bgB := bgPaint scaledBlue.
+ bgA := bgPaint scaledAlpha.
+ ] ifFalse:[
+ "/ when drawing into a pixmap...
+ bgPixel := bgPaint colorId.
+ bgPixel == 0 ifTrue:[
+ bgR := bgG := bgB := 0.
+ ] ifFalse:[
+ bgR := bgG := bgB := 16rFFFF.
+ ].
+ bgA := 16rFFFF.
+ ].
+ ] ifFalse:[
+ "images as background are not yet implemented"
+ "/ #todo: fill background rectangle
+ bgR := bgG := bgB := bgA := 16rFFFF.
+ ].
+ ].
+
+ screen := device screen.
+ self isPixmap ifTrue:[
+ pixmapDepth := depth.
+ ].
+ fontId := font getXftFontId.
+
+%{ /* STACK: 64000 */
+#ifdef XFT
+ XftColor color;
+ XGlyphInfo extents;
+ XRectangle clipRX;
+ char *string;
+ int len;
+ int __bytesPerCharacter;
+ XftDraw *__xftDrawId;
+ XftFont *__xftFont;
+
+ if (!(__bothSmallInteger(drawX, drawY)
+ && __bothSmallInteger(index1, index2)
+ && __isSmallInteger(bytesPerCharacter)
+ && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
+ && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
+ && __isNonNilObject(aString)
+ && __isExternalAddress(displayId)
+ && __isExternalAddressLike(fontId)
+ )) {
+ error = @symbol(badArgument);
+ goto out;
+ }
+
+ __xftFont = XFT_FONT(fontId);
+ __bytesPerCharacter = __intVal(bytesPerCharacter);
+
+ if (__INST(xftDrawId) != nil) {
+ __xftDrawId = __externalAddressVal(__INST(xftDrawId));
+ } else {
+ if (pixmapDepth != nil) {
+ int __pixmapDepth = __intVal(pixmapDepth);
+
+ if (__pixmapDepth == 1) {
+ __xftDrawId = XftDrawCreateBitmap(DISPLAY(displayId), DRAWABLE(__INST(drawableId)));
+ } else {
+ __xftDrawId = XftDrawCreateAlpha(DISPLAY(displayId), DRAWABLE(__INST(drawableId)), __pixmapDepth);
+ }
+ } else {
+ __xftDrawId = XftDrawCreate(DISPLAY(displayId),
+ DRAWABLE(__INST(drawableId)),
+ DefaultVisual(DISPLAY(displayId), SCREEN(screen)),
+ DefaultColormap(DISPLAY(displayId), SCREEN(screen)));
+ }
+ __INST(xftDrawId) = newXftDrawId = XFT_DRAW_HANDLE_NEW(__xftDrawId);
+ __STORE(self, newXftDrawId);
+ }
+
+ string = __stringVal(aString) + ((__intVal(index1) - 1 ) * __bytesPerCharacter);
+ len = __intVal(index2) - __intVal(index1) + 1;
+
+ if (clipX != nil) {
+ clipRX.x = __intVal(clipX);
+ clipRX.y = __intVal(clipY);
+ clipRX.width = __intVal(clipW);
+ clipRX.height = __intVal(clipH);
+ XftDrawSetClipRectangles(__xftDrawId, 0, 0, &clipRX, 1);
+ } else {
+ XftDrawSetClip(__xftDrawId, 0);
+ }
+
+ if (opaque == true) {
+ if (bgPixel != nil) {
+ color.pixel = (unsigned long)__intVal(bgPixel);
+ }
+ color.color.red = __intVal(bgR);
+ color.color.green = __intVal(bgG);
+ color.color.blue = __intVal(bgB);
+ color.color.alpha = __intVal(bgA);
+
+ switch (__bytesPerCharacter) {
+ case 1:
+ XftTextExtents8(DISPLAY(displayId), __xftFont, (FcChar8*)string, len, &extents);
+ break;
+ case 2:
+ XftTextExtents16(DISPLAY(displayId), __xftFont, (FcChar16*)string, len, &extents);
+ break;
+ case 4:
+ XftTextExtents32(DISPLAY(displayId), __xftFont, (FcChar32*)string, len, &extents);
+ break;
+ }
+if (extents.width < 0) printf("width: %d < 0\n", extents.width);
+
+ XftDrawRect(__xftDrawId, &color, __intVal(drawX) - extents.x, __intVal(drawY) - __xftFont->ascent, extents.width, __xftFont->height);
+ }
+ if (__isSmallInteger(fgPixel)) {
+ color.pixel = (unsigned long)__intVal(fgPixel);
+ }
+ color.color.red = __intVal(fgR);
+ color.color.green = __intVal(fgG);
+ color.color.blue = __intVal(fgB);
+ color.color.alpha = __intVal(fgA);
+
+ switch (__bytesPerCharacter) {
+ case 1:
+ XftDrawString8(__xftDrawId, &color,__xftFont,
+ __intVal(drawX),
+ __intVal(drawY),
+ (FcChar8*)string,
+ len);
+ break;
+
+ case 2:
+ XftDrawString16(__xftDrawId, &color, __xftFont,
+ __intVal(drawX),
+ __intVal(drawY),
+ (FcChar16*)string,
+ len);
+ break;
+
+ case 4:
+ XftDrawString32(__xftDrawId, &color, __xftFont,
+ __intVal(drawX),
+ __intVal(drawY),
+ (FcChar32*)string,
+ len);
+ break;
+
+ default:
+ error = @symbol(invalidStringSize);
+ goto out;
+ }
+
+out:;
+#endif
+%}.
+ error notNil ifTrue:[
+ self primitiveFailed: error.
+ ].
+! !
+
+!X11GraphicsContext methodsFor:'drawing'!
+
+XXclearDeviceRectangleX:x y:y width:width height:height
+ device clearRectangleX:x y:y width:width height:height in:drawableId with:gcId
+!
+
+XXclearRectangleX:x y:y width:w height:h
+ "draw a filled rectangle; apply transformation if nonNil"
+
+ |pX pY nW nH pO pC|
+
+ gcId isNil ifTrue:[
+ self initGC
+ ].
+ transformation notNil ifTrue:[
+ pO := transformation transformPoint:x@y.
+ pC := transformation transformPoint:(x+w-1)@(y+h-1).
+ pX := pO x.
+ pY := pO y.
+ nW := pC x - pX + 1.
+ nH := pC y - pY + 1.
+
+ nW < 0 ifTrue:[
+ nW := nW abs.
+ pX := pX - nW.
+ ].
+ nH < 0 ifTrue:[
+ nH := nH abs.
+ pY := pY - nH.
+ ].
+ ] ifFalse:[
+ pX := x.
+ pY := y.
+ nW := w.
+ nH := h.
+ ].
+ pX := pX rounded.
+ pY := pY rounded.
+ nW := nW rounded.
+ nH := nH rounded.
+
+ device
+ clearRectangleX:pX
+ y:pY
+ width:nW
+ height:nH
+ in:drawableId with:gcId
+! !
+
+!X11GraphicsContext methodsFor:'view creation'!
+
+createBitmapFromArray:data width:width height:height
+ depth := 1.
+ super createBitmapFromArray:data width:width height:height
+!
+
+createPixmapWidth:w height:h depth:d
+ depth := d.
+ super createPixmapWidth:w height:h depth:d
+! !
+
+!X11GraphicsContext class methodsFor:'documentation'!
+
+version
+ ^ '$Header$'
+!
+
+version_CVS
+ ^ '$Header$'
+! !
+
+
+X11GraphicsContext initialize!