[Vm-dev] [commit] r2355 - add generated B3D and Rome plugins

commits at squeakvm.org commits at squeakvm.org
Sun Jan 23 09:41:32 UTC 2011


Author: piumarta
Date: 2011-01-23 01:41:21 -0800 (Sun, 23 Jan 2011)
New Revision: 2355

Added:
   trunk/platforms/unix/src/plugins/RomePlugin/
   trunk/platforms/unix/src/plugins/RomePlugin/RomePlugin.c
   trunk/platforms/unix/src/plugins/Squeak3D/
   trunk/platforms/unix/src/plugins/Squeak3D/Squeak3D.c
Modified:
   trunk/platforms/unix/src/plugins.ext
   trunk/platforms/unix/src/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c
   trunk/platforms/unix/src/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c
   trunk/platforms/unix/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c
   trunk/platforms/unix/src/vm/sqNamedPrims.h
Log:
add generated B3D and Rome plugins

Modified: trunk/platforms/unix/src/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c
===================================================================
--- trunk/platforms/unix/src/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c	2011-01-23 07:34:41 UTC (rev 2354)
+++ trunk/platforms/unix/src/plugins/B3DAcceleratorPlugin/B3DAcceleratorPlugin.c	2011-01-23 09:41:21 UTC (rev 2355)
@@ -1,4 +1,4 @@
-/* Automatically generated from Squeak on 23 January 2011 3:55:50 pm 
+/* Automatically generated from Squeak on 23 January 2011 6:31:52 pm 
    by VMMaker 4.4.7
  */
 
