Milán Major

netscape-revival

1 branch
Code

sun-java/awt/tinyx/tiny_Graphics.c

#include "tiny.h"
#include "image.h"
#include "java_awt_Rectangle.h"
#include "sun_awt_tiny_TinyGraphics.h"
#include "sun_awt_tiny_TinyWindow.h"

#define OX(this)		(unhand(this)->originX)
#define OY(this)		(unhand(this)->originY)
#define TX(this, x)		((x) + OX(this))
#define TY(this, y)		((y) + OY(this))


/**
 * There is no need to worry about the gc_owner being
 * garbage collected. If that happens, and if a new
 * one is created at exactly the same address it would
 * still be marked touched and the gc will be reinitialized.
 */
static TinyGraphics *gc_owner = 0;
static GC gc = 0;

static GC 
tiny_gc(TinyGraphics *this)
{
    Window win = (Window)unhand(this)->pDrawable;
    XGCValues atts;
    int mask = 0;

    if (win == 0) {
	return 0;
    }

    if ((gc == 0) || (this != gc_owner) || unhand(this)->touched) {
	if (gc == 0) {
	    gc = XCreateGC(awt_display, win, 0, 0);
	    if (gc == 0) {
		return 0;
	    }
	}
	gc_owner = this;

	if (unhand(this)->font) {
	    XFontStruct *f = awt_getFont(unhand(this)->font);
	    if (f) {
		atts.font = f->fid;
		mask |= GCFont;
	    }
	}
	if (unhand(this)->color) {
	    atts.foreground = awt_getColor(unhand(this)->color);
	    mask |= GCForeground;
	} else {
	    atts.foreground = 0;
	}
	if (unhand(this)->xorColor) {
	    atts.foreground ^= awt_getColor(unhand(this)->xorColor);
	    atts.function = GXxor;
	    mask |= GCFunction | GCForeground;
	} else {
	    atts.function = GXcopy;
	    mask |= GCFunction;
	}
	XChangeGC(awt_display, gc, mask, &atts);

	if (unhand(this)->clip) {
	    XRectangle rect;
	    int w = unhand(unhand(this)->clip)->width;
	    int h = unhand(unhand(this)->clip)->height;
	    rect.x = unhand(unhand(this)->clip)->x;
	    rect.y = unhand(unhand(this)->clip)->y;
	    rect.width = (w < 0) ? 0 : w;
	    rect.height = (h < 0) ? 0 : h;
	    XSetClipRectangles(awt_display, gc, 0, 0, &rect, 1, YXBanded);
	} else {
	    XSetClipMask(awt_display, gc, None);
	}
	unhand(this)->touched = 0;
    }

    tiny_flush();
    return gc;
}

void 
sun_awt_tiny_TinyGraphics_createFromGraphics(TinyGraphics *this, TinyGraphics *g)
{
    Window win;
    GC gc;

    AWT_LOCK();
    unhand(this)->pDrawable = unhand(g)->pDrawable;
    unhand(this)->touched = 1;
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_createFromWindow(TinyGraphics *this, TinyWindow *window)
{
    Window win;
    GC gc;

    AWT_LOCK();
    if (window == 0) {
	SignalError(0, JAVAPKG "NullPointerException", "window");
	AWT_UNLOCK();
	return;
    }
    win = (Window)unhand(window)->xid;
    if (win == 0) {
	AWT_UNLOCK();
	return;
    }

    unhand(this)->pDrawable = (long)win;
    unhand(this)->touched = 1;
    AWT_UNLOCK();
}

void
sun_awt_tiny_TinyGraphics_imageCreate(TinyGraphics *this, struct Hsun_awt_image_ImageRepresentation *ir)
{
    extern Drawable image_getIRDrawable(struct Hsun_awt_image_ImageRepresentation *ir);
    Drawable win;
    GC gc;

    AWT_LOCK();
    if (ir == 0) {
	SignalError(0, JAVAPKG "NullPointerException", "ir");
	AWT_UNLOCK();
	return;
    }

    win = image_getIRDrawable(ir);
    if (win == 0) {
	AWT_UNLOCK();
	return;
    }

    unhand(this)->pDrawable = (long)win;
    unhand(this)->touched = 1;
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_dispose(TinyGraphics *this)
{
    GC gc;

    AWT_LOCK();
    if (this == gc_owner) {
	gc_owner = 0;
    }
    unhand(this)->pDrawable = 0;
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_drawLine(TinyGraphics *this, long x1, long y1, long x2, long y2)
{
    Drawable win;
    GC gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }

    XDrawLine(awt_display, win, gc, 
	      TX(this, x1), TY(this, y1), TX(this, x2), TY(this, y2));
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_fillRect(TinyGraphics *this, long x, long y, long w, long h)
{
    Drawable win;
    GC gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }
    if (w < 0) {
	w = 0;
    }
    if (h < 0) {
	h = 0;
    }

    XFillRectangle(awt_display, win, gc, 
		   TX(this, x), TY(this, y), w, h);
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_drawString(TinyGraphics *this, struct Hjava_lang_String *str, long x, long y)
{
    Classjava_lang_String *strptr;
    ushort *dataptr;
    int	length;
    Drawable win;
    GC	gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if (str == 0) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	AWT_UNLOCK();
	return;
    }
    if ((win == 0) || (gc == 0)) {
	AWT_UNLOCK();
	return;
    }

    strptr = unhand(str);
    dataptr = unhand(strptr->value)->body + strptr->offset;
    length = javaStringLength(str);

    if (length > 1024) {
	length = 1024;
    }

    XDrawString16(awt_display, win, gc, TX(this, x), TY(this, y), (XChar2b *)dataptr, length);
    AWT_UNLOCK();
}

void
sun_awt_tiny_TinyGraphics_drawChars(TinyGraphics *this, HArrayOfChar *data, long off, long len, long x, long y)
{
    ushort *dataptr;
    Drawable win;
    GC	gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if (data == 0) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	AWT_UNLOCK();
	return;
    }
    if ((win == 0) || (gc == 0)) {
	AWT_UNLOCK();
	return;
    }

    if (off < 0 || len < 0 || off + len > obj_length(data)) {
	SignalError(0, JAVAPKG "ArrayIndexOutOfBoundsException", 0);
	AWT_UNLOCK();
	return;
    }
    dataptr = unhand(data)->body;
    if (len > 1024) {
	len = 1024;
    }
    XDrawString16(awt_display, win, gc, TX(this,x), TY(this,y), 
		  (XChar2b*)dataptr + off, len);
    AWT_UNLOCK();
}

void
sun_awt_tiny_TinyGraphics_drawBytes(TinyGraphics *this, HArrayOfByte *data, long off, long len, long x, long y)
{
    char *dataptr;
    Drawable win;
    GC	gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if (data == 0) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	AWT_UNLOCK();
	return;
    }
    if ((win == 0) || (gc == 0)) {
	AWT_UNLOCK();
	return;
    }

    if (off < 0 || len < 0 || off + len > obj_length(data)) {
	SignalError(0, JAVAPKG "ArrayIndexOutOfBoundsException", 0);
	AWT_UNLOCK();
	return;
    }
    dataptr = unhand(data)->body;
    if (len > 1024) {
	len = 1024;
    }
    XDrawString(awt_display, win, gc, TX(this,x), TY(this,y), dataptr + off, len);
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_copyArea(TinyGraphics *this, long x, long y, long w, long h, long dx, long dy)
{
    Drawable win;
    GC gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }
    dx += x;
    dy += y;

    XCopyArea(awt_display, win, win, gc,
	      TX(this,x), TY(this,y), w, h,
	      TX(this,dx), TY(this, dy));
    AWT_UNLOCK();
}