Added: trunk/platforms/unix/src/plugins/RomePlugin/RomePlugin.c
===================================================================
--- trunk/platforms/unix/src/plugins/RomePlugin/RomePlugin.c	                        (rev 0)
+++ trunk/platforms/unix/src/plugins/RomePlugin/RomePlugin.c	2011-01-23 09:41:21 UTC (rev 2355)
@@ -0,0 +1,3601 @@
+/* Automatically generated from Squeak on 23 January 2011 6:31:55 pm 
+   by VMMaker 4.4.7
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Default EXPORT macro that does nothing (see comment in sq.h): */
+#define EXPORT(returnType) returnType
+
+/* Do not include the entire sq.h file but just those parts needed. */
+/*  The virtual machine proxy definition */
+#include "sqVirtualMachine.h"
+/* Configuration options */
+#include "sqConfig.h"
+/* Platform specific definitions */
+#include "sqPlatformSpecific.h"
+
+#define true 1
+#define false 0
+#define null 0  /* using 'null' because nil is predefined in Think C */
+#ifdef SQUEAK_BUILTIN_PLUGIN
+#undef EXPORT
+// was #undef EXPORT(returnType) but screws NorCroft cc
+#define EXPORT(returnType) static returnType
+#endif
+#include <cairo.h>
+#include <cairo-ft.h>
+#include <pango/pangocairo.h>
+#include "SurfacePlugin.h"
+#define NUM_OF(array) (sizeof (array) / sizeof *(array))
+#define lastIndex(array) (NUM_OF(array) - 1)
+#define degrees(a) (a * 3.141592653589793 / 180.0)
+
+#define log(msg) fprintf(stderr, "Squeak-Rome: " msg "\n")
+#define logwith(msg, a) fprintf(stderr, "Squeak-Rome: " msg "\n", a)
+#define logwithwith(msg, a, b) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b)
+#define logwithwithwith(msg, a, b, c) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c)
+#define logwithwithwithwith(msg, a, b, c, d) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c, d)
+#define logwithwithwithwithwith(msg, a, b, c, d, e) fprintf(stderr, "Squeak-Rome: " msg "\n", a, b, c, d, e)
+
+#define primFail interpreterProxy->primitiveFail()
+#define fail(msg) log(msg "!"); primFail
+#define failwith(msg, a) logwith(msg "!", a); primFail
+#define failwithwith(msg, a, b) logwithwith(msg "!", a, b); primFail
+
+
+#include "sqMemoryAccess.h"
+
+
+/*** Constants ***/
+#define CairoExtendRepeat CAIRO_EXTEND_REPEAT
+#define CairoOperatorSource CAIRO_OPERATOR_SOURCE
+#define CanvasFlagFill 256
+#define CanvasFlagStroke 255
+#define CanvasFlagsIndex 2
+#define CanvasHandleIndex 0
+#define CanvasInstSize 8
+#define CanvasStrokeColorIndex 3
+#define CanvasTargetIndex 1
+#define FormBitsIndex 0
+#define FormDepthIndex 3
+#define FormHeightIndex 2
+#define FormInstSize 5
+#define FormWidthIndex 1
+#define PluginVersion 39
+#define TextLineBottomIndex 3
+#define TextLineEndIndex 5
+#define TextLineInternalSpaceIndex 6
+#define TextLineLeftIndex 0
+#define TextLinePaddingWidthIndex 7
+#define TextLineRightIndex 1
+#define TextLineStartIndex 4
+#define TextLineTopIndex 2
+
+/*** Function Prototypes ***/
+static sqInt addAlignmentinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList);
+static sqInt addColorinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList);
+static void addColorStopTooffsetrgbalpha(cairo_pattern_t*pattern, sqInt intOffset, sqInt rgb, sqInt alpha);
+static sqInt addDefaultInto(PangoAttrList *pangoAttrList);
+static sqInt addEmphasisinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList);
+static sqInt addFontinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList);
+static sqInt addLanguageinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList);
+static sqInt addSelectionAtpixelwith(PangoRectangle *rect, unsigned int c, cairo_t*context);
+static sqInt addSelectionFromtopixelinto(sqInt start, sqInt end, unsigned int c, PangoAttrList *pangoAttrList);
+static cairo_t* contextFrom(sqInt canvasOop);
+static sqInt createContextFor(sqInt canvasOop);
+static sqInt createSurfaceFor(sqInt formOop);
+static sqInt destroyContextFor(sqInt canvasOop);
+static sqInt destroySurface(sqInt surfaceID);
+static void fillOrStrokefrom(cairo_t*context, sqInt canvasOop);
+static cairo_surface_t* findSurface(sqInt surfaceID);
+static VirtualMachine * getInterpreter(void);
+#pragma export on
+EXPORT(const char*) getModuleName(void);
+#pragma export off
+static sqInt getSurfaceFormatgetWgetHgetDgetMsb(cairo_surface_t *surfaceHandle, int*wReturn, int*hReturn, int*dReturn, int*mReturn);
+static sqInt halt(void);
+#pragma export on
+EXPORT(sqInt) initialiseModule(void);
+#pragma export off
+static sqInt leadingCharOf(unsigned int value);
+static sqInt loadSurfacePlugin(void);
+static unsigned char* lockSurfacegetPitchxywh(cairo_surface_t*surfaceHandle, int*pitchReturn, sqInt x, sqInt y, sqInt w, sqInt h);
+#pragma export on
+EXPORT(sqInt) moduleUnloaded(char *aModuleName);
+#pragma export off
+static sqInt msg(char *s);
+static void polyPathfrom(cairo_t*context, sqInt pointsOop);
+#pragma export on
+EXPORT(sqInt) primitivePangoBlockAtIndex(void);
+EXPORT(sqInt) primitiveClear(void);
+EXPORT(sqInt) primitiveClipRectangleLeftRightTopBottom(void);
+EXPORT(sqInt) primitiveClose(void);
+EXPORT(sqInt) primitivePangoComposeString(void);
+EXPORT(sqInt) primitivePangoComposeString2(void);
+EXPORT(sqInt) primitiveCreateFormHandle(void);
+EXPORT(sqInt) primitiveDestroyFormHandle(void);
+EXPORT(sqInt) primitiveDrawArcRadiusXYFromTo(void);
+EXPORT(sqInt) primitiveDrawCurveFromXYviaXYandXYtoXY(void);
+EXPORT(sqInt) primitiveDrawCurveFromXYviaXYtoXY(void);
+EXPORT(sqInt) primitiveDrawGeneralBezierShape(void);
+EXPORT(sqInt) primitiveDrawImageSrcLRTBDestLRTB(void);
+EXPORT(sqInt) primitiveDrawLineFromXYtoXY(void);
+EXPORT(sqInt) primitiveDrawOvalLeftRightTopBottom(void);
+EXPORT(sqInt) primitiveDrawPolygon(void);
+EXPORT(sqInt) primitiveDrawPolyline(void);
+EXPORT(sqInt) primitiveDrawRectangleLeftRightTopBottom(void);
+EXPORT(sqInt) primitiveDrawRoundRectLeftRightTopBottomRadiusCorner(void);
+EXPORT(sqInt) primitiveDrawZeroTerminatedUtf8StringXY(void);
+EXPORT(sqInt) primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage(void);
+EXPORT(sqInt) primitiveFillColorAlpha(void);
+EXPORT(sqInt) primitiveFillLinearOriginXYdirectionXYcolorStops(void);
+EXPORT(sqInt) primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops(void);
+EXPORT(sqInt) primitiveFontFace(void);
+EXPORT(sqInt) primitiveFontSize(void);
+EXPORT(sqInt) primitiveGetLineWidth(void);
+EXPORT(sqInt) primitivePangoFontDescriptionIndex(void);
+EXPORT(sqInt) primitiveGetTransform(void);
+EXPORT(sqInt) primitivePangoIndexAtPoint(void);
+EXPORT(sqInt) primitiveLanguageAttributes(void);
+EXPORT(sqInt) primitiveOpen(void);
+EXPORT(sqInt) primitivePangoIsAvailable(void);
+EXPORT(sqInt) primitivePluginVersion(void);
+EXPORT(sqInt) primitiveRestoreState(void);
+EXPORT(sqInt) primitiveRotateBy(void);
+EXPORT(sqInt) primitiveSaveState(void);
+EXPORT(sqInt) primitiveScaleBy(void);
+EXPORT(sqInt) primitiveSetLineWidth(void);
+EXPORT(sqInt) primitiveSetTransform(void);
+EXPORT(sqInt) primitivePangoShowString(void);
+EXPORT(sqInt) primitiveShowZeroTerminatedUtf8StringXY(void);
+EXPORT(sqInt) primitiveStencilImageSrcLRTBDestLRTB(void);
+EXPORT(sqInt) primitiveTransformBy(void);
+EXPORT(sqInt) primitiveTranslateBy(void);
+EXPORT(sqInt) primitiveUTF8StringWith2Indexes(void);
+EXPORT(sqInt) primitiveUTF8StringWithIndex(void);
+#pragma export off
+static sqInt putCharintoat(sqInt c, unsigned char*utf8String, sqInt utf8Index);
+static sqInt registerSurface(cairo_surface_t*surfaceHandle);
+#pragma export on
+EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
+#pragma export off
+static void setSourcergbalpha(cairo_t*context, sqInt rgb, sqInt alpha);
+static sqInt showSurfacexywh(cairo_surface_t *surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h);
+#pragma export on
+EXPORT(sqInt) shutdownModule(void);
+#pragma export off
+static sqInt sqAssert(sqInt aBool);
+static sqInt sqCharCountInfromto(unsigned char* aString, sqInt from, sqInt to);
+static void strokefrom(cairo_t*context, sqInt canvasOop);
+static cairo_surface_t* surfaceFrom(sqInt formOop);
+static sqInt translateSqAttrsToPangoAttrsinto(sqInt sqAttrsArrayOop, PangoAttrList *pangoAttrList);
+static sqInt unlockSurfacexywh(cairo_surface_t*surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h);
+static sqInt unregisterSurface(sqInt surfaceID);
+static sqInt utf8CountFor(unsigned int value);
+/*** Variables ***/
+static cairo_t* contexts[64];
+static PangoFontDescription *defaultFontDescription;
+static fn_ioFindSurface findSurfaceFn;
+static PangoFontDescription *fontDescriptions[256];
+static int formatToDepth[] = {
+32, 32, 8, 1, 16};
+
+#ifdef SQUEAK_BUILTIN_PLUGIN
+extern
+#endif
+struct VirtualMachine* interpreterProxy;
+static sqInt maxSurfaceID;
+static const char *moduleName =
+#ifdef SQUEAK_BUILTIN_PLUGIN
+	"RomePlugin Aeneas.39 23 January 2011 (i)"
+#else
+	"RomePlugin Aeneas.39 23 January 2011 (e)"
+#endif
+;
+static fn_ioRegisterSurface registerSurfaceFn;
+static sqSurfaceDispatch surfaceDispatch = {
+  1,
+  0,
+  (fn_getSurfaceFormat) getSurfaceFormatgetWgetHgetDgetMsb,
+  (fn_lockSurface) lockSurfacegetPitchxywh,
+  (fn_unlockSurface) unlockSurfacexywh,
+  (fn_showSurface) showSurfacexywh
+};
+static fn_ioUnregisterSurface unregisterSurfaceFn;
+static int utf8Headers[] = {
+0, 192, 224, 240, 248, 252, 254, 255};
+
+
+static sqInt addAlignmentinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt start;
+	sqInt alignment;
+	int pangoAlignment;
+	sqInt end;
+	sqInt *attrArray;
+
+	attrArray = interpreterProxy->firstIndexableField(attrArrayOop);
+	start = ((attrArray[1]) >> 1);
+	end = ((attrArray[2]) >> 1);
+	alignment = ((attrArray[3]) >> 1);
+	if (alignment == 0) {
+		pangoAlignment = PANGO_ALIGN_LEFT;
+	}
+	if (alignment == 1) {
+		pangoAlignment = PANGO_ALIGN_RIGHT;
+	}
+	if (alignment == 2) {
+		pangoAlignment = PANGO_ALIGN_CENTER;
+	}
+	if (alignment == 3) {
+		null;
+	}
+}
+
+static sqInt addColorinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt start;
+	sqInt r;
+	sqInt b;
+	PangoAttribute *pangoAttr;
+	sqInt end;
+	sqInt g;
+	sqInt alpha;
+	sqInt *attrArray;
+	unsigned int c;
+
+	attrArray = interpreterProxy->firstIndexableField(attrArrayOop);
+	start = ((attrArray[1]) >> 1);
+	end = ((attrArray[2]) >> 1);
+
+	/* self log: 'color: %u' with: c. */
+
+	c = interpreterProxy->positive32BitValueOf(attrArray[3]);
+	alpha = ((usqInt) (c && 4278190080U)) >> 24;
+	r = ((usqInt) (c & 16711680)) >> 16;
+	g = ((usqInt) (c & 65280)) >> 8;
+	b = c & 255;
+	if (!(r == 0)) {
+		r = r * 257;
+	}
+	if (!(g == 0)) {
+		g = g * 257;
+	}
+	if (!(b == 0)) {
+		b = b * 257;
+	}
+	pangoAttr = pango_attr_foreground_new(r, g, b);
+	pangoAttr->start_index = start;
+	pangoAttr->end_index = end;
+	pango_attr_list_change(pangoAttrList, pangoAttr);
+}
+
+static void addColorStopTooffsetrgbalpha(cairo_pattern_t*pattern, sqInt intOffset, sqInt rgb, sqInt alpha) {
+	sqInt b;
+	sqInt r;
+	sqInt g;
+
+	r = (((usqInt) rgb) >> 20) & 1023;
+	g = (((usqInt) rgb) >> 10) & 1023;
+	b = (((usqInt) rgb) >> 0) & 1023;
+	if (alpha == 255) {
+		cairo_pattern_add_color_stop_rgb(pattern, intOffset / 65536.0, r / 1023.0, g / 1023.0, b / 1023.0);
+	} else {
+		cairo_pattern_add_color_stop_rgba(pattern, intOffset / 65536.0, r / 1023.0, g / 1023.0, b / 1023.0, alpha / 255.0);
+	}
+}
+
+static sqInt addDefaultInto(PangoAttrList *pangoAttrList) {
+	PangoAttribute *pangoAttr;
+	PangoLanguage *lang;
+
+	pangoAttr = pango_attr_foreground_new(0, 0, 1);
+	pangoAttr->start_index = 0;
+	pangoAttr->end_index = 0x7fffffff;
+	pango_attr_list_insert(pangoAttrList, pangoAttr);
+	pangoAttr = pango_attr_font_desc_new(defaultFontDescription);
+	pangoAttr->start_index = 0;
+	pangoAttr->end_index = 0x7fffffff;
+	pango_attr_list_insert(pangoAttrList, pangoAttr);
+	lang = pango_language_from_string("en-US");
+	pangoAttr = pango_attr_language_new(lang);
+	pangoAttr->start_index = 0;
+	pangoAttr->end_index = 0x7fffffff;
+	pango_attr_list_insert(pangoAttrList, pangoAttr);
+}
+
+static sqInt addEmphasisinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt start;
+	PangoAttribute *pangoAttr;
+	sqInt end;
+	sqInt *attrArray;
+	sqInt c;
+
+	attrArray = interpreterProxy->firstIndexableField(attrArrayOop);
+	start = ((attrArray[1]) >> 1);
+	end = ((attrArray[2]) >> 1);
+	c = ((attrArray[3]) >> 1);
+	if (c & 1) {
+		pangoAttr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
+		pangoAttr->start_index = start;
+		pangoAttr->end_index = end;
+		pango_attr_list_change(pangoAttrList, pangoAttr);
+	}
+	if (c & 2) {
+		pangoAttr = pango_attr_style_new(PANGO_STYLE_OBLIQUE);
+		pangoAttr->start_index = start;
+		pangoAttr->end_index = end;
+		pango_attr_list_change(pangoAttrList, pangoAttr);
+	}
+	if (c & 4) {
+		pangoAttr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
+		pangoAttr->start_index = start;
+		pangoAttr->end_index = end;
+		pango_attr_list_change(pangoAttrList, pangoAttr);
+	}
+	if (c & 8) {
+		pangoAttr = pango_attr_stretch_new(PANGO_STRETCH_CONDENSED);
+		pangoAttr->start_index = start;
+		pangoAttr->end_index = end;
+		pango_attr_list_change(pangoAttrList, pangoAttr);
+	}
+	if (c & 16) {
+		pangoAttr = pango_attr_strikethrough_new(1);
+		pangoAttr->start_index = start;
+		pangoAttr->end_index = end;
+		pango_attr_list_change(pangoAttrList, pangoAttr);
+	}
+}
+
+static sqInt addFontinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt start;
+	PangoFontDescription *desc;
+	sqInt fontDescIndex;
+	PangoAttribute *pangoAttr;
+	sqInt end;
+	sqInt *attrArray;
+
+	attrArray = interpreterProxy->firstIndexableField(attrArrayOop);
+	start = ((attrArray[1]) >> 1);
+	end = ((attrArray[2]) >> 1);
+	fontDescIndex = interpreterProxy->fetchIntegerofObject(5, attrArray[4]);
+	if (fontDescIndex < 0) {
+		return null;
+	}
+	if (fontDescIndex > 255) {
+		return null;
+	}
+	desc = fontDescriptions[fontDescIndex];
+	if (desc == null) {
+		return null;
+	}
+	pangoAttr = pango_attr_font_desc_new(desc);
+	pangoAttr->start_index = start;
+	pangoAttr->end_index = end;
+	pango_attr_list_change(pangoAttrList, pangoAttr);
+}
+
+static sqInt addLanguageinto(sqInt attrArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt start;
+	PangoAttribute *pangoAttr;
+	sqInt end;
+	sqInt lang;
+	char *cLang;
+	sqInt *attrArray;
+	PangoLanguage *pangoLang;
+
+	attrArray = interpreterProxy->firstIndexableField(attrArrayOop);
+	start = ((attrArray[1]) >> 1);
+	end = ((attrArray[2]) >> 1);
+	lang = ((attrArray[3]) >> 1);
+	if (lang == 0) {
+		cLang = "en-US";
+	}
+	if (lang == 5) {
+		cLang = "ja-JP";
+	}
+	if (lang == 6) {
+		cLang = "zh-CN";
+	}
+	if (lang == 7) {
+		cLang = "ko-KR";
+	}
+	if (lang == 9) {
+		cLang = "zh-TW";
+	}
+	if (lang == 13) {
+		cLang = "el-EL";
+	}
+	if (lang == 15) {
+		cLang = "ne-NP";
+	}
+	pangoLang = pango_language_from_string(cLang);
+	pangoAttr = pango_attr_language_new(pangoLang);
+	pangoAttr->start_index = start;
+	pangoAttr->end_index = end;
+	pango_attr_list_change(pangoAttrList, pangoAttr);
+}
+
+static sqInt addSelectionAtpixelwith(PangoRectangle *rect, unsigned int c, cairo_t*context) {
+	sqInt a;
+	sqInt r;
+	sqInt b;
+	sqInt g;
+
+	a = ((usqInt) (c & 4278190080U)) >> 24;
+	if (a == 0) {
+		return null;
+	}
+	r = ((usqInt) (c & 16711680)) >> 16;
+	g = ((usqInt) (c & 65280)) >> 8;
+	b = c & 255;
+	cairo_save(context);
+	cairo_set_source_rgba(context, r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+	cairo_new_path(context);
+	cairo_move_to(context, PANGO_PIXELS(rect->x) + 1, PANGO_PIXELS(rect->y));
+	cairo_line_to(context, PANGO_PIXELS(rect->x) + 1, PANGO_PIXELS(rect->y+rect->height));
+	cairo_stroke(context);
+	cairo_restore(context);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+}
+
+static sqInt addSelectionFromtopixelinto(sqInt start, sqInt end, unsigned int c, PangoAttrList *pangoAttrList) {
+	sqInt r;
+	sqInt b;
+	PangoAttribute *pangoAttr;
+	sqInt g;
+	sqInt alpha;
+
+	alpha = ((usqInt) (c && 4278190080U)) >> 24;
+	r = ((usqInt) (c & 16711680)) >> 16;
+	g = ((usqInt) (c & 65280)) >> 8;
+	b = c & 255;
+	if ((alpha == 0) && ((r == 0) && ((g == 0) && (b == 0)))) {
+		return null;
+	}
+	if (!(r == 0)) {
+		r = r * 257;
+	}
+	if (!(g == 0)) {
+		g = g * 257;
+	}
+	if (!(b == 0)) {
+		b = b * 257;
+	}
+	pangoAttr = pango_attr_background_new(r, g, b);
+	pangoAttr->start_index = start;
+	pangoAttr->end_index = end;
+	pango_attr_list_change(pangoAttrList, pangoAttr);
+}
+
+
+/*	Get contexts[canvasOop's handle] */
+
+static cairo_t* contextFrom(sqInt canvasOop) {
+	cairo_t*context;
+	sqInt contextIndex;
+	sqInt targetOop;
+
+	if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) {
+		fail("canvas oop invalid");
+		return null;
+	}
+	contextIndex = interpreterProxy->fetchIntegerofObject(CanvasHandleIndex, canvasOop);
+	if (interpreterProxy->failed()) {
+		contextIndex = interpreterProxy->fetchPointerofObject(CanvasHandleIndex, canvasOop);
+		if (!(contextIndex == (interpreterProxy->nilObject()))) {
+			fail("canvas handle not an integer");
+		}
+		return null;
+	}
+	if ((contextIndex < 0) || (contextIndex > (lastIndex(contexts)))) {
+		failwith("canvas handle %i out of bounds", contextIndex);
+		return null;
+	}
+	context = contexts[contextIndex];
+	if (context == null) {
+		failwith("canvas handle %i invalid", contextIndex);
+		return null;
+	}
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	targetOop = interpreterProxy->fetchPointerofObject(CanvasTargetIndex, canvasOop);
+	if (!((surfaceFrom(targetOop)) == (cairo_get_target(context)))) {
+		failwith("canvas handle %i does not match target", contextIndex);
+		return null;
+	}
+	return context;
+}
+
+static sqInt createContextFor(sqInt canvasOop) {
+	sqInt i;
+	cairo_surface_t*targetSurface;
+	cairo_t*context;
+	sqInt targetID;
+	sqInt contextIndex;
+	sqInt targetOop;
+
+	if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) {
+		fail("canvas oop invalid");
+		return null;
+	}
+	targetOop = interpreterProxy->fetchPointerofObject(CanvasTargetIndex, canvasOop);
+	if ((interpreterProxy->slotSizeOf(targetOop)) <= FormBitsIndex) {
+		fail("target oop invalid");
+		return null;
+	}
+	targetID = interpreterProxy->fetchIntegerofObject(FormBitsIndex, targetOop);
+	if (interpreterProxy->failed()) {
+		fail("target handle not an integer");
+		return null;
+	}
+	targetSurface = findSurface(targetID);
+	if (!((targetSurface != null) && ((cairo_surface_status(targetSurface)) == 0))) {
+		fail("target surface invalid");
+		return null;
+	}
+	contextIndex = -1;
+	i = 0;
+	while (i <= (lastIndex(contexts))) {
+		if ((contexts[i]) == null) {
+			contextIndex = i;
+			i = lastIndex(contexts);
+		}
+		i += 1;
+	}
+	if (contextIndex < 0) {
+		fail("too many canvases");
+		return null;
+	}
+	context = cairo_create(targetSurface);
+	contexts[contextIndex] = context;
+	/* missing DebugCode */;
+	return contextIndex;
+}
+
+
+/*	create a surface, register it in SurfacePlugin and answer its surface plugin ID */
+
+static sqInt createSurfaceFor(sqInt formOop) {
+	cairo_format_t format;
+	sqInt bits;
+	sqInt width;
+	sqInt status;
+	cairo_surface_t*surface;
+	sqInt height;
+	sqInt depth;
+
+	if ((interpreterProxy->slotSizeOf(formOop)) < FormInstSize) {
+		fail("form oop invalid");
+		return -1;
+	}
+	width = interpreterProxy->fetchIntegerofObject(FormWidthIndex, formOop);
+	height = interpreterProxy->fetchIntegerofObject(FormHeightIndex, formOop);
+	depth = interpreterProxy->fetchIntegerofObject(FormDepthIndex, formOop);
+	if (interpreterProxy->failed()) {
+		fail("form fields are not integers");
+		return -1;
+	}
+	switch(depth) {
+		case 32: format = CAIRO_FORMAT_ARGB32; break;
+		case 24: format = CAIRO_FORMAT_RGB24; break;
+		case 16: format = CAIRO_FORMAT_RGB16_565; break;
+		case  8: format = CAIRO_FORMAT_A8; break;
+		case  1: format = CAIRO_FORMAT_A1; break;
+		default: format = -1;
+	}
+	if ((width <= 0) || ((height <= 0) || (format < 0))) {
+		fail("form fields out of range");
+		return -1;
+	}
+	bits = interpreterProxy->fetchPointerofObject(FormBitsIndex, formOop);
+	if (!(bits == (interpreterProxy->nilObject()))) {
+		fail("form handle not nil");
+		return -1;
+	}
+	surface = cairo_image_surface_create(format, width, height);
+	status = cairo_surface_status(surface);
+	if (!(status == 0)) {
+		failwith("failed to create surface - %s", cairo_status_to_string(status));
+		cairo_surface_destroy(surface);
+		return -1;
+	}
+	return registerSurface(surface);
+}
+
+static sqInt destroyContextFor(sqInt canvasOop) {
+	cairo_t*context;
+	sqInt contextIndex;
+
+	if ((interpreterProxy->slotSizeOf(canvasOop)) < CanvasInstSize) {
+		fail("canvas oop invalid");
+		return null;
+	}
+	contextIndex = interpreterProxy->fetchIntegerofObject(CanvasHandleIndex, canvasOop);
+	if (interpreterProxy->failed()) {
+		fail("canvas handle not an integer");
+		return null;
+	}
+	if ((contextIndex < 0) || (contextIndex > (lastIndex(contexts)))) {
+		failwith("canvas handle %i out of bounds", contextIndex);
+		return null;
+	}
+	context = contexts[contextIndex];
+	if (context == null) {
+		failwith("canvas handle %i invalid", contextIndex);
+		return null;
+	}
+	/* missing DebugCode */;
+	cairo_destroy(context);
+	contexts[contextIndex] = null;
+	return null;
+}
+
+
+/*	fetch surface from surfaceID, destroy it and unregister from SurfacePlugin */
+
+static sqInt destroySurface(sqInt surfaceID) {
+	cairo_surface_t*surface;
+
+	surface = findSurface(surfaceID);
+	if (surface == null) {
+		failwith("could not find surface %i", surfaceID);
+		return null;
+	}
+	cairo_surface_destroy(surface);
+	unregisterSurface(surfaceID);
+	return null;
+}
+
+
+/*	fill or stroke depending on canvasOop's flags */
+
+static void fillOrStrokefrom(cairo_t*context, sqInt canvasOop) {
+	sqInt stroke;
+	sqInt canvasFlags;
+	sqInt fill;
+	sqInt rgb;
+
+	canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop);
+	if (interpreterProxy->failed()) {
+		fail("canvas flags not an integer");
+	} else {
+		fill = canvasFlags & CanvasFlagFill;
+		stroke = canvasFlags & CanvasFlagStroke;
+		if (fill != 0) {
+			if (stroke != 0) {
+				cairo_fill_preserve(context);
+			} else {
+				cairo_fill(context);
+			}
+		}
+		if (stroke != 0) {
+			rgb = interpreterProxy->fetchIntegerofObject(CanvasStrokeColorIndex, canvasOop);
+			cairo_save(context);
+			setSourcergbalpha(context, rgb, stroke);
+			cairo_stroke(context);
+			cairo_restore(context);
+		}
+	}
+}
+
+
+/*	Answer surface handle for surfaceID */
+
+static cairo_surface_t* findSurface(sqInt surfaceID) {
+	sqInt surfaceHandle;
+
+	if (findSurfaceFn == null) {
+		if (!(loadSurfacePlugin())) {
+			return null;
+		}
+	}
+	if (!((*findSurfaceFn)(surfaceID, &surfaceDispatch, &surfaceHandle))) {
+		return null;
+	}
+	return ((cairo_surface_t*) surfaceHandle);
+}
+
+
+/*	Note: This is coded so that plugins can be run from Squeak. */
+
+static VirtualMachine * getInterpreter(void) {
+	return interpreterProxy;
+}
+
+
+/*	Note: This is hardcoded so it can be run from Squeak.
+	The module name is used for validating a module *after*
+	it is loaded to check if it does really contain the module
+	we're thinking it contains. This is important! */
+
+EXPORT(const char*) getModuleName(void) {
+	return moduleName;
+}
+
+static sqInt getSurfaceFormatgetWgetHgetDgetMsb(cairo_surface_t *surfaceHandle, int*wReturn, int*hReturn, int*dReturn, int*mReturn) {
+	sqInt msb;
+	sqInt width;
+	sqInt depth;
+	sqInt height;
+
+	/* missing DebugCode */;
+	width = cairo_image_surface_get_width(surfaceHandle);
+	height = cairo_image_surface_get_height(surfaceHandle);
+	depth = formatToDepth[cairo_image_surface_get_format(surfaceHandle)];
+	msb = 1;
+	*wReturn = width;
+	*hReturn = height;
+	*dReturn = depth;
+	*mReturn = msb;
+	return 1;
+}
+
+static sqInt halt(void) {
+	;
+}
+
+EXPORT(sqInt) initialiseModule(void) {
+	sqInt i;
+
+	for (i = 0; i <= (lastIndex(contexts)); i += 1) {
+		contexts[i] = null;
+	}
+	for (i = 0; i <= (lastIndex(fontDescriptions)); i += 1) {
+		fontDescriptions[i] = null;
+	}
+	defaultFontDescription = pango_font_description_from_string("Times New Roman 10");
+	registerSurfaceFn = null;
+	unregisterSurfaceFn = null;
+	findSurfaceFn = null;
+	return 1;
+}
+
+static sqInt leadingCharOf(unsigned int value) {
+	return ((usqInt) (value & 1069547520) >> 22);
+}
+
+
+/*	Load the surface support plugin */
+
+static sqInt loadSurfacePlugin(void) {
+	sqInt found;
+
+	registerSurfaceFn = ((fn_ioRegisterSurface) (interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface", "SurfacePlugin")));
+	unregisterSurfaceFn = ((fn_ioUnregisterSurface) (interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface", "SurfacePlugin")));
+	findSurfaceFn = ((fn_ioFindSurface) (interpreterProxy->ioLoadFunctionFrom("ioFindSurface", "SurfacePlugin")));
+	found = (registerSurfaceFn != null) && ((unregisterSurfaceFn != null) && (findSurfaceFn != null));
+	if (!(found)) {
+		fail("could not load SurfacePlugin");
+	}
+	maxSurfaceID = -1;
+	return found;
+}
+
+static unsigned char* lockSurfacegetPitchxywh(cairo_surface_t*surfaceHandle, int*pitchReturn, sqInt x, sqInt y, sqInt w, sqInt h) {
+	sqInt pitch;
+	unsigned char*data;
+
+	/* missing DebugCode */;
+	cairo_surface_flush(surfaceHandle);
+	data = cairo_image_surface_get_data(surfaceHandle);
+	pitch = cairo_image_surface_get_stride(surfaceHandle);
+	*pitchReturn = pitch;
+	return data;
+}
+
+
+/*	The module with the given name was just unloaded.
+	Make sure we have no dangling references. */
+
+EXPORT(sqInt) moduleUnloaded(char *aModuleName) {
+	if ((strcmp(aModuleName, "SurfacePlugin")) == 0) {
+		registerSurfaceFn = null;
+		unregisterSurfaceFn = null;
+		findSurfaceFn = null;
+	}
+	return 1;
+}
+
+static sqInt msg(char *s) {
+	fprintf(stderr, "\n%s: %s", moduleName, s);
+}
+
+static void polyPathfrom(cairo_t*context, sqInt pointsOop) {
+	float*points;
+	sqInt i;
+	sqInt pointsCount;
+
+	points = interpreterProxy->arrayValueOf(pointsOop);
+	pointsCount = interpreterProxy->slotSizeOf(pointsOop);
+	if (!(interpreterProxy->failed())) {
+		if (pointsCount >= 2) {
+			cairo_move_to(context, points[0], points[1]);
+			for (i = 2; i <= (pointsCount - 1); i += 2) {
+				cairo_line_to(context, points[i], points[i + 1]);
+			}
+		}
+	}
+}
+
+EXPORT(sqInt) primitivePangoBlockAtIndex(void) {
+	sqInt index;
+	cairo_t*context;
+	sqInt origin;
+	unsigned char*aString;
+	sqInt trailing;
+	sqInt aStringOop;
+	sqInt stringLength;
+	PangoAttrList*attrList;
+	sqInt atEnd;
+	PangoLayout*layout;
+	sqInt canvasOop;
+	sqInt corner;
+	sqInt charData;
+	PangoRectangle pos;
+	sqInt inStringOop;
+	sqInt utf8Index;
+	sqInt x;
+	sqInt y;
+	sqInt sqAttrArray;
+	sqInt w;
+	sqInt h;
+	sqInt withWrap;
+	sqInt cData;
+	sqInt _return_value;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(8), "Object"));
+	inStringOop = interpreterProxy->stackValue(8);
+	utf8Index = interpreterProxy->stackIntegerValue(7);
+	x = interpreterProxy->stackIntegerValue(6);
+	y = interpreterProxy->stackIntegerValue(5);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object"));
+	sqAttrArray = interpreterProxy->stackValue(4);
+	w = interpreterProxy->stackIntegerValue(3);
+	h = interpreterProxy->stackIntegerValue(2);
+	withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	cData = interpreterProxy->stackValue(0);
+	;
+	canvasOop = interpreterProxy->stackValue(9);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	aStringOop = inStringOop;
+	aString = interpreterProxy->firstIndexableField(aStringOop);
+	layout = pango_cairo_create_layout(context);
+	attrList = pango_attr_list_new();
+	translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList);
+	pango_layout_set_text(layout, aString, strlen(aString));
+	pango_layout_set_attributes(layout, attrList);
+	pango_layout_set_width(layout, w * (PANGO_SCALE));
+	if (withWrap) {
+		pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+	}
+	cairo_translate(context, x, y);
+	pango_cairo_update_layout(context, layout);
+	stringLength = strlen(aString);
+	if (utf8Index == (stringLength + 1)) {
+		atEnd = 1;
+		pango_layout_index_to_pos(layout, ((((((utf8Index - 1) < 0) ? 0 : (utf8Index - 1))) < stringLength) ? ((((utf8Index - 1) < 0) ? 0 : (utf8Index - 1))) : stringLength), &pos);
+		pos.x = pos.x + pos.width;
+	} else {
+		atEnd = 0;
+		pango_layout_index_to_pos(layout, (((((utf8Index < 0) ? 0 : utf8Index)) < stringLength) ? (((utf8Index < 0) ? 0 : utf8Index)) : stringLength), &pos);
+	}
+	pango_attr_list_unref(attrList);
+	g_object_unref(layout);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	interpreterProxy->pushRemappableOop(aStringOop);
+	interpreterProxy->pushRemappableOop(cData);
+	origin = interpreterProxy->makePointwithxValueyValue((PANGO_PIXELS(pos.x)) + x, (PANGO_PIXELS(pos.y)) + y);
+	interpreterProxy->pushRemappableOop(origin);
+	corner = interpreterProxy->makePointwithxValueyValue((PANGO_PIXELS(pos.x+pos.width)) + x, (PANGO_PIXELS(pos.y+pos.height)) + y);
+	origin = interpreterProxy->popRemappableOop();
+	charData = interpreterProxy->popRemappableOop();
+	aStringOop = interpreterProxy->popRemappableOop();
+	aString = interpreterProxy->firstIndexableField(aStringOop);
+	interpreterProxy->storePointerofObjectwithValue(0, charData, origin);
+	interpreterProxy->storePointerofObjectwithValue(1, charData, corner);
+	index = sqCharCountInfromto(aString, 0, utf8Index);
+	if (!(atEnd)) {
+		index += 1;
+	}
+	interpreterProxy->storePointerofObjectwithValue(2, charData, ((index << 1) | 1));
+	_return_value = interpreterProxy->integerObjectOf(index);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(10, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitiveClear(void) {
+	sqInt op;
+	sqInt canvasFlags;
+	sqInt fill;
+	cairo_t*context;
+	sqInt canvasOop;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop);
+	if (interpreterProxy->failed()) {
+		fail("canvas flags not an integer");
+		return null;
+	}
+	fill = canvasFlags & CanvasFlagFill;
+	if (!(fill)) {
+		cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.0);
+	}
+	op = cairo_get_operator(context);
+	cairo_set_operator(context, CairoOperatorSource);
+	cairo_paint(context);
+	cairo_set_operator(context, op);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitiveClipRectangleLeftRightTopBottom(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double left;
+	double right;
+	double top;
+	double bottom;
+
+	left = interpreterProxy->stackFloatValue(3);
+	right = interpreterProxy->stackFloatValue(2);
+	top = interpreterProxy->stackFloatValue(1);
+	bottom = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	cairo_rectangle(context, left, top, right - left, bottom - top);
+	cairo_clip(context);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(4);
+	return null;
+}
+
+EXPORT(sqInt) primitiveClose(void) {
+	sqInt canvasOop;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	destroyContextFor(canvasOop);
+	if (!(interpreterProxy->failed())) {
+		interpreterProxy->storePointerofObjectwithValue(CanvasHandleIndex, canvasOop, interpreterProxy->nilObject());
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoComposeString(void) {
+	cairo_t*context;
+	sqInt linesSize;
+	sqInt newW;
+	sqInt sqStart;
+	sqInt lineCount;
+	PangoRectangle ink;
+	sqInt start;
+	sqInt lineIndex;
+	PangoAttrList*attrList;
+	sqInt sqEnd;
+	sqInt baseline;
+	PangoLayoutLine*line;
+	PangoRectangle logical;
+	sqInt totalY;
+	sqInt prevBaseline;
+	PangoLayout*layout;
+	sqInt lastLine;
+	sqInt canvasOop;
+	sqInt addition;
+	PangoLayoutIter*lineIter;
+	sqInt next;
+	char *aString;
+	sqInt x;
+	sqInt y;
+	sqInt sqAttrArray;
+	sqInt w;
+	sqInt h;
+	sqInt withWrap;
+	sqInt lines;
+	sqInt _return_value;
+
+	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(7)));
+	aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(7))));
+	x = interpreterProxy->stackIntegerValue(6);
+	y = interpreterProxy->stackIntegerValue(5);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object"));
+	sqAttrArray = interpreterProxy->stackValue(4);
+	w = interpreterProxy->stackIntegerValue(3);
+	h = interpreterProxy->stackIntegerValue(2);
+	withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	lines = interpreterProxy->stackValue(0);
+	;
+	canvasOop = interpreterProxy->stackValue(8);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	layout = pango_cairo_create_layout(context);
+	attrList = pango_attr_list_new();
+	translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList);
+	pango_layout_set_text(layout, aString, strlen(aString));
+	pango_layout_set_attributes(layout, attrList);
+	pango_layout_set_width(layout, w * (PANGO_SCALE));
+	if (withWrap) {
+		pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+	}
+	cairo_translate(context, x, y);
+	pango_cairo_update_layout(context, layout);
+	lineCount = pango_layout_get_line_count(layout);
+	lineIter = pango_layout_get_iter(layout);
+	baseline = pango_layout_iter_get_baseline(lineIter);
+	prevBaseline = 0;
+	cairo_translate(context, 0, PANGO_PIXELS(baseline));
+	sqEnd = 0;
+	totalY = 0;
+	linesSize = interpreterProxy->stSizeOf(lines);
+	lastLine = (((lineCount < linesSize) ? lineCount : linesSize)) - 1;
+	for (lineIndex = 0; lineIndex <= lastLine; lineIndex += 1) {
+		line = pango_layout_iter_get_line_readonly(lineIter);
+		pango_layout_line_get_extents(line, &ink, &logical);
+		sqStart = sqEnd + 1;
+		start = line->start_index;
+
+		/* self log: 'sqStart, sqEnd: %d %d' with: sqStart with: sqEnd. */
+
+		sqEnd = (sqStart + (sqCharCountInfromto(aString, start, start + (line->length)))) - 1;
+		if (((start + (line->length)) < (interpreterProxy->stSizeOf(((int) aString)))) && ((aString[start + (line->length)]) == 13)) {
+			sqEnd += 1;
+		}
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineStartIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), sqStart);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineEndIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), sqEnd);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineLeftIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), (PANGO_PIXELS(logical.x)) + x);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineRightIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), (PANGO_PIXELS(logical.x+logical.width)) + x);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineTopIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), totalY + y);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineInternalSpaceIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), ((0 << 1) | 1));
+		interpreterProxy->storeIntegerofObjectwithValue(TextLinePaddingWidthIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), ((0 << 1) | 1));
+		next = pango_layout_iter_next_line(lineIter);
+		if (next) {
+			addition = (logical.height) + (pango_layout_get_spacing(layout));
+		} else {
+			addition = logical.height;
+		}
+		totalY += PANGO_PIXELS(addition);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineBottomIndex, interpreterProxy->fetchPointerofObject(lineIndex, lines), totalY + y);
+	}
+	pango_layout_get_extents(layout, &ink, &logical);
+	newW = PANGO_PIXELS(logical.width);
+	pango_layout_iter_free(lineIter);
+	pango_attr_list_unref(attrList);
+	g_object_unref(layout);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	_return_value = interpreterProxy->integerObjectOf(newW);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(9, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoComposeString2(void) {
+	cairo_t*context;
+	sqInt newW;
+	sqInt sqStart;
+	sqInt lineCount;
+	PangoRectangle ink;
+	unsigned char*aString;
+	unsigned char*inString;
+	sqInt start;
+	sqInt lineIndex;
+	PangoAttrList*attrList;
+	sqInt sqEnd;
+	sqInt baseline;
+	PangoLayoutLine*line;
+	PangoRectangle logical;
+	sqInt totalY;
+	sqInt prevBaseline;
+	sqInt arrayOop;
+	sqInt retArrayOop;
+	sqInt textLine;
+	sqInt i;
+	PangoLayout*layout;
+	sqInt lastLine;
+	sqInt canvasOop;
+	sqInt addition;
+	sqInt textLineClass;
+	sqInt inStringSize;
+	PangoLayoutIter*lineIter;
+	sqInt next;
+	sqInt inStringOop;
+	sqInt x;
+	sqInt y;
+	sqInt sqAttrArray;
+	sqInt w;
+	sqInt h;
+	sqInt withWrap;
+	sqInt inTextLineClass;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(7), "Object"));
+	inStringOop = interpreterProxy->stackValue(7);
+	x = interpreterProxy->stackIntegerValue(6);
+	y = interpreterProxy->stackIntegerValue(5);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object"));
+	sqAttrArray = interpreterProxy->stackValue(4);
+	w = interpreterProxy->stackIntegerValue(3);
+	h = interpreterProxy->stackIntegerValue(2);
+	withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	inTextLineClass = interpreterProxy->stackValue(0);
+	;
+	canvasOop = interpreterProxy->stackValue(8);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	inStringSize = interpreterProxy->stSizeOf(inStringOop);
+	if (inStringSize == 0) {
+		primitiveFail();
+		return null;
+	}
+	aString = alloca(inStringSize);
+	inString = interpreterProxy->firstIndexableField(inStringOop);
+	strncpy(aString, inString, inStringSize);
+	textLineClass = inTextLineClass;
+	layout = pango_cairo_create_layout(context);
+	attrList = pango_attr_list_new();
+	translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList);
+	pango_layout_set_text(layout, aString, strlen(aString));
+	pango_layout_set_attributes(layout, attrList);
+	pango_layout_set_width(layout, w * (PANGO_SCALE));
+	if (withWrap) {
+		pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+	}
+	cairo_translate(context, x, y);
+	pango_cairo_update_layout(context, layout);
+	lineCount = pango_layout_get_line_count(layout);
+	lineIter = pango_layout_get_iter(layout);
+	baseline = pango_layout_iter_get_baseline(lineIter);
+	prevBaseline = 0;
+	cairo_translate(context, 0, PANGO_PIXELS(baseline));
+	sqEnd = 0;
+	totalY = 0;
+	interpreterProxy->pushRemappableOop(textLineClass);
+	arrayOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), lineCount);
+	textLineClass = interpreterProxy->popRemappableOop();
+	for (i = 0; i <= (lineCount - 1); i += 1) {
+		interpreterProxy->pushRemappableOop(textLineClass);
+		interpreterProxy->pushRemappableOop(arrayOop);
+		textLine = interpreterProxy->instantiateClassindexableSize(textLineClass, 0);
+		arrayOop = interpreterProxy->popRemappableOop();
+		textLineClass = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(i, arrayOop, textLine);
+	}
+	lastLine = lineCount - 1;
+	for (lineIndex = 0; lineIndex <= lastLine; lineIndex += 1) {
+		line = pango_layout_iter_get_line_readonly(lineIter);
+		pango_layout_line_get_extents(line, &ink, &logical);
+		sqStart = sqEnd + 1;
+		start = line->start_index;
+
+		/* self log: 'sqStart, sqEnd: %d %d' with: sqStart with: sqEnd. */
+
+		sqEnd = (sqStart + (sqCharCountInfromto(aString, start, start + (line->length)))) - 1;
+		if (((start + (line->length)) < (interpreterProxy->stSizeOf(((int) aString)))) && ((aString[start + (line->length)]) == 13)) {
+			sqEnd += 1;
+		}
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineStartIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), sqStart);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineEndIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), sqEnd);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineLeftIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), (PANGO_PIXELS(logical.x)) + x);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineRightIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), (PANGO_PIXELS(logical.x+logical.width)) + x);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineTopIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), totalY + y);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineInternalSpaceIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), ((0 << 1) | 1));
+		interpreterProxy->storeIntegerofObjectwithValue(TextLinePaddingWidthIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), ((0 << 1) | 1));
+		next = pango_layout_iter_next_line(lineIter);
+		if (next) {
+			addition = (logical.height) + (pango_layout_get_spacing(layout));
+		} else {
+			addition = logical.height;
+		}
+		totalY += PANGO_PIXELS(addition);
+		interpreterProxy->storeIntegerofObjectwithValue(TextLineBottomIndex, interpreterProxy->fetchPointerofObject(lineIndex, arrayOop), totalY + y);
+	}
+	pango_layout_get_extents(layout, &ink, &logical);
+	newW = PANGO_PIXELS(logical.width);
+	pango_layout_iter_free(lineIter);
+	pango_attr_list_unref(attrList);
+	g_object_unref(layout);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	interpreterProxy->pushRemappableOop(arrayOop);
+	retArrayOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 2);
+	arrayOop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storeIntegerofObjectwithValue(0, retArrayOop, newW);
+	interpreterProxy->storePointerofObjectwithValue(1, retArrayOop, arrayOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(9, retArrayOop);
+	return null;
+}
+
+EXPORT(sqInt) primitiveCreateFormHandle(void) {
+	sqInt formOop;
+	sqInt surfaceID;
+	sqInt _return_value;
+
+	formOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	surfaceID = createSurfaceFor(formOop);
+	if (surfaceID < 0) {
+		interpreterProxy->primitiveFail();
+	}
+	if (!(interpreterProxy->failed())) {
+		_return_value = interpreterProxy->integerObjectOf(surfaceID);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(1, _return_value);
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitiveDestroyFormHandle(void) {
+	sqInt surfaceID;
+
+	surfaceID = interpreterProxy->stackIntegerValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!(interpreterProxy->failed())) {
+		destroySurface(surfaceID);
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawArcRadiusXYFromTo(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double radius;
+	double x;
+	double y;
+	double angle1;
+	double angle2;
+
+	radius = interpreterProxy->stackFloatValue(4);
+	x = interpreterProxy->stackFloatValue(3);
+	y = interpreterProxy->stackFloatValue(2);
+	angle1 = interpreterProxy->stackFloatValue(1);
+	angle2 = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(5);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	if (radius > 0.0) {
+		cairo_arc(context, x, y, radius, angle1, angle2);
+	} else {
+		cairo_arc_negative(context, x, y, -1.0 * radius, angle1, angle2);
+	}
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(5);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawCurveFromXYviaXYandXYtoXY(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double x0;
+	double y0;
+	double x1;
+	double y1;
+	double x2;
+	double y2;
+	double x3;
+	double y3;
+
+	x0 = interpreterProxy->stackFloatValue(7);
+	y0 = interpreterProxy->stackFloatValue(6);
+	x1 = interpreterProxy->stackFloatValue(5);
+	y1 = interpreterProxy->stackFloatValue(4);
+	x2 = interpreterProxy->stackFloatValue(3);
+	y2 = interpreterProxy->stackFloatValue(2);
+	x3 = interpreterProxy->stackFloatValue(1);
+	y3 = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(8);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	cairo_move_to(context, x0, y0);
+	cairo_curve_to(context, x1, y1, x2, y2, x3, y3);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(8);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawCurveFromXYviaXYtoXY(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double x0;
+	double y0;
+	double x1;
+	double y1;
+	double x2;
+	double y2;
+
+	x0 = interpreterProxy->stackFloatValue(5);
+	y0 = interpreterProxy->stackFloatValue(4);
+	x1 = interpreterProxy->stackFloatValue(3);
+	y1 = interpreterProxy->stackFloatValue(2);
+	x2 = interpreterProxy->stackFloatValue(1);
+	y2 = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(6);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	cairo_move_to(context, x0, y0);
+	cairo_curve_to(context, ((2.0 * x1) + x0) / 3.0, ((2.0 * y1) + y0) / 3.0, ((2.0 * x1) + x2) / 3.0, ((2.0 * y1) + y2) / 3.0, x2, y2);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(6);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawGeneralBezierShape(void) {
+	cairo_t*context;
+	sqInt shapeCount;
+	sqInt segmentCount;
+	short*seg;
+	sqInt j;
+	sqInt yVia;
+	sqInt i;
+	sqInt xFrom;
+	sqInt contourOop;
+	sqInt canvasOop;
+	sqInt xTo;
+	sqInt yTo;
+	sqInt xVia;
+	sqInt yFrom;
+	sqInt shapeOop;
+
+	shapeOop = interpreterProxy->stackValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	shapeCount = interpreterProxy->slotSizeOf(shapeOop);
+	cairo_new_path(context);
+	for (i = 0; i <= (shapeCount - 1); i += 1) {
+		contourOop = interpreterProxy->fetchPointerofObject(i, shapeOop);
+		if (!(interpreterProxy->isMemberOf(contourOop, "ShortPointArray"))) {
+			failwith("bezier contour %i is no ShortPointArray", i + 1);
+			return null;
+		}
+		segmentCount = (interpreterProxy->slotSizeOf(contourOop)) / 3;
+		seg = interpreterProxy->arrayValueOf(contourOop);
+		for (j = 0; j <= (segmentCount - 1); j += 1) {
+			xFrom = seg[0];
+			yFrom = seg[1];
+			xVia = seg[2];
+			yVia = seg[3];
+			xTo = seg[4];
+			yTo = seg[5];
+			if (j == 0) {
+				cairo_move_to(context, xFrom, yFrom);
+			}
+			if ((xFrom == xVia) && (yFrom == yVia)) {
+				cairo_line_to(context, xTo, yTo);
+			} else {
+				cairo_curve_to(context, (xFrom + (2.0 * xVia)) / 3.0, (yFrom + (2.0 * yVia)) / 3.0, ((2.0 * xVia) + xTo) / 3.0, ((2.0 * yVia) + yTo) / 3.0, xTo, yTo);
+			}
+			seg += 6;
+		}
+		cairo_close_path(context);
+	}
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawImageSrcLRTBDestLRTB(void) {
+	cairo_surface_t*srcSurface;
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt formOop;
+	double dstL;
+	double dstR;
+	double dstT;
+	double dstB;
+	double srcL;
+	double srcR;
+	double srcT;
+	double srcB;
+
+	formOop = interpreterProxy->stackValue(8);
+	dstL = interpreterProxy->stackFloatValue(7);
+	dstR = interpreterProxy->stackFloatValue(6);
+	dstT = interpreterProxy->stackFloatValue(5);
+	dstB = interpreterProxy->stackFloatValue(4);
+	srcL = interpreterProxy->stackFloatValue(3);
+	srcR = interpreterProxy->stackFloatValue(2);
+	srcT = interpreterProxy->stackFloatValue(1);
+	srcB = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(9);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	srcSurface = surfaceFrom(formOop);
+	if (!((srcSurface != null) && ((cairo_surface_status(srcSurface)) == 0))) {
+		fail("source surface invalid");
+		return null;
+	}
+	if ((srcR != srcL) && (srcT != srcB)) {
+		cairo_save(context);
+		cairo_translate(context, dstL, dstT);
+		cairo_scale(context, (dstR - dstL) / (srcR - srcL), (dstB - dstT) / (srcB - srcT));
+		cairo_new_path(context);
+		cairo_rectangle(context, 0.0, 0.0, srcR - srcL, srcB - srcT);
+		cairo_set_source_surface(context, srcSurface, 0.0 - srcL, 0.0 - srcT);
+		cairo_fill(context);
+		cairo_restore(context);
+	}
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(9);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawLineFromXYtoXY(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double fromX;
+	double fromY;
+	double toX;
+	double toY;
+
+	fromX = interpreterProxy->stackFloatValue(3);
+	fromY = interpreterProxy->stackFloatValue(2);
+	toX = interpreterProxy->stackFloatValue(1);
+	toY = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	cairo_move_to(context, fromX, fromY);
+	cairo_line_to(context, toX, toY);
+	strokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(4);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawOvalLeftRightTopBottom(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double left;
+	double right;
+	double top;
+	double bottom;
+
+	left = interpreterProxy->stackFloatValue(3);
+	right = interpreterProxy->stackFloatValue(2);
+	top = interpreterProxy->stackFloatValue(1);
+	bottom = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if ((right != left) && (top != bottom)) {
+		cairo_save(context);
+		cairo_new_path(context);
+		cairo_translate(context, (left + right) / 2.0, (top + bottom) / 2.0);
+		cairo_scale(context, (right - left) / 2.0, (bottom - top) / 2.0);
+		cairo_arc(context, 0.0, 0.0, 1.0, 0.0, degrees(360.0));
+		cairo_restore(context);
+		fillOrStrokefrom(context, canvasOop);
+	}
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(4);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawPolygon(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt pointsOop;
+
+	pointsOop = interpreterProxy->stackValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	polyPathfrom(context, pointsOop);
+	cairo_close_path(context);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawPolyline(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt pointsOop;
+
+	pointsOop = interpreterProxy->stackValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	polyPathfrom(context, pointsOop);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveDrawRectangleLeftRightTopBottom(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double left;
+	double right;
+	double top;
+	double bottom;
+
+	left = interpreterProxy->stackFloatValue(3);
+	right = interpreterProxy->stackFloatValue(2);
+	top = interpreterProxy->stackFloatValue(1);
+	bottom = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_new_path(context);
+	cairo_rectangle(context, left, top, right - left, bottom - top);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(4);
+	return null;
+}
+
+
+/*		x1	x2		x3	x4
+	y1	+	/	-	\	+
+	y2	/	.		.	\
+		|				|
+	y3	\	.		.	/
+	y4	+	\	-	/	+ */
+
+EXPORT(sqInt) primitiveDrawRoundRectLeftRightTopBottomRadiusCorner(void) {
+	cairo_t*context;
+	double y3;
+	double y2;
+	double x3;
+	double x2;
+	sqInt canvasOop;
+	double ry;
+	double rx;
+	double r;
+	double x1;
+	double x4;
+	double y1;
+	double y4;
+	double radius;
+	sqInt cornerFlags;
+
+	x1 = interpreterProxy->stackFloatValue(5);
+	x4 = interpreterProxy->stackFloatValue(4);
+	y1 = interpreterProxy->stackFloatValue(3);
+	y4 = interpreterProxy->stackFloatValue(2);
+	radius = interpreterProxy->stackFloatValue(1);
+	cornerFlags = interpreterProxy->stackIntegerValue(0);
+	canvasOop = interpreterProxy->stackValue(6);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	rx = (x4 - x1) / 2.0;
+	ry = (y4 - y1) / 2.0;
+	r = (((((radius < rx) ? radius : rx)) < ry) ? (((radius < rx) ? radius : rx)) : ry);
+	x2 = x1 + r;
+	x3 = x4 - r;
+	y2 = y1 + r;
+	y3 = y4 - r;
+	cairo_new_path(context);
+	if (cornerFlags & 1) {
+		cairo_arc(context, x2, y2, r, degrees(180), degrees(270));
+	} else {
+		cairo_move_to(context, x1, y1);
+	}
+	if (cornerFlags & 8) {
+		cairo_arc(context, x3, y2, r, degrees(270), degrees(360));
+	} else {
+		cairo_line_to(context, x4, y1);
+	}
+	if (cornerFlags & 4) {
+		cairo_arc(context, x3, y3, r, degrees(0), degrees(90));
+	} else {
+		cairo_line_to(context, x4, y4);
+	}
+	if (cornerFlags & 2) {
+		cairo_arc(context, x2, y3, r, degrees(90), degrees(180));
+	} else {
+		cairo_line_to(context, x1, y4);
+	}
+	cairo_close_path(context);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(6);
+	return null;
+}
+
+
+/*	draw a string including its outline if selected */
+
+EXPORT(sqInt) primitiveDrawZeroTerminatedUtf8StringXY(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	char *aString;
+	double x;
+	double y;
+
+	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
+	aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
+	x = interpreterProxy->stackFloatValue(1);
+	y = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(3);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_move_to(context, x, y);
+	cairo_text_path(context, aString);
+	fillOrStrokefrom(context, canvasOop);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(3);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage(void) {
+	cairo_pattern_t*pattern;
+	cairo_t*context;
+	sqInt canvasOop;
+	cairo_matrix_t*m;
+	cairo_matrix_t mdata;
+	cairo_surface_t*surface;
+	double ox;
+	double oy;
+	double dx;
+	double dy;
+	double nx;
+	double ny;
+	sqInt aBoolean;
+	sqInt formOop;
+
+	ox = interpreterProxy->stackFloatValue(7);
+	oy = interpreterProxy->stackFloatValue(6);
+	dx = interpreterProxy->stackFloatValue(5);
+	dy = interpreterProxy->stackFloatValue(4);
+	nx = interpreterProxy->stackFloatValue(3);
+	ny = interpreterProxy->stackFloatValue(2);
+	aBoolean = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
+	formOop = interpreterProxy->stackValue(0);
+	m = &mdata;
+	canvasOop = interpreterProxy->stackValue(8);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	surface = surfaceFrom(formOop);
+	if (!((surface != null) && ((cairo_surface_status(surface)) == 0))) {
+		fail("surface invalid");
+		return null;
+	}
+	pattern = cairo_pattern_create_for_surface(surface);
+	cairo_matrix_init(m, dx, dy, nx, ny, ox, oy);
+	cairo_matrix_invert(m);
+	cairo_pattern_set_matrix(pattern, m);
+	if (aBoolean) {
+		cairo_pattern_set_extend(pattern, CairoExtendRepeat);
+	}
+	if (cairo_pattern_status(pattern)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern)));
+		return null;
+	}
+	cairo_set_source(context, pattern);
+	cairo_pattern_destroy(pattern);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(8);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFillColorAlpha(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt rgb;
+	sqInt alpha;
+
+	rgb = interpreterProxy->stackIntegerValue(1);
+	alpha = interpreterProxy->stackIntegerValue(0);
+	canvasOop = interpreterProxy->stackValue(2);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	setSourcergbalpha(context, rgb, alpha);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(2);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFillLinearOriginXYdirectionXYcolorStops(void) {
+	cairo_pattern_t*pattern;
+	int*colorStops;
+	sqInt i;
+	sqInt colorStopsCount;
+	cairo_t*context;
+	sqInt canvasOop;
+	double ox;
+	double oy;
+	double dx;
+	double dy;
+	sqInt colorStopsOop;
+
+	ox = interpreterProxy->stackFloatValue(4);
+	oy = interpreterProxy->stackFloatValue(3);
+	dx = interpreterProxy->stackFloatValue(2);
+	dy = interpreterProxy->stackFloatValue(1);
+	colorStopsOop = interpreterProxy->stackValue(0);
+	canvasOop = interpreterProxy->stackValue(5);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	colorStops = interpreterProxy->arrayValueOf(colorStopsOop);
+	colorStopsCount = interpreterProxy->slotSizeOf(colorStopsOop);
+	if (interpreterProxy->failed()) {
+		fail("bad colorStops array");
+		return null;
+	}
+	pattern = cairo_pattern_create_linear(ox, oy, ox + dx, oy + dy);
+	if (cairo_pattern_status(pattern)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern)));
+		return null;
+	}
+	for (i = 0; i <= (colorStopsCount - 1); i += 3) {
+		addColorStopTooffsetrgbalpha(pattern, colorStops[i], colorStops[i + 1], colorStops[i + 2]);
+	}
+	cairo_set_source(context, pattern);
+	cairo_pattern_destroy(pattern);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(5);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops(void) {
+	int*colorStops;
+	cairo_t*context;
+	sqInt colorStopsCount;
+	cairo_matrix_t*m;
+	cairo_matrix_t mdata;
+	sqInt i;
+	sqInt canvasOop;
+	cairo_pattern_t*pattern;
+	double ox;
+	double oy;
+	double dx;
+	double dy;
+	double nx;
+	double ny;
+	sqInt colorStopsOop;
+
+	ox = interpreterProxy->stackFloatValue(6);
+	oy = interpreterProxy->stackFloatValue(5);
+	dx = interpreterProxy->stackFloatValue(4);
+	dy = interpreterProxy->stackFloatValue(3);
+	nx = interpreterProxy->stackFloatValue(2);
+	ny = interpreterProxy->stackFloatValue(1);
+	colorStopsOop = interpreterProxy->stackValue(0);
+	m = &mdata;
+	canvasOop = interpreterProxy->stackValue(7);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	colorStops = interpreterProxy->arrayValueOf(colorStopsOop);
+	colorStopsCount = interpreterProxy->slotSizeOf(colorStopsOop);
+	if (interpreterProxy->failed()) {
+		fail("bad colorStops array");
+		return null;
+	}
+	pattern = cairo_pattern_create_radial(0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
+	cairo_matrix_init(m, dx, dy, nx, ny, ox, oy);
+	cairo_matrix_invert(m);
+	cairo_pattern_set_matrix(pattern, m);
+	if (cairo_pattern_status(pattern)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_pattern_status(pattern)));
+		return null;
+	}
+	for (i = 0; i <= (colorStopsCount - 1); i += 3) {
+		addColorStopTooffsetrgbalpha(pattern, colorStops[i], colorStops[i + 1], colorStops[i + 2]);
+	}
+	cairo_set_source(context, pattern);
+	cairo_pattern_destroy(pattern);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(7);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFontFace(void) {
+	cairo_font_face_t*crFace;
+	FT_Face ftFace;
+	cairo_t*context;
+	sqInt canvasOop;
+	char *faceHandle;
+
+	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
+	faceHandle = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	ftFace = *(void**)faceHandle;
+	crFace = cairo_ft_font_face_create_for_ft_face(ftFace, FT_LOAD_NO_HINTING);
+	cairo_set_font_face(context, crFace);
+	cairo_font_face_destroy(crFace);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveFontSize(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double size;
+
+	size = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_set_font_size(context, size);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveGetLineWidth(void) {
+	double width;
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt _return_value;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	width = cairo_get_line_width(context);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	_return_value = interpreterProxy->floatObjectOf(width);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(1, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoFontDescriptionIndex(void) {
+	sqInt familyNameSize;
+	sqInt newInd;
+	PangoFontDescription *desc;
+	sqInt i;
+	sqInt ind;
+	char cFamilyName[128];
+	sqInt size;
+	sqInt pangoStyle;
+	char *familyName;
+	sqInt isAbsolute;
+	sqInt familyNameOop;
+	sqInt ptSize;
+	sqInt _return_value;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object"));
+	familyNameOop = interpreterProxy->stackValue(1);
+	ptSize = interpreterProxy->stackIntegerValue(0);
+	;
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	familyNameSize = interpreterProxy->stSizeOf(familyNameOop);
+	if (familyNameSize > 127) {
+		return null;
+	}
+	if ((ptSize < 0) || (ptSize > 1000000)) {
+		_return_value = ((-1 << 1) | 1);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(3, _return_value);
+		return null;
+	}
+	familyName = interpreterProxy->firstIndexableField(familyNameOop);
+	for (i = 0; i <= (familyNameSize - 1); i += 1) {
+		cFamilyName[i] = (familyName[i]);
+	}
+	cFamilyName[familyNameSize] = 0;
+	newInd = -1;
+	ind = 0;
+	desc = null;
+	while (newInd == -1) {
+		desc = fontDescriptions[ind];
+		if (desc == null) {
+			newInd = ind;
+		} else {
+			isAbsolute = pango_font_description_get_size_is_absolute(desc);
+			size = pango_font_description_get_size(desc);
+			if (isAbsolute) {
+				size = size;
+			}
+			if (((strcmp(cFamilyName, pango_font_description_get_family(desc))) == 0) && (size == (ptSize * (PANGO_SCALE)))) {
+				newInd = ind;
+			}
+		}
+		ind += 1;
+		if (ind > 255) {
+			newInd = 256;
+		}
+	}
+	if (newInd == 256) {
+		_return_value = ((-1 << 1) | 1);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(3, _return_value);
+		return null;
+	}
+	if (desc == null) {
+		null;
+	} else {
+		_return_value = ((newInd << 1) | 1);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(3, _return_value);
+		return null;
+	}
+	desc = pango_font_description_new();
+	pango_font_description_set_family(desc, cFamilyName);
+	pangoStyle = PANGO_STYLE_NORMAL;
+	pango_font_description_set_style(desc, pangoStyle);
+	pango_font_description_set_size(desc, ptSize * (PANGO_SCALE));
+	fontDescriptions[newInd] = desc;
+	_return_value = ((newInd << 1) | 1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(3, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitiveGetTransform(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	cairo_matrix_t m;
+	float *aTransform;
+
+	aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0))));
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_get_matrix(context, &m);
+	aTransform[0] = (m.xx);
+	aTransform[1] = (m.xy);
+	aTransform[2] = (m.x0);
+	aTransform[3] = (m.yx);
+	aTransform[4] = (m.yy);
+	aTransform[5] = (m.y0);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoIndexAtPoint(void) {
+	sqInt index;
+	cairo_t*context;
+	sqInt origin;
+	unsigned char*aString;
+	sqInt trailing;
+	sqInt aStringOop;
+	sqInt lineIndex;
+	sqInt inside;
+	PangoAttrList*attrList;
+	PangoLayoutLine*line;
+	sqInt xPos;
+	PangoLayout*layout;
+	sqInt canvasOop;
+	sqInt corner;
+	sqInt charData;
+	PangoRectangle pos;
+	sqInt inStringOop;
+	sqInt x;
+	sqInt y;
+	sqInt sqAttrArray;
+	sqInt w;
+	sqInt h;
+	sqInt withWrap;
+	sqInt cData;
+	sqInt _return_value;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(7), "Object"));
+	inStringOop = interpreterProxy->stackValue(7);
+	x = interpreterProxy->stackIntegerValue(6);
+	y = interpreterProxy->stackIntegerValue(5);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object"));
+	sqAttrArray = interpreterProxy->stackValue(4);
+	w = interpreterProxy->stackIntegerValue(3);
+	h = interpreterProxy->stackIntegerValue(2);
+	withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	cData = interpreterProxy->stackValue(0);
+	;
+	canvasOop = interpreterProxy->stackValue(8);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	aStringOop = inStringOop;
+	aString = interpreterProxy->firstIndexableField(aStringOop);
+	layout = pango_cairo_create_layout(context);
+	attrList = pango_attr_list_new();
+	translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList);
+	pango_layout_set_text(layout, aString, strlen(aString));
+	pango_layout_set_attributes(layout, attrList);
+	pango_layout_set_width(layout, w * (PANGO_SCALE));
+	if (withWrap) {
+		pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+	}
+	cairo_translate(context, x, y);
+	pango_cairo_update_layout(context, layout);
+	inside = pango_layout_xy_to_index(layout, x * (PANGO_SCALE), y * (PANGO_SCALE), &index, &trailing);
+	pango_layout_index_to_pos(layout, index, &pos);
+	line = null;
+	if (!(inside)) {
+		pango_layout_index_to_line_x(layout, index, trailing, &lineIndex, &xPos);
+
+		/* self log: 'lineIndex %x' with: line. */
+
+		line = pango_layout_get_line_readonly(layout, ((lineIndex < 0) ? 0 : lineIndex));
+		if (line == null) {
+			index = strlen(aString);
+		} else {
+			pango_layout_line_ref(line);
+
+			/* self log: 'line->length %d' with: (self cCode: 'line->length'). */
+
+			index = line->start_index;
+			index += line->length;
+			if (trailing > 0) {
+				trailing = 1;
+			}
+		}
+	}
+	pango_attr_list_unref(attrList);
+	g_object_unref(layout);
+	if (!(line == null)) {
+		pango_layout_line_unref(line);
+	}
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	interpreterProxy->pushRemappableOop(aStringOop);
+	interpreterProxy->pushRemappableOop(cData);
+	origin = interpreterProxy->makePointwithxValueyValue(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.y));
+	interpreterProxy->pushRemappableOop(origin);
+	corner = interpreterProxy->makePointwithxValueyValue(PANGO_PIXELS(pos.x+pos.width), PANGO_PIXELS(pos.y+pos.height));
+	origin = interpreterProxy->popRemappableOop();
+	charData = interpreterProxy->popRemappableOop();
+	aStringOop = interpreterProxy->popRemappableOop();
+	aString = interpreterProxy->firstIndexableField(aStringOop);
+	interpreterProxy->storePointerofObjectwithValue(0, charData, origin);
+	interpreterProxy->storePointerofObjectwithValue(1, charData, corner);
+	index = sqCharCountInfromto(aString, 0, (((index + trailing) < (1 + (strlen(aString)))) ? (index + trailing) : (1 + (strlen(aString)))));
+	if (inside || (xPos <= 0)) {
+		index += 1;
+	}
+	interpreterProxy->storePointerofObjectwithValue(2, charData, ((index << 1) | 1));
+	_return_value = interpreterProxy->integerObjectOf(index);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(9, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitiveLanguageAttributes(void) {
+	sqInt arraySize;
+	sqInt array4Oop;
+	sqInt lOop;
+	sqInt currentStart;
+	sqInt ws;
+	sqInt stringOop;
+	int *array;
+	int *array4;
+	unsigned int *string;
+	sqInt currentTag;
+	sqInt leadingChar;
+	sqInt arrayOop;
+	sqInt i;
+	sqInt arrayIndex;
+	sqInt stringSize;
+	sqInt currentEnd;
+	sqInt oStringOop;
+	sqInt oLOop;
+	sqInt oArrayOop;
+	sqInt _return_value;
+	sqInt v;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Object"));
+	oStringOop = interpreterProxy->stackValue(2);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object"));
+	oLOop = interpreterProxy->stackValue(1);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	oArrayOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	lOop = oLOop;
+	arrayOop = oArrayOop;
+	stringOop = oStringOop;
+	if (interpreterProxy->isBytes(stringOop)) {
+		_return_value = interpreterProxy->integerObjectOf(0);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(4, _return_value);
+		return null;
+	}
+	if (!(interpreterProxy->isWords(stringOop))) {
+		primitiveFail();
+		return null;
+	}
+	arraySize = interpreterProxy->stSizeOf(arrayOop);
+	if (arraySize <= 0) {
+		primitiveFail();
+		return null;
+	}
+	stringSize = interpreterProxy->stSizeOf(stringOop);
+	if (stringSize == 0) {
+		_return_value = interpreterProxy->integerObjectOf(0);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(4, _return_value);
+		return null;
+	}
+	string = interpreterProxy->firstIndexableField(stringOop);
+	array = interpreterProxy->firstIndexableField(arrayOop);
+	ws = string[0];
+	currentTag = ((usqInt) (ws & 1069547520) >> 22);
+	leadingChar = -1;
+	currentStart = 0;
+	/* begin utf8CountFor: */
+	v = ws & 2097151;
+	if ((0 <= v) && (v <= 127)) {
+		currentEnd = 1;
+		goto l1;
+	}
+	if ((128 <= v) && (v <= 2047)) {
+		currentEnd = 2;
+		goto l1;
+	}
+	if ((2048 <= v) && (v <= 55295)) {
+		currentEnd = 3;
+		goto l1;
+	}
+	if ((57344 <= v) && (v <= 65535)) {
+		currentEnd = 3;
+		goto l1;
+	}
+	if ((65536 <= v) && (v <= 1114111)) {
+		currentEnd = 4;
+		goto l1;
+	}
+	currentEnd = 0;
+l1:	/* end utf8CountFor: */;
+	arrayIndex = 0;
+	for (i = 1; i <= (stringSize - 1); i += 1) {
+		ws = string[i];
+		leadingChar = ((usqInt) (ws & 1069547520) >> 22);
+		if (leadingChar != currentTag) {
+			interpreterProxy->pushRemappableOop(stringOop);
+			interpreterProxy->pushRemappableOop(arrayOop);
+			interpreterProxy->pushRemappableOop(lOop);
+			array4Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4);
+			lOop = interpreterProxy->popRemappableOop();
+			arrayOop = interpreterProxy->popRemappableOop();
+			stringOop = interpreterProxy->popRemappableOop();
+			array = interpreterProxy->firstIndexableField(arrayOop);
+			string = interpreterProxy->firstIndexableField(stringOop);
+			array4 = interpreterProxy->firstIndexableField(array4Oop);
+			array4[0] = lOop;
+			array4[1] = (((currentStart << 1) | 1));
+			array4[2] = (((currentEnd << 1) | 1));
+			array4[3] = (((currentTag << 1) | 1));
+			array[arrayIndex] = array4Oop;
+			arrayIndex += 1;
+			if (arrayIndex >= arraySize) {
+				primitiveFail();
+				return null;
+			}
+			currentTag = leadingChar;
+			currentStart = currentEnd;
+		}
+		currentEnd += utf8CountFor(ws);
+	}
+	interpreterProxy->pushRemappableOop(stringOop);
+	interpreterProxy->pushRemappableOop(arrayOop);
+	interpreterProxy->pushRemappableOop(lOop);
+	array4Oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), 4);
+	lOop = interpreterProxy->popRemappableOop();
+	arrayOop = interpreterProxy->popRemappableOop();
+	stringOop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(0, array4Oop, lOop);
+	interpreterProxy->storeIntegerofObjectwithValue(1, array4Oop, currentStart);
+	interpreterProxy->storeIntegerofObjectwithValue(2, array4Oop, currentEnd);
+	interpreterProxy->storeIntegerofObjectwithValue(3, array4Oop, currentTag);
+	interpreterProxy->storePointerofObjectwithValue(arrayIndex, arrayOop, array4Oop);
+	arrayIndex += 1;
+	_return_value = interpreterProxy->integerObjectOf(arrayIndex);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(4, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitiveOpen(void) {
+	sqInt handleOop;
+	sqInt contextIndex;
+	sqInt canvasOop;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	contextIndex = createContextFor(canvasOop);
+	if (!(interpreterProxy->failed())) {
+		handleOop = interpreterProxy->integerObjectOf(contextIndex);
+		interpreterProxy->storePointerofObjectwithValue(CanvasHandleIndex, canvasOop, handleOop);
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoIsAvailable(void) {
+	PangoLayout*layout;
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt _return_value;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	layout = pango_cairo_create_layout(context);
+	if (layout == null) {
+		_return_value = interpreterProxy->integerObjectOf(2);
+		if (interpreterProxy->failed()) {
+			return null;
+		}
+		interpreterProxy->popthenPush(1, _return_value);
+		return null;
+	}
+	g_object_unref(layout);
+	_return_value = (1? interpreterProxy->trueObject(): interpreterProxy->falseObject());
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(1, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitivePluginVersion(void) {
+	sqInt _return_value;
+
+	_return_value = interpreterProxy->integerObjectOf(PluginVersion);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(1, _return_value);
+	return null;
+}
+
+EXPORT(sqInt) primitiveRestoreState(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_restore(context);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitiveRotateBy(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double angle;
+
+	angle = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_rotate(context, angle);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveSaveState(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+
+	canvasOop = interpreterProxy->stackValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_save(context);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	return null;
+}
+
+EXPORT(sqInt) primitiveScaleBy(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double x;
+	double y;
+
+	x = interpreterProxy->stackFloatValue(1);
+	y = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(2);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_scale(context, x, y);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(2);
+	return null;
+}
+
+EXPORT(sqInt) primitiveSetLineWidth(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double width;
+
+	width = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_set_line_width(context, width);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveSetTransform(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	cairo_matrix_t m;
+	float *aTransform;
+
+	aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0))));
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_matrix_init(&m, aTransform[0], aTransform[3], aTransform[1], aTransform[4], aTransform[2], aTransform[5]);
+	cairo_set_matrix(context, &m);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitivePangoShowString(void) {
+	cairo_t*context;
+	sqInt newW;
+	sqInt lineCount;
+	PangoRectangle ink;
+	unsigned int cursorColor;
+	PangoAttrList*attrList;
+	PangoLayoutLine*line;
+	PangoRectangle logical;
+	sqInt prevBaseline;
+	PangoLayout*layout;
+	PangoRectangle startRect;
+	sqInt canvasOop;
+	PangoLayoutIter*lineIter;
+	sqInt indexToX;
+	char *aString;
+	sqInt x;
+	sqInt y;
+	sqInt sqAttrArray;
+	sqInt w;
+	sqInt h;
+	sqInt withWrap;
+	sqInt selStart;
+	sqInt selEnd;
+	sqInt cPixel;
+	sqInt _return_value;
+
+	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(9)));
+	aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(9))));
+	x = interpreterProxy->stackIntegerValue(8);
+	y = interpreterProxy->stackIntegerValue(7);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(6), "Object"));
+	sqAttrArray = interpreterProxy->stackValue(6);
+	w = interpreterProxy->stackIntegerValue(5);
+	h = interpreterProxy->stackIntegerValue(4);
+	withWrap = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(3));
+	selStart = interpreterProxy->stackIntegerValue(2);
+	selEnd = interpreterProxy->stackIntegerValue(1);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(0), "Object"));
+	cPixel = interpreterProxy->stackValue(0);
+	;
+	canvasOop = interpreterProxy->stackValue(10);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	cursorColor = interpreterProxy->positive32BitValueOf(cPixel);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	layout = pango_cairo_create_layout(context);
+	attrList = pango_attr_list_new();
+	translateSqAttrsToPangoAttrsinto(sqAttrArray, attrList);
+	if (!(selStart == selEnd)) {
+		if ((selStart >= 0) && (selEnd >= 0)) {
+			addSelectionFromtopixelinto(selStart, selEnd, cursorColor, attrList);
+		}
+	}
+	pango_layout_set_text(layout, aString, strlen(aString));
+	pango_layout_set_attributes(layout, attrList);
+	pango_layout_set_width(layout, w * (PANGO_SCALE));
+	if (withWrap) {
+		pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+	}
+	cairo_translate(context, x, y);
+	pango_cairo_update_layout(context, layout);
+
+	/* 	lineIter := self pangoLayoutGetIter: layout.
+	baseline := self pangoLayoutIterGetBaseline: lineIter.
+	prevBaseline := 0.
+ */
+
+	lineCount = pango_layout_get_line_count(layout);
+	if (1) {
+		pango_cairo_show_layout(context, layout);
+	} else {
+		null;
+	}
+	if (selStart == selEnd) {
+		if ((selStart >= 0) && (selEnd >= 0)) {
+			pango_layout_index_to_pos(layout, selStart, &startRect);
+			addSelectionAtpixelwith(&startRect, cursorColor, context);
+		}
+	}
+	pango_layout_get_extents(layout, &ink, &logical);
+
+	/* self pangoLayoutIterFree: lineIter. */
+
+	newW = PANGO_PIXELS(logical.width);
+	pango_attr_list_unref(attrList);
+	g_object_unref(layout);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	_return_value = interpreterProxy->integerObjectOf(newW);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(11, _return_value);
+	return null;
+}
+
+
+/*	Show a string - ignores outline (use drawString primitive for outlines) */
+
+EXPORT(sqInt) primitiveShowZeroTerminatedUtf8StringXY(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	char *aString;
+	double x;
+	double y;
+
+	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
+	aString = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
+	x = interpreterProxy->stackFloatValue(1);
+	y = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(3);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_move_to(context, x, y);
+	cairo_show_text(context, aString);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(3);
+	return null;
+}
+
+EXPORT(sqInt) primitiveStencilImageSrcLRTBDestLRTB(void) {
+	cairo_surface_t*srcSurface;
+	cairo_t*context;
+	sqInt canvasOop;
+	sqInt formOop;
+	double dstL;
+	double dstR;
+	double dstT;
+	double dstB;
+	double srcL;
+	double srcR;
+	double srcT;
+	double srcB;
+
+	formOop = interpreterProxy->stackValue(8);
+	dstL = interpreterProxy->stackFloatValue(7);
+	dstR = interpreterProxy->stackFloatValue(6);
+	dstT = interpreterProxy->stackFloatValue(5);
+	dstB = interpreterProxy->stackFloatValue(4);
+	srcL = interpreterProxy->stackFloatValue(3);
+	srcR = interpreterProxy->stackFloatValue(2);
+	srcT = interpreterProxy->stackFloatValue(1);
+	srcB = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(9);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	srcSurface = surfaceFrom(formOop);
+	if (!((srcSurface != null) && ((cairo_surface_status(srcSurface)) == 0))) {
+		fail("source surface invalid");
+		return null;
+	}
+	if ((srcR != srcL) && (srcT != srcB)) {
+		cairo_save(context);
+		cairo_translate(context, dstL, dstT);
+		cairo_scale(context, (dstR - dstL) / (srcR - srcL), (dstB - dstT) / (srcB - srcT));
+		cairo_new_path(context);
+		cairo_rectangle(context, 0.0, 0.0, srcR - srcL, srcB - srcT);
+		cairo_clip(context);
+		cairo_mask_surface(context, srcSurface, 0.0 - srcL, 0.0 - srcT);
+		cairo_restore(context);
+	}
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(9);
+	return null;
+}
+
+EXPORT(sqInt) primitiveTransformBy(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	cairo_matrix_t m;
+	float *aTransform;
+
+	aTransform = ((float *) (interpreterProxy->arrayValueOf(interpreterProxy->stackValue(0))));
+	canvasOop = interpreterProxy->stackValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_matrix_init(&m, aTransform[0], aTransform[3], aTransform[1], aTransform[4], aTransform[2], aTransform[5]);
+	cairo_transform(context, &m);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(1);
+	return null;
+}
+
+EXPORT(sqInt) primitiveTranslateBy(void) {
+	cairo_t*context;
+	sqInt canvasOop;
+	double x;
+	double y;
+
+	x = interpreterProxy->stackFloatValue(1);
+	y = interpreterProxy->stackFloatValue(0);
+	canvasOop = interpreterProxy->stackValue(2);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	context = contextFrom(canvasOop);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	cairo_translate(context, x, y);
+	if (cairo_status(context)) {
+		failwith("cairo error: %s", cairo_status_to_string(cairo_status(context)));
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->pop(2);
+	return null;
+}
+
+EXPORT(sqInt) primitiveUTF8StringWith2Indexes(void) {
+	sqInt utf8StringOop;
+	sqInt size;
+	sqInt bytes;
+	sqInt mult;
+	unsigned char *byteString;
+	sqInt stringOop;
+	sqInt utf8Index;
+	sqInt arrayOop;
+	sqInt i;
+	sqInt newIndex2;
+	sqInt realutf8StringOop;
+	sqInt newIndex1;
+	unsigned int *wideString;
+	unsigned char *realutf8String;
+	sqInt val;
+	unsigned int c;
+	unsigned char *utf8String;
+	sqInt oStringOop;
+	sqInt sqIndex1;
+	sqInt sqIndex2;
+	sqInt oArrayOop;
+	sqInt nullFlag;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(4), "Object"));
+	oStringOop = interpreterProxy->stackValue(4);
+	sqIndex1 = interpreterProxy->stackIntegerValue(3);
+	sqIndex2 = interpreterProxy->stackIntegerValue(2);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object"));
+	oArrayOop = interpreterProxy->stackValue(1);
+	nullFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0));
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	arrayOop = oArrayOop;
+	stringOop = oStringOop;
+	if (interpreterProxy->isPointers(stringOop)) {
+		primitiveFail();
+		return null;
+	}
+	bytes = interpreterProxy->isBytes(stringOop);
+	size = interpreterProxy->stSizeOf(stringOop);
+	if (bytes) {
+		mult = 2;
+	} else {
+		mult = 4;
+	}
+	interpreterProxy->pushRemappableOop(stringOop);
+	interpreterProxy->pushRemappableOop(arrayOop);
+	utf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), (size * mult) + 1);
+	arrayOop = interpreterProxy->popRemappableOop();
+	stringOop = interpreterProxy->popRemappableOop();
+	if (bytes) {
+		byteString = interpreterProxy->firstIndexableField(stringOop);
+	} else {
+		wideString = interpreterProxy->firstIndexableField(stringOop);
+	}
+	utf8Index = 0;
+	newIndex1 = -1;
+	newIndex2 = -1;
+	utf8String = interpreterProxy->firstIndexableField(utf8StringOop);
+	if (bytes) {
+		for (i = 0; i <= (size - 1); i += 1) {
+			c = byteString[i];
+			if ((i + 1) == sqIndex1) {
+				newIndex1 = utf8Index;
+			}
+			if ((i + 1) == sqIndex2) {
+				newIndex2 = utf8Index;
+			}
+			utf8Index = putCharintoat(c, utf8String, utf8Index);
+		}
+	} else {
+		for (i = 0; i <= (size - 1); i += 1) {
+			c = wideString[i];
+			if ((i + 1) == sqIndex1) {
+				newIndex1 = utf8Index;
+			}
+			if ((i + 1) == sqIndex2) {
+				newIndex2 = utf8Index;
+			}
+			utf8Index = putCharintoat(c, utf8String, utf8Index);
+		}
+	}
+	if (nullFlag) {
+		utf8String[utf8Index] = 0;
+		utf8Index += 1;
+	}
+	interpreterProxy->pushRemappableOop(utf8StringOop);
+	interpreterProxy->pushRemappableOop(arrayOop);
+	realutf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), utf8Index);
+	arrayOop = interpreterProxy->popRemappableOop();
+	utf8StringOop = interpreterProxy->popRemappableOop();
+	utf8String = interpreterProxy->firstIndexableField(utf8StringOop);
+	realutf8String = interpreterProxy->firstIndexableField(realutf8StringOop);
+	memcpy(realutf8String, utf8String, utf8Index);
+	interpreterProxy->storePointerofObjectwithValue(0, arrayOop, realutf8StringOop);
+	if (newIndex1 == -1) {
+		if (sqIndex1 == -1) {
+			val = -1;
+		} else {
+			val = utf8Index;
+		}
+	} else {
+		val = newIndex1;
+	}
+	interpreterProxy->storeIntegerofObjectwithValue(1, arrayOop, val);
+	if (newIndex2 == -1) {
+		if (sqIndex2 == -1) {
+			val = -1;
+		} else {
+			val = utf8Index;
+		}
+	} else {
+		val = newIndex2;
+	}
+	interpreterProxy->storeIntegerofObjectwithValue(2, arrayOop, val);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(6, arrayOop);
+	return null;
+}
+
+EXPORT(sqInt) primitiveUTF8StringWithIndex(void) {
+	sqInt utf8StringOop;
+	sqInt size;
+	sqInt bytes;
+	sqInt mult;
+	unsigned char *byteString;
+	sqInt stringOop;
+	sqInt utf8Index;
+	sqInt arrayOop;
+	sqInt i;
+	sqInt realutf8StringOop;
+	unsigned int *wideString;
+	unsigned char *realutf8String;
+	sqInt val;
+	unsigned int c;
+	sqInt newIndex;
+	unsigned char *utf8String;
+	sqInt oStringOop;
+	sqInt sqIndex;
+	sqInt oArrayOop;
+	sqInt nullFlag;
+
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(3), "Object"));
+	oStringOop = interpreterProxy->stackValue(3);
+	sqIndex = interpreterProxy->stackIntegerValue(2);
+	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(1), "Object"));
+	oArrayOop = interpreterProxy->stackValue(1);
+	nullFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(0));
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	arrayOop = oArrayOop;
+	stringOop = oStringOop;
+	if (interpreterProxy->isPointers(stringOop)) {
+		primitiveFail();
+		return null;
+	}
+	bytes = interpreterProxy->isBytes(stringOop);
+	size = interpreterProxy->stSizeOf(stringOop);
+	if (bytes) {
+		mult = 2;
+	} else {
+		mult = 4;
+	}
+	interpreterProxy->pushRemappableOop(stringOop);
+	interpreterProxy->pushRemappableOop(arrayOop);
+	utf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), (size * mult) + 1);
+	arrayOop = interpreterProxy->popRemappableOop();
+	stringOop = interpreterProxy->popRemappableOop();
+	if (bytes) {
+		byteString = interpreterProxy->firstIndexableField(stringOop);
+	} else {
+		wideString = interpreterProxy->firstIndexableField(stringOop);
+	}
+	utf8Index = 0;
+	newIndex = -1;
+	utf8String = interpreterProxy->firstIndexableField(utf8StringOop);
+	if (bytes) {
+		for (i = 0; i <= (size - 1); i += 1) {
+			c = byteString[i];
+			if ((i + 1) == sqIndex) {
+				newIndex = utf8Index;
+			}
+			utf8Index = putCharintoat(c, utf8String, utf8Index);
+		}
+	} else {
+		for (i = 0; i <= (size - 1); i += 1) {
+			c = wideString[i];
+			if ((i + 1) == sqIndex) {
+				newIndex = utf8Index;
+			}
+			utf8Index = putCharintoat(c, utf8String, utf8Index);
+		}
+	}
+	if (nullFlag) {
+		utf8String[utf8Index] = 0;
+		utf8Index += 1;
+	}
+	interpreterProxy->pushRemappableOop(utf8StringOop);
+	interpreterProxy->pushRemappableOop(arrayOop);
+	realutf8StringOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), utf8Index);
+	arrayOop = interpreterProxy->popRemappableOop();
+	utf8StringOop = interpreterProxy->popRemappableOop();
+	utf8String = interpreterProxy->firstIndexableField(utf8StringOop);
+	realutf8String = interpreterProxy->firstIndexableField(realutf8StringOop);
+	memcpy(realutf8String, utf8String, utf8Index);
+	interpreterProxy->storePointerofObjectwithValue(0, arrayOop, realutf8StringOop);
+	if (newIndex == -1) {
+		if (sqIndex == -1) {
+			val = -1;
+		} else {
+			val = utf8Index;
+		}
+	} else {
+		val = newIndex;
+	}
+	interpreterProxy->storeIntegerofObjectwithValue(1, arrayOop, val);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	interpreterProxy->popthenPush(5, arrayOop);
+	return null;
+}
+
+static sqInt putCharintoat(sqInt c, unsigned char*utf8String, sqInt utf8Index) {
+	unsigned int val;
+	sqInt nBytes;
+	sqInt mask;
+	sqInt i;
+	sqInt index;
+	sqInt shift;
+	sqInt v;
+
+	val = c & 2097151;
+	index = utf8Index;
+	if ((0 <= val) && (val <= 127)) {
+		utf8String[index] = val;
+		return utf8Index + 1;
+	}
+	/* begin utf8CountFor: */
+	v = c & 2097151;
+	if ((0 <= v) && (v <= 127)) {
+		nBytes = 1;
+		goto l1;
+	}
+	if ((128 <= v) && (v <= 2047)) {
+		nBytes = 2;
+		goto l1;
+	}
+	if ((2048 <= v) && (v <= 55295)) {
+		nBytes = 3;
+		goto l1;
+	}
+	if ((57344 <= v) && (v <= 65535)) {
+		nBytes = 3;
+		goto l1;
+	}
+	if ((65536 <= v) && (v <= 1114111)) {
+		nBytes = 4;
+		goto l1;
+	}
+	nBytes = 0;
+l1:	/* end utf8CountFor: */;
+	mask = utf8Headers[nBytes - 1];
+	shift = (nBytes - 1) * -6;
+	utf8String[index] = ((((shift < 0) ? ((usqInt) val >> -shift) : ((usqInt) val << shift))) | mask);
+	index += 1;
+	for (i = 2; i <= nBytes; i += 1) {
+		shift += 6;
+		utf8String[index] = (((((shift < 0) ? ((usqInt) val >> -shift) : ((usqInt) val << shift))) & 63) + 128);
+		index += 1;
+	}
+	return utf8Index + nBytes;
+}
+
+
+/*	Register the given surface, answer an ID or -1 on failure */
+
+static sqInt registerSurface(cairo_surface_t*surfaceHandle) {
+	sqInt surfaceID;
+
+	if (registerSurfaceFn == null) {
+		if (!(loadSurfacePlugin())) {
+			return -1;
+		}
+	}
+	if (!((*registerSurfaceFn)((int)surfaceHandle, &surfaceDispatch, &surfaceID))) {
+		fail("could not register surface");
+		return -1;
+	}
+	/* missing DebugCode */;
+	if (surfaceID > maxSurfaceID) {
+		maxSurfaceID = surfaceID;
+	}
+	return surfaceID;
+}
+
+
+/*	Note: This is coded so that is can be run from Squeak. */
+
+EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) {
+	sqInt ok;
+
+	interpreterProxy = anInterpreter;
+	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
+	if (ok == 0) {
+		return 0;
+	}
+	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
+	return ok;
+}
+
+static void setSourcergbalpha(cairo_t*context, sqInt rgb, sqInt alpha) {
+	sqInt b;
+	sqInt r;
+	sqInt g;
+
+	r = (((usqInt) rgb) >> 20) & 1023;
+	g = (((usqInt) rgb) >> 10) & 1023;
+	b = (((usqInt) rgb) >> 0) & 1023;
+	if (alpha == 255) {
+		cairo_set_source_rgb(context, r / 1023.0, g / 1023.0, b / 1023.0);
+	} else {
+		cairo_set_source_rgba(context, r / 1023.0, g / 1023.0, b / 1023.0, alpha / 255.0);
+	}
+}
+
+static sqInt showSurfacexywh(cairo_surface_t *surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h) {
+	return 0;
+}
+
+EXPORT(sqInt) shutdownModule(void) {
+	PangoFontDescription*desc;
+	sqInt i;
+	sqInt id;
+	cairo_surface_t*surface;
+
+	for (i = 0; i <= (lastIndex(contexts)); i += 1) {
+		if (!((contexts[i]) == null)) {
+			logwith("context %i still active when unloading module!", i);
+			cairo_destroy(contexts[i]);
+			contexts[i] = null;
+		}
+	}
+	for (id = 0; id <= maxSurfaceID; id += 1) {
+		surface = findSurface(id);
+		if (surface != null) {
+			logwith("surface %i still active when unloading module!", id);
+			destroySurface(id);
+		}
+	}
+	for (i = 0; i <= 255; i += 1) {
+		desc = fontDescriptions[i];
+		if (desc != null) {
+			pango_font_description_free(desc);
+			fontDescriptions[i] = null;
+		}
+	}
+	if (defaultFontDescription != null) {
+		pango_font_description_free(defaultFontDescription);
+		defaultFontDescription = null;
+	}
+	return 1;
+}
+
+static sqInt sqAssert(sqInt aBool) {
+	/* missing DebugCode */;
+}
+
+static sqInt sqCharCountInfromto(unsigned char* aString, sqInt from, sqInt to) {
+	sqInt sqCount;
+	sqInt aChar;
+	sqInt index;
+
+	index = from;
+	sqCount = 0;
+	while (index < to) {
+		aChar = aString[index];
+		if (aChar < 128) {
+			index += 1;
+		} else {
+			if (aChar < 224) {
+				index += 2;
+			} else {
+				if (aChar < 240) {
+					index += 3;
+				} else {
+					if (aChar < 248) {
+						index += 4;
+					} else {
+						if (aChar < 252) {
+							index += 5;
+						} else {
+							if (aChar >= 252) {
+								index += 6;
+							}
+						}
+					}
+				}
+			}
+		}
+		sqCount += 1;
+	}
+	return sqCount;
+}
+
+
+/*	stroke depending on canvasOop's stroke flag */
+
+static void strokefrom(cairo_t*context, sqInt canvasOop) {
+	sqInt stroke;
+	sqInt canvasFlags;
+	sqInt rgb;
+
+	canvasFlags = interpreterProxy->fetchIntegerofObject(CanvasFlagsIndex, canvasOop);
+	if (interpreterProxy->failed()) {
+		fail("canvas flags not an integer");
+	} else {
+		stroke = canvasFlags & CanvasFlagStroke;
+		if (stroke != 0) {
+			rgb = interpreterProxy->fetchIntegerofObject(CanvasStrokeColorIndex, canvasOop);
+			cairo_save(context);
+			setSourcergbalpha(context, rgb, stroke);
+			cairo_stroke(context);
+			cairo_restore(context);
+		}
+	}
+}
+
+
+/*	answer a surface by looking up its surface plugin ID stored as bits in formOop */
+
+static cairo_surface_t* surfaceFrom(sqInt formOop) {
+	sqInt surfaceID;
+
+	if ((interpreterProxy->slotSizeOf(formOop)) < FormInstSize) {
+		fail("form oop invalid");
+		return null;
+	}
+	surfaceID = interpreterProxy->fetchIntegerofObject(FormBitsIndex, formOop);
+	if (interpreterProxy->failed()) {
+		fail("form handle not an integer");
+		return null;
+	}
+	return findSurface(surfaceID);
+}
+
+static sqInt translateSqAttrsToPangoAttrsinto(sqInt sqAttrsArrayOop, PangoAttrList *pangoAttrList) {
+	sqInt ind;
+	sqInt symbolOop;
+	sqInt *sqAttrsArray;
+	char *symbol;
+	sqInt sqAttrsSize;
+	sqInt attrArray;
+
+	sqAttrsSize = interpreterProxy->stSizeOf(sqAttrsArrayOop);
+	sqAttrsArray = interpreterProxy->firstIndexableField(sqAttrsArrayOop);
+	addDefaultInto(pangoAttrList);
+	for (ind = 0; ind <= (sqAttrsSize - 1); ind += 1) {
+		attrArray = sqAttrsArray[ind];
+		symbolOop = interpreterProxy->fetchPointerofObject(0, attrArray);
+		symbol = interpreterProxy->firstIndexableField(symbolOop);
+		if ((symbol[0]) == 65) {
+			addAlignmentinto(attrArray, pangoAttrList);
+		}
+		if ((symbol[0]) == 67) {
+			addColorinto(attrArray, pangoAttrList);
+		}
+		if ((symbol[0]) == 69) {
+			addEmphasisinto(attrArray, pangoAttrList);
+		}
+		if ((symbol[0]) == 70) {
+			addFontinto(attrArray, pangoAttrList);
+		}
+		if ((symbol[0]) == 76) {
+			addLanguageinto(attrArray, pangoAttrList);
+		}
+	}
+	return 1;
+}
+
+static sqInt unlockSurfacexywh(cairo_surface_t*surfaceHandle, sqInt x, sqInt y, sqInt w, sqInt h) {
+	/* missing DebugCode */;
+	if ((w > 0) && (h > 0)) {
+		cairo_surface_mark_dirty_rectangle(surfaceHandle, x, y, w, h);
+	}
+	return 1;
+}
+
+
+/*	Unregister the surface, answer true if successful */
+
+static sqInt unregisterSurface(sqInt surfaceID) {
+	if (unregisterSurfaceFn == null) {
+		if (!(loadSurfacePlugin())) {
+			return 0;
+		}
+	}
+	/* missing DebugCode */;
+	if (!((*unregisterSurfaceFn)(surfaceID))) {
+		failwith("could not unregister surface %i", surfaceID);
+		return 0;
+	}
+	return 1;
+}
+
+static sqInt utf8CountFor(unsigned int value) {
+	sqInt v;
+
+	v = value & 2097151;
+	if ((0 <= v) && (v <= 127)) {
+		return 1;
+	}
+	if ((128 <= v) && (v <= 2047)) {
+		return 2;
+	}
+	if ((2048 <= v) && (v <= 55295)) {
+		return 3;
+	}
+	if ((57344 <= v) && (v <= 65535)) {
+		return 3;
+	}
+	if ((65536 <= v) && (v <= 1114111)) {
+		return 4;
+	}
+	return 0;
+}
+
+
+#ifdef SQUEAK_BUILTIN_PLUGIN
+
+
+void* RomePlugin_exports[][3] = {
+	{"RomePlugin", "primitivePangoBlockAtIndex", (void*)primitivePangoBlockAtIndex},
+	{"RomePlugin", "primitiveDrawImageSrcLRTBDestLRTB", (void*)primitiveDrawImageSrcLRTBDestLRTB},
+	{"RomePlugin", "primitiveDrawGeneralBezierShape", (void*)primitiveDrawGeneralBezierShape},
+	{"RomePlugin", "initialiseModule", (void*)initialiseModule},
+	{"RomePlugin", "primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops", (void*)primitiveFillRadialOriginXYdirectionXYnormalXYcolorStops},
+	{"RomePlugin", "primitiveFillColorAlpha", (void*)primitiveFillColorAlpha},
+	{"RomePlugin", "primitiveFillLinearOriginXYdirectionXYcolorStops", (void*)primitiveFillLinearOriginXYdirectionXYcolorStops},
+	{"RomePlugin", "primitiveDestroyFormHandle", (void*)primitiveDestroyFormHandle},
+	{"RomePlugin", "primitiveClear", (void*)primitiveClear},
+	{"RomePlugin", "primitiveTransformBy", (void*)primitiveTransformBy},
+	{"RomePlugin", "primitiveDrawOvalLeftRightTopBottom", (void*)primitiveDrawOvalLeftRightTopBottom},
+	{"RomePlugin", "primitiveDrawPolygon", (void*)primitiveDrawPolygon},
+	{"RomePlugin", "primitivePluginVersion", (void*)primitivePluginVersion},
+	{"RomePlugin", "primitiveShowZeroTerminatedUtf8StringXY", (void*)primitiveShowZeroTerminatedUtf8StringXY},
+	{"RomePlugin", "primitiveFontFace", (void*)primitiveFontFace},
+	{"RomePlugin", "primitiveClipRectangleLeftRightTopBottom", (void*)primitiveClipRectangleLeftRightTopBottom},
+	{"RomePlugin", "getModuleName", (void*)getModuleName},
+	{"RomePlugin", "primitiveFontSize", (void*)primitiveFontSize},
+	{"RomePlugin", "primitivePangoIndexAtPoint", (void*)primitivePangoIndexAtPoint},
+	{"RomePlugin", "primitiveDrawPolyline", (void*)primitiveDrawPolyline},
+	{"RomePlugin", "primitiveDrawCurveFromXYviaXYandXYtoXY", (void*)primitiveDrawCurveFromXYviaXYandXYtoXY},
+	{"RomePlugin", "primitiveRotateBy", (void*)primitiveRotateBy},
+	{"RomePlugin", "primitiveDrawRoundRectLeftRightTopBottomRadiusCorner", (void*)primitiveDrawRoundRectLeftRightTopBottomRadiusCorner},
+	{"RomePlugin", "moduleUnloaded", (void*)moduleUnloaded},
+	{"RomePlugin", "primitiveDrawLineFromXYtoXY", (void*)primitiveDrawLineFromXYtoXY},
+	{"RomePlugin", "primitivePangoShowString", (void*)primitivePangoShowString},
+	{"RomePlugin", "primitiveDrawArcRadiusXYFromTo", (void*)primitiveDrawArcRadiusXYFromTo},
+	{"RomePlugin", "primitiveDrawZeroTerminatedUtf8StringXY", (void*)primitiveDrawZeroTerminatedUtf8StringXY},
+	{"RomePlugin", "primitiveSetLineWidth", (void*)primitiveSetLineWidth},
+	{"RomePlugin", "primitivePangoComposeString", (void*)primitivePangoComposeString},
+	{"RomePlugin", "primitiveUTF8StringWithIndex", (void*)primitiveUTF8StringWithIndex},
+	{"RomePlugin", "primitiveStencilImageSrcLRTBDestLRTB", (void*)primitiveStencilImageSrcLRTBDestLRTB},
+	{"RomePlugin", "setInterpreter", (void*)setInterpreter},
+	{"RomePlugin", "primitiveRestoreState", (void*)primitiveRestoreState},
+	{"RomePlugin", "primitiveScaleBy", (void*)primitiveScaleBy},
+	{"RomePlugin", "primitivePangoComposeString2", (void*)primitivePangoComposeString2},
+	{"RomePlugin", "primitiveDrawRectangleLeftRightTopBottom", (void*)primitiveDrawRectangleLeftRightTopBottom},
+	{"RomePlugin", "primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage", (void*)primitiveFillBitmapOriginXYdirectionXYnormalXYRepeatImage},
+	{"RomePlugin", "primitiveSetTransform", (void*)primitiveSetTransform},
+	{"RomePlugin", "primitiveSaveState", (void*)primitiveSaveState},
+	{"RomePlugin", "primitiveLanguageAttributes", (void*)primitiveLanguageAttributes},
+	{"RomePlugin", "primitiveGetTransform", (void*)primitiveGetTransform},
+	{"RomePlugin", "primitivePangoFontDescriptionIndex", (void*)primitivePangoFontDescriptionIndex},
+	{"RomePlugin", "primitiveUTF8StringWith2Indexes", (void*)primitiveUTF8StringWith2Indexes},
+	{"RomePlugin", "primitiveCreateFormHandle", (void*)primitiveCreateFormHandle},
+	{"RomePlugin", "primitivePangoIsAvailable", (void*)primitivePangoIsAvailable},
+	{"RomePlugin", "primitiveClose", (void*)primitiveClose},
+	{"RomePlugin", "primitiveOpen", (void*)primitiveOpen},
+	{"RomePlugin", "primitiveDrawCurveFromXYviaXYtoXY", (void*)primitiveDrawCurveFromXYviaXYtoXY},
+	{"RomePlugin", "primitiveGetLineWidth", (void*)primitiveGetLineWidth},
+	{"RomePlugin", "shutdownModule", (void*)shutdownModule},
+	{"RomePlugin", "primitiveTranslateBy", (void*)primitiveTranslateBy},
+	{NULL, NULL, NULL}
+};
+
+
+#endif /* ifdef SQ_BUILTIN_PLUGIN */
+
Added: trunk/platforms/unix/src/plugins/Squeak3D/Squeak3D.c
===================================================================
--- trunk/platforms/unix/src/plugins/Squeak3D/Squeak3D.c	                        (rev 0)
+++ trunk/platforms/unix/src/plugins/Squeak3D/Squeak3D.c	2011-01-23 09:41:21 UTC (rev 2355)
@@ -0,0 +1,3087 @@
+/* Automatically generated from Squeak on 23 January 2011 6:34:03 pm 
+   by VMMaker 4.4.7
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Default EXPORT macro that does nothing (see comment in sq.h): */
+#define EXPORT(returnType) returnType
+
+/* Do not include the entire sq.h file but just those parts needed. */
+/*  The virtual machine proxy definition */
+#include "sqVirtualMachine.h"
+/* Configuration options */
+#include "sqConfig.h"
+/* Platform specific definitions */
+#include "sqPlatformSpecific.h"
+
+#define true 1
+#define false 0
+#define null 0  /* using 'null' because nil is predefined in Think C */
+#ifdef SQUEAK_BUILTIN_PLUGIN
+#undef EXPORT
+// was #undef EXPORT(returnType) but screws NorCroft cc
+#define EXPORT(returnType) static returnType
+#endif
+#include "b3d.h"
+#include "b3d.h"
+
+#include "sqMemoryAccess.h"
+
+
+/*** Constants ***/
+#define AmbientPart 0
+#define DiffusePart 4
+#define EmissionAlpha 15
+#define EmissionBlue 14
+#define EmissionGreen 13
+#define EmissionRed 12
+#define FlagAmbientPart 256
+#define FlagAttenuated 4
+#define FlagDiffusePart 512
+#define FlagDirectional 2
+#define FlagHasSpot 8
+#define FlagM44Identity 1
+#define FlagM44NoPerspective 2
+#define FlagM44NoTranslation 4
+#define FlagPositional 1
+#define FlagSpecularPart 1024
+#define InAllMask 1365
+#define InBackBit 1024
+#define InBottomBit 64
+#define InFrontBit 256
+#define InLeftBit 1
+#define InRightBit 4
+#define InTopBit 16
+#define MaterialShininess 16
+#define MaterialSize 17
+#define OutAllMask 2730
+#define OutBackBit 2048
+#define OutBottomBit 128
+#define OutFrontBit 512
+#define OutLeftBit 2
+#define OutRightBit 8
+#define OutTopBit 32
+#define PrimLightAttenuationConstant 18
+#define PrimLightAttenuationLinear 19
+#define PrimLightAttenuationSquared 20
+#define PrimLightDirection 15
+#define PrimLightDirectionX 15
+#define PrimLightDirectionY 16
+#define PrimLightDirectionZ 17
+#define PrimLightFlags 21
+#define PrimLightPositionX 12
+#define PrimLightPositionY 13
+#define PrimLightPositionZ 14
+#define PrimLightSize 32
+#define PrimTypeMax 6
+#define PrimVertexSize 16
+#define PrimVtxClipFlags 13
+#define PrimVtxColor32 12
+#define PrimVtxNormal 3
+#define PrimVtxNormalX 3
+#define PrimVtxNormalY 4
+#define PrimVtxNormalZ 5
+#define PrimVtxPosition 0
+#define PrimVtxPositionX 0
+#define PrimVtxPositionY 1
+#define PrimVtxPositionZ 2
+#define PrimVtxRasterPosW 11
+#define PrimVtxRasterPosX 8
+#define PrimVtxRasterPosY 9
+#define PrimVtxRasterPosZ 10
+#define PrimVtxTexCoordU 6
+#define PrimVtxTexCoordV 7
+#define PrimVtxTexCoords 6
+#define SpecularPart 8
+#define SpotLightDeltaCos 24
+#define SpotLightExponent 25
+#define SpotLightMinCos 22
+#define VBTrackAmbient 1
+#define VBTrackDiffuse 2
+#define VBTrackEmission 8
+#define VBTrackSpecular 4
+#define VBTwoSidedLighting 64
+#define VBUseLocalViewer 128
+#define VBVtxHasNormals 16
+
+/*** Function Prototypes ***/
+static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale);
+static sqInt analyzeMatrix3x3Length(float *m);
+static sqInt analyzeMatrix(float *m);
+#pragma export on
+EXPORT(sqInt) b3dClipPolygon(void);
+EXPORT(sqInt) b3dComputeMinIndexZ(void);
+EXPORT(sqInt) b3dComputeMinZ(void);
+EXPORT(sqInt) b3dDetermineClipFlags(void);
+EXPORT(sqInt) b3dInitPrimitiveObject(void);
+EXPORT(sqInt) b3dInitializeRasterizerState(void);
+EXPORT(sqInt) b3dInplaceHouseHolderInvert(void);
+EXPORT(sqInt) b3dLoadIndexArray(void);
+EXPORT(sqInt) b3dLoadVertexBuffer(void);
+EXPORT(sqInt) b3dMapVertexBuffer(void);
+EXPORT(sqInt) b3dOrthoNormInverseMatrix(void);
+EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void);
+EXPORT(sqInt) b3dPrimitiveObjectSize(void);
+EXPORT(sqInt) b3dPrimitiveTextureSize(void);
+EXPORT(sqInt) b3dRasterizerVersion(void);
+EXPORT(sqInt) b3dShadeVertexBuffer(void);
+EXPORT(sqInt) b3dShaderVersion(void);
+EXPORT(sqInt) b3dStartRasterizer(void);
+EXPORT(sqInt) b3dTransformDirection(void);
+EXPORT(sqInt) b3dTransformMatrixWithInto(void);
+EXPORT(sqInt) b3dTransformPoint(void);
+EXPORT(sqInt) b3dTransformPrimitiveNormal(void);
+EXPORT(sqInt) b3dTransformPrimitivePosition(void);
+EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void);
+EXPORT(sqInt) b3dTransformVertexBuffer(void);
+EXPORT(sqInt) b3dTransformerVersion(void);
+EXPORT(sqInt) b3dTransposeMatrix(void);
+#pragma export off
+static double backClipValueFromto(sqInt last, sqInt next);
+static double bottomClipValueFromto(sqInt last, sqInt next);
+static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask);
+static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n);
+static sqInt computeAttenuation(void);
+static sqInt computeDirection(void);
+static sqInt computeSpecularDirection(void);
+static double computeSpotFactor(void);
+static sqInt determineClipFlagscount(void *vtxArray, sqInt count);
+static double dotProductOfFloatwithDouble(float * v1, double *v2);
+static void* fetchLightSourceofObject(sqInt index, sqInt anArray);
+static double frontClipValueFromto(sqInt last, sqInt next);
+static VirtualMachine * getInterpreter(void);
+#pragma export on
+EXPORT(const char*) getModuleName(void);
+#pragma export off
+static sqInt halt(void);
+#pragma export on
+EXPORT(sqInt) initialiseModule(void);
+#pragma export off
+static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out);
+static double inverseLengthOfDouble(double * aVector);
+static double inverseLengthOfFloat(float * aVector);
+static double leftClipValueFromto(sqInt last, sqInt next);
+static sqInt loadObjectsFrom(sqInt stackIndex);
+static sqInt loadPrimitiveLightSource(void);
+static sqInt loadPrimitiveVertex(void);
+static sqInt loadRasterizerState(sqInt stackIndex);
+static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr);
+static sqInt loadTexturesFrom(sqInt stackIndex);
+static sqInt loadViewportFrom(sqInt stackIndex);
+static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray);
+#pragma export on
+EXPORT(sqInt) moduleUnloaded(char *aModuleName);
+#pragma export off
+static sqInt msg(char *s);
+#pragma export on
+EXPORT(sqInt) primitiveSetBitBltPlugin(void);
+#pragma export off
+static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize);
+static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize);
+static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize);
+static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize);
+static double rightClipValueFromto(sqInt last, sqInt next);
+#pragma export on
+EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
+#pragma export off
+static sqInt shadeVertex(void);
+static sqInt stackLightArrayValue(sqInt stackIndex);
+static void * stackMaterialValue(sqInt stackIndex);
+static void* stackMatrix(sqInt index);
+static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex);
+static void* stackPrimitiveVertex(sqInt index);
+static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems);
+static sqInt storeObjectsInto(sqInt stackIndex);
+static sqInt storePrimitiveVertex(void);
+static double topClipValueFromto(sqInt last, sqInt next);
+static sqInt transformMatrixwithinto(float *src, float *arg, float *dst);
+static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale);
+static sqInt transformPrimitivePositionby(float *pVertex, float *matrix);
+static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix);
+static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix);
+static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix);
+static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags);
+static void* vbLoadArraysize(sqInt oop, sqInt count);
+/*** Variables ***/
+static char bbPluginName[256] = "BitBltPlugin";
+static sqInt copyBitsFn;
+
+#ifdef SQUEAK_BUILTIN_PLUGIN
+extern
+#endif
+struct VirtualMachine* interpreterProxy;
+static double l2vDirection[3];
+static double l2vDistance;
+static double l2vSpecDir[3];
+static sqInt lightFlags;
+static double lightScale;
+static float* litVertex;
+static sqInt loadBBFn;
+static const char *moduleName =
+#ifdef SQUEAK_BUILTIN_PLUGIN
+	"Squeak3D 23 January 2011 (i)"
+#else
+	"Squeak3D 23 January 2011 (e)"
+#endif
+;
+static float* primLight;
+static float* primMaterial;
+static B3DRasterizerState state;
+static sqInt vbFlags;
+static B3DPrimitiveViewport viewport;
+static double vtxInColor[4];
+static double vtxOutColor[4];
+
+
+
+/*	Add the given light part to the output color, scaled by the given scale factor.
+	If the given flag is set in vbFlags then load the part from the primitive vertex */
+
+static sqInt addPartfromtrackFlagscale(float *lightPart, float *materialPart, sqInt vbTrackFlag, double scale) {
+    double aPart;
+    double bPart;
+    double gPart;
+    double rPart;
+
+	if (vbFlags & vbTrackFlag) {
+		rPart = ((vtxInColor[0]) * (lightPart[0])) * scale;
+		gPart = ((vtxInColor[1]) * (lightPart[1])) * scale;
+		bPart = ((vtxInColor[2]) * (lightPart[2])) * scale;
+		aPart = ((vtxInColor[3]) * (lightPart[3])) * scale;
+	} else {
+
+		/* Note: This should be pre-computed. */
+
+		rPart = ((materialPart[0]) * (lightPart[0])) * scale;
+		gPart = ((materialPart[1]) * (lightPart[1])) * scale;
+		bPart = ((materialPart[2]) * (lightPart[2])) * scale;
+		aPart = ((materialPart[3]) * (lightPart[3])) * scale;
+	}
+	vtxOutColor[0] = ((vtxOutColor[0]) + rPart);
+	vtxOutColor[1] = ((vtxOutColor[1]) + gPart);
+	vtxOutColor[2] = ((vtxOutColor[2]) + bPart);
+	vtxOutColor[3] = ((vtxOutColor[3]) + aPart);
+}
+
+
+/*	Check if the matrix scales normals to non-unit length. */
+
+static sqInt analyzeMatrix3x3Length(float *m) {
+    double det;
+
+	det = (((((((m[0]) * (m[5])) * (m[10])) - (((m[2]) * (m[5])) * (m[8]))) + (((m[4]) * (m[9])) * (m[2]))) - (((m[6]) * (m[9])) * (m[0]))) + (((m[8]) * (m[1])) * (m[6]))) - (((m[10]) * (m[1])) * (m[4]));
+	return (det < 0.99) || (det > 1.01);
+}
+
+
+/*	Analyze the matrix and return the appropriate flags */
+
+static sqInt analyzeMatrix(float *m) {
+    sqInt flags;
+
+	flags = 0;
+	if (((m[12]) == 0.0) && (((m[13]) == 0.0) && (((m[14]) == 0.0) && ((m[15]) == 1.0)))) {
+
+		/* Check translation */
+
+		flags = flags | FlagM44NoPerspective;
+		if (((m[3]) == 0.0) && (((m[7]) == 0.0) && ((m[11]) == 0.0))) {
+
+			/* Check for identity */
+
+			flags = flags | FlagM44NoTranslation;
+			if (((m[0]) == 1.0) && (((m[5]) == 1.0) && (((m[10]) == 1.0) && (((m[1]) == 0.0) && (((m[2]) == 0.0) && (((m[4]) == 0.0) && (((m[6]) == 0.0) && (((m[8]) == 0.0) && ((m[9]) == 0.0))))))))) {
+				flags = flags | FlagM44Identity;
+			}
+		}
+	}
+	return flags;
+}
+
+
+/*	Primitive. Clip the polygon given in the vertexArray using the temporary vertex array which is assumed to have sufficient size. */
+
+EXPORT(sqInt) b3dClipPolygon(void) {
+    sqInt count;
+    sqInt outMask;
+    int *tempVtxArray;
+    int *vtxArray;
+    sqInt vtxCount;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 4)) {
+		return interpreterProxy->primitiveFail();
+	}
+	outMask = interpreterProxy->stackIntegerValue(0);
+	vtxCount = interpreterProxy->stackIntegerValue(2);
+	vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount + 4);
+	tempVtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount + 4);
+	if ((vtxArray == null) || ((tempVtxArray == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	vtxArray -= PrimVertexSize;
+	tempVtxArray -= PrimVertexSize;
+	count = clipPolygoncountwithmask(vtxArray, vtxCount, tempVtxArray, outMask);
+	interpreterProxy->pop(5);
+	interpreterProxy->pushInteger(count);
+}
+
+
+/*	Primitive. Compute and return the index for the minimal z value of all objects in the vertex buffer. */
+
+EXPORT(sqInt) b3dComputeMinIndexZ(void) {
+    int *idxArray;
+    sqInt idxSize;
+    sqInt minIndex;
+    sqInt primType;
+    float *vtxArray;
+    sqInt vtxSize;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 5)) {
+		return interpreterProxy->primitiveFail();
+	}
+	idxSize = interpreterProxy->stackIntegerValue(0);
+	vtxSize = interpreterProxy->stackIntegerValue(2);
+	primType = interpreterProxy->stackIntegerValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize);
+	idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize);
+	if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if ((primType < 1) || (primType > 6)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (primType <= 3) {
+		minIndex = processNonIndexedIDXofSize(vtxArray, vtxSize);
+	} else {
+		minIndex = processIndexedIDXofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize);
+	}
+	if (!(interpreterProxy->failed())) {
+		interpreterProxy->pop(6);
+		interpreterProxy->pushInteger(minIndex);
+	}
+}
+
+
+/*	Primitive. Compute and return the minimal z value of all objects in the vertex buffer. */
+
+EXPORT(sqInt) b3dComputeMinZ(void) {
+    int *idxArray;
+    sqInt idxSize;
+    double minZ;
+    sqInt primType;
+    float *vtxArray;
+    sqInt vtxSize;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 5)) {
+		return interpreterProxy->primitiveFail();
+	}
+	idxSize = interpreterProxy->stackIntegerValue(0);
+	vtxSize = interpreterProxy->stackIntegerValue(2);
+	primType = interpreterProxy->stackIntegerValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxArray = stackPrimitiveVertexArrayofSize(3, vtxSize);
+	idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxSize, 1, vtxSize);
+	if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if ((primType < 1) || (primType > 6)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (primType <= 3) {
+		minZ = processNonIndexedofSize(vtxArray, vtxSize);
+	} else {
+		minZ = processIndexedofSizeidxArrayidxSize(vtxArray, vtxSize, idxArray, idxSize);
+	}
+	if (!(interpreterProxy->failed())) {
+		interpreterProxy->pop(6);
+		interpreterProxy->pushFloat(minZ);
+	}
+}
+
+
+/*	Primitive. Determine the clipping flags for all vertices. */
+
+EXPORT(sqInt) b3dDetermineClipFlags(void) {
+    sqInt result;
+    void *vtxArray;
+    sqInt vtxCount;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 2)) {
+		return interpreterProxy->primitiveFail();
+	}
+	vtxCount = interpreterProxy->stackIntegerValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxArray = stackPrimitiveVertexArrayofSize(1, vtxCount);
+	if ((vtxArray == null) || (interpreterProxy->failed())) {
+		return interpreterProxy->primitiveFail();
+	}
+	result = determineClipFlagscount(vtxArray, vtxCount);
+	if (!(interpreterProxy->failed())) {
+		interpreterProxy->pop(3);
+		interpreterProxy->pushInteger(result);
+	}
+}
+
+EXPORT(sqInt) b3dInitPrimitiveObject(void) {
+    int *idxArray;
+    sqInt idxSize;
+    void *primObj;
+    sqInt primOop;
+    sqInt primSize;
+    sqInt primitive;
+    sqInt textureIndex;
+    int *vtxArray;
+    sqInt vtxSize;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 8)) {
+		return interpreterProxy->primitiveFail();
+	}
+	textureIndex = interpreterProxy->stackIntegerValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	loadViewportFrom(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxSize = interpreterProxy->stackIntegerValue(4);
+	vtxArray = stackPrimitiveVertexArrayofSize(5, vtxSize);
+	if (vtxArray == null) {
+		return interpreterProxy->primitiveFail();
+	}
+	idxSize = interpreterProxy->stackIntegerValue(2);
+	idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(3, idxSize, 1, vtxSize);
+	if (idxArray == null) {
+		return interpreterProxy->primitiveFail();
+	}
+	primitive = interpreterProxy->stackIntegerValue(6);
+	if ((primitive < 1) || (primitive > PrimTypeMax)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (!((primitive == 3) || ((primitive == 5) || (primitive == 6)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	primOop = interpreterProxy->stackObjectValue(7);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!(interpreterProxy->isWords(primOop))) {
+		return interpreterProxy->primitiveFail();
+	}
+	primObj = interpreterProxy->firstIndexableField(primOop);
+
+	/* Do the work */
+
+	primSize = interpreterProxy->byteSizeOf(primOop);
+	if (primitive == 3) {
+		if (b3dAddPolygonObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, &viewport) != B3D_NO_ERROR) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	if (primitive == 5) {
+		if (b3dAddIndexedTriangleObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputFace*) idxArray, idxSize / 3, &viewport) != B3D_NO_ERROR) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	if (primitive == 6) {
+		if (b3dAddIndexedQuadObject((void*) primObj, primSize, B3D_FACE_RGB, textureIndex, (B3DPrimitiveVertex*) vtxArray, vtxSize, (B3DInputQuad*) idxArray, idxSize / 4, &viewport) != B3D_NO_ERROR) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	interpreterProxy->pop(9);
+	interpreterProxy->push(primOop);
+}
+
+
+/*	Primitive. Initialize the primitive level objects of the given rasterizer. */
+
+EXPORT(sqInt) b3dInitializeRasterizerState(void) {
+    void *obj;
+    sqInt objLen;
+    sqInt objOop;
+    sqInt stateOop;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 0)) {
+		return interpreterProxy->primitiveFail();
+	}
+	stateOop = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 7))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(0, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeFaceAllocator(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(1, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeEdgeAllocator(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(2, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeAttrAllocator(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(3, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeAET(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(4, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeEdgeList(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+	objOop = interpreterProxy->fetchPointerofObject(5, stateOop);
+	if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+		return interpreterProxy->primitiveFail();
+	}
+	objLen = interpreterProxy->byteSizeOf(objOop);
+	obj = interpreterProxy->firstIndexableField(objOop);
+	if (b3dInitializeFillList(obj, objLen) != B3D_NO_ERROR) {
+		return interpreterProxy->primitiveFail();
+	}
+}
+
+
+/*	Primitive. Perform an inplace house holder matrix inversion */
+
+EXPORT(sqInt) b3dInplaceHouseHolderInvert(void) {
+    double beta;
+    double d[4][4];
+    sqInt i;
+    sqInt j;
+    sqInt k;
+    double m[4][4];
+    sqInt r;
+    float *rcvr;
+    double s;
+    double sigma;
+    double sum;
+    double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} };
+
+	;
+	rcvr = stackMatrix(0);
+	for (i = 0; i <= 3; i += 1) {
+		for (j = 0; j <= 3; j += 1) {
+			(m[i])[j] = (rcvr[(i * 4) + j]);
+		}
+	}
+	for (j = 0; j <= 3; j += 1) {
+		sigma = 0.0;
+		for (i = j; i <= 3; i += 1) {
+			sigma += ((m[i])[j]) * ((m[i])[j]);
+		}
+		if (sigma < 1.0e-10) {
+			return interpreterProxy->primitiveFail();
+		}
+		if (((m[j])[j]) < 0.0) {
+			s = sqrt(sigma);
+		} else {
+			s = 0.0 - (sqrt(sigma));
+		}
+		for (r = 0; r <= 3; r += 1) {
+			(d[j])[r] = s;
+		}
+		beta = 1.0 / ((s * ((m[j])[j])) - sigma);
+		(m[j])[j] = (((m[j])[j]) - s);
+		for (k = (j + 1); k <= 3; k += 1) {
+			sum = 0.0;
+			for (i = j; i <= 3; i += 1) {
+				sum += ((m[i])[j]) * ((m[i])[k]);
+			}
+			sum = sum * beta;
+			for (i = j; i <= 3; i += 1) {
+				(m[i])[k] = (((m[i])[k]) + (((m[i])[j]) * sum));
+			}
+		}
+		for (r = 0; r <= 3; r += 1) {
+			sum = 0.0;
+			for (i = j; i <= 3; i += 1) {
+				sum += ((x[i])[r]) * ((m[i])[j]);
+			}
+			sum = sum * beta;
+			for (i = j; i <= 3; i += 1) {
+				(x[i])[r] = (((x[i])[r]) + (sum * ((m[i])[j])));
+			}
+		}
+	}
+	for (r = 0; r <= 3; r += 1) {
+		for (i = 3; i >= 0; i += -1) {
+			for (j = (i + 1); j <= 3; j += 1) {
+				(x[i])[r] = (((x[i])[r]) - (((x[j])[r]) * ((m[i])[j])));
+			}
+			(x[i])[r] = (((x[i])[r]) / ((d[i])[r]));
+		}
+	}
+	for (i = 0; i <= 3; i += 1) {
+		for (j = 0; j <= 3; j += 1) {
+			rcvr[(i * 4) + j] = (((float) ((x[i])[j])));
+		}
+	}
+}
+
+
+/*	Primitive. Load the given index array into the receiver.
+	NOTE: dstStart is a zero-based index. */
+
+EXPORT(sqInt) b3dLoadIndexArray(void) {
+    sqInt count;
+    sqInt dstArray;
+    int *dstPtr;
+    sqInt dstSize;
+    sqInt dstStart;
+    sqInt i;
+    sqInt idx;
+    sqInt maxValue;
+    sqInt srcArray;
+    int *srcPtr;
+    sqInt vtxOffset;
+
+	vtxOffset = interpreterProxy->stackIntegerValue(0);
+	maxValue = interpreterProxy->stackIntegerValue(1);
+	count = interpreterProxy->stackIntegerValue(2);
+	srcArray = interpreterProxy->stackObjectValue(3);
+	dstStart = interpreterProxy->stackIntegerValue(4);
+	dstArray = interpreterProxy->stackObjectValue(5);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!(interpreterProxy->isWords(srcArray))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if ((interpreterProxy->slotSizeOf(srcArray)) < count) {
+		return interpreterProxy->primitiveFail();
+	}
+
+	/* Check dstArray */
+
+	srcPtr = ((int*) (interpreterProxy->firstIndexableField(srcArray)));
+
+	/* Check if there is enough room left in dstArray */
+
+	dstSize = interpreterProxy->slotSizeOf(dstArray);
+	if ((dstStart + count) > dstSize) {
+		return interpreterProxy->primitiveFail();
+	}
+
+	/* Do the actual work */
+
+	dstPtr = ((int *) (interpreterProxy->firstIndexableField(dstArray)));
+	for (i = 0; i <= (count - 1); i += 1) {
+		idx = srcPtr[i];
+		if ((idx < 1) || (idx > maxValue)) {
+			return interpreterProxy->primitiveFail();
+		}
+		dstPtr[dstStart + i] = (idx + vtxOffset);
+	}
+	interpreterProxy->pop(7);
+	interpreterProxy->pushInteger(count);
+}
+
+
+/*	Primitive. Load the data into the given vertex buffer.
+	NOTE: dstStart is a zero-based index. */
+
+EXPORT(sqInt) b3dLoadVertexBuffer(void) {
+    int *colorPtr;
+    sqInt count;
+    int *defaultColor;
+    int *defaultNormal;
+    int *defaultTexCoords;
+    int *defaultVtx;
+    int *dstPtr;
+    sqInt dstStart;
+    sqInt i;
+    int *normalPtr;
+    int *pVtx;
+    int *texPtr;
+    int *vtxPtr;
+
+	defaultVtx = stackPrimitiveVertex(0);
+	count = interpreterProxy->stackIntegerValue(1);
+	texPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(2), 2 * count);
+	colorPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(3), count);
+	normalPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(4), 3 * count);
+	vtxPtr = vbLoadArraysize(interpreterProxy->stackObjectValue(5), 3 * count);
+	dstStart = interpreterProxy->stackIntegerValue(6);
+
+	/* Check for all problems above */
+
+	dstPtr = stackPrimitiveVertexArrayofSize(7, dstStart + count);
+	if ((dstPtr == null) || ((defaultVtx == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (normalPtr == null) {
+		defaultNormal = defaultVtx + PrimVtxNormal;
+	} else {
+		defaultNormal = normalPtr;
+	}
+	if (texPtr == null) {
+		defaultTexCoords = defaultVtx + PrimVtxTexCoords;
+	} else {
+		defaultTexCoords = texPtr;
+	}
+	if (colorPtr == null) {
+		defaultColor = defaultVtx + PrimVtxColor32;
+	} else {
+		defaultColor = colorPtr;
+	}
+	pVtx = dstPtr + (dstStart * PrimVertexSize);
+	for (i = 0; i <= (count - 1); i += 1) {
+		pVtx[PrimVtxPositionX] = (vtxPtr[0]);
+		pVtx[PrimVtxPositionY] = (vtxPtr[1]);
+		pVtx[PrimVtxPositionZ] = (vtxPtr[2]);
+		pVtx[PrimVtxNormalX] = (defaultNormal[0]);
+		pVtx[PrimVtxNormalY] = (defaultNormal[1]);
+		pVtx[PrimVtxNormalZ] = (defaultNormal[2]);
+		pVtx[PrimVtxColor32] = (defaultColor[0]);
+		pVtx[PrimVtxTexCoordU] = (defaultTexCoords[0]);
+		pVtx[PrimVtxTexCoordV] = (defaultTexCoords[1]);
+		pVtx += PrimVertexSize;
+		vtxPtr += 3;
+		if (!(normalPtr == null)) {
+			defaultNormal += 3;
+		}
+		if (!(colorPtr == null)) {
+			defaultColor += 1;
+		}
+		if (!(texPtr == null)) {
+			defaultTexCoords += 2;
+		}
+	}
+	interpreterProxy->pop(9);
+	interpreterProxy->pushInteger(count);
+}
+
+
+/*	Primitive. Determine the bounds for all vertices in the vertex buffer. */
+
+EXPORT(sqInt) b3dMapVertexBuffer(void) {
+    sqInt boxArray;
+    void *vtxArray;
+    sqInt vtxCount;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 3)) {
+		return interpreterProxy->primitiveFail();
+	}
+	boxArray = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!(((interpreterProxy->fetchClassOf(boxArray)) == (interpreterProxy->classArray())) && ((interpreterProxy->slotSizeOf(boxArray)) == 4))) {
+		return interpreterProxy->primitiveFail();
+	}
+	vtxCount = interpreterProxy->stackIntegerValue(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxArray = stackPrimitiveVertexArrayofSize(2, vtxCount);
+	if ((vtxArray == null) || (interpreterProxy->failed())) {
+		return interpreterProxy->primitiveFail();
+	}
+	mapVBofSizeinto(vtxArray, vtxCount, boxArray);
+	if (!(interpreterProxy->failed())) {
+		interpreterProxy->pop(3);
+	}
+}
+
+EXPORT(sqInt) b3dOrthoNormInverseMatrix(void) {
+    float *dst;
+    sqInt dstOop;
+    double rx;
+    double ry;
+    double rz;
+    float *src;
+    sqInt srcOop;
+    double x;
+    double y;
+    double z;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 0)) {
+		return interpreterProxy->primitiveFail();
+	}
+	srcOop = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) {
+		return interpreterProxy->primitiveFail();
+	}
+
+	/* reload srcOop in case of GC */
+
+	dstOop = interpreterProxy->clone(srcOop);
+	srcOop = interpreterProxy->stackObjectValue(0);
+	src = interpreterProxy->firstIndexableField(srcOop);
+
+	/* Transpose upper 3x3 matrix */
+	/* dst at: 0 put: (src at: 0). */
+
+	dst = interpreterProxy->firstIndexableField(dstOop);
+	dst[1] = (src[4]);
+	dst[2] = (src[8]);
+	dst[4] = (src[1]);
+	dst[6] = (src[9]);
+	dst[8] = (src[2]);
+	dst[9] = (src[6]);
+	x = src[3];
+	y = src[7];
+	z = src[11];
+	rx = ((x * (dst[0])) + (y * (dst[1]))) + (z * (dst[2]));
+	ry = ((x * (dst[4])) + (y * (dst[5]))) + (z * (dst[6]));
+	rz = ((x * (dst[8])) + (y * (dst[9]))) + (z * (dst[10]));
+	dst[3] = (((float) (0.0 - rx)));
+	dst[7] = (((float) (0.0 - ry)));
+	dst[11] = (((float) (0.0 - rz)));
+	interpreterProxy->pop(1);
+	interpreterProxy->push(dstOop);
+}
+
+
+/*	Primitive. Return the next clipped triangle from the vertex buffer and return its index. */
+
+EXPORT(sqInt) b3dPrimitiveNextClippedTriangle(void) {
+    sqInt firstIndex;
+    sqInt i;
+    sqInt idx1;
+    sqInt idx2;
+    sqInt idx3;
+    int *idxArray;
+    sqInt idxCount;
+    sqInt triMask;
+    int *vtxArray;
+    sqInt vtxCount;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 5)) {
+		return interpreterProxy->primitiveFail();
+	}
+	idxCount = interpreterProxy->stackIntegerValue(0);
+	vtxCount = interpreterProxy->stackIntegerValue(2);
+	firstIndex = interpreterProxy->stackIntegerValue(4);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	vtxArray = stackPrimitiveVertexArrayofSize(3, vtxCount);
+	idxArray = stackPrimitiveIndexArrayofSizevalidateforVertexSize(1, idxCount, 1, vtxCount);
+	if ((vtxArray == null) || ((idxArray == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	idxArray -= 1;
+	vtxArray -= PrimVertexSize;
+	for (i = firstIndex; i <= idxCount; i += 3) {
+		idx1 = idxArray[i];
+		idx2 = idxArray[i + 1];
+		idx3 = idxArray[i + 2];
+		if (!((idx1 == 0) || ((idx2 == 0) || (idx3 == 0)))) {
+
+			/* Check if tri is completely inside */
+
+			triMask = (vtxArray[(idx1 * PrimVertexSize) + PrimVtxClipFlags]) & ((vtxArray[(idx2 * PrimVertexSize) + PrimVtxClipFlags]) & (vtxArray[(idx3 * PrimVertexSize) + PrimVtxClipFlags]));
+			if (!((InAllMask & triMask) == InAllMask)) {
+				if (triMask & OutAllMask) {
+					idxArray[i] = 0;
+					idxArray[i + 1] = 0;
+					idxArray[i + 2] = 0;
+				} else {
+					interpreterProxy->pop(6);
+					interpreterProxy->pushInteger(i);
+					return null;
+				}
+			}
+		}
+	}
+	interpreterProxy->pop(6);
+	interpreterProxy->pushInteger(0);
+}
+
+
+/*	Primitive. Return the minimal number of words needed for a primitive object. */
+
+EXPORT(sqInt) b3dPrimitiveObjectSize(void) {
+    sqInt objSize;
+
+	objSize = (((sqInt) (sizeof(B3DPrimitiveObject) + sizeof(B3DPrimitiveVertex)) >> 2)) + 1;
+	interpreterProxy->pop(1);
+	interpreterProxy->pushInteger(objSize);
+}
+
+
+/*	Primitive. Return the minimal number of words needed for a primitive object. */
+
+EXPORT(sqInt) b3dPrimitiveTextureSize(void) {
+    sqInt objSize;
+
+	objSize = (((sqInt) (sizeof(B3DTexture)) >> 2)) + 1;
+	interpreterProxy->pop(1);
+	interpreterProxy->pushInteger(objSize);
+}
+
+
+/*	Primitive. Return the version of the rasterizer. */
+
+EXPORT(sqInt) b3dRasterizerVersion(void) {
+	interpreterProxy->pop(1);
+	interpreterProxy->pushInteger(1);
+}
+
+
+/*	Primitive. Shade all the vertices in the vertex buffer using the given array of primitive light sources. Return true on success. */
+
+EXPORT(sqInt) b3dShadeVertexBuffer(void) {
+    sqInt i;
+    sqInt j;
+    sqInt lightArray;
+    sqInt lightCount;
+    float *vtxArray;
+    sqInt vtxCount;
+    sqInt lightOop;
+    sqInt rgba;
+    sqInt a;
+    sqInt b;
+    sqInt g;
+    sqInt r;
+
+	vbFlags = interpreterProxy->stackIntegerValue(0);
+	primMaterial = stackMaterialValue(1);
+	lightArray = stackLightArrayValue(2);
+	vtxCount = interpreterProxy->stackIntegerValue(3);
+	vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount);
+	if ((vtxArray == null) || ((primMaterial == null) || (interpreterProxy->failed()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	litVertex = vtxArray;
+
+	/* Go over all vertices */
+
+	lightCount = interpreterProxy->slotSizeOf(lightArray);
+	for (i = 1; i <= vtxCount; i += 1) {
+		/* begin loadPrimitiveVertex */
+		rgba = (((int*) litVertex))[PrimVtxColor32];
+		vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0));
+		rgba = ((usqInt) rgba) >> 8;
+		vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0));
+		rgba = ((usqInt) rgba) >> 8;
+		vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0));
+		rgba = ((usqInt) rgba) >> 8;
+		vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0));
+		if (vbFlags & VBTrackEmission) {
+			vtxOutColor[0] = ((vtxInColor[0]) + (primMaterial[EmissionRed]));
+			vtxOutColor[1] = ((vtxInColor[1]) + (primMaterial[EmissionGreen]));
+			vtxOutColor[2] = ((vtxInColor[2]) + (primMaterial[EmissionBlue]));
+			vtxOutColor[3] = ((vtxInColor[3]) + (primMaterial[EmissionAlpha]));
+		} else {
+			vtxOutColor[0] = (primMaterial[EmissionRed]);
+			vtxOutColor[1] = (primMaterial[EmissionGreen]);
+			vtxOutColor[2] = (primMaterial[EmissionBlue]);
+			vtxOutColor[3] = (primMaterial[EmissionAlpha]);
+		}
+		for (j = 0; j <= (lightCount - 1); j += 1) {
+			/* begin fetchLightSource:ofObject: */
+			lightOop = interpreterProxy->fetchPointerofObject(j, lightArray);
+			primLight = interpreterProxy->firstIndexableField(lightOop);
+			/* begin loadPrimitiveLightSource */
+			lightFlags = (((int*) primLight))[PrimLightFlags];
+			shadeVertex();
+		}
+		/* begin storePrimitiveVertex */
+		r = ((sqInt)((vtxOutColor[0]) * 255));
+		r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255)));
+		g = ((sqInt)((vtxOutColor[1]) * 255));
+		g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255)));
+		b = ((sqInt)((vtxOutColor[2]) * 255));
+		b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255)));
+		a = ((sqInt)((vtxOutColor[3]) * 255));
+		a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255)));
+		(((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8));
+		litVertex += PrimVertexSize;
+	}
+	interpreterProxy->pop(6);
+	interpreterProxy->pushBool(1);
+}
+
+
+/*	Return the current shader version. */
+
+EXPORT(sqInt) b3dShaderVersion(void) {
+	interpreterProxy->pop(1);
+	interpreterProxy->pushInteger(1);
+}
+
+
+/*	Primitive. Start the rasterizer. */
+
+EXPORT(sqInt) b3dStartRasterizer(void) {
+    sqInt errCode;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 3)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (!(loadRasterizerState(2))) {
+		return interpreterProxy->primitiveFail();
+	}
+	loadTexturesFrom(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	loadObjectsFrom(1);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	errCode = b3dMainLoop(&state, B3D_NO_ERROR);
+	storeObjectsInto(1);
+	interpreterProxy->pop(4);
+	interpreterProxy->pushInteger(errCode);
+}
+
+EXPORT(sqInt) b3dTransformDirection(void) {
+    float *matrix;
+    double rx;
+    double ry;
+    double rz;
+    sqInt v3Oop;
+    float *vertex;
+    double x;
+    double y;
+    double z;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 1)) {
+		return interpreterProxy->primitiveFail();
+	}
+	v3Oop = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) {
+		return interpreterProxy->primitiveFail();
+	}
+	vertex = interpreterProxy->firstIndexableField(v3Oop);
+	matrix = stackMatrix(1);
+	if (matrix == null) {
+		return interpreterProxy->primitiveFail();
+	}
+	x = vertex[0];
+	y = vertex[1];
+	z = vertex[2];
+	rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]));
+	ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]));
+	rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]));
+	v3Oop = interpreterProxy->clone(v3Oop);
+	vertex = interpreterProxy->firstIndexableField(v3Oop);
+	vertex[0] = (((float) rx));
+	vertex[1] = (((float) ry));
+	vertex[2] = (((float) rz));
+	interpreterProxy->pop(2);
+	interpreterProxy->push(v3Oop);
+}
+
+
+/*	Transform two matrices into the third */
+
+EXPORT(sqInt) b3dTransformMatrixWithInto(void) {
+    float *m1;
+    float *m2;
+    float *m3;
+
+	m3 = stackMatrix(0);
+	m2 = stackMatrix(1);
+	m1 = stackMatrix(2);
+	if (((m1 == null) || (m2 == null)) || (m3 == null)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (m2 == m3) {
+		return interpreterProxy->primitiveFail();
+	}
+	transformMatrixwithinto(m1, m2, m3);
+	interpreterProxy->pop(3);
+}
+
+EXPORT(sqInt) b3dTransformPoint(void) {
+    float *matrix;
+    double rw;
+    double rx;
+    double ry;
+    double rz;
+    sqInt v3Oop;
+    float *vertex;
+    double x;
+    double y;
+    double z;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 1)) {
+		return interpreterProxy->primitiveFail();
+	}
+	v3Oop = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->isWords(v3Oop)) && ((interpreterProxy->slotSizeOf(v3Oop)) == 3))) {
+		return interpreterProxy->primitiveFail();
+	}
+	vertex = interpreterProxy->firstIndexableField(v3Oop);
+	matrix = stackMatrix(1);
+	if (matrix == null) {
+		return interpreterProxy->primitiveFail();
+	}
+	x = vertex[0];
+	y = vertex[1];
+	z = vertex[2];
+	rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]);
+	ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]);
+	rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]);
+	rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]);
+	v3Oop = interpreterProxy->clone(v3Oop);
+	vertex = interpreterProxy->firstIndexableField(v3Oop);
+	if (rw == 1.0) {
+		vertex[0] = (((float) rx));
+		vertex[1] = (((float) ry));
+		vertex[2] = (((float) rz));
+	} else {
+		if (rw == 0.0) {
+			rw = 0.0;
+		} else {
+			rw = 1.0 / rw;
+		}
+		vertex[0] = (((float) (rx * rw)));
+		vertex[1] = (((float) (ry * rw)));
+		vertex[2] = (((float) (rz * rw)));
+	}
+	interpreterProxy->pop(2);
+	interpreterProxy->push(v3Oop);
+}
+
+
+/*	Transform the normal of the given primitive vertex using the argument matrix and rescale the normal if necessary. */
+
+EXPORT(sqInt) b3dTransformPrimitiveNormal(void) {
+    float *matrix;
+    float *pVertex;
+    sqInt rescale;
+
+	rescale = interpreterProxy->stackValue(0);
+	if (!(rescale == (interpreterProxy->nilObject()))) {
+		rescale = interpreterProxy->booleanValueOf(rescale);
+	}
+	matrix = stackMatrix(1);
+	pVertex = stackPrimitiveVertex(2);
+	if ((matrix == null) || (pVertex == null)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if ((rescale != 1) && (rescale != 0)) {
+		rescale = analyzeMatrix3x3Length(matrix);
+	}
+	transformPrimitiveNormalbyrescale(pVertex, matrix, rescale);
+	interpreterProxy->pop(3);
+}
+
+
+/*	Transform the position of the given primitive vertex the given matrix
+	and store the result back inplace. */
+
+EXPORT(sqInt) b3dTransformPrimitivePosition(void) {
+    float *matrix;
+    float *pVertex;
+
+	matrix = stackMatrix(0);
+	pVertex = stackPrimitiveVertex(1);
+	if ((matrix == null) || (pVertex == null)) {
+		return interpreterProxy->primitiveFail();
+	}
+	transformPrimitivePositionby(pVertex, matrix);
+	interpreterProxy->pop(2);
+}
+
+
+/*	Transform the position of the given primitive vertex the given matrix
+	and store the result in homogenous coordinates at rasterPos. */
+
+EXPORT(sqInt) b3dTransformPrimitiveRasterPosition(void) {
+    float *matrix;
+    float *pVertex;
+
+	matrix = stackMatrix(0);
+	pVertex = stackPrimitiveVertex(1);
+	if ((matrix == null) || (pVertex == null)) {
+		return interpreterProxy->primitiveFail();
+	}
+	transformPrimitiveRasterPositionby(pVertex, matrix);
+	interpreterProxy->pop(2);
+}
+
+
+/*	Transform an entire vertex buffer using the supplied modelview and projection matrix. */
+
+EXPORT(sqInt) b3dTransformVertexBuffer(void) {
+    sqInt flags;
+    float *modelViewMatrix;
+    float *projectionMatrix;
+    float *vtxArray;
+    sqInt vtxCount;
+
+	flags = interpreterProxy->stackIntegerValue(0);
+	projectionMatrix = stackMatrix(1);
+	modelViewMatrix = stackMatrix(2);
+	vtxCount = interpreterProxy->stackIntegerValue(3);
+	vtxArray = stackPrimitiveVertexArrayofSize(4, vtxCount);
+	if (((projectionMatrix == null) || (modelViewMatrix == null)) || (vtxArray == null)) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	transformVBcountbyandflags(vtxArray, vtxCount, modelViewMatrix, projectionMatrix, flags);
+	interpreterProxy->pop(5);
+}
+
+
+/*	Return the current version of the transformer */
+
+EXPORT(sqInt) b3dTransformerVersion(void) {
+	interpreterProxy->pop(1);
+	interpreterProxy->pushInteger(1);
+}
+
+EXPORT(sqInt) b3dTransposeMatrix(void) {
+    float *dst;
+    sqInt dstOop;
+    float *src;
+    sqInt srcOop;
+
+	if (!((interpreterProxy->methodArgumentCount()) == 0)) {
+		return interpreterProxy->primitiveFail();
+	}
+	srcOop = interpreterProxy->stackObjectValue(0);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->isWords(srcOop)) && ((interpreterProxy->slotSizeOf(srcOop)) == 16))) {
+		return interpreterProxy->primitiveFail();
+	}
+
+	/* reload srcOop in case of GC */
+
+	dstOop = interpreterProxy->clone(srcOop);
+	srcOop = interpreterProxy->stackObjectValue(0);
+	src = interpreterProxy->firstIndexableField(srcOop);
+
+	/* dst at: 0 put: (src at: 0). */
+
+	dst = interpreterProxy->firstIndexableField(dstOop);
+	dst[1] = (src[4]);
+	dst[2] = (src[8]);
+	dst[3] = (src[12]);
+	dst[4] = (src[1]);
+	dst[6] = (src[9]);
+	dst[7] = (src[13]);
+	dst[8] = (src[2]);
+	dst[9] = (src[6]);
+	dst[11] = (src[14]);
+	dst[12] = (src[3]);
+	dst[13] = (src[7]);
+	dst[14] = (src[11]);
+	interpreterProxy->pop(1);
+	interpreterProxy->push(dstOop);
+}
+
+static double backClipValueFromto(sqInt last, sqInt next) {
+	return (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ])));
+}
+
+static double bottomClipValueFromto(sqInt last, sqInt next) {
+	return (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY])));
+}
+
+static sqInt clipPolygoncountwithmask(int *vtxArray, sqInt vtxCount, int *tempVtxArray, sqInt outMask) {
+    sqInt count;
+
+	if (outMask == OutLeftBit) {
+		return clipPolygonLeftFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	if (outMask == OutRightBit) {
+		return clipPolygonRightFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	if (outMask == OutTopBit) {
+		return clipPolygonTopFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	if (outMask == OutBottomBit) {
+		return clipPolygonBottomFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	if (outMask == OutFrontBit) {
+		return clipPolygonFrontFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	if (outMask == OutBackBit) {
+		return clipPolygonBackFromtocount(tempVtxArray, vtxArray, vtxCount);
+	}
+	count = vtxCount;
+	count = clipPolygonLeftFromtocount(vtxArray, tempVtxArray, count);
+	if (count == 0) {
+		return 0;
+	}
+	count = clipPolygonRightFromtocount(tempVtxArray, vtxArray, count);
+	if (count == 0) {
+		return 0;
+	}
+	count = clipPolygonTopFromtocount(vtxArray, tempVtxArray, count);
+	if (count == 0) {
+		return 0;
+	}
+	count = clipPolygonBottomFromtocount(tempVtxArray, vtxArray, count);
+	if (count == 0) {
+		return 0;
+	}
+	count = clipPolygonFrontFromtocount(vtxArray, tempVtxArray, count);
+	if (count == 0) {
+		return 0;
+	}
+	count = clipPolygonBackFromtocount(tempVtxArray, vtxArray, count);
+	return count;
+}
+
+static sqInt clipPolygonBackFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InBackBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InBackBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (((((float *) last))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+static sqInt clipPolygonBottomFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InBottomBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InBottomBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (0.0 - (((((float *) last))[PrimVtxRasterPosY]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+static sqInt clipPolygonFrontFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InFrontBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InFrontBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+static sqInt clipPolygonLeftFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InLeftBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InLeftBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+static sqInt clipPolygonRightFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InRightBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InRightBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+static sqInt clipPolygonTopFromtocount(int *buf1, int *buf2, sqInt n) {
+    sqInt i;
+    sqInt inLast;
+    sqInt inNext;
+    sqInt j;
+    int *last;
+    int *next;
+    sqInt outIndex;
+    double t;
+
+	outIndex = 0;
+	last = buf1 + (n * PrimVertexSize);
+	next = buf1 + PrimVertexSize;
+	inLast = (last[PrimVtxClipFlags]) & InTopBit;
+	for (i = 1; i <= n; i += 1) {
+		inNext = (next[PrimVtxClipFlags]) & InTopBit;
+		if (!(inLast == inNext)) {
+
+			/* Passes clip boundary */
+
+			t = (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY])));
+			outIndex += 1;
+			interpolateFromtoatinto(((float *) last), ((float *) next), t, ((float*) (buf2 + (outIndex * PrimVertexSize))));
+		}
+		if (inNext) {
+			outIndex += 1;
+			for (j = 0; j <= (PrimVertexSize - 1); j += 1) {
+				buf2[(outIndex * PrimVertexSize) + j] = (next[j]);
+			}
+		}
+		last = next;
+		inLast = inNext;
+		next += PrimVertexSize;
+	}
+	return outIndex;
+}
+
+
+/*	Compute the attenuation for the current light and vertex */
+
+static sqInt computeAttenuation(void) {
+	lightScale = 1.0;
+	if (lightFlags & FlagAttenuated) {
+		lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared])))));
+	}
+}
+
+
+/*	Compute the direction for the current light and vertex */
+
+static sqInt computeDirection(void) {
+    double scale;
+
+	if (lightFlags & FlagPositional) {
+		l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX]));
+		l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY]));
+		l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ]));
+		l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2]));
+		if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) {
+			l2vDistance = sqrt(l2vDistance);
+			scale = -1.0 / l2vDistance;
+		}
+		l2vDirection[0] = ((l2vDirection[0]) * scale);
+		l2vDirection[1] = ((l2vDirection[1]) * scale);
+		l2vDirection[2] = ((l2vDirection[2]) * scale);
+	} else {
+		if (lightFlags & FlagDirectional) {
+			l2vDirection[0] = (primLight[PrimLightDirectionX]);
+			l2vDirection[1] = (primLight[PrimLightDirectionY]);
+			l2vDirection[2] = (primLight[PrimLightDirectionZ]);
+		}
+	}
+}
+
+
+/*	Computes
+		l2vSpecDir _ l2vSpecDir - vtx position safelyNormalized.
+	 */
+
+static sqInt computeSpecularDirection(void) {
+    double scale;
+
+	scale = inverseLengthOfFloat(litVertex + PrimVtxPosition);
+	l2vSpecDir[0] = ((l2vSpecDir[0]) - ((litVertex[PrimVtxPositionX]) * scale));
+	l2vSpecDir[1] = ((l2vSpecDir[1]) - ((litVertex[PrimVtxPositionY]) * scale));
+	l2vSpecDir[2] = ((l2vSpecDir[2]) - ((litVertex[PrimVtxPositionZ]) * scale));
+}
+
+
+/*	Compute the spot factor for a spot light */
+
+static double computeSpotFactor(void) {
+    double cosAngle;
+    double deltaCos;
+    double minCos;
+
+	cosAngle = dotProductOfFloatwithDouble(primLight + PrimLightDirection, l2vDirection);
+	cosAngle = 0.0 - cosAngle;
+	minCos = primLight[SpotLightMinCos];
+	if (cosAngle < minCos) {
+		return 0.0;
+	}
+	deltaCos = primLight[SpotLightDeltaCos];
+	if (deltaCos <= 1.0e-5) {
+		return 1.0;
+	}
+	cosAngle = (cosAngle - minCos) / deltaCos;
+	return pow(cosAngle,(primLight[SpotLightExponent]));
+}
+
+static sqInt determineClipFlagscount(void *vtxArray, sqInt count) {
+    sqInt flags;
+    sqInt fullMask;
+    sqInt i;
+    float *vtxPtr;
+    double w;
+    double w2;
+    double x;
+    double y;
+    double z;
+
+	vtxPtr = ((float *) vtxArray);
+	fullMask = InAllMask + OutAllMask;
+	for (i = 1; i <= count; i += 1) {
+		w = vtxPtr[PrimVtxRasterPosW];
+		w2 = 0.0 - w;
+		flags = 0;
+		x = vtxPtr[PrimVtxRasterPosX];
+		if (x >= w2) {
+			flags = flags | InLeftBit;
+		} else {
+			flags = flags | OutLeftBit;
+		}
+		if (x <= w) {
+			flags = flags | InRightBit;
+		} else {
+			flags = flags | OutRightBit;
+		}
+		y = vtxPtr[PrimVtxRasterPosY];
+		if (y >= w2) {
+			flags = flags | InBottomBit;
+		} else {
+			flags = flags | OutBottomBit;
+		}
+		if (y <= w) {
+			flags = flags | InTopBit;
+		} else {
+			flags = flags | OutTopBit;
+		}
+		z = vtxPtr[PrimVtxRasterPosZ];
+		if (z >= w2) {
+			flags = flags | InFrontBit;
+		} else {
+			flags = flags | OutFrontBit;
+		}
+		if (z <= w) {
+			flags = flags | InBackBit;
+		} else {
+			flags = flags | OutBackBit;
+		}
+		fullMask = fullMask & flags;
+		(((int *) vtxPtr))[PrimVtxClipFlags] = flags;
+		vtxPtr += PrimVertexSize;
+	}
+	return fullMask;
+}
+
+static double dotProductOfFloatwithDouble(float * v1, double *v2) {
+	return (((v1[0]) * (v2[0])) + ((v1[1]) * (v2[1]))) + ((v1[2]) * (v2[2]));
+}
+
+
+/*	Fetch the primitive light source from the given array.
+	Note: No checks are done within here - that happened in stackLightArrayValue: */
+
+static void* fetchLightSourceofObject(sqInt index, sqInt anArray) {
+    sqInt lightOop;
+
+	lightOop = interpreterProxy->fetchPointerofObject(index, anArray);
+	return interpreterProxy->firstIndexableField(lightOop);
+}
+
+static double frontClipValueFromto(sqInt last, sqInt next) {
+	return (0.0 - (((((float *) last))[PrimVtxRasterPosZ]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosZ]) - ((((float *) last))[PrimVtxRasterPosZ])));
+}
+
+
+/*	Note: This is coded so that plugins can be run from Squeak. */
+
+static VirtualMachine * getInterpreter(void) {
+	return interpreterProxy;
+}
+
+
+/*	Note: This is hardcoded so it can be run from Squeak.
+	The module name is used for validating a module *after*
+	it is loaded to check if it does really contain the module
+	we're thinking it contains. This is important! */
+
+EXPORT(const char*) getModuleName(void) {
+	return moduleName;
+}
+
+static sqInt halt(void) {
+	;
+}
+
+EXPORT(sqInt) initialiseModule(void) {
+	loadBBFn = interpreterProxy->ioLoadFunctionFrom("loadBitBltFrom", bbPluginName);
+	copyBitsFn = interpreterProxy->ioLoadFunctionFrom("copyBitsFromtoat", bbPluginName);
+	return (loadBBFn != 0) && (copyBitsFn != 0);
+}
+
+
+/*	Interpolate the primitive vertices last/next at the parameter t */
+
+static sqInt interpolateFromtoatinto(float *last, float *next, double t, float *out) {
+    double delta;
+    sqInt flags;
+    unsigned int lastValue;
+    unsigned int newValue;
+    unsigned int nextValue;
+    unsigned int rgbaLast;
+    unsigned int rgbaNext;
+    double w;
+    double w2;
+    double x;
+    double y;
+    double z;
+
+	delta = (next[PrimVtxRasterPosX]) - (last[PrimVtxRasterPosX]);
+	x = (last[PrimVtxRasterPosX]) + (delta * t);
+	out[PrimVtxRasterPosX] = (((float) x));
+	delta = (next[PrimVtxRasterPosY]) - (last[PrimVtxRasterPosY]);
+	y = (last[PrimVtxRasterPosY]) + (delta * t);
+	out[PrimVtxRasterPosY] = (((float) y));
+	delta = (next[PrimVtxRasterPosZ]) - (last[PrimVtxRasterPosZ]);
+	z = (last[PrimVtxRasterPosZ]) + (delta * t);
+	out[PrimVtxRasterPosZ] = (((float) z));
+	delta = (next[PrimVtxRasterPosW]) - (last[PrimVtxRasterPosW]);
+	w = (last[PrimVtxRasterPosW]) + (delta * t);
+	out[PrimVtxRasterPosW] = (((float) w));
+	w2 = 0.0 - w;
+	flags = 0;
+	if (x >= w2) {
+		flags = flags | InLeftBit;
+	} else {
+		flags = flags | OutLeftBit;
+	}
+	if (x <= w) {
+		flags = flags | InRightBit;
+	} else {
+		flags = flags | OutRightBit;
+	}
+	if (y >= w2) {
+		flags = flags | InBottomBit;
+	} else {
+		flags = flags | OutBottomBit;
+	}
+	if (y <= w) {
+		flags = flags | InTopBit;
+	} else {
+		flags = flags | OutTopBit;
+	}
+	if (z >= w2) {
+		flags = flags | InFrontBit;
+	} else {
+		flags = flags | OutFrontBit;
+	}
+	if (z <= w) {
+		flags = flags | InBackBit;
+	} else {
+		flags = flags | OutBackBit;
+	}
+	(((int *) out))[PrimVtxClipFlags] = flags;
+	rgbaLast = (((unsigned int *) last))[PrimVtxColor32];
+	lastValue = rgbaLast & 255;
+	rgbaLast = ((usqInt) rgbaLast) >> 8;
+	rgbaNext = (((unsigned int *) next))[PrimVtxColor32];
+	nextValue = rgbaNext & 255;
+	rgbaNext = ((usqInt) rgbaNext) >> 8;
+	delta = (((int) (nextValue - lastValue))) * t;
+	newValue = ((sqInt)(lastValue + delta));
+	lastValue = rgbaLast & 255;
+	rgbaLast = ((usqInt) rgbaLast) >> 8;
+	nextValue = rgbaNext & 255;
+	rgbaNext = ((usqInt) rgbaNext) >> 8;
+	delta = (((int) (nextValue - lastValue))) * t;
+	newValue += (((sqInt)(lastValue + delta))) << 8;
+	lastValue = rgbaLast & 255;
+	rgbaLast = ((usqInt) rgbaLast) >> 8;
+	nextValue = rgbaNext & 255;
+	rgbaNext = ((usqInt) rgbaNext) >> 8;
+	delta = (((int) (nextValue - lastValue))) * t;
+	newValue += (((sqInt)(lastValue + delta))) << 16;
+	lastValue = rgbaLast & 255;
+	nextValue = rgbaNext & 255;
+	delta = (((int) (nextValue - lastValue))) * t;
+	newValue += (((sqInt)(lastValue + delta))) << 24;
+	(((unsigned int*) out))[PrimVtxColor32] = newValue;
+	delta = (next[PrimVtxTexCoordU]) - (last[PrimVtxTexCoordU]);
+	out[PrimVtxTexCoordU] = (((float) ((last[PrimVtxTexCoordU]) + (delta * t))));
+	delta = (next[PrimVtxTexCoordV]) - (last[PrimVtxTexCoordV]);
+	out[PrimVtxTexCoordV] = (((float) ((last[PrimVtxTexCoordV]) + (delta * t))));
+}
+
+static double inverseLengthOfDouble(double * aVector) {
+    double scale;
+
+	scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2]));
+	if ((scale == 0.0) || (scale == 1.0)) {
+		return scale;
+	}
+	return 1.0 / (sqrt(scale));
+}
+
+static double inverseLengthOfFloat(float * aVector) {
+    double scale;
+
+	scale = (((aVector[0]) * (aVector[0])) + ((aVector[1]) * (aVector[1]))) + ((aVector[2]) * (aVector[2]));
+	if ((scale == 0.0) || (scale == 1.0)) {
+		return scale;
+	}
+	return 1.0 / (sqrt(scale));
+}
+
+static double leftClipValueFromto(sqInt last, sqInt next) {
+	return (0.0 - (((((float *) last))[PrimVtxRasterPosX]) + ((((float *) last))[PrimVtxRasterPosW]))) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) + (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX])));
+}
+
+static sqInt loadObjectsFrom(sqInt stackIndex) {
+    sqInt arrayOop;
+    sqInt arraySize;
+    sqInt i;
+    B3DPrimitiveObject **objArray;
+    sqInt objOop;
+    B3DPrimitiveObject *objPtr;
+
+	arrayOop = interpreterProxy->stackObjectValue(stackIndex);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	arraySize = interpreterProxy->slotSizeOf(arrayOop);
+	if (arraySize > (state.nObjects)) {
+		return interpreterProxy->primitiveFail();
+	}
+	objArray = state.objects;
+	for (i = 0; i <= (arraySize - 1); i += 1) {
+		objOop = interpreterProxy->fetchPointerofObject(i, arrayOop);
+		if (((objOop & 1)) || (!(interpreterProxy->isWords(objOop)))) {
+			return interpreterProxy->primitiveFail();
+		}
+		objPtr = ((B3DPrimitiveObject*) (interpreterProxy->firstIndexableField(objOop)));
+		if (objPtr->magic != B3D_PRIMITIVE_OBJECT_MAGIC) {
+			return interpreterProxy->primitiveFail();
+		}
+		objPtr->__oop__ = objOop;
+		objArray[i] = objPtr;
+	}
+}
+
+static sqInt loadPrimitiveLightSource(void) {
+	lightFlags = (((int*) primLight))[PrimLightFlags];
+}
+
+
+/*	Load the necessary values from the current primitive vertex */
+
+static sqInt loadPrimitiveVertex(void) {
+    sqInt rgba;
+
+	rgba = (((int*) litVertex))[PrimVtxColor32];
+	vtxInColor[2] = ((rgba & 255) * (1.0 / 255.0));
+	rgba = ((usqInt) rgba) >> 8;
+	vtxInColor[1] = ((rgba & 255) * (1.0 / 255.0));
+	rgba = ((usqInt) rgba) >> 8;
+	vtxInColor[0] = ((rgba & 255) * (1.0 / 255.0));
+	rgba = ((usqInt) rgba) >> 8;
+	vtxInColor[3] = ((rgba & 255) * (1.0 / 255.0));
+}
+
+
+/*	Load the rasterizer state from the given stack index. */
+
+static sqInt loadRasterizerState(sqInt stackIndex) {
+    sqInt obj;
+    sqInt objLen;
+    void *objPtr;
+    sqInt stateOop;
+
+	if ((copyBitsFn == 0) || (loadBBFn == 0)) {
+		if (!(initialiseModule())) {
+			return 0;
+		}
+	}
+	stateOop = interpreterProxy->stackObjectValue(stackIndex);
+	if (interpreterProxy->failed()) {
+		return 0;
+	}
+	if (!((interpreterProxy->isPointers(stateOop)) && ((interpreterProxy->slotSizeOf(stateOop)) >= 10))) {
+		return 0;
+	}
+	obj = interpreterProxy->fetchPointerofObject(0, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.faceAlloc = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(1, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.edgeAlloc = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(2, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.attrAlloc = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(3, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.aet = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(4, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.addedEdges = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(5, stateOop);
+	if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+		return 0;
+	}
+	objPtr = interpreterProxy->firstIndexableField(obj);
+	state.fillList = objPtr;
+	obj = interpreterProxy->fetchPointerofObject(6, stateOop);
+	if (obj == (interpreterProxy->nilObject())) {
+		state.nObjects = 0;
+		state.objects = NULL;
+	} else {
+		if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+			return 0;
+		}
+		objLen = interpreterProxy->slotSizeOf(obj);
+		objPtr = interpreterProxy->firstIndexableField(obj);
+		state.objects = (B3DPrimitiveObject **)objPtr;
+		state.nObjects = objLen;
+	}
+	obj = interpreterProxy->fetchPointerofObject(7, stateOop);
+	if (obj == (interpreterProxy->nilObject())) {
+		state.nTextures = 0;
+		state.textures = NULL;
+	} else {
+		if (((obj & 1)) || (!(interpreterProxy->isWords(obj)))) {
+			return 0;
+		}
+		objLen = interpreterProxy->byteSizeOf(obj);
+		objPtr = interpreterProxy->firstIndexableField(obj);
+		state.textures = (B3DTexture *)objPtr;
+		state.nTextures = objLen / sizeof(B3DTexture);
+	}
+	obj = interpreterProxy->fetchPointerofObject(8, stateOop);
+	if (obj == (interpreterProxy->nilObject())) {
+		state.spanSize = 0;
+		state.spanBuffer = NULL;
+	} else {
+		if (!((interpreterProxy->fetchClassOf(obj)) == (interpreterProxy->classBitmap()))) {
+			return 0;
+		}
+		objLen = interpreterProxy->slotSizeOf(obj);
+		objPtr = interpreterProxy->firstIndexableField(obj);
+		state.spanBuffer = (unsigned int *)objPtr;
+		state.spanSize = objLen;
+	}
+	obj = interpreterProxy->fetchPointerofObject(9, stateOop);
+	if (obj == (interpreterProxy->nilObject())) {
+		state.spanDrawer = NULL;
+	} else {
+		if (!(((int (*) (int))loadBBFn)(obj))) {
+			return 0;
+		}
+		state.spanDrawer = (b3dDrawBufferFunction) copyBitsFn;
+	}
+	return !(interpreterProxy->failed());
+}
+
+
+/*	Note: This still uses the old-style textures */
+
+static sqInt loadTextureinto(sqInt textureOop, B3DTexture *destPtr) {
+    void *bitsPtr;
+    sqInt form;
+    sqInt formBits;
+    sqInt formDepth;
+    sqInt formHeight;
+    sqInt formWidth;
+    sqInt texEnvMode;
+    sqInt texInterpolate;
+    sqInt texWrap;
+
+	form = textureOop;
+	if (!(interpreterProxy->isPointers(form))) {
+		return 0;
+	}
+	if ((interpreterProxy->slotSizeOf(form)) < 8) {
+		return 0;
+	}
+	formBits = interpreterProxy->fetchPointerofObject(0, form);
+	formWidth = interpreterProxy->fetchIntegerofObject(1, form);
+	formHeight = interpreterProxy->fetchIntegerofObject(2, form);
+	formDepth = interpreterProxy->fetchIntegerofObject(3, form);
+	texWrap = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(5, form));
+	texInterpolate = interpreterProxy->booleanValueOf(interpreterProxy->fetchPointerofObject(6, form));
+	texEnvMode = interpreterProxy->fetchIntegerofObject(7, form);
+	if (interpreterProxy->failed()) {
+		return 0;
+	}
+	if ((formWidth < 1) || ((formHeight < 1) || (formDepth != 32))) {
+		return 0;
+	}
+	if (!((interpreterProxy->fetchClassOf(formBits)) == (interpreterProxy->classBitmap()))) {
+		return 0;
+	}
+	if (!((interpreterProxy->byteSizeOf(formBits)) == ((formWidth * formHeight) * 4))) {
+		return 0;
+	}
+	if ((texEnvMode < 0) || (texEnvMode > 1)) {
+		return 0;
+	}
+
+	/* Set the texture parameters */
+
+	bitsPtr = interpreterProxy->firstIndexableField(formBits);
+	return b3dLoadTexture(destPtr, formWidth, formHeight, formDepth, (unsigned int*) bitsPtr, 0, NULL) == B3D_NO_ERROR;
+}
+
+static sqInt loadTexturesFrom(sqInt stackIndex) {
+    sqInt arrayOop;
+    B3DTexture *destPtr;
+    sqInt i;
+    sqInt n;
+    sqInt textureOop;
+
+	arrayOop = interpreterProxy->stackObjectValue(stackIndex);
+	if (!((interpreterProxy->fetchClassOf(arrayOop)) == (interpreterProxy->classArray()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	n = interpreterProxy->slotSizeOf(arrayOop);
+	n = ((n < (state.nTextures)) ? n : (state.nTextures));
+	for (i = 0; i <= (n - 1); i += 1) {
+		destPtr = state.textures + i;
+		textureOop = interpreterProxy->fetchPointerofObject(i, arrayOop);
+		if (!(loadTextureinto(textureOop, destPtr))) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	return 0;
+}
+
+
+/*	Load the viewport from the given stack index */
+
+static sqInt loadViewportFrom(sqInt stackIndex) {
+    sqInt oop;
+    sqInt p1;
+    sqInt p2;
+    sqInt x0;
+    sqInt x1;
+    sqInt y0;
+    sqInt y1;
+
+	oop = interpreterProxy->stackObjectValue(stackIndex);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!(interpreterProxy->isPointers(oop))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if ((interpreterProxy->slotSizeOf(oop)) < 2) {
+		return interpreterProxy->primitiveFail();
+	}
+	p1 = interpreterProxy->fetchPointerofObject(0, oop);
+	p2 = interpreterProxy->fetchPointerofObject(1, oop);
+	if (!((interpreterProxy->fetchClassOf(p1)) == (interpreterProxy->classPoint()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	if (!((interpreterProxy->fetchClassOf(p2)) == (interpreterProxy->classPoint()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	x0 = interpreterProxy->fetchIntegerofObject(0, p1);
+	y0 = interpreterProxy->fetchIntegerofObject(1, p1);
+	x1 = interpreterProxy->fetchIntegerofObject(0, p2);
+	y1 = interpreterProxy->fetchIntegerofObject(1, p2);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	viewport.x0 = x0;
+	viewport.y0 = y0;
+	viewport.x1 = x1;
+	viewport.y1 = y1;
+	return 0;
+}
+
+static sqInt mapVBofSizeinto(void *vtxArray, sqInt vtxCount, sqInt boxArray) {
+    double bottom;
+    sqInt flags;
+    sqInt floatOop;
+    sqInt i;
+    double left;
+    sqInt oop;
+    double right;
+    double top;
+    float *vtxPtr;
+    double w;
+    double x;
+    double y;
+
+	vtxPtr = ((float *) vtxArray);
+	for (i = 1; i <= vtxCount; i += 1) {
+		flags = (((int *) vtxPtr))[PrimVtxClipFlags];
+		w = vtxPtr[PrimVtxRasterPosW];
+		if (!(w == 0.0)) {
+			w = 1.0 / w;
+		}
+		if ((flags & OutLeftBit) != 0) {
+			x = -1.0;
+		} else {
+			if ((flags & OutRightBit) != 0) {
+				x = 1.0;
+			} else {
+				x = (vtxPtr[PrimVtxRasterPosX]) * w;
+			}
+		}
+		if ((flags & OutTopBit) != 0) {
+			y = -1.0;
+		} else {
+			if ((flags & OutBottomBit) != 0) {
+				y = 1.0;
+			} else {
+				y = (vtxPtr[PrimVtxRasterPosY]) * w;
+			}
+		}
+		if (i == 1) {
+			left = right = x;
+			top = bottom = y;
+		}
+		if (x < left) {
+			left = x;
+		}
+		if (x > right) {
+			right = x;
+		}
+		if (y < top) {
+			top = y;
+		}
+		if (y > bottom) {
+			bottom = y;
+		}
+		vtxPtr += PrimVertexSize;
+	}
+	oop = boxArray;
+	interpreterProxy->pushRemappableOop(oop);
+	floatOop = interpreterProxy->floatObjectOf(left);
+	oop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(0, oop, floatOop);
+	interpreterProxy->pushRemappableOop(oop);
+	floatOop = interpreterProxy->floatObjectOf(top);
+	oop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(1, oop, floatOop);
+	interpreterProxy->pushRemappableOop(oop);
+	floatOop = interpreterProxy->floatObjectOf(right);
+	oop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(2, oop, floatOop);
+	interpreterProxy->pushRemappableOop(oop);
+	floatOop = interpreterProxy->floatObjectOf(bottom);
+	oop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(3, oop, floatOop);
+}
+
+
+/*	The module with the given name was just unloaded.
+	Make sure we have no dangling references. */
+
+EXPORT(sqInt) moduleUnloaded(char *aModuleName) {
+	if ((strcmp(aModuleName, bbPluginName)) == 0) {
+
+		/* BitBlt just shut down. How nasty. */
+
+		loadBBFn = 0;
+		copyBitsFn = 0;
+	}
+}
+
+static sqInt msg(char *s) {
+	fprintf(stderr, "\n%s: %s", moduleName, s);
+}
+
+
+/*	Primitive. Set the BitBlt plugin to use. */
+
+EXPORT(sqInt) primitiveSetBitBltPlugin(void) {
+    sqInt i;
+    sqInt length;
+    sqInt needReload;
+    sqInt pluginName;
+    char *ptr;
+
+
+	/* Must be string to work */
+
+	pluginName = interpreterProxy->stackValue(0);
+	if (!(interpreterProxy->isBytes(pluginName))) {
+		return interpreterProxy->primitiveFail();
+	}
+	length = interpreterProxy->byteSizeOf(pluginName);
+	if (length >= 256) {
+		return interpreterProxy->primitiveFail();
+	}
+	ptr = interpreterProxy->firstIndexableField(pluginName);
+	needReload = 0;
+	for (i = 0; i <= (length - 1); i += 1) {
+		if (!((bbPluginName[i]) == (ptr[i]))) {
+			bbPluginName[i] = (ptr[i]);
+			needReload = 1;
+		}
+	}
+	if (!((bbPluginName[length]) == 0)) {
+		bbPluginName[length] = 0;
+		needReload = 1;
+	}
+	if (needReload) {
+		if (!(initialiseModule())) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	interpreterProxy->pop(1);
+}
+
+static double processIndexedofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) {
+    sqInt i;
+    sqInt index;
+    double minZ;
+    float *vtxPtr;
+    double wValue;
+    double zValue;
+
+	minZ = 10.0;
+	for (i = 1; i <= idxSize; i += 1) {
+		index = idxArray[i];
+		if (index > 0) {
+			vtxPtr = vtxArray + ((index - 1) * PrimVertexSize);
+			zValue = vtxPtr[PrimVtxRasterPosZ];
+			wValue = vtxPtr[PrimVtxRasterPosW];
+			if (!(wValue == 0.0)) {
+				zValue = zValue / wValue;
+			}
+			if (zValue < minZ) {
+				minZ = zValue;
+			}
+		}
+	}
+	return minZ;
+}
+
+static sqInt processIndexedIDXofSizeidxArrayidxSize(float *vtxArray, sqInt vtxSize, int *idxArray, sqInt idxSize) {
+    sqInt i;
+    sqInt index;
+    sqInt minIndex;
+    double minZ;
+    float *vtxPtr;
+    double wValue;
+    double zValue;
+
+	minZ = 10.0;
+	minIndex = 0;
+	for (i = 1; i <= idxSize; i += 1) {
+		index = idxArray[i];
+		if (index > 0) {
+			vtxPtr = vtxArray + ((index - 1) * PrimVertexSize);
+			zValue = vtxPtr[PrimVtxRasterPosZ];
+			wValue = vtxPtr[PrimVtxRasterPosW];
+			if (!(wValue == 0.0)) {
+				zValue = zValue / wValue;
+			}
+			if ((minIndex == 0) || (zValue < minZ)) {
+				minIndex = i;
+				minZ = zValue;
+			}
+		}
+	}
+	return minIndex;
+}
+
+static double processNonIndexedofSize(float *vtxArray, sqInt vtxSize) {
+    sqInt i;
+    double minZ;
+    float *vtxPtr;
+    double wValue;
+    double zValue;
+
+	minZ = 10.0;
+	vtxPtr = vtxArray;
+	for (i = 1; i <= vtxSize; i += 1) {
+		zValue = vtxPtr[PrimVtxRasterPosZ];
+		wValue = vtxPtr[PrimVtxRasterPosW];
+		if (!(wValue == 0.0)) {
+			zValue = zValue / wValue;
+		}
+		if (zValue < minZ) {
+			minZ = zValue;
+		}
+	}
+	return minZ;
+}
+
+static sqInt processNonIndexedIDXofSize(float *vtxArray, sqInt vtxSize) {
+    sqInt i;
+    sqInt minIndex;
+    double minZ;
+    float *vtxPtr;
+    double wValue;
+    double zValue;
+
+	minZ = 10.0;
+	minIndex = 0;
+	vtxPtr = vtxArray;
+	for (i = 1; i <= vtxSize; i += 1) {
+		zValue = vtxPtr[PrimVtxRasterPosZ];
+		wValue = vtxPtr[PrimVtxRasterPosW];
+		if (!(wValue == 0.0)) {
+			zValue = zValue / wValue;
+		}
+		if ((minIndex == 0) || (zValue < minZ)) {
+			minIndex = i;
+			minZ = zValue;
+		}
+	}
+	return minIndex;
+}
+
+static double rightClipValueFromto(sqInt last, sqInt next) {
+	return (((((float *) last))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosX]) - ((((float *) last))[PrimVtxRasterPosX])));
+}
+
+
+/*	Note: This is coded so that is can be run from Squeak. */
+
+EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) {
+    sqInt ok;
+
+	interpreterProxy = anInterpreter;
+	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
+	if (ok == 0) {
+		return 0;
+	}
+	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
+	return ok;
+}
+
+static sqInt shadeVertex(void) {
+    double cosAngle;
+    double specularFactor;
+    double aPart;
+    double bPart;
+    double gPart;
+    double rPart;
+    double aPart1;
+    double bPart1;
+    double gPart1;
+    double rPart1;
+    double aPart2;
+    double bPart2;
+    double gPart2;
+    double rPart2;
+    double scale;
+
+	/* begin computeDirection */
+	if (lightFlags & FlagPositional) {
+		l2vDirection[0] = ((litVertex[PrimVtxPositionX]) - (primLight[PrimLightPositionX]));
+		l2vDirection[1] = ((litVertex[PrimVtxPositionY]) - (primLight[PrimLightPositionY]));
+		l2vDirection[2] = ((litVertex[PrimVtxPositionZ]) - (primLight[PrimLightPositionZ]));
+		l2vDistance = (((l2vDirection[0]) * (l2vDirection[0])) + ((l2vDirection[1]) * (l2vDirection[1]))) + ((l2vDirection[2]) * (l2vDirection[2]));
+		if (!((l2vDistance == 0.0) || (l2vDistance == 1.0))) {
+			l2vDistance = sqrt(l2vDistance);
+			scale = -1.0 / l2vDistance;
+		}
+		l2vDirection[0] = ((l2vDirection[0]) * scale);
+		l2vDirection[1] = ((l2vDirection[1]) * scale);
+		l2vDirection[2] = ((l2vDirection[2]) * scale);
+	} else {
+		if (lightFlags & FlagDirectional) {
+			l2vDirection[0] = (primLight[PrimLightDirectionX]);
+			l2vDirection[1] = (primLight[PrimLightDirectionY]);
+			l2vDirection[2] = (primLight[PrimLightDirectionZ]);
+		}
+	}
+	/* begin computeAttenuation */
+	lightScale = 1.0;
+	if (lightFlags & FlagAttenuated) {
+		lightScale = 1.0 / ((primLight[PrimLightAttenuationConstant]) + (l2vDistance * ((primLight[PrimLightAttenuationLinear]) + (l2vDistance * (primLight[PrimLightAttenuationSquared])))));
+	}
+	if (lightFlags & FlagHasSpot) {
+		lightScale = lightScale * (computeSpotFactor());
+	}
+	if (lightScale > 0.001) {
+		if (lightFlags & FlagAmbientPart) {
+			/* begin addPart:from:trackFlag:scale: */
+			if (vbFlags & VBTrackAmbient) {
+				rPart = ((vtxInColor[0]) * ((primLight + AmbientPart)[0])) * lightScale;
+				gPart = ((vtxInColor[1]) * ((primLight + AmbientPart)[1])) * lightScale;
+				bPart = ((vtxInColor[2]) * ((primLight + AmbientPart)[2])) * lightScale;
+				aPart = ((vtxInColor[3]) * ((primLight + AmbientPart)[3])) * lightScale;
+			} else {
+				rPart = (((primMaterial + AmbientPart)[0]) * ((primLight + AmbientPart)[0])) * lightScale;
+				gPart = (((primMaterial + AmbientPart)[1]) * ((primLight + AmbientPart)[1])) * lightScale;
+				bPart = (((primMaterial + AmbientPart)[2]) * ((primLight + AmbientPart)[2])) * lightScale;
+				aPart = (((primMaterial + AmbientPart)[3]) * ((primLight + AmbientPart)[3])) * lightScale;
+			}
+			vtxOutColor[0] = ((vtxOutColor[0]) + rPart);
+			vtxOutColor[1] = ((vtxOutColor[1]) + gPart);
+			vtxOutColor[2] = ((vtxOutColor[2]) + bPart);
+			vtxOutColor[3] = ((vtxOutColor[3]) + aPart);
+		}
+		if (lightFlags & FlagDiffusePart) {
+
+			/* Compute angle from light->vertex to vertex normal */
+			/* For one-sided lighting negate cosAngle if necessary */
+
+			cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vDirection);
+			if (((vbFlags & VBTwoSidedLighting) == 0) && (cosAngle < 0.0)) {
+				cosAngle = 0.0 - cosAngle;
+			}
+			if (cosAngle > 0.0) {
+				/* begin addPart:from:trackFlag:scale: */
+				if (vbFlags & VBTrackDiffuse) {
+					rPart1 = ((vtxInColor[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle);
+					gPart1 = ((vtxInColor[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle);
+					bPart1 = ((vtxInColor[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle);
+					aPart1 = ((vtxInColor[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle);
+				} else {
+					rPart1 = (((primMaterial + DiffusePart)[0]) * ((primLight + DiffusePart)[0])) * (lightScale * cosAngle);
+					gPart1 = (((primMaterial + DiffusePart)[1]) * ((primLight + DiffusePart)[1])) * (lightScale * cosAngle);
+					bPart1 = (((primMaterial + DiffusePart)[2]) * ((primLight + DiffusePart)[2])) * (lightScale * cosAngle);
+					aPart1 = (((primMaterial + DiffusePart)[3]) * ((primLight + DiffusePart)[3])) * (lightScale * cosAngle);
+				}
+				vtxOutColor[0] = ((vtxOutColor[0]) + rPart1);
+				vtxOutColor[1] = ((vtxOutColor[1]) + gPart1);
+				vtxOutColor[2] = ((vtxOutColor[2]) + bPart1);
+				vtxOutColor[3] = ((vtxOutColor[3]) + aPart1);
+			}
+		}
+	}
+	if ((lightFlags & FlagSpecularPart) && ((primMaterial[MaterialShininess]) > 0.0)) {
+		l2vSpecDir[0] = (l2vDirection[0]);
+		l2vSpecDir[1] = (l2vDirection[1]);
+		l2vSpecDir[2] = (l2vDirection[2]);
+		if (vbFlags & VBUseLocalViewer) {
+			computeSpecularDirection();
+		} else {
+			l2vSpecDir[2] = ((l2vSpecDir[2]) - 1.0);
+		}
+		cosAngle = dotProductOfFloatwithDouble(litVertex + PrimVtxNormal, l2vSpecDir);
+		if (cosAngle > 0.0) {
+
+			/* Normalize the angle */
+			/* cosAngle should be somewhere between 0 and 1.
+			If not, then the vertex normal was not normalized */
+
+			cosAngle = cosAngle * (inverseLengthOfDouble(l2vSpecDir));
+			if (cosAngle > 1.0) {
+				specularFactor = pow(cosAngle,(primMaterial[MaterialShininess]));
+			} else {
+				if (cosAngle == 0.0) {
+					specularFactor = 1.0;
+				} else {
+					specularFactor = pow(cosAngle,(primMaterial[MaterialShininess]));
+				}
+			}
+			/* begin addPart:from:trackFlag:scale: */
+			if (vbFlags & VBTrackSpecular) {
+				rPart2 = ((vtxInColor[0]) * ((primLight + SpecularPart)[0])) * specularFactor;
+				gPart2 = ((vtxInColor[1]) * ((primLight + SpecularPart)[1])) * specularFactor;
+				bPart2 = ((vtxInColor[2]) * ((primLight + SpecularPart)[2])) * specularFactor;
+				aPart2 = ((vtxInColor[3]) * ((primLight + SpecularPart)[3])) * specularFactor;
+			} else {
+				rPart2 = (((primMaterial + SpecularPart)[0]) * ((primLight + SpecularPart)[0])) * specularFactor;
+				gPart2 = (((primMaterial + SpecularPart)[1]) * ((primLight + SpecularPart)[1])) * specularFactor;
+				bPart2 = (((primMaterial + SpecularPart)[2]) * ((primLight + SpecularPart)[2])) * specularFactor;
+				aPart2 = (((primMaterial + SpecularPart)[3]) * ((primLight + SpecularPart)[3])) * specularFactor;
+			}
+			vtxOutColor[0] = ((vtxOutColor[0]) + rPart2);
+			vtxOutColor[1] = ((vtxOutColor[1]) + gPart2);
+			vtxOutColor[2] = ((vtxOutColor[2]) + bPart2);
+			vtxOutColor[3] = ((vtxOutColor[3]) + aPart2);
+		}
+	}
+}
+
+
+/*	Load an Array of B3DPrimitiveLights from the given stack index */
+
+static sqInt stackLightArrayValue(sqInt stackIndex) {
+    sqInt array;
+    sqInt arraySize;
+    sqInt i;
+    sqInt oop;
+
+	array = interpreterProxy->stackObjectValue(stackIndex);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if (!((interpreterProxy->fetchClassOf(array)) == (interpreterProxy->classArray()))) {
+		return interpreterProxy->primitiveFail();
+	}
+	arraySize = interpreterProxy->slotSizeOf(array);
+	for (i = 0; i <= (arraySize - 1); i += 1) {
+		oop = interpreterProxy->fetchPointerofObject(i, array);
+		if ((oop & 1)) {
+			return interpreterProxy->primitiveFail();
+		}
+		if (!((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimLightSize))) {
+			return interpreterProxy->primitiveFail();
+		}
+	}
+	return array;
+}
+
+
+/*	Load a B3DMaterial from the given stack index */
+
+static void * stackMaterialValue(sqInt stackIndex) {
+    sqInt oop;
+
+	oop = interpreterProxy->stackObjectValue(stackIndex);
+	if (interpreterProxy->failed()) {
+		return null;
+	}
+	if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == MaterialSize)) {
+		return interpreterProxy->firstIndexableField(oop);
+	}
+	return null;
+}
+
+
+/*	Load a 4x4 transformation matrix from the interpreter stack.
+	Return a pointer to the matrix data if successful, nil otherwise. */
+
+static void* stackMatrix(sqInt index) {
+    sqInt oop;
+
+	oop = interpreterProxy->stackObjectValue(index);
+	if (oop == null) {
+		return null;
+	}
+	if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == 16)) {
+		return interpreterProxy->firstIndexableField(oop);
+	}
+	return null;
+}
+
+
+/*	Load a primitive index array from the interpreter stack.
+	If aBool is true then check that all the indexes are in the range (1,maxIndex).
+	Return a pointer to the index data if successful, nil otherwise. */
+
+static void* stackPrimitiveIndexArrayofSizevalidateforVertexSize(sqInt stackIndex, sqInt nItems, sqInt aBool, sqInt maxIndex) {
+    sqInt i;
+    int *idxPtr;
+    sqInt index;
+    sqInt oop;
+    sqInt oopSize;
+
+	oop = interpreterProxy->stackObjectValue(stackIndex);
+	if (oop == null) {
+		return null;
+	}
+	if (!(interpreterProxy->isWords(oop))) {
+		return null;
+	}
+	oopSize = interpreterProxy->slotSizeOf(oop);
+	if (oopSize < nItems) {
+		return null;
+	}
+	idxPtr = ((int *) (interpreterProxy->firstIndexableField(oop)));
+	if (aBool) {
+		for (i = 0; i <= (nItems - 1); i += 1) {
+			index = idxPtr[i];
+			if ((index < 0) || (index > maxIndex)) {
+				return null;
+			}
+		}
+	}
+	return idxPtr;
+}
+
+
+/*	Load a primitive vertex from the interpreter stack.
+	Return a pointer to the vertex data if successful, nil otherwise. */
+
+static void* stackPrimitiveVertex(sqInt index) {
+    sqInt oop;
+
+	oop = interpreterProxy->stackObjectValue(index);
+	if (oop == null) {
+		return null;
+	}
+	if ((interpreterProxy->isWords(oop)) && ((interpreterProxy->slotSizeOf(oop)) == PrimVertexSize)) {
+		return interpreterProxy->firstIndexableField(oop);
+	}
+	return null;
+}
+
+
+/*	Load a primitive vertex array from the interpreter stack.
+	Return a pointer to the vertex data if successful, nil otherwise. */
+
+static void* stackPrimitiveVertexArrayofSize(sqInt index, sqInt nItems) {
+    sqInt oop;
+    sqInt oopSize;
+
+	oop = interpreterProxy->stackObjectValue(index);
+	if (oop == null) {
+		return null;
+	}
+	if (interpreterProxy->isWords(oop)) {
+		oopSize = interpreterProxy->slotSizeOf(oop);
+		if (((oopSize >= nItems) * PrimVertexSize) && ((oopSize % PrimVertexSize) == 0)) {
+			return interpreterProxy->firstIndexableField(oop);
+		}
+	}
+	return null;
+}
+
+static sqInt storeObjectsInto(sqInt stackIndex) {
+    sqInt arrayOop;
+    sqInt arraySize;
+    sqInt i;
+    sqInt objOop;
+
+	arrayOop = interpreterProxy->stackObjectValue(stackIndex);
+	arraySize = state.nObjects;
+	for (i = 0; i <= (arraySize - 1); i += 1) {
+		objOop = state.objects[i]->__oop__;
+		interpreterProxy->storePointerofObjectwithValue(i, arrayOop, objOop);
+	}
+}
+
+
+/*	Store the computed output color back into the current primitive vertex.
+	Clamp the r,g,b,a part to be in the range 0-255. */
+
+static sqInt storePrimitiveVertex(void) {
+    sqInt a;
+    sqInt b;
+    sqInt g;
+    sqInt r;
+
+	r = ((sqInt)((vtxOutColor[0]) * 255));
+	r = (((((r < 255) ? r : 255)) < 0) ? 0 : (((r < 255) ? r : 255)));
+	g = ((sqInt)((vtxOutColor[1]) * 255));
+	g = (((((g < 255) ? g : 255)) < 0) ? 0 : (((g < 255) ? g : 255)));
+	b = ((sqInt)((vtxOutColor[2]) * 255));
+	b = (((((b < 255) ? b : 255)) < 0) ? 0 : (((b < 255) ? b : 255)));
+	a = ((sqInt)((vtxOutColor[3]) * 255));
+
+	/* The following is equal to b + (g << 8) + (r << 16) + (a << 24) */
+
+	a = (((((a < 255) ? a : 255)) < 0) ? 0 : (((a < 255) ? a : 255)));
+	(((int*) litVertex))[PrimVtxColor32] = (b + ((g + ((r + (a << 8)) << 8)) << 8));
+}
+
+static double topClipValueFromto(sqInt last, sqInt next) {
+	return (((((float *) last))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosW])) / ((((((float *) next))[PrimVtxRasterPosW]) - ((((float *) last))[PrimVtxRasterPosW])) - (((((float *) next))[PrimVtxRasterPosY]) - ((((float *) last))[PrimVtxRasterPosY])));
+}
+
+
+/*	Transform src with arg into dst.
+	It is allowed that src == dst but not arg == dst */
+
+static sqInt transformMatrixwithinto(float *src, float *arg, float *dst) {
+    float c1;
+    float c2;
+    float c3;
+    float c4;
+    sqInt i;
+    float *m1;
+    float *m2;
+    float *m3;
+
+	m1 = ((float *) src);
+	m2 = ((float *) arg);
+	m3 = ((float *) dst);
+	for (i = 0; i <= 3; i += 1) {
+
+		/* Compute next row */
+
+		c1 = ((((m1[0]) * (m2[0])) + ((m1[1]) * (m2[4]))) + ((m1[2]) * (m2[8]))) + ((m1[3]) * (m2[12]));
+		c2 = ((((m1[0]) * (m2[1])) + ((m1[1]) * (m2[5]))) + ((m1[2]) * (m2[9]))) + ((m1[3]) * (m2[13]));
+		c3 = ((((m1[0]) * (m2[2])) + ((m1[1]) * (m2[6]))) + ((m1[2]) * (m2[10]))) + ((m1[3]) * (m2[14]));
+
+		/* Store result */
+
+		c4 = ((((m1[0]) * (m2[3])) + ((m1[1]) * (m2[7]))) + ((m1[2]) * (m2[11]))) + ((m1[3]) * (m2[15]));
+		m3[0] = c1;
+		m3[1] = c2;
+		m3[2] = c3;
+		m3[3] = c4;
+		m1 += 4;
+		m3 += 4;
+	}
+}
+
+
+/*	Transform the normal of the given primitive vertex */
+
+static sqInt transformPrimitiveNormalbyrescale(float *pVertex, float *matrix, sqInt rescale) {
+    double dot;
+    double rx;
+    double ry;
+    double rz;
+    double x;
+    double y;
+    double z;
+
+	x = pVertex[PrimVtxNormalX];
+	y = pVertex[PrimVtxNormalY];
+	z = pVertex[PrimVtxNormalZ];
+	rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]));
+	ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]));
+	rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]));
+	if (rescale) {
+		dot = ((rx * rx) + (ry * ry)) + (rz * rz);
+		if (dot < 1.0e-20) {
+			rx = ry = rz = 0.0;
+		} else {
+			if (!(dot == 1.0)) {
+				dot = 1.0 / (sqrt(dot));
+				rx = rx * dot;
+				ry = ry * dot;
+				rz = rz * dot;
+			}
+		}
+	}
+	pVertex[PrimVtxNormalX] = (((float) rx));
+	pVertex[PrimVtxNormalY] = (((float) ry));
+	pVertex[PrimVtxNormalZ] = (((float) rz));
+}
+
+
+/*	Transform the normal of the given primitive vertex */
+
+static sqInt transformPrimitivePositionby(float *pVertex, float *matrix) {
+    double rw;
+    double rx;
+    double ry;
+    double rz;
+    double x;
+    double y;
+    double z;
+
+	x = pVertex[PrimVtxPositionX];
+	y = pVertex[PrimVtxPositionY];
+	z = pVertex[PrimVtxPositionZ];
+	rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]);
+	ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]);
+	rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]);
+	rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]);
+	if (rw == 1.0) {
+		pVertex[PrimVtxPositionX] = (((float) rx));
+		pVertex[PrimVtxPositionY] = (((float) ry));
+		pVertex[PrimVtxPositionZ] = (((float) rz));
+	} else {
+		if (rw == 0.0) {
+			rw = 0.0;
+		} else {
+			rw = 1.0 / rw;
+		}
+		pVertex[PrimVtxPositionX] = (((float) (rx * rw)));
+		pVertex[PrimVtxPositionY] = (((float) (ry * rw)));
+		pVertex[PrimVtxPositionZ] = (((float) (rz * rw)));
+	}
+}
+
+
+/*	Transform the position of the given primitive vertex assuming that 
+	matrix a41 = a42 = a43 = 0.0 and a44 = 1.0 */
+
+static sqInt transformPrimitivePositionFastby(float *pVertex, float *matrix) {
+    double rx;
+    double ry;
+    double rz;
+    double x;
+    double y;
+    double z;
+
+	x = pVertex[PrimVtxPositionX];
+	y = pVertex[PrimVtxPositionY];
+	z = pVertex[PrimVtxPositionZ];
+	rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]);
+	ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]);
+	rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]);
+	pVertex[PrimVtxPositionX] = (((float) rx));
+	pVertex[PrimVtxPositionY] = (((float) ry));
+	pVertex[PrimVtxPositionZ] = (((float) rz));
+}
+
+
+/*	Transform the position of the given primitive vertex assuming that 
+	matrix a14 = a24 = a34 = a41 = a42 = a43 = 0.0 and a44 = 1.0 */
+
+static sqInt transformPrimitivePositionFasterby(float *pVertex, float *matrix) {
+    double rx;
+    double ry;
+    double rz;
+    double x;
+    double y;
+    double z;
+
+	x = pVertex[PrimVtxPositionX];
+	y = pVertex[PrimVtxPositionY];
+	z = pVertex[PrimVtxPositionZ];
+	rx = ((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]));
+	ry = ((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]));
+	rz = ((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]));
+	pVertex[PrimVtxPositionX] = (((float) rx));
+	pVertex[PrimVtxPositionY] = (((float) ry));
+	pVertex[PrimVtxPositionZ] = (((float) rz));
+}
+
+
+/*	Transform the normal of the given primitive vertex */
+
+static sqInt transformPrimitiveRasterPositionby(float *pVertex, float *matrix) {
+    double rw;
+    double rx;
+    double ry;
+    double rz;
+    double x;
+    double y;
+    double z;
+
+	x = pVertex[PrimVtxPositionX];
+	y = pVertex[PrimVtxPositionY];
+	z = pVertex[PrimVtxPositionZ];
+	rx = (((x * (matrix[0])) + (y * (matrix[1]))) + (z * (matrix[2]))) + (matrix[3]);
+	ry = (((x * (matrix[4])) + (y * (matrix[5]))) + (z * (matrix[6]))) + (matrix[7]);
+	rz = (((x * (matrix[8])) + (y * (matrix[9]))) + (z * (matrix[10]))) + (matrix[11]);
+	rw = (((x * (matrix[12])) + (y * (matrix[13]))) + (z * (matrix[14]))) + (matrix[15]);
+	pVertex[PrimVtxRasterPosX] = (((float) rx));
+	pVertex[PrimVtxRasterPosY] = (((float) ry));
+	pVertex[PrimVtxRasterPosZ] = (((float) rz));
+	pVertex[PrimVtxRasterPosW] = (((float) rw));
+}
+
+
+/*	Transform the entire vertex array by the given matrices */
+/*	TODO: Check the actual trade-offs between vtxCount and analyzing */
+
+static sqInt transformVBcountbyandflags(float *vtxArray, sqInt vtxCount, float *modelViewMatrix, float *projectionMatrix, sqInt flags) {
+    sqInt hasNormals;
+    sqInt i;
+    sqInt mvFlags;
+    float *pVertex;
+    sqInt prFlags;
+    sqInt rescale;
+
+	mvFlags = analyzeMatrix(modelViewMatrix);
+	prFlags = analyzeMatrix(projectionMatrix);
+	pVertex = ((float *) vtxArray);
+
+	/* Check if we have to rescale the normals */
+
+	hasNormals = flags & VBVtxHasNormals;
+	if (hasNormals) {
+		if (mvFlags & FlagM44Identity) {
+			rescale = 0;
+		} else {
+			rescale = analyzeMatrix3x3Length(modelViewMatrix);
+		}
+	}
+	if ((mvFlags & FlagM44NoPerspective) && (prFlags == 0)) {
+		if ((mvFlags == FlagM44NoTranslation) == 0) {
+			for (i = 1; i <= vtxCount; i += 1) {
+				if (hasNormals) {
+					transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale);
+				}
+				transformPrimitivePositionFastby(pVertex, modelViewMatrix);
+				transformPrimitiveRasterPositionby(pVertex, projectionMatrix);
+				pVertex += PrimVertexSize;
+			}
+		} else {
+			for (i = 1; i <= vtxCount; i += 1) {
+				if (hasNormals) {
+					transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale);
+				}
+				transformPrimitivePositionFasterby(pVertex, modelViewMatrix);
+				transformPrimitiveRasterPositionby(pVertex, projectionMatrix);
+				pVertex += PrimVertexSize;
+			}
+		}
+		return null;
+	}
+	if ((mvFlags & prFlags) & FlagM44Identity) {
+		for (i = 1; i <= vtxCount; i += 1) {
+			pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]);
+			pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]);
+			pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]);
+			pVertex[PrimVtxRasterPosW] = 1.0;
+			pVertex += PrimVertexSize;
+		}
+		return null;
+	}
+	if (mvFlags & FlagM44Identity) {
+		for (i = 1; i <= vtxCount; i += 1) {
+			transformPrimitiveRasterPositionby(pVertex, projectionMatrix);
+			pVertex += PrimVertexSize;
+		}
+		return null;
+	}
+	if (prFlags & FlagM44Identity) {
+		for (i = 1; i <= vtxCount; i += 1) {
+			if (hasNormals) {
+				transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale);
+			}
+			if (mvFlags == (FlagM44NoPerspective + FlagM44NoPerspective)) {
+				transformPrimitivePositionFasterby(pVertex, modelViewMatrix);
+			} else {
+				if (mvFlags == FlagM44NoPerspective) {
+					transformPrimitivePositionFastby(pVertex, modelViewMatrix);
+				} else {
+					transformPrimitivePositionby(pVertex, modelViewMatrix);
+				}
+			}
+			pVertex[PrimVtxRasterPosX] = (pVertex[PrimVtxPositionX]);
+			pVertex[PrimVtxRasterPosY] = (pVertex[PrimVtxPositionY]);
+			pVertex[PrimVtxRasterPosZ] = (pVertex[PrimVtxPositionZ]);
+			pVertex[PrimVtxRasterPosW] = 1.0;
+			pVertex += PrimVertexSize;
+		}
+		return null;
+	}
+	for (i = 1; i <= vtxCount; i += 1) {
+		if (hasNormals) {
+			transformPrimitiveNormalbyrescale(pVertex, modelViewMatrix, rescale);
+		}
+		transformPrimitivePositionby(pVertex, modelViewMatrix);
+		transformPrimitiveRasterPositionby(pVertex, projectionMatrix);
+		pVertex += PrimVertexSize;
+	}
+}
+
+
+/*	Load the word based array of size count from the given oop */
+
+static void* vbLoadArraysize(sqInt oop, sqInt count) {
+	if (oop == null) {
+		interpreterProxy->primitiveFail();
+		return null;
+	}
+	if (oop == (interpreterProxy->nilObject())) {
+		return null;
+	}
+	if (!(interpreterProxy->isWords(oop))) {
+		interpreterProxy->primitiveFail();
+		return null;
+	}
+	if (!((interpreterProxy->slotSizeOf(oop)) == count)) {
+		interpreterProxy->primitiveFail();
+		return null;
+	}
+	return interpreterProxy->firstIndexableField(oop);
+}
+
+
+#ifdef SQUEAK_BUILTIN_PLUGIN
+
+
+void* Squeak3D_exports[][3] = {
+	{"Squeak3D", "b3dShaderVersion", (void*)b3dShaderVersion},
+	{"Squeak3D", "b3dTransformPrimitiveNormal", (void*)b3dTransformPrimitiveNormal},
+	{"Squeak3D", "b3dClipPolygon", (void*)b3dClipPolygon},
+	{"Squeak3D", "b3dOrthoNormInverseMatrix", (void*)b3dOrthoNormInverseMatrix},
+	{"Squeak3D", "b3dTransformVertexBuffer", (void*)b3dTransformVertexBuffer},
+	{"Squeak3D", "b3dComputeMinZ", (void*)b3dComputeMinZ},
+	{"Squeak3D", "b3dInitializeRasterizerState", (void*)b3dInitializeRasterizerState},
+	{"Squeak3D", "b3dDetermineClipFlags", (void*)b3dDetermineClipFlags},
+	{"Squeak3D", "getModuleName", (void*)getModuleName},
+	{"Squeak3D", "setInterpreter", (void*)setInterpreter},
+	{"Squeak3D", "b3dTransformPrimitiveRasterPosition", (void*)b3dTransformPrimitiveRasterPosition},
+	{"Squeak3D", "primitiveSetBitBltPlugin", (void*)primitiveSetBitBltPlugin},
+	{"Squeak3D", "b3dTransformMatrixWithInto", (void*)b3dTransformMatrixWithInto},
+	{"Squeak3D", "b3dStartRasterizer", (void*)b3dStartRasterizer},
+	{"Squeak3D", "b3dShadeVertexBuffer", (void*)b3dShadeVertexBuffer},
+	{"Squeak3D", "b3dRasterizerVersion", (void*)b3dRasterizerVersion},
+	{"Squeak3D", "b3dInitPrimitiveObject", (void*)b3dInitPrimitiveObject},
+	{"Squeak3D", "b3dLoadVertexBuffer", (void*)b3dLoadVertexBuffer},
+	{"Squeak3D", "b3dTransformDirection", (void*)b3dTransformDirection},
+	{"Squeak3D", "moduleUnloaded", (void*)moduleUnloaded},
+	{"Squeak3D", "b3dPrimitiveTextureSize", (void*)b3dPrimitiveTextureSize},
+	{"Squeak3D", "b3dComputeMinIndexZ", (void*)b3dComputeMinIndexZ},
+	{"Squeak3D", "b3dMapVertexBuffer", (void*)b3dMapVertexBuffer},
+	{"Squeak3D", "initialiseModule", (void*)initialiseModule},
+	{"Squeak3D", "b3dTransformerVersion", (void*)b3dTransformerVersion},
+	{"Squeak3D", "b3dTransposeMatrix", (void*)b3dTransposeMatrix},
+	{"Squeak3D", "b3dPrimitiveNextClippedTriangle", (void*)b3dPrimitiveNextClippedTriangle},
+	{"Squeak3D", "b3dTransformPoint", (void*)b3dTransformPoint},
+	{"Squeak3D", "b3dTransformPrimitivePosition", (void*)b3dTransformPrimitivePosition},
+	{"Squeak3D", "b3dPrimitiveObjectSize", (void*)b3dPrimitiveObjectSize},
+	{"Squeak3D", "b3dLoadIndexArray", (void*)b3dLoadIndexArray},
+	{"Squeak3D", "b3dInplaceHouseHolderInvert", (void*)b3dInplaceHouseHolderInvert},
+	{NULL, NULL, NULL}
+};
+
+
+#endif /* ifdef SQ_BUILTIN_PLUGIN */
+
Modified: trunk/platforms/unix/src/plugins.ext
===================================================================
--- trunk/platforms/unix/src/plugins.ext	2011-01-23 07:34:41 UTC (rev 2354)
+++ trunk/platforms/unix/src/plugins.ext	2011-01-23 09:41:21 UTC (rev 2355)
@@ -1,2 +1,2 @@
 # Automatically generated makefile include for external plugins