static XPoint *
transformPoints(TinyGraphics *this, HArrayOfInt *xpoints, HArrayOfInt *ypoints,	long npoints)
{
    static XPoint	*points;
    static int		points_length = 0;
    XPoint		*xp;
    ArrayOfInt		*xpoints_array;
    ArrayOfInt		*ypoints_array;
    int			i;

    xpoints_array = unhand(xpoints);
    ypoints_array = unhand(ypoints);
    if (obj_length(ypoints) < npoints || obj_length(xpoints) < npoints) {
	SignalError(0, JAVAPKG "IllegalArgumentException",0);
	return 0;
    }
    if (points_length < npoints) {
	if (points_length != 0) {
	    sysFree((void *)points);
	}
	points = (XPoint *)sysMalloc(sizeof(XPoint) * npoints);
	if (points == 0) {
	    SignalError(0, JAVAPKG "OutOfMemoryError",0);
	    return 0;
	}
	points_length = npoints;
    }
    for (i=0; i < points_length; i++) {
	xp = (points + i);

	xp->x = TX(this, (xpoints_array->body)[i]);
	xp->y = TY(this, (ypoints_array->body)[i]);
    }

    return points;
}

void 
sun_awt_tiny_TinyGraphics_fillPolygon(TinyGraphics * this, HArrayOfInt *xp, HArrayOfInt *yp, long np)
{
    Drawable win;
    GC	gc;
    XPoint *points;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }

    if (points = transformPoints(this, xp, yp, np)) {
	XFillPolygon(awt_display, win, gc, points, np, Complex, CoordModeOrigin);
    }
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_drawArc(TinyGraphics *this, long x, long y, long w, long h, long startAngle, long endAngle)
{
    long	s, e;
    Drawable win;
    GC	gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }

    if (endAngle >= 360 || endAngle <= -360) {
	s = 0;
	e = 360 * 64;
    } else {
	s = (startAngle % 360) * 64;
	e = endAngle * 64;
    }
    XDrawArc(awt_display, win, gc, 
	     TX(this, x),
	     TY(this, y),
	     w,
	     h, 
	     s, e);
    AWT_UNLOCK();
}

void 
sun_awt_tiny_TinyGraphics_fillArc(TinyGraphics *this, long x, long y, long w, long h, long startAngle, long endAngle)
{
    long	s, e;
    Drawable win;
    GC	gc;

    AWT_LOCK();
    win = (Drawable)unhand(this)->pDrawable;
    gc = tiny_gc(this);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }

    if (endAngle >= 360 || endAngle <= -360) {
	s = 0;
	e = 360 * 64;
    } else {
	s = (startAngle % 360) * 64;
	e = endAngle * 64;
    }
    XFillArc(awt_display, win, gc, 
	     TX(this, x),
	     TY(this, y),
	     w,
	     h, 
	     s, e);
    AWT_UNLOCK();
}

void 
sun_awt_image_ImageRepresentation_imageDraw(struct Hsun_awt_image_ImageRepresentation *this,
					    Graphics *g, long x, long y,
					    struct Hjava_awt_Color *c)
{
    TinyGraphics *tg = (TinyGraphics *)g;
    Drawable win;
    GC	gc;
    int xormode;
    unsigned long fgpixel, xorpixel;

    if (tg == 0) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return;
    }

    if (obj_classblock(tg) != FindClass(0, "sun/awt/tiny/TinyGraphics", TRUE)) {
	SignalError(0, JAVAPKG "IllegalArgumentException",0);
 	return;
    }

    AWT_LOCK();
    win = (Drawable)unhand(tg)->pDrawable;
    gc = tiny_gc(tg);
    if ((gc == 0) || (win == 0)) {
	AWT_UNLOCK();
	return;
    }
    xormode = (int) unhand(tg)->xorColor;
    if (xormode) {
	fgpixel = awt_getColor(unhand(tg)->color);
	xorpixel = awt_getColor(unhand(tg)->xorColor);
    }
    if (unhand(tg)->clip) {
	XRectangle clip;
	clip.x = unhand(unhand(tg)->clip)->x;
	clip.y = unhand(unhand(tg)->clip)->y;
	clip.width = unhand(unhand(tg)->clip)->width;
	clip.height = unhand(unhand(tg)->clip)->height;
	awt_imageDraw(win, gc, this,
		      xormode, xorpixel, fgpixel,
		      TX(tg, x), TY(tg, y), c, &clip);
    } else {
	awt_imageDraw(win, gc, this,
		      xormode, xorpixel, fgpixel,
		      TX(tg, x), TY(tg, y), c, 0);
    }
    AWT_UNLOCK();
}