-EXTERNAL_PLUGINS = B3DAcceleratorPlugin ClipboardExtendedPlugin DBusPlugin SqueakFFIPrims FileCopyPlugin GStreamerPlugin HostWindowPlugin KedamaPlugin KedamaPlugin2 MIDIPlugin Mpeg3Plugin UUIDPlugin AioPlugin UnixOSProcessPlugin XDisplayControlPlugin
+EXTERNAL_PLUGINS = B3DAcceleratorPlugin Squeak3D ClipboardExtendedPlugin DBusPlugin SqueakFFIPrims FileCopyPlugin GStreamerPlugin HostWindowPlugin KedamaPlugin KedamaPlugin2 MIDIPlugin Mpeg3Plugin RomePlugin UUIDPlugin AioPlugin UnixOSProcessPlugin XDisplayControlPlugin
Modified: trunk/platforms/unix/src/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c
===================================================================
--- trunk/platforms/unix/src/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c	2011-01-23 07:34:41 UTC (rev 2354)
+++ trunk/platforms/unix/src/vm/intplugins/ADPCMCodecPlugin/ADPCMCodecPlugin.c	2011-01-23 09:41:21 UTC (rev 2355)
@@ -1,4 +1,4 @@
-/* Automatically generated from Squeak on 23 January 2011 3:55:22 pm 
+/* Automatically generated from Squeak on 23 January 2011 6:33:58 pm 
    by VMMaker 4.4.7
  */
 
Modified: trunk/platforms/unix/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c
===================================================================
--- trunk/platforms/unix/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c	2011-01-23 07:34:41 UTC (rev 2354)
+++ trunk/platforms/unix/src/vm/intplugins/SoundGenerationPlugin/SoundGenerationPlugin.c	2011-01-23 09:41:21 UTC (rev 2355)
@@ -1,4 +1,4 @@
-/* Automatically generated from Squeak on 23 January 2011 3:55:48 pm 
+/* Automatically generated from Squeak on 23 January 2011 6:34:01 pm 
    by VMMaker 4.4.7
  */
 
Modified: trunk/platforms/unix/src/vm/sqNamedPrims.h
===================================================================
--- trunk/platforms/unix/src/vm/sqNamedPrims.h	2011-01-23 07:34:41 UTC (rev 2354)
+++ trunk/platforms/unix/src/vm/sqNamedPrims.h	2011-01-23 09:41:21 UTC (rev 2355)
@@ -1,4 +1,4 @@
-/* Automatically generated from Squeak on 23 January 2011 3:55:49 pm 
+/* Automatically generated from Squeak on 23 January 2011 6:34:01 pm 
    by VMMaker 4.4.7
  */
 /* This is an automatically generated table of all builtin modules in the VM */


More information about the Vm-dev mailing list