From 3d3540772cf9865f6383622fb753a89154a57e6f Mon Sep 17 00:00:00 2001 From: Eliot Miranda Date: Tue, 15 Oct 2024 13:04:55 -0700 Subject: [PATCH] CogVM source as per Name: VMMaker.oscog-eem.3461 Slang: Adapt to Compiler-eem.508 (better comment formatting). Include compiler package version in Slang version comment added to source files. Plugins: Add get/set working directory primitives to FilePlugin. Fix a type mismatch in the BalloonEnginePlugin. Split the transform/shape loading code in the BalloonEnginePlugin (B2DPlugin) so that it tests for short points once per primituve invocation (which allows for accurate simulation via a typed firstIndexableField:type:). Add primitiveRenderAllScanlines and primitiveGetAllStats to reduce number of primitive invocations substantially, and achieve about a 15% decrease in TTCFont character rendering times. --- .../Cross/plugins/FilePlugin/FilePlugin.h | 5 +- platforms/iOS/plugins/FilePlugin/sqUnixFile.c | 362 +-- .../Common/Classes/sqSqueakFileDirectoryAPI.m | 9 - .../unix/plugins/FilePlugin/sqUnixFile.c | 32 +- platforms/win32/vm/sqWin32Directory.c | 32 + platforms/win32/vm/sqWin32Main.c | 9 +- scripts/revertIfEssentiallyUnchanged | 4 +- src/plugins/B2DPlugin/B2DPlugin.c | 2323 +++++++++++------ src/plugins/FilePlugin/FilePlugin.c | 122 +- 9 files changed, 1758 insertions(+), 1140 deletions(-) diff --git a/platforms/Cross/plugins/FilePlugin/FilePlugin.h b/platforms/Cross/plugins/FilePlugin/FilePlugin.h index 1ef5a1f221..b3963eee67 100644 --- a/platforms/Cross/plugins/FilePlugin/FilePlugin.h +++ b/platforms/Cross/plugins/FilePlugin/FilePlugin.h @@ -82,6 +82,9 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char *nameString /* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, sqInt *isDirectory, squeakFileOffsetType *sizeIfFile, sqInt *posixPermissions, sqInt *isSymlink); -sqInt dir_PathToWorkingDir(char *pathName, sqInt pathNameMax); + // copy working directory name into path answering byte len, or negative errno +sqInt dir_GetPathToWorkingDirAsUTF8(char *pathName, sqInt pathNameMax); + // set working directory to pathName, answering 0 if ok, otherwise errno +sqInt dir_SetPathToWorkingDirAsUTF8(char *pathName); sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator); sqInt dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator); diff --git a/platforms/iOS/plugins/FilePlugin/sqUnixFile.c b/platforms/iOS/plugins/FilePlugin/sqUnixFile.c index d3396a2b10..65bbb08c33 100644 --- a/platforms/iOS/plugins/FilePlugin/sqUnixFile.c +++ b/platforms/iOS/plugins/FilePlugin/sqUnixFile.c @@ -1,361 +1 @@ -/* sqUnixFile.c -- directory operations for Unix - * - * Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors - * listed elsewhere in this file. - * All rights reserved. - * - * This file is part of Unix Squeak. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* Author: Ian.Piumarta@INRIA.Fr - */ - -#include "sq.h" -#include "sqVirtualMachine.h" -#include "FilePlugin.h" -#include "sqUnixCharConv.h" - -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif -#endif - -#ifdef HAVE_UNISTD_H -# include -# include -#endif - -#include -#include -#include -#include -#include - -/*** - The interface to the directory primitive is path based. - That is, the client supplies a Squeak string describing - the path to the directory on every call. To avoid traversing - this path on every call, a cache is maintained of the last - path seen, along with the Mac volume and folder reference - numbers corresponding to that path. -***/ - -/*** Constants ***/ -#define ENTRY_FOUND 0 -#define NO_MORE_ENTRIES 1 -#define BAD_PATH 2 - -#define DELIMITER '/' - -/*** Variables ***/ -char lastPath[MAXPATHLEN+1]; -int lastPathValid = false; -int lastIndex= -1; -DIR *openDir= 0; - - -/*** Functions ***/ - -static sqInt -fileAsSqueakTime(time_t unixTime) -{ -extern struct VirtualMachine* interpreterProxy; - - /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970: 17 leap years - and 52 non-leap years later than Squeak. */ - if (interpreterProxy->fileTimesInUTC()) - return unixTime + (52*365UL + 17*366UL) * 24*60*60UL; - -#ifdef HAVE_TM_GMTOFF - unixTime+= localtime(&unixTime)->tm_gmtoff; -#else -# ifdef HAVE_TIMEZONE - unixTime+= ((daylight) * 60*60) - timezone; -# else -# error: cannot determine timezone correction -# endif -#endif - /* Squeak epoch is Jan 1, 1901. Unix epoch is Jan 1, 1970: 17 leap years - and 52 non-leap years later than Squeak. */ - return unixTime + ((52*365UL + 17*366UL) * 24*60*60UL); -} - -sqInt dir_Create(char *pathString, sqInt pathStringLength) -{ - /* Create a new directory with the given path. By default, this - directory is created relative to the cwd. */ - char name[MAXPATHLEN+1]; - if (pathStringLength >= MAXPATHLEN) - return false; - if (!sq2uxPath(pathString, pathStringLength, name, MAXPATHLEN, 1)) - return false; - return mkdir(name, 0777) == 0; /* rwxrwxrwx & ~umask */ -} - - -sqInt dir_Delete(char *pathString, sqInt pathStringLength) -{ - /* Delete the existing directory with the given path. */ - char name[MAXPATHLEN+1]; - if (pathStringLength >= MAXPATHLEN) - return false; - if (!sq2uxPath(pathString, pathStringLength, name, MAXPATHLEN, 1)) - return false; - if (lastPathValid && !strcmp(lastPath, name)) - { - closedir(openDir); - lastPathValid= false; - lastIndex= -1; - lastPath[0]= '\0'; - } - return rmdir(name) == 0; -} - - -sqInt dir_Delimitor(void) -{ - return DELIMITER; -} - - -static int maybeOpenDir(char *unixPath) -{ - /* if the last opendir was to the same directory, re-use the directory - pointer from last time. Otherwise close the previous directory, - open the new one, and save its name. Return true if the operation - was successful, false if not. */ - if (!lastPathValid || strcmp(lastPath, unixPath)) - { - /* invalidate the old, open the new */ - if (lastPathValid) - closedir(openDir); - lastPathValid= false; - strncpy(lastPath, unixPath, MAXPATHLEN); - if ((openDir= opendir(unixPath)) == 0) - return false; - lastPathValid= true; - lastIndex= 0; /* first entry is index 1 */ - } - return true; -} - -sqInt dir_Lookup(char *pathString, sqInt pathStringLength, sqInt index, -/* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, - sqInt *isDirectory, squeakFileOffsetType *sizeIfFile, sqInt * posixPermissions, sqInt *isSymlink) -{ - /* Lookup the index-th entry of the directory with the given path, starting - at the root of the file system. Set the name, name length, creation date, - creation time, directory flag, and file size (if the entry is a file). - Return: 0 if a entry is found at the given index - 1 if the directory has fewer than index entries - 2 if the given path has bad syntax or does not reach a directory - */ - - int i; - int nameLen= 0; - struct dirent *dirEntry= 0; - char unixPath[MAXPATHLEN+1]; - struct stat statBuf; - - /* default return values */ - *name = 0; - *nameLength = 0; - *creationDate = 0; - *modificationDate = 0; - *isDirectory = false; - *sizeIfFile = 0; - *posixPermissions = 0; - *isSymlink = false; - - if (pathStringLength == 0) - strcpy(unixPath, "."); - else if (!sq2uxPath(pathString, pathStringLength, unixPath, MAXPATHLEN, 1)) - return BAD_PATH; - - /* get file or directory info */ - if (!maybeOpenDir(unixPath)) - return BAD_PATH; - - if (++lastIndex == index) - index= 1; /* fake that the dir is rewound and we want the first entry */ - else - { - rewinddir(openDir); /* really rewind it, and read to the index */ - lastIndex= index; - } - - for (i= 0; i < index; i++) - { - nextEntry: - do - { - errno= 0; - dirEntry= readdir(openDir); - } - while ((dirEntry == 0) && (errno == EINTR)); - - if (!dirEntry) - return NO_MORE_ENTRIES; - - nameLen= NAMLEN(dirEntry); - - /* ignore '.' and '..' (these are not *guaranteed* to be first) */ - if (nameLen < 3 && dirEntry->d_name[0] == '.') - if (nameLen == 1 || dirEntry->d_name[1] == '.') - goto nextEntry; - } - - *nameLength= ux2sqPath(dirEntry->d_name, nameLen, name, MAXPATHLEN, 0); - - { - char terminatedName[MAXPATHLEN+1]; - if(nameLen > MAXPATHLEN) - return BAD_PATH; - strncpy(terminatedName, dirEntry->d_name, nameLen); - terminatedName[nameLen]= '\0'; - if(strlen(unixPath) + 1 + nameLen > MAXPATHLEN) - return BAD_PATH; - strcat(unixPath, "/"); - strcat(unixPath, terminatedName); - if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) - { - /* We can't stat the entry, but failing here would invalidate - the whole directory --bertf */ - return ENTRY_FOUND; - } - } - - /* last change time */ - *creationDate= fileAsSqueakTime(statBuf.st_ctime); - /* modification time */ - *modificationDate= fileAsSqueakTime(statBuf.st_mtime); - - if (S_ISDIR(statBuf.st_mode)) - *isDirectory= true; - else - *sizeIfFile= statBuf.st_size; - - *isSymlink = S_ISLNK(statBuf.st_mode); - *posixPermissions = statBuf.st_mode & 0777; - - return ENTRY_FOUND; -} - - -sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char* nameString, sqInt nameStringLength, -/* outputs: */ char *name, sqInt *nameLength, sqInt *creationDate, sqInt *modificationDate, - sqInt *isDirectory, squeakFileOffsetType *sizeIfFile, sqInt *posixPermissions, sqInt *isSymlink) -{ - /* Lookup the given name in the given directory, - Set the name, name length, creation date, - creation time, directory flag, and file size (if the entry is a file). - Return: 0 if a entry is found at the given index - 1 if there is no such entry in the directory - 2 if the given path has bad syntax or does not reach a directory - */ - - char unixPath[MAXPATHLEN+1]; - struct stat statBuf; - - /* default return values */ - *name = 0; - *nameLength = 0; - *creationDate = 0; - *modificationDate = 0; - *isDirectory = false; - *sizeIfFile = 0; - *posixPermissions = 0; - *isSymlink = false; - - if (pathStringLength == 0) - strcpy(unixPath, "."); - else if (!sq2uxPath(pathString, pathStringLength, unixPath, MAXPATHLEN, 1)) - return BAD_PATH; - - char terminatedName[MAXPATHLEN+1]; - if(nameStringLength > MAXPATHLEN) - return BAD_PATH; - strncpy(terminatedName, nameString, nameStringLength); - terminatedName[nameStringLength]= '\0'; - if(strlen(unixPath) + 1 + nameStringLength > MAXPATHLEN) - return BAD_PATH; - strcat(unixPath, "/"); - strcat(unixPath, terminatedName); - if (stat(unixPath, &statBuf) && lstat(unixPath, &statBuf)) { - return NO_MORE_ENTRIES; - } - - /* To match the results of dir_Lookup, copy back the file name */ - *nameLength = ux2sqPath(nameString, nameStringLength, name, 256, 0); - - /* last change time */ - *creationDate= fileAsSqueakTime(statBuf.st_ctime); - /* modification time */ - *modificationDate= fileAsSqueakTime(statBuf.st_mtime); - - if (S_ISDIR(statBuf.st_mode)) - *isDirectory= true; - else - *sizeIfFile= statBuf.st_size; - - *isSymlink = S_ISLNK(statBuf.st_mode); - *posixPermissions = statBuf.st_mode & 0777; - - return ENTRY_FOUND; -} - -/* unix files are untyped, and the creator is correct by default */ - - -sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) -{ - return true; -} - -sqInt dir_GetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) -{ - return true; -} - - -/* - * The following is useful in a debugging context when the VM's output has been - * directed to a log file. It binds stdout to /dev/tty, arranging that output - * of debugging print routines such as printOop appear on stdout. - */ -void -sqStdoutToDevTTY() -{ - if (!freopen("/dev/tty","w",stdout)) - perror("sqStdoutToDevTTY freopen(\"/dev/tty\",\"w\",stdout):"); -} +#include "../../../unix/plugins/FilePlugin/sqUnixFile.c" diff --git a/platforms/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.m b/platforms/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.m index 19b820b44b..9dd6a9f842 100644 --- a/platforms/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.m +++ b/platforms/iOS/vm/Common/Classes/sqSqueakFileDirectoryAPI.m @@ -216,12 +216,3 @@ sqInt sqGetFilenameFromString(char * aCharBuffer, char * aFilenameString, } return 0; } - -/* This routine is exposed but no-one seems to call it from the VM - in the past the macintosh VM used this to set the working directory based - on where the VM was opened from, but it seems now post os-x no-one uses it */ - -sqInt dir_PathToWorkingDir(char *pathName, sqInt pathNameMax){ - //API Documented - return 0; -} diff --git a/platforms/unix/plugins/FilePlugin/sqUnixFile.c b/platforms/unix/plugins/FilePlugin/sqUnixFile.c index 82efc9f6b0..c020f2cf1a 100644 --- a/platforms/unix/plugins/FilePlugin/sqUnixFile.c +++ b/platforms/unix/plugins/FilePlugin/sqUnixFile.c @@ -111,7 +111,9 @@ extern struct VirtualMachine* interpreterProxy; } -void +#if !BUILD_FOR_OSX // On iOS/OSX these are elsewhere + +static void sqCloseDir() { /* Ensure that the cached open directory is closed */ @@ -122,8 +124,6 @@ sqCloseDir() lastPath[0]= '\0'; } - - sqInt dir_Create(char *pathString, sqInt pathStringLength) { /* Create a new directory with the given path. By default, this @@ -349,8 +349,30 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathStringLength, char* nameString return ENTRY_FOUND; } -/* unix files are untyped, and the creator is correct by default */ +#endif // BUILD_FOR_OSX +/* UTF8 access to the working directory */ +// copy working directory name into path answering byte len, or negative errno +sqInt +dir_GetPathToWorkingDirAsUTF8(char *pathName, sqInt pathNameMax) +{ + return getcwd(pathName,pathNameMax) + ? strlen(pathName) + : -errno; +} + +// set working directory to pathName, answering 0 if ok, otherwise errno +sqInt +dir_SetPathToWorkingDirAsUTF8(char *pathName) +{ + return chdir(pathName) + ? errno + : 0; +} + +#if !BUILD_FOR_OSX + +/* unix files are untyped, and the creator is correct by default */ sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { @@ -374,3 +396,5 @@ sqStdoutToDevTTY() if (!freopen("/dev/tty","w",stdout)) perror("sqStdoutToDevTTY freopen(\"/dev/tty\",\"w\",stdout):"); } + +#endif // BUILD_FOR_OSX diff --git a/platforms/win32/vm/sqWin32Directory.c b/platforms/win32/vm/sqWin32Directory.c index 42c4af02b0..cbb76db032 100644 --- a/platforms/win32/vm/sqWin32Directory.c +++ b/platforms/win32/vm/sqWin32Directory.c @@ -499,6 +499,38 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn } +// UTF8 access to the working directory +// copy working directory name into path answering byte len, or negative errno +sqInt +dir_GetPathToWorkingDirAsUTF8(char *pathName, sqInt pathNameMax) +{ + WCHAR buff[MAX_PATH+1]; + sqInt nWChars, nBytes; + + if ((nWChars = GetCurrentDirectoryW(MAX_PATH+1,buff)) > 0) { + nBytes = WideCharToMultiByte(CP_UTF8, 0, buff, nWChars, + pathName, pathNameMax, 0, 0); + if (nBytes > 0) + return nBytes; + } + return 0 - GetLastError(); +} + +// set working directory to pathName, answering 0 if ok, otherwise errno +sqInt +dir_SetPathToWorkingDirAsUTF8(char *pathName) +{ + WCHAR buff[MAX_PATH+1]; + + if (!MultiByteToWideChar(CP_UTF8, 0, pathName, -1, buff, MAX_PATH+1)) + return GetLastError(); + + return SetCurrentDirectoryW(buff) + ? 0 + : GetLastError(); +} + +// Compatibility with the Mac sqInt dir_SetMacFileTypeAndCreator(char *filename, sqInt filenameSize, char *fType, char *fCreator) { diff --git a/platforms/win32/vm/sqWin32Main.c b/platforms/win32/vm/sqWin32Main.c index f63cac13eb..2b51ae660f 100755 --- a/platforms/win32/vm/sqWin32Main.c +++ b/platforms/win32/vm/sqWin32Main.c @@ -1712,7 +1712,12 @@ sqMain(int argc, char *argv[]) # endif #endif /* !NO_FIRST_LEVEL_EXCEPTION_HANDLER */ -#if !NewspeakVM + // Generally a bad idea. Used to be done on startup on Windows. Used to + // be done a long time ago on MacOS. But it gets in teh way of real apps + // that want to run in specific places, and the image's FileDirectory + // facilities don't depend on the working directory; instead they depend + // omn the image's path name +#if SET_WORKING_DIR_TO_IMAGE_DIR_ON_STARTUP /* set the CWD to the image location */ if (*imageNameW) { WCHAR path[MAX_PATH+1], *ptr; @@ -1724,7 +1729,7 @@ sqMain(int argc, char *argv[]) SetCurrentDirectoryW(path); } } -#endif /* !NewspeakVM */ +#endif // SET_WORKING_DIR_TO_IMAGE_DIR_ON_STARTUP /* display the splash screen */ ShowSplashScreen(); diff --git a/scripts/revertIfEssentiallyUnchanged b/scripts/revertIfEssentiallyUnchanged index 9b89166a66..da4217b2ce 100755 --- a/scripts/revertIfEssentiallyUnchanged +++ b/scripts/revertIfEssentiallyUnchanged @@ -15,14 +15,14 @@ for f in "$@"; do *M*) ;; *) continue esac - RESULT="`git diff -w -- "$f" | grep '^[+-]' | egrep -v ' VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]* uuid:| Cog[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| 3DICC-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| CryptographyPlugins[a-z.-][a-z.-]*\.[0-9][0-9]* | VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]*[ "]|static const char \*moduleName.*" INT_EXT;| Cog[-.][a-z][a-z-]*\.[0-9][0-9]* | Qwaq-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* | VMConstruction-Plugins-OSProcessPlugin[a-z.-][a-z.-]*\.[0-9][0-9]* | Sound[-.][a-z][a-z]*\.[0-9][0-9]* uuid:|^[+-]const char \*interpreterVersion = |^\-\-\-|^\+\+\+|^[+-]$'`" + RESULT="`git diff -w -- "$f" | grep '^[+-]' | egrep -vi ' VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]* uuid:|\([* ]*Compiler[-.][a-z][a-z-]*\.[0-9][0-9]*| Cog[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| 3DICC-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| CryptographyPlugins[a-z.-][a-z.-]*\.[0-9][0-9]* | VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]*[ "]|static const char \*moduleName.*" INT_EXT;| Cog[-.][a-z][a-z-]*\.[0-9][0-9]* | Qwaq-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* | VMConstruction-Plugins-OSProcessPlugin[a-z.-][a-z.-]*\.[0-9][0-9]* | Sound[-.][a-z][a-z]*\.[0-9][0-9]* uuid:|^[+-]const char \*interpreterVersion = |^\-\-\-|^\+\+\+|^[+-]$'`" if [ -z "$TEST" ]; then test -z "$RESULT" && (echo reverting "$f"; git checkout -- "$f") elif [ "$TEST" = "-T" ]; then test -z "$RESULT" && echo $f essentially unchanged || echo $f changed else echo "testing; no output implies this would be reverted" - git diff -w -- "$f" | grep '^[+-]' | egrep -v ' VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]* uuid:| Cog[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| 3DICC-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| CryptographyPlugins[a-z.-][a-z.-]*\.[0-9][0-9]* | VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]*[ "]|static const char \*moduleName.*" INT_EXT;| Cog[-.][a-z][a-z-]*\.[0-9][0-9]* | Qwaq-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* | VMConstruction-Plugins-OSProcessPlugin[a-z.-][a-z.-]*\.[0-9][0-9]* | Sound[-.][a-z][a-z]*\.[0-9][0-9]* uuid:|^[+-]const char \*interpreterVersion =|^\-\-\-|^\+\+\+|^[+-]$' + git diff -w -- "$f" | grep '^[+-]' | egrep -vi ' VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]* uuid:|\([* ]*Compiler[-.][a-z][a-z-]*\.[0-9][0-9]| Cog[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| 3DICC-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* uuid:| CryptographyPlugins[a-z.-][a-z.-]*\.[0-9][0-9]* | VMMaker[-.][a-z][a-z-]*\.[0-9][0-9]*[ "]|static const char \*moduleName.*" INT_EXT;| Cog[-.][a-z][a-z-]*\.[0-9][0-9]* | Qwaq-Plugins[-.][a-z][a-z]*\.[0-9][0-9]* | VMConstruction-Plugins-OSProcessPlugin[a-z.-][a-z.-]*\.[0-9][0-9]* | Sound[-.][a-z][a-z]*\.[0-9][0-9]* uuid:|^[+-]const char \*interpreterVersion =|^\-\-\-|^\+\+\+|^[+-]$' fi fi done diff --git a/src/plugins/B2DPlugin/B2DPlugin.c b/src/plugins/B2DPlugin/B2DPlugin.c index 671ee9e47e..4cb29c7bc6 100644 --- a/src/plugins/B2DPlugin/B2DPlugin.c +++ b/src/plugins/B2DPlugin/B2DPlugin.c @@ -1,9 +1,10 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 + VMPluginCodeGenerator VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c + (Compiler-eem.508) from - BalloonEnginePlugin VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 + BalloonEnginePlugin VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c */ -static char __buildInfo[] = "BalloonEnginePlugin VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 " __DATE__ ; +static char __buildInfo[] = "BalloonEnginePlugin VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c " __DATE__ ; #include "config.h" @@ -292,12 +293,11 @@ static sqInt insertToAETbeforeIndex(sqInt edge, sqInt index); static sqInt isEdge(sqInt edge); static sqInt isFillOkay(sqInt fill); static sqInt loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqInt wideFlag); -static sqInt loadArrayShapenSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill); -static sqInt loadArrayTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadBeziersegmentleftFillrightFilloffset(sqInt bezier, sqInt index, sqInt leftFillIndex, sqInt rightFillIndex, sqInt yOffset); static sqInt loadBitBltFrom(sqInt bbObj); static int * loadBitsFrom(sqInt bmFill); -static sqInt loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList, sqInt pointsShort); +static sqInt loadCompressedShapeFromIntPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList); +static sqInt loadCompressedShapeFromShortPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(short *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList); static int loadEdgeStateFrom(sqInt edgeOop); static sqInt loadEdgeTransformFrom(sqInt transformOop); static sqInt loadFillOrientationfromalongnormalwidthheight(sqInt fill, int *point1, int *point2, int *point3, sqInt fillWidth, sqInt fillHeight); @@ -307,12 +307,12 @@ static sqInt loadOvalSegmentwhcxcy(sqInt seg, sqInt w, sqInt h, sqInt cx, sqInt static sqInt loadOvallineFillleftFillrightFill(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill); static sqInt loadPointfrom(int *pointArray, sqInt pointOop); static sqInt loadRenderingState(void); -static sqInt loadShapenSegmentsfilllineWidthlineFillpointsShort(int *points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt pointsShort); +static sqInt loadShapeFromArraynSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill); static sqInt loadSpanBufferFrom(sqInt spanOop); +static sqInt loadTransformFromArrayintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadWideBezierlineFillleftFillrightFilln(sqInt lineWidth, sqInt lineFill, sqInt leftFill, sqInt rightFill, sqInt nSegments); static sqInt loadWideLinefromtolineFillleftFillrightFill(sqInt lineWidth, int *p1, int *p2, sqInt lineFill, sqInt leftFill, sqInt rightFill); -static sqInt loadWordTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n); static sqInt loadWorkBufferFrom(sqInt wbOop); EXPORT(sqInt) moduleUnloaded(char *aModuleName); static sqInt moveAETEntryFromedgex(sqInt index, sqInt edge, sqInt xValue); @@ -334,6 +334,7 @@ EXPORT(sqInt) primitiveDisplaySpanBuffer(void); EXPORT(sqInt) primitiveDoProfileStats(void); EXPORT(sqInt) primitiveFinishedProcessing(void); EXPORT(sqInt) primitiveGetAALevel(void); +EXPORT(sqInt) primitiveGetAllStats(void); EXPORT(sqInt) primitiveGetBezierStats(void); EXPORT(sqInt) primitiveGetClipRect(void); EXPORT(sqInt) primitiveGetCounts(void); @@ -351,6 +352,7 @@ EXPORT(sqInt) primitiveNextFillEntry(void); EXPORT(sqInt) primitiveNextGlobalEdgeEntry(void); EXPORT(sqInt) primitiveRegisterExternalEdge(void); EXPORT(sqInt) primitiveRegisterExternalFill(void); +EXPORT(sqInt) primitiveRenderAllScanlines(void); EXPORT(sqInt) primitiveRenderImage(void); EXPORT(sqInt) primitiveRenderScanline(void); EXPORT(sqInt) primitiveSetAALevel(void); @@ -439,6 +441,8 @@ static sqInt (*isPointers)(sqInt oop); static sqInt (*isWords)(sqInt oop); static sqInt (*makePointwithxValueyValue)(sqInt xValue, sqInt yValue); static sqInt (*methodArgumentCount)(void); +static sqInt (*methodReturnInteger)(sqInt integer); +static sqInt (*methodReturnReceiver)(void); static sqInt (*nilObject)(void); static sqInt (*pop)(sqInt nItems); static sqInt (*popthenPush)(sqInt nItems, sqInt oop); @@ -490,6 +494,8 @@ extern sqInt isPointers(sqInt oop); extern sqInt isWords(sqInt oop); extern sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue); extern sqInt methodArgumentCount(void); +extern sqInt methodReturnInteger(sqInt integer); +extern sqInt methodReturnReceiver(void); extern sqInt nilObject(void); extern sqInt pop(sqInt nItems); extern sqInt popthenPush(sqInt nItems, sqInt oop); @@ -512,7 +518,7 @@ extern #endif struct VirtualMachine* interpreterProxy; static void * loadBBFn; -static const char *moduleName = "B2DPlugin VMMaker.oscog-eem.3456 " INT_EXT; +static const char *moduleName = "B2DPlugin VMMaker.oscog-eem.3461 " INT_EXT; static int* objBuffer; static sqInt objUsed; static unsigned int* spanBuffer; @@ -565,6 +571,7 @@ addEdgeToGET(sqInt edge) if (!(allocateGETEntry(1))) { return 0; } + /* Install edge in the GET */ getBuffer[workBuffer[GWGETUsed]] = edge; /* getUsedPut: */ @@ -583,10 +590,13 @@ adjustWideBezierLeftwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOff int lastY; ((objBuffer + bezier) + GBUpdateData)[GBUpdateX] = ((((objBuffer + bezier) + GBUpdateData)[GBUpdateX]) - (lineOffset * 0x100)); + /* Set the lastX/Y value of the second curve lineWidth pixels right/down */ lastX = ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateX]; ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateX] = (lastX + ((lineWidth - lineOffset) * 0x100)); + /* Set lineWidth pixels down */ lastY = ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateY]; ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateY] = (lastY + (lineWidth * 0x100)); + /* Record the last X value */ /* #bezierFinalXOf:put: #obj:at:put: */ objBuffer[bezier + GBFinalX] = (endX - lineOffset); @@ -604,12 +614,14 @@ adjustWideBezierRightwidthoffsetendX(sqInt bezier, sqInt lineWidth, sqInt lineOf int lastY; ((objBuffer + bezier) + GBUpdateData)[GBUpdateX] = ((((objBuffer + bezier) + GBUpdateData)[GBUpdateX]) + (lineOffset * 0x100)); + /* Set the lastX/Y value of the second curve lineWidth pixels right/down + Set lineWidth-lineOffset pixels left */ lastX = ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateX]; ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateX] = (lastX - ((lineWidth - lineOffset) * 0x100)); - - /* Set lineWidth pixels down */ lastY = ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateY]; + /* Set lineWidth pixels down */ ((objBuffer + bezier) + GBWideUpdateData)[GBUpdateY] = (lastY + (lineWidth * 0x100)); + /* Record the last X value */ /* #bezierFinalXOf:put: #obj:at:put: */ objBuffer[bezier + GBFinalX] = ((endX - lineOffset) + lineWidth); @@ -642,9 +654,8 @@ adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX) lineOffset = baseWidth / 2; lineWidth = objBuffer[line + GLWideWidth]; xDir = objBuffer[line + GLXDirection]; - - /* Adjust the start of the line to fill an entire rectangle */ deltaX = nextX - lastX; + /* Adjust the start of the line to fill an entire rectangle */ if (yEntry < baseWidth) { if (xDir < 0) { /* effectively adding */ @@ -657,6 +668,7 @@ adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX) objBuffer[line + GEXValue] = lastX; } } + /* Adjust the end of x-major lines */ if (!(yExit + lineOffset)) { if (xDir > 0) { lineWidth -= objBuffer[line + GLXIncrement]; @@ -669,6 +681,7 @@ adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX) objBuffer[line + GEXValue] = lastX; } } + /* Adjust the end of the line to fill an entire rectangle */ if ((yExit + lineOffset) > 0) { if (xDir < 0) { /* effectively subtracting */ @@ -681,6 +694,7 @@ adjustWideLineafterSteppingFromto(sqInt line, sqInt lastX, sqInt nextX) lineWidth -= deltaX; } } + /* Store the manipulated line width back */ /* #wideLineWidthOf:put: #obj:at:put: */ objBuffer[line + GLWideWidth] = lineWidth; @@ -797,11 +811,12 @@ checkCompressedFills(sqInt indexList) if (!(isWords(indexList))) { return 0; } + /* Then check the fill entries */ length = slotSizeOf(indexList); fillPtr = firstIndexableField(indexList); for (i = 0; i < length; i += 1) { - /* Make sure the fill is okay */ fillIndex = fillPtr[i]; + /* Make sure the fill is okay */ if (!(isFillOkay(fillIndex))) { return 0; } @@ -844,12 +859,11 @@ checkCompressedPointssegments(sqInt points, sqInt nSegments) if (!(isWords(points))) { return 0; } - + pSize = slotSizeOf(points); /* The points must be either in PointArray format or ShortPointArray format. Also, we currently handle only quadratic segments (e.g., 3 points each) and thus either pSize = nSegments * 3, for ShortPointArrays or, pSize = nSegments * 6, for PointArrays */ - pSize = slotSizeOf(points); if (!((pSize == (nSegments * 3)) || (pSize == (nSegments * 6)))) { return 0; @@ -1004,19 +1018,16 @@ computeBezierSplitAtHalf(sqInt index) rightViaX = (viaX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); rightViaY = (viaY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]); endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; - - /* Compute intermediate points */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; + /* Compute intermediate points */ leftViaX += (viaX - startX) / 2; leftViaY += (viaY - startY) / 2; sharedX = (rightViaX += (endX - viaX) / 2); - - /* Compute new shared point */ sharedY = (rightViaY += (endY - viaY) / 2); + /* Compute new shared point */ sharedX += (leftViaX - rightViaX) / 2; - - /* Store the first part back */ sharedY += (leftViaY - rightViaY) / 2; + /* Store the first part back */ /* #bzViaX:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)] = leftViaX; @@ -1029,6 +1040,7 @@ computeBezierSplitAtHalf(sqInt index) /* #bzEndY:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)] = sharedY; + /* Store the second point back */ /* #bzStartX:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex))] = sharedX; @@ -1079,19 +1091,16 @@ computeBeziersplitAt(sqInt index, double param) rightViaX = (viaX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); rightViaY = (viaY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]); endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; - - /* Compute intermediate points */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; + /* Compute intermediate points */ sharedX = (leftViaX += ((sqInt)((((double) (viaX - startX) )) * param))); sharedY = (leftViaY += ((sqInt)((((double) (viaY - startY) )) * param))); rightViaX += ((sqInt)((((double) (endX - viaX) )) * param)); - - /* Compute new shared point */ rightViaY += ((sqInt)((((double) (endY - viaY) )) * param)); + /* Compute new shared point */ sharedX += ((sqInt)((((double) (rightViaX - leftViaX) )) * param)); - - /* Check the new via points */ sharedY += ((sqInt)((((double) (rightViaY - leftViaY) )) * param)); + /* Check the new via points */ /* begin assureValue:between:and: */ if (startY > sharedY) { @@ -1170,6 +1179,7 @@ computeBeziersplitAt(sqInt index, double param) /* #bzEndY:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)] = sharedY; + /* Store the second point back */ /* #bzStartX:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - newIndex))] = sharedX; @@ -1270,6 +1280,7 @@ createGlobalEdgeTable(void) if (((objBuffer[object + GLEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { goto l1; } + /* Overlaps in Y but may still be entirely right of clip region */ if ((((objBuffer[object + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[object + GLEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { goto l1; @@ -1288,6 +1299,7 @@ createGlobalEdgeTable(void) if (((objBuffer[object + GBEndY]) + lineWidth) < (workBuffer[GWFillMinY])) { goto l1; } + /* Overlaps in Y but may still be entirely right of clip region */ if ((((objBuffer[object + GEXValue]) - lineWidth) >= (workBuffer[GWFillMaxX])) && (((objBuffer[object + GBEndX]) - lineWidth) >= (workBuffer[GWFillMaxX]))) { goto l1; @@ -1467,13 +1479,12 @@ fillBitmapSpanAAfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) fillValue = uncheckedTransformColor(value); goto l1; } + /* rShift - shift value to convert from pixel to word index */ rShift = (rShiftTable())[bmDepth]; - - /* cMask - mask out the pixel from the word */ value = (((int *) bits))[(bmRaster * yp) + (((usqInt)(xp)) >> rShift)]; - - /* rShift - shift value to move the pixel in the word to the lowest bit position */ + /* cMask - mask out the pixel from the word */ cMaskSqInt = (1U << bmDepth) - 1; + /* rShift - shift value to move the pixel in the word to the lowest bit position */ rShift = (32 - bmDepth) - ((xp & ((1U << rShift) - 1)) * bmDepth); value = (((usqInt)(value)) >> rShift) & cMaskSqInt; if (bmDepth == 16) { @@ -1577,13 +1588,12 @@ fillBitmapSpanAAfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) fillValue = uncheckedTransformColor(value); goto l2; } + /* rShift - shift value to convert from pixel to word index */ rShift = (rShiftTable())[bmDepth]; - - /* cMask - mask out the pixel from the word */ value = (((int *) bits))[(bmRaster * yp) + (((usqInt)(xp)) >> rShift)]; - - /* rShift - shift value to move the pixel in the word to the lowest bit position */ + /* cMask - mask out the pixel from the word */ cMaskSqInt = (1U << bmDepth) - 1; + /* rShift - shift value to move the pixel in the word to the lowest bit position */ rShift = (32 - bmDepth) - ((xp & ((1U << rShift) - 1)) * bmDepth); value = (((usqInt)(value)) >> rShift) & cMaskSqInt; if (bmDepth == 16) { @@ -1687,13 +1697,12 @@ fillBitmapSpanAAfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) fillValue = uncheckedTransformColor(value); goto l3; } + /* rShift - shift value to convert from pixel to word index */ rShift = (rShiftTable())[bmDepth]; - - /* cMask - mask out the pixel from the word */ value = (((int *) bits))[(bmRaster * yp) + (((usqInt)(xp)) >> rShift)]; - - /* rShift - shift value to move the pixel in the word to the lowest bit position */ + /* cMask - mask out the pixel from the word */ cMaskSqInt = (1U << bmDepth) - 1; + /* rShift - shift value to move the pixel in the word to the lowest bit position */ rShift = (32 - bmDepth) - ((xp & ((1U << rShift) - 1)) * bmDepth); value = (((usqInt)(value)) >> rShift) & cMaskSqInt; if (bmDepth == 16) { @@ -1907,13 +1916,12 @@ fillBitmapSpanfromtoat(sqInt bmFill, sqInt leftX, sqInt rightX, sqInt yValue) fillValue = uncheckedTransformColor(value); goto l1; } + /* rShift - shift value to convert from pixel to word index */ rShift = (rShiftTable())[bmDepth]; - - /* cMask - mask out the pixel from the word */ value = (((int *) bits))[(bmRaster * yp) + (((usqInt)(xp)) >> rShift)]; - - /* rShift - shift value to move the pixel in the word to the lowest bit position */ + /* cMask - mask out the pixel from the word */ cMask = (1U << bmDepth) - 1; + /* rShift - shift value to move the pixel in the word to the lowest bit position */ rShift = (32 - bmDepth) - ((xp & ((1U << rShift) - 1)) * bmDepth); value = (((usqInt)(value)) >> rShift) & cMask; if (bmDepth == 16) { @@ -1986,9 +1994,8 @@ fillColorSpanAAx0x1(sqInt pixelValue32, sqInt leftX, sqInt rightX) lastPixel = (rightX - 1) & ((unsigned int)~((workBuffer[GWAALevel]) - 1)); aaLevel = workBuffer[GWAALevel]; baseShift = workBuffer[GWAAShift]; - - /* Part a: Deal with the first n sub-pixels */ x = leftX; + /* Part a: Deal with the first n sub-pixels */ if (x < firstPixel) { pv32 = ((usqInt)((pixelValue32 & (workBuffer[GWAAColorMask])))) >> (workBuffer[GWAAColorShift]); while (x < firstPixel) { @@ -1997,6 +2004,7 @@ fillColorSpanAAx0x1(sqInt pixelValue32, sqInt leftX, sqInt rightX) x += 1; } } + /* Part b: Deal with the full pixels */ if (x < lastPixel) { colorMask = (((usqInt)((workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAShift])) | 0xF0F0F0F0U; pv32 = ((usqInt)((pixelValue32 & colorMask))) >> (workBuffer[GWAAShift]); @@ -2006,6 +2014,7 @@ fillColorSpanAAx0x1(sqInt pixelValue32, sqInt leftX, sqInt rightX) x += aaLevel; } } + /* Part c: Deal with the last n sub-pixels */ if (x < rightX) { pv32 = ((usqInt)((pixelValue32 & (workBuffer[GWAAColorMask])))) >> (workBuffer[GWAAColorShift]); while (x < rightX) { @@ -2053,18 +2062,16 @@ fillLinearGradientAArampdsdsXfromto(sqInt fill, int *ramp, sqInt deltaS, sqInt d else { firstPixel = firstPixelSqInt; } - - /* Deal with the first n sub-pixels */ lastPixel = (rightX - 1) & ((unsigned int)~((workBuffer[GWAALevel]) - 1)); + /* Deal with the first n sub-pixels */ colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; while ((x < firstPixel) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; - - /* Copy as many pixels as possible */ rampValue = ((usqInt)((rampValue & colorMask))) >> colorShift; + /* Copy as many pixels as possible */ while ((x < firstPixel) && ((ds / 0x10000) == rampIndex)) { idx = ((usqInt)(x)) >> baseShift; @@ -2074,15 +2081,15 @@ fillLinearGradientAArampdsdsXfromto(sqInt fill, int *ramp, sqInt deltaS, sqInt d } rampIndex = ds / 0x10000; } + /* Deal with the full pixels */ colorMask = (((usqInt)((workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAShift])) | 0xF0F0F0F0U; colorShift = workBuffer[GWAAShift]; while ((x < lastPixel) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; - - /* Copy as many pixels as possible */ rampValue = ((usqInt)((rampValue & colorMask))) >> colorShift; + /* Copy as many pixels as possible */ while ((x < lastPixel) && ((ds / 0x10000) == rampIndex)) { idx = ((usqInt)(x)) >> baseShift; @@ -2092,15 +2099,15 @@ fillLinearGradientAArampdsdsXfromto(sqInt fill, int *ramp, sqInt deltaS, sqInt d } rampIndex = ds / 0x10000; } + /* Deal with the last n sub-pixels */ colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; while ((x < rightX) && ((rampIndex < rampSize) && (rampIndex >= 0))) { rampValue = (((int *) ramp))[rampIndex]; - - /* Copy as many pixels as possible */ rampValue = ((usqInt)((rampValue & colorMask))) >> colorShift; + /* Copy as many pixels as possible */ while ((x < rightX) && ((ds / 0x10000) == rampIndex)) { idx = ((usqInt)(x)) >> baseShift; @@ -2136,10 +2143,9 @@ fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) dsX = objBuffer[fill + GFDirectionX]; ds = ((leftX - (objBuffer[fill + GFOriginX])) * dsX) + ((yValue - (objBuffer[fill + GFOriginY])) * (objBuffer[fill + GFDirectionY])); x = (x0 = leftX); - - /* Note: The inner loop has been divided into three parts for speed */ - /* Part one: Fill everything outside the left boundary */ x1 = rightX; + /* Note: The inner loop has been divided into three parts for speed + Part one: Fill everything outside the left boundary */ while (((((rampIndex = ds / 0x10000)) < 0) || (rampIndex >= rampSize)) && (x < x1)) { @@ -2159,9 +2165,8 @@ fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) fillColorSpanAAx0x1(ramp[rampIndex], x0, x); goto l1; } - - /* Unroll the inner loop four times, since we're only storing data. */ x0SqInt = x0; + /* Unroll the inner loop four times, since we're only storing data. */ while ((x0SqInt + 4) < x) { spanBuffer[x0SqInt] = (ramp[rampIndex]); spanBuffer[x0SqInt + 1] = (ramp[rampIndex]); @@ -2175,6 +2180,7 @@ fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) } l1: /* end fillColorSpan:from:to: */; } + /* Part two: Fill everything inside the boundaries */ if ((workBuffer[GWAALevel]) == 1) { /* Fast version w/o anti-aliasing */ @@ -2189,6 +2195,7 @@ fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) else { x = fillLinearGradientAArampdsdsXfromto(fill, ramp, ds, dsX, x, rightX); } + /* Part three fill everything outside right boundary */ if (x < x1) { if (rampIndex < 0) { rampIndex = 0; @@ -2202,9 +2209,8 @@ fillLinearGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) fillColorSpanAAx0x1(ramp[rampIndex], x, x1); goto l2; } - - /* Unroll the inner loop four times, since we're only storing data. */ x0SqInt = x; + /* Unroll the inner loop four times, since we're only storing data. */ while ((x0SqInt + 4) < x1) { spanBuffer[x0SqInt] = (ramp[rampIndex]); spanBuffer[x0SqInt + 1] = (ramp[rampIndex]); @@ -2265,9 +2271,8 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS else { firstPixel = firstPixelSqInt; } - - /* Deal with the first n sub-pixels */ lastPixel = (x1 - 1) & ((unsigned int)~((workBuffer[GWAALevel]) - 1)); + /* Deal with the first n sub-pixels */ if (x < firstPixel) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; @@ -2284,6 +2289,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS ds += dsX; dt += dtX; } + /* Step to next ramp value */ nextLength = ((ds / 0x10000) * (ds / 0x10000)) + ((dt / 0x10000) * (dt / 0x10000)); while (nextLength < length2) { rampIndex -= 1; @@ -2293,6 +2299,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Deal with the full pixels */ if (x < lastPixel) { colorMask = (((usqInt)((workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAShift])) | 0xF0F0F0F0U; colorShift = workBuffer[GWAAShift]; @@ -2309,6 +2316,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS ds += (((usqInt)(dsX) << colorShift)); dt += (((usqInt)(dtX) << colorShift)); } + /* Step to next ramp value */ nextLength = ((ds / 0x10000) * (ds / 0x10000)) + ((dt / 0x10000) * (dt / 0x10000)); while (nextLength < length2) { rampIndex -= 1; @@ -2318,6 +2326,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Deal with the last n sub-pixels */ if (x < x1) { colorMask = workBuffer[GWAAColorMask]; colorShift = workBuffer[GWAAColorShift]; @@ -2334,6 +2343,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS ds += dsX; dt += dtX; } + /* Step to next ramp value */ nextLength = ((ds / 0x10000) * (ds / 0x10000)) + ((dt / 0x10000) * (dt / 0x10000)); while (nextLength < length2) { rampIndex -= 1; @@ -2343,6 +2353,7 @@ fillRadialDecreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Done -- store stuff back */ (*((int *) deltaST) = ds); (((int *) deltaST))[1] = dt; return x; @@ -2389,10 +2400,9 @@ fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) ds = (deltaX * dsX) + (deltaY * (objBuffer[fill + GFDirectionY])); dt = (deltaX * dtX) + (deltaY * (objBuffer[fill + GFNormalY])); x = leftX; - - /* Note: The inner loop has been divided into three parts for speed */ - /* Part one: Fill everything outside the left boundary */ x1 = rightX; + /* Note: The inner loop has been divided into three parts for speed + Part one: Fill everything outside the left boundary */ /* This is the upper bound */ length2 = (rampSize - 1) * (rampSize - 1); @@ -2408,9 +2418,8 @@ fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) fillColorSpanAAx0x1(ramp[rampSize - 1], leftX, x); goto l1; } - - /* Unroll the inner loop four times, since we're only storing data. */ x0 = leftX; + /* Unroll the inner loop four times, since we're only storing data. */ while ((x0 + 4) < x) { spanBuffer[x0] = (ramp[rampSize - 1]); spanBuffer[x0 + 1] = (ramp[rampSize - 1]); @@ -2424,6 +2433,7 @@ fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) } l1: /* end fillColorSpan:from:to: */; } + /* Part two: Fill everything inside the boundaries */ deltaST = ((int *) (workBuffer + GWPoint1)); deltaST[0] = ds; deltaST[1] = dt; @@ -2452,6 +2462,7 @@ fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) dsInt += dsX; dtInt += dtX; } + /* Step to next ramp value */ nextLength = ((dsInt / 0x10000) * (dsInt / 0x10000)) + ((dtInt / 0x10000) * (dtInt / 0x10000)); while (nextLength < length2SqInt) { rampIndex -= 1; @@ -2510,15 +2521,15 @@ fillRadialGradientfromtoat(sqInt fill, sqInt leftX, sqInt rightX, sqInt yValue) x = fillRadialIncreasingAArampdeltaSTdsXdtXfromto(fill, ramp, deltaST, dsX, dtX, x, x1); } } + /* Part three fill everything outside right boundary */ if (x < rightX) { /* begin fillColorSpan:from:to: */ if (!((workBuffer[GWAALevel]) == 1)) { fillColorSpanAAx0x1(ramp[rampSize - 1], x, rightX); goto l2; } - - /* Unroll the inner loop four times, since we're only storing data. */ x0 = x; + /* Unroll the inner loop four times, since we're only storing data. */ while ((x0 + 4) < rightX) { spanBuffer[x0] = (ramp[rampSize - 1]); spanBuffer[x0 + 1] = (ramp[rampSize - 1]); @@ -2581,9 +2592,8 @@ fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS else { firstPixel = firstPixelSqInt; } - - /* Deal with the first n subPixels */ lastPixel = (rightX - 1) & ((unsigned int)~((workBuffer[GWAALevel]) - 1)); + /* Deal with the first n subPixels */ if ((x < firstPixel) && (lastLength < length2)) { colorMask = workBuffer[GWAAColorMask]; @@ -2611,6 +2621,7 @@ fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Deal with the full pixels */ if ((x < lastPixel) && (lastLength < length2)) { colorMask = (((usqInt)((workBuffer[GWAAColorMask]))) >> (workBuffer[GWAAShift])) | 0xF0F0F0F0U; @@ -2638,6 +2649,7 @@ fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Deal with last n sub-pixels */ if ((x < rightX) && (lastLength < length2)) { colorMask = workBuffer[GWAAColorMask]; @@ -2665,6 +2677,7 @@ fillRadialIncreasingAArampdeltaSTdsXdtXfromto(sqInt fill, int *ramp, int *deltaS } } } + /* Done -- store stuff back */ (*((int *) deltaST) = ds); (((int *) deltaST))[1] = dt; return x; @@ -2685,6 +2698,7 @@ fillSortsbefore(sqInt fillEntry1, sqInt fillEntry2) if (diff) { return diff > 0; } + /* See the class comment for aetScanningProblems */ return (((unsigned) (workBuffer[(workBuffer[GWBufferTop]) + fillEntry1]))) < (((unsigned) (workBuffer[(workBuffer[GWBufferTop]) + fillEntry2]))); } @@ -2717,12 +2731,14 @@ fillSpanfromto(unsigned int fill, sqInt leftX, sqInt rightX) else { x1 = rightX; } + /* Clip left and right values */ if (x0 < (workBuffer[GWFillMinX])) { x0 = workBuffer[GWFillMinX]; } if (x1 > (workBuffer[GWFillMaxX])) { x1 = workBuffer[GWFillMaxX]; } + /* Adjust start and end values of span */ if (x0 < (workBuffer[GWSpanStart])) { /* spanStartPut: */ workBuffer[GWSpanStart] = x0; @@ -2744,9 +2760,8 @@ fillSpanfromto(unsigned int fill, sqInt leftX, sqInt rightX) fillColorSpanAAx0x1(fill, x0, x1); goto l1; } - - /* Unroll the inner loop four times, since we're only storing data. */ x0SqInt = x0; + /* Unroll the inner loop four times, since we're only storing data. */ while ((x0SqInt + 4) < x1) { spanBuffer[x0SqInt] = fill; spanBuffer[x0SqInt + 1] = fill; @@ -2810,8 +2825,8 @@ findNextExternalEntryFromGET(void) unsigned int type; int yValue; - /* As long as we have entries in the GET */ yValue = workBuffer[GWCurrentY]; + /* As long as we have entries in the GET */ while ((workBuffer[GWGETStart]) < (workBuffer[GWGETUsed])) { edge = getBuffer[workBuffer[GWGETStart]]; if ((objBuffer[edge + GEYValue]) > yValue) { @@ -2850,11 +2865,13 @@ findNextExternalEntryFromGET(void) stepToFirstWideBezierInat(getBuffer[workBuffer[GWGETStart]], workBuffer[GWCurrentY]); break; } + /* Insert the edge into the AET */ insertEdgeIntoAET(edge); /* getStartPut: */ workBuffer[GWGETStart] = ((workBuffer[GWGETStart]) + 1); } + /* No entries in GET */ return 0; } @@ -2883,11 +2900,11 @@ findNextExternalFillFromAET(void) leftX = (rightX = workBuffer[GWFillMaxX]); while ((workBuffer[GWAETStart]) < (workBuffer[GWAETUsed])) { + leftEdge = (rightEdge = aetBuffer[workBuffer[GWAETStart]]); /* TODO: We should check if leftX from last operation is greater than leftX from next edge. Currently, we rely here on spanEndAA from the span buffer fill. */ - leftEdge = (rightEdge = aetBuffer[workBuffer[GWAETStart]]); leftX = (rightX = objBuffer[leftEdge + GEXValue]); if (leftX >= (workBuffer[GWFillMaxX])) { return 0; @@ -2904,8 +2921,10 @@ findNextExternalFillFromAET(void) } } l1: /* end quickRemoveInvalidFillsAt: */; + /* Check if we need to draw the edge */ if (((objBuffer[leftEdge + GEObjectType]) & GEPrimitiveTypeMask) & GEPrimitiveWide) { toggleWideFillOf(leftEdge); + /* leftX := rightX := self drawWideEdge: leftEdge from: leftX. */; } if (!((objBuffer[leftEdge + GEObjectType]) & GEEdgeFillsInvalid)) { toggleFillsOf(leftEdge); @@ -2987,9 +3006,13 @@ findNextExternalFillFromAET(void) goto l3; } l3: /* end fillAllFrom:to: */; + /* Fetch the currently active fill + fill := self makeUnsignedFrom: self topFill. + fill = 0 ifFalse:[self fillSpan: fill from: leftX to: rightX max: self topRightX] */; } } } + /* Note: Due to pre-clipping we may have to draw remaining stuff with the last fill */ if (rightX < (workBuffer[GWFillMaxX])) { /* begin fillAllFrom:to: */ /* begin topFill */ @@ -3056,6 +3079,8 @@ findNextExternalFillFromAET(void) goto l5; } l5: /* end fillAllFrom:to: */; + /* fill := self makeUnsignedFrom: self topFill. + fill = 0 ifFalse:[self fillSpan: fill from: rightX to: self fillMaxXGet max: self topRightX]. */; } return 0; } @@ -3142,6 +3167,7 @@ findNextExternalUpdateFromAET(void) /* #wideLineExitOf:put: #obj:at:put: */ objBuffer[lineSqInt + GLWideExit] = yExit; + /* Turn fills on/off */ lineWidth = objBuffer[lineSqInt + GLWideExtent]; lineOffset = lineWidth / 2; if (yEntry >= lineOffset) { @@ -3152,6 +3178,7 @@ findNextExternalUpdateFromAET(void) /* #edgeFillsInvalidate: #objectTypeOf:put: #obj:at:put: */ objBuffer[lineSqInt + GEObjectType] = (((objBuffer[lineSqInt + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } + /* Step to the next scan line */ lastXInt = objBuffer[lineSqInt + GEXValue]; /* begin stepToNextLineIn:at: */ @@ -3167,9 +3194,8 @@ findNextExternalUpdateFromAET(void) /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[lineSqInt + GEXValue] = xInt; - - /* Check for special start/end adjustments */ nextX = objBuffer[lineSqInt + GEXValue]; + /* Check for special start/end adjustments */ if ((yEntry <= lineWidth) || ((yExit + lineOffset) >= 0)) { @@ -3185,12 +3211,11 @@ findNextExternalUpdateFromAET(void) lastY = updateData[GBUpdateY]; fwDx = updateData[GBUpdateDX]; fwDy = updateData[GBUpdateDY]; - + minY = (workBuffer[GWCurrentY]) * 0x100; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ - minY = (workBuffer[GWCurrentY]) * 0x100; while ((minY > lastY) && (fwDy >= 0)) { lastX += (((sqInt)((fwDx + 0x8000))) >> 16); @@ -3270,10 +3295,12 @@ getSortsbefore(sqInt edge1, sqInt edge2) if (edge1 == edge2) { return 1; } + /* First, sort by Y */ diff = (objBuffer[edge1 + GEYValue]) - (objBuffer[edge2 + GEYValue]); if (diff) { return diff < 0; } + /* Then, by X */ diff = (objBuffer[edge1 + GEXValue]) - (objBuffer[edge2 + GEXValue]); return diff < 0; } @@ -3303,6 +3330,7 @@ hideFilldepth(sqInt fillIndex, sqInt depth) workBuffer[GWBufferTop] = ((workBuffer[GWBufferTop]) + 3 /* stackFillEntryLength */); return 1; } + /* Fill is visible - replace it with the last entry on the stack */ /* #stackFillValue:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + index] = (workBuffer[(workBuffer[GWBufferTop])]); @@ -3458,6 +3486,7 @@ initializeGETProcessing(void) /* clipMaxXPut: */ workBuffer[GWClipMaxX] = (workBuffer[GWSpanSize]); } + /* Convert clipRect to aaLevel */ /* fillMinXPut: */ workBuffer[GWFillMinX] = (((sqInt)((usqInt)((workBuffer[GWClipMinX])) << (workBuffer[GWAAShift])))); @@ -3470,6 +3499,7 @@ initializeGETProcessing(void) /* fillMaxYPut: */ workBuffer[GWFillMaxY] = (((sqInt)((usqInt)((workBuffer[GWClipMaxY])) << (workBuffer[GWAAShift])))); + /* Reset GET and AET */ /* getUsedPut: */ workBuffer[GWGETUsed] = 0; @@ -3477,9 +3507,8 @@ initializeGETProcessing(void) /* aetUsedPut: */ workBuffer[GWAETUsed] = 0; getBuffer = objBuffer + objUsed; - - /* Create the global edge table */ aetBuffer = objBuffer + objUsed; + /* Create the global edge table */ createGlobalEdgeTable(); if (engineStopped) { return null; @@ -3491,6 +3520,7 @@ initializeGETProcessing(void) workBuffer[GWCurrentY] = (workBuffer[GWFillMaxY]); return 0; } + /* Sort entries in the GET */ /* begin sortGlobalEdgeTable */ quickSortGlobalEdgeTablefromto(getBuffer, 0, (workBuffer[GWGETUsed]) - 1); @@ -3502,6 +3532,7 @@ initializeGETProcessing(void) /* currentYPut: */ workBuffer[GWCurrentY] = (workBuffer[GWFillMinY]); } + /* Load and clear the span buffer */ /* spanStartPut: */ workBuffer[GWSpanStart] = 0; @@ -3531,9 +3562,8 @@ insertEdgeIntoAET(sqInt edge) if ((objBuffer[edge + GENumLines]) <= 0) { return null; } - - /* And insert edge */ index = indexForInsertingIntoAET(edge); + /* And insert edge */ insertToAETbeforeIndex(edge, index); return 0; } @@ -3628,6 +3658,7 @@ loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqI if (engineStopped) { return 0; } + /* Load point1/point2/point3 on the top of the stack */ /* #bzStartX:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1))] = (point1[0]); @@ -3646,6 +3677,7 @@ loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqI /* #bzEndY:put: #wbStackValue:put: */ workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - bz1) + 5)] = (point3[1]); + /* Now check if the bezier curve is monoton. If not, subdivide it. */ index2 = (bz2 = subdivideToBeMonotoninX(bz1, wideFlag)); for (index = bz1; index <= bz2; index += 6) { index1 = subdivideBezierFrom(index); @@ -3656,281 +3688,423 @@ loadAndSubdivideBezierFromviatoisWide(int *point1, int *point2, int *point3, sqI return 0; } } + /* Return the number of segments */ return index2 / 6; } - /* BalloonEnginePlugin>>#loadArrayShape:nSegments:fill:lineWidth:lineFill: */ + +/* Initialize the bezier segment stored on the stack */ + + /* BalloonEnginePlugin>>#loadBezier:segment:leftFill:rightFill:offset: */ static sqInt -loadArrayShapenSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill) +loadBeziersegmentleftFillrightFilloffset(sqInt bezier, sqInt index, sqInt leftFillIndex, sqInt rightFillIndex, sqInt yOffset) { - int *dstPoint1; - sqInt i; - int *point; - sqInt pointOop; - sqInt segs; - float *transform; - sqInt x; - int x0; - int x1; - int x2; - sqInt y; - int y0; - int y1; - int y2; + if ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) >= (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)])) { - for (i = 0; i < nSegments; i += 1) { - pointOop = fetchPointerofObject(i * 3, points); - loadPointfrom(((int *) (workBuffer + GWPoint1)), pointOop); - pointOop = fetchPointerofObject((i * 3) + 1, points); - loadPointfrom(((int *) (workBuffer + GWPoint2)), pointOop); - pointOop = fetchPointerofObject((i * 3) + 2, points); - loadPointfrom(((int *) (workBuffer + GWPoint3)), pointOop); - if (failed()) { - return null; - } + /* Top to bottom */ + /* #edgeXValueOf:put: #obj:at:put: */ + objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index))]); - /* begin transformPoints: */ - if (3 > 0) { - point = ((int *) (workBuffer + GWPoint1)); + /* #edgeYValueOf:put: #obj:at:put: */ + objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + /* #bezierViaXOf:put: #obj:at:put: */ + objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { + /* #bezierViaYOf:put: #obj:at:put: */ + objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (3 > 1) { - point = ((int *) (workBuffer + GWPoint2)); + /* #bezierEndXOf:put: #obj:at:put: */ + objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + /* #bezierEndYOf:put: #obj:at:put: */ + objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); + } + else { + /* #edgeXValueOf:put: #obj:at:put: */ + objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { + /* #edgeYValueOf:put: #obj:at:put: */ + objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (3 > 2) { - point = ((int *) (workBuffer + GWPoint3)); + /* #bezierViaXOf:put: #obj:at:put: */ + objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + /* #bezierViaYOf:put: #obj:at:put: */ + objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { + /* #bezierEndXOf:put: #obj:at:put: */ + objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index))]); - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (3 > 3) { - point = ((int *) (workBuffer + GWPoint4)); + /* #bezierEndYOf:put: #obj:at:put: */ + objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); + } - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + /* #edgeZValueOf:put: #obj:at:put: */ + objBuffer[bezier + GEZValue] = (workBuffer[GWCurrentZ]); - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { + /* #edgeLeftFillOf:put: #obj:at:put: */ + objBuffer[bezier + GEFillIndexLeft] = leftFillIndex; - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - x0 = (*((int *) (workBuffer + GWPoint1))); - y0 = (((int *) (workBuffer + GWPoint1)))[1]; - x1 = (*((int *) (workBuffer + GWPoint2))); - y1 = (((int *) (workBuffer + GWPoint2)))[1]; - x2 = (*((int *) (workBuffer + GWPoint3))); + /* #edgeRightFillOf:put: #obj:at:put: */ + objBuffer[bezier + GEFillIndexRight] = rightFillIndex; + return 0; +} - /* Check if we can use a line */ - y2 = (((int *) (workBuffer + GWPoint3)))[1]; - if (((x0 == y0) - && (x1 == y1)) - || ((x1 == x2) - && (y1 == y2))) { - loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint3)), lineFill, fillIndex, 0); - } - else { + /* BalloonEngineBase>>#loadBitBltFrom: */ +static sqInt +loadBitBltFrom(sqInt bbObj) +{ + if (!loadBBFn) { - /* Need bezier */ - segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (lineWidth != 0) - && (lineFill != 0)); - if (engineStopped) { - return null; - } - loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); - } - if (engineStopped) { - return null; + /* We need copyBits here so try to load it implicitly */ + if (!(initialiseModule())) { + return 0; } } - return 0; + return ((sqInt (*)(sqInt))loadBBFn)(bbObj); } -/* Load a transformation from the given array. */ +/* Note: Assumes that the contents of formArray has been checked before */ - /* BalloonEngineBase>>#loadArrayTransformFrom:into:length: */ + /* BalloonEnginePlugin>>#loadBitsFrom: */ +static int * +loadBitsFrom(sqInt bmFill) +{ + sqInt bitsLen; + sqInt bitsOop; + sqInt formOop; + int xIndex; + + xIndex = objBuffer[bmFill + GEObjectIndex]; + if (xIndex > (slotSizeOf(formArray))) { + return null; + } + formOop = fetchPointerofObject(xIndex, formArray); + bitsOop = fetchPointerofObject(0, formOop); + bitsLen = slotSizeOf(bitsOop); + if (!(bitsLen == (objBuffer[bmFill + GBBitmapSize]))) { + return null; + } + return firstIndexableField(bitsOop); +} + + +/* Load a compressed shape into the engine. + WARNING: THIS METHOD NEEDS THE FULL FRAME SIZE!!!! + */ + + /* BalloonEnginePlugin>>#loadCompressedShapeFromIntPoints:segments:leftFills:rightFills:lineWidths:lineFills:fillIndexList: */ static sqInt -loadArrayTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) +loadCompressedShapeFromIntPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList) { + int *dstPoint1; sqInt i; - sqInt value; + sqInt index; + sqInt leftLength; + sqInt leftRun; + sqInt leftValue; + sqInt lineFillLength; + sqInt lineFillRun; + unsigned int lineFillValue; + int *point; + sqInt rightLength; + sqInt rightRun; + sqInt rightValue; + sqInt segs; + float *transform; + sqInt widthLength; + sqInt widthRun; + sqInt widthValue; + sqInt x; + int x0; + int x1; + int x2; + sqInt y; + int y0; + int y1; + int y2; - for (i = 0; i < n; i += 1) { - value = fetchPointerofObject(i, transformOop); - if (!((isIntegerObject(value)) - || (isFloatObject(value)))) { - return primitiveFail(); + if (!nSegments) { + return 0; + } + /* Initialize run length encodings */ + leftRun = (rightRun = (widthRun = (lineFillRun = -1))); + leftLength = (rightLength = (widthLength = (lineFillLength = 1))); + leftValue = (rightValue = (widthValue = (lineFillValue = 0))); + for (i = 1; i <= nSegments; i += 1) { + if (((leftLength -= 1)) <= 0) { + leftRun += 1; + leftLength = (((usqInt)(((((int *) leftFills))[leftRun]))) >> 16); + leftValue = ((((int *) leftFills))[leftRun]) & 0xFFFF; + if (leftValue) { + leftValue = fillIndexList[leftValue - 1]; + leftValue = transformColor(leftValue); + if (engineStopped) { + return null; + } + } } - if (isIntegerObject(value)) { - destPtr[i] = (((float) (((double) (integerValueOf(value)) )))); + if (((rightLength -= 1)) <= 0) { + rightRun += 1; + rightLength = (((usqInt)(((((int *) rightFills))[rightRun]))) >> 16); + rightValue = ((((int *) rightFills))[rightRun]) & 0xFFFF; + if (rightValue) { + rightValue = fillIndexList[rightValue - 1]; + rightValue = transformColor(rightValue); + } } - else { - destPtr[i] = (((float) (floatValueOf(value)))); + if (((widthLength -= 1)) <= 0) { + widthRun += 1; + widthLength = (((usqInt)(((((int *) lineWidths))[widthRun]))) >> 16); + widthValue = ((((int *) lineWidths))[widthRun]) & 0xFFFF; + if (widthValue) { + widthValue = transformWidth(widthValue); + } + } + if (((lineFillLength -= 1)) <= 0) { + lineFillRun += 1; + lineFillLength = (((usqInt)(((((int *) lineFills))[lineFillRun]))) >> 16); + lineFillValue = ((((int *) lineFills))[lineFillRun]) & 0xFFFF; + if (lineFillValue) { + lineFillValue = fillIndexList[lineFillValue - 1]; + } } - } - return 0; -} + /* begin loadCompressedSegment:fromIntPoints:leftFill:rightFill:lineWidth:lineColor: */ + if ((leftValue == rightValue) + && ((widthValue == 0) + || (lineFillValue == 0))) { + goto l1; + } -/* Initialize the bezier segment stored on the stack */ + /* 3 points with x/y each */ + index = (i - 1) * 6; + x0 = points[index]; + y0 = points[index + 1]; + x1 = points[index + 2]; + y1 = points[index + 3]; + x2 = points[index + 4]; + y2 = points[index + 5]; + /* Briefly check if can represent the bezier as a line */ + if (((x0 == x1) + && (y0 == y1)) + || ((x1 == x2) + && (y1 == y2))) { - /* BalloonEnginePlugin>>#loadBezier:segment:leftFill:rightFill:offset: */ -static sqInt -loadBeziersegmentleftFillrightFilloffset(sqInt bezier, sqInt index, sqInt leftFillIndex, sqInt rightFillIndex, sqInt yOffset) -{ - if ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) >= (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)])) { + /* We can use a line from x0/y0 to x2/y2 */ + if ((x0 == x2) + && (y0 == y2)) { + goto l1; + } + (*((int *) (workBuffer + GWPoint1)) = x0); + (((int *) (workBuffer + GWPoint1)))[1] = y0; + (*((int *) (workBuffer + GWPoint2)) = x2); + (((int *) (workBuffer + GWPoint2)))[1] = y2; - /* Top to bottom */ - /* #edgeXValueOf:put: #obj:at:put: */ - objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index))]); + /* begin transformPoints: */ + if (2 > 0) { + point = ((int *) (workBuffer + GWPoint1)); - /* #edgeYValueOf:put: #obj:at:put: */ - objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* #bezierViaXOf:put: #obj:at:put: */ - objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* #bezierViaYOf:put: #obj:at:put: */ - objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 1) { + point = ((int *) (workBuffer + GWPoint2)); - /* #bezierEndXOf:put: #obj:at:put: */ - objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* #bezierEndYOf:put: #obj:at:put: */ - objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); - } - else { - /* #edgeXValueOf:put: #obj:at:put: */ - objBuffer[bezier + GEXValue] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]); + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* #edgeYValueOf:put: #obj:at:put: */ - objBuffer[bezier + GEYValue] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]) - yOffset); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 2) { + point = ((int *) (workBuffer + GWPoint3)); - /* #bezierViaXOf:put: #obj:at:put: */ - objBuffer[bezier + GBViaX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 2)]); + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* #bezierViaYOf:put: #obj:at:put: */ - objBuffer[bezier + GBViaY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 3)]) - yOffset); + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* #bezierEndXOf:put: #obj:at:put: */ - objBuffer[bezier + GBEndX] = (workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index))]); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 3) { + point = ((int *) (workBuffer + GWPoint4)); - /* #bezierEndYOf:put: #obj:at:put: */ - objBuffer[bezier + GBEndY] = ((workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]) - yOffset); - } + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + loadWideLinefromtolineFillleftFillrightFill(widthValue, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFillValue, leftValue, rightValue); + goto l1; + } + /* Need bezier curve + Load and transform points */ + (*((int *) (workBuffer + GWPoint1)) = x0); + (((int *) (workBuffer + GWPoint1)))[1] = y0; + (*((int *) (workBuffer + GWPoint2)) = x1); + (((int *) (workBuffer + GWPoint2)))[1] = y1; + (*((int *) (workBuffer + GWPoint3)) = x2); + (((int *) (workBuffer + GWPoint3)))[1] = y2; + + /* begin transformPoints: */ + if (3 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* #edgeZValueOf:put: #obj:at:put: */ - objBuffer[bezier + GEZValue] = (workBuffer[GWCurrentZ]); + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* #edgeLeftFillOf:put: #obj:at:put: */ - objBuffer[bezier + GEFillIndexLeft] = leftFillIndex; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 2) { + point = ((int *) (workBuffer + GWPoint3)); - /* #edgeRightFillOf:put: #obj:at:put: */ - objBuffer[bezier + GEFillIndexRight] = rightFillIndex; - return 0; -} + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* BalloonEngineBase>>#loadBitBltFrom: */ -static sqInt -loadBitBltFrom(sqInt bbObj) -{ - if (!loadBBFn) { + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* We need copyBits here so try to load it implicitly */ - if (!(initialiseModule())) { - return 0; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - } - return ((sqInt (*)(sqInt))loadBBFn)(bbObj); -} - + if (3 > 3) { + point = ((int *) (workBuffer + GWPoint4)); -/* Note: Assumes that the contents of formArray has been checked before */ + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { - /* BalloonEnginePlugin>>#loadBitsFrom: */ -static int * -loadBitsFrom(sqInt bmFill) -{ - sqInt bitsLen; - sqInt bitsOop; - sqInt formOop; - int xIndex; + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - xIndex = objBuffer[bmFill + GEObjectIndex]; - if (xIndex > (slotSizeOf(formArray))) { - return null; - } - formOop = fetchPointerofObject(xIndex, formArray); - bitsOop = fetchPointerofObject(0, formOop); - bitsLen = slotSizeOf(bitsOop); - if (!(bitsLen == (objBuffer[bmFill + GBBitmapSize]))) { - return null; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (widthValue != 0) + && (lineFillValue != 0)); + if (engineStopped) { + goto l1; + } + loadWideBezierlineFillleftFillrightFilln(widthValue, lineFillValue, leftValue, rightValue, segs); +l1: /* end loadCompressedSegment:fromIntPoints:leftFill:rightFill:lineWidth:lineColor: */; + if (engineStopped) { + return null; + } } - return firstIndexableField(bitsOop); + return 0; } @@ -3938,9 +4112,9 @@ loadBitsFrom(sqInt bmFill) WARNING: THIS METHOD NEEDS THE FULL FRAME SIZE!!!! */ - /* BalloonEnginePlugin>>#loadCompressedShape:segments:leftFills:rightFills:lineWidths:lineFills:fillIndexList:pointShort: */ + /* BalloonEnginePlugin>>#loadCompressedShapeFromShortPoints:segments:leftFills:rightFills:lineWidths:lineFills:fillIndexList: */ static sqInt -loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(int *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList, sqInt pointsShort) +loadCompressedShapeFromShortPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(short *points, sqInt nSegments, int *leftFills, int *rightFills, int *lineWidths, int *lineFills, int *fillIndexList) { int *dstPoint1; sqInt i; @@ -3961,23 +4135,22 @@ loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpo sqInt widthRun; sqInt widthValue; sqInt x; - sqInt x0; - sqInt x1; - sqInt x2; + short x0; + short x1; + short x2; sqInt y; - sqInt y0; - sqInt y1; - sqInt y2; + short y0; + short y1; + short y2; if (!nSegments) { return 0; } + /* Initialize run length encodings */ leftRun = (rightRun = (widthRun = (lineFillRun = -1))); leftLength = (rightLength = (widthLength = (lineFillLength = 1))); leftValue = (rightValue = (widthValue = (lineFillValue = 0))); for (i = 1; i <= nSegments; i += 1) { - - /* Decrement current run length and load new stuff */ if (((leftLength -= 1)) <= 0) { leftRun += 1; leftLength = (((usqInt)(((((int *) leftFills))[leftRun]))) >> 16); @@ -4016,7 +4189,7 @@ loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpo } } - /* begin loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */ + /* begin loadCompressedSegment:fromShortPoints:leftFill:rightFill:lineWidth:lineColor: */ if ((leftValue == rightValue) && ((widthValue == 0) || (lineFillValue == 0))) { @@ -4025,24 +4198,13 @@ loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpo /* 3 points with x/y each */ index = (i - 1) * 6; - if (pointsShort) { - - /* Load short points */ - x0 = (((short *) points))[index]; - y0 = (((short *) points))[index + 1]; - x1 = (((short *) points))[index + 2]; - y1 = (((short *) points))[index + 3]; - x2 = (((short *) points))[index + 4]; - y2 = (((short *) points))[index + 5]; - } - else { - x0 = (((int *) points))[index]; - y0 = (((int *) points))[index + 1]; - x1 = (((int *) points))[index + 2]; - y1 = (((int *) points))[index + 3]; - x2 = (((int *) points))[index + 4]; - y2 = (((int *) points))[index + 5]; - } + x0 = points[index]; + y0 = points[index + 1]; + x1 = points[index + 2]; + y1 = points[index + 3]; + x2 = points[index + 4]; + y2 = points[index + 5]; + /* Briefly check if can represent the bezier as a line */ if (((x0 == x1) && (y0 == y1)) || ((x1 == x2) @@ -4150,6 +4312,8 @@ loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpo loadWideLinefromtolineFillleftFillrightFill(widthValue, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFillValue, leftValue, rightValue); goto l1; } + /* Need bezier curve + Load and transform points */ (*((int *) (workBuffer + GWPoint1)) = x0); (((int *) (workBuffer + GWPoint1)))[1] = y0; (*((int *) (workBuffer + GWPoint2)) = x1); @@ -4252,7 +4416,7 @@ loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpo goto l1; } loadWideBezierlineFillleftFillrightFilln(widthValue, lineFillValue, leftValue, rightValue, segs); -l1: /* end loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */; +l1: /* end loadCompressedSegment:fromShortPoints:leftFill:rightFill:lineWidth:lineColor: */; if (engineStopped) { return null; } @@ -4320,6 +4484,7 @@ loadEdgeTransformFrom(sqInt transformOop) /* hasEdgeTransformPut: */ workBuffer[GWHasEdgeTransform] = 1; + /* Add the fill offset to the matrix */ transform[2] = (((float) ((transform[2]) + (((double) (workBuffer[GWDestOffsetX]) ))))); transform[5] = (((float) ((transform[5]) + (((double) (workBuffer[GWDestOffsetY]) ))))); return 1; @@ -4411,9 +4576,8 @@ loadFillOrientationfromalongnormalwidthheight(sqInt fill, int *point1, int *poin dirX = (point2[0]) - (point1[0]); dirY = (point2[1]) - (point1[1]); nrmX = (point3[0]) - (point1[0]); - - /* Compute the scale from direction/normal into ramp size */ nrmY = (point3[1]) - (point1[1]); + /* Compute the scale from direction/normal into ramp size */ dsLength2 = (dirX * dirX) + (dirY * dirY); if (dsLength2 > 0) { dsX = ((sqInt)((((((double) dirX )) * (((double) fillWidth ))) * 65536.0) / (((double) dsLength2 )))); @@ -4519,7 +4683,6 @@ loadGradientFillfromalongnormalisRadial(sqInt rampOop, int *point1, int *point2, sqInt fillSize; sqInt fillSqInt; sqInt i; - int *ramp; int *rampPtr; sqInt rampWidth; @@ -4527,7 +4690,6 @@ loadGradientFillfromalongnormalisRadial(sqInt rampOop, int *point1, int *point2, return primitiveFail(); } rampWidth = slotSizeOf(rampOop); - ramp = firstIndexableField(rampOop); /* begin allocateGradientFill:rampWidth:isRadial: */ fillSize = GGBaseSize + rampWidth; @@ -4554,12 +4716,12 @@ loadGradientFillfromalongnormalisRadial(sqInt rampOop, int *point1, int *point2, rampPtr = (objBuffer + fillSqInt) + GFRampOffset; if (workBuffer[GWHasColorTransform]) { for (i = 0; i < rampWidth; i += 1) { - rampPtr[i] = (transformColor(ramp[i])); + rampPtr[i] = (transformColor((((int *) (firstIndexableField(rampOop))))[i])); } } else { for (i = 0; i < rampWidth; i += 1) { - rampPtr[i] = (ramp[i]); + rampPtr[i] = ((((int *) (firstIndexableField(rampOop))))[i]); } } @@ -4591,15 +4753,16 @@ loadOvalSegmentwhcxcy(sqInt seg, sqInt w, sqInt h, sqInt cx, sqInt cy) y0 = ((sqInt)((((circleSinTable())[(seg * 2)]) * (((double) h ))) + cy)); (*((int *) (workBuffer + GWPoint1)) = x0); (((int *) (workBuffer + GWPoint1)))[1] = y0; + /* Load end point of segment */ x2 = ((sqInt)((((circleCosTable())[(seg * 2) + 2]) * (((double) w ))) + cx)); y2 = ((sqInt)((((circleSinTable())[(seg * 2) + 2]) * (((double) h ))) + cy)); (*((int *) (workBuffer + GWPoint3)) = x2); (((int *) (workBuffer + GWPoint3)))[1] = y2; + /* Load intermediate point of segment */ x1 = ((sqInt)((((circleCosTable())[(seg * 2) + 1]) * (((double) w ))) + cx)); - + y1 = ((sqInt)((((circleSinTable())[(seg * 2) + 1]) * (((double) h ))) + cy)); /* NOTE: The intermediate point is the point ON the curve and not yet the control point (which is OFF the curve) */ - y1 = ((sqInt)((((circleSinTable())[(seg * 2) + 1]) * (((double) h ))) + cy)); x1 = (x1 * 2) - ((x0 + x2) / 2); y1 = (y1 * 2) - ((y0 + y2) / 2); (*((int *) (workBuffer + GWPoint2)) = x1); @@ -4796,190 +4959,63 @@ loadRenderingState(void) if (failed()) { return PrimErrBadArgument; } + /* Load span buffer and bitBlt */ if ((failCode = loadSpanBufferFrom(fetchPointerofObject(BESpanIndex, engine)))) { return failCode; } - if (!(loadBitBltFrom(fetchPointerofObject(BEBitBltIndex, engine)))) { - return GEFBitBltLoadFailed; - } - if (!(loadFormsFrom(fetchPointerofObject(BEFormsIndex, engine)))) { - return GEFFormLoadFailed; - } - if ((slotSizeOf(edgeOop)) < ETBalloonEdgeDataSize) { - return GEFEdgeDataTooSmall; - } - if ((slotSizeOf(fillOop)) < FTBalloonFillDataSize) { - return GEFFillDataTooSmall; - } - state = workBuffer[GWState]; - if ((state == GEStateWaitingForEdge) - || ((state == GEStateWaitingForFill) - || (state == GEStateWaitingChange))) { - return GEFWrongState; - } - return 0; -} - - /* BalloonEnginePlugin>>#loadShape:nSegments:fill:lineWidth:lineFill:pointsShort: */ -static sqInt -loadShapenSegmentsfilllineWidthlineFillpointsShort(int *points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill, sqInt pointsShort) -{ - int *dstPoint1; - sqInt i; - sqInt index; - int *point; - sqInt segs; - float *transform; - sqInt x; - sqInt x0; - sqInt x1; - sqInt x2; - sqInt y; - sqInt y0; - sqInt y1; - sqInt y2; - - for (i = 1; i <= nSegments; i += 1) { - /* begin loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */ - if ((fillIndex == 0) - && ((lineWidth == 0) - || (lineFill == 0))) { - goto l1; - } - - /* 3 points with x/y each */ - index = (i - 1) * 6; - if (pointsShort) { - - /* Load short points */ - x0 = (((short *) points))[index]; - y0 = (((short *) points))[index + 1]; - x1 = (((short *) points))[index + 2]; - y1 = (((short *) points))[index + 3]; - x2 = (((short *) points))[index + 4]; - y2 = (((short *) points))[index + 5]; - } - else { - x0 = (((int *) points))[index]; - y0 = (((int *) points))[index + 1]; - x1 = (((int *) points))[index + 2]; - y1 = (((int *) points))[index + 3]; - x2 = (((int *) points))[index + 4]; - y2 = (((int *) points))[index + 5]; - } - if (((x0 == x1) - && (y0 == y1)) - || ((x1 == x2) - && (y1 == y2))) { - - /* We can use a line from x0/y0 to x2/y2 */ - if ((x0 == x2) - && (y0 == y2)) { - goto l1; - } - (*((int *) (workBuffer + GWPoint1)) = x0); - (((int *) (workBuffer + GWPoint1)))[1] = y0; - (*((int *) (workBuffer + GWPoint2)) = x2); - (((int *) (workBuffer + GWPoint2)))[1] = y2; - - /* begin transformPoints: */ - if (2 > 0) { - point = ((int *) (workBuffer + GWPoint1)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { - - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { - - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (2 > 1) { - point = ((int *) (workBuffer + GWPoint2)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { - - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { - - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (2 > 2) { - point = ((int *) (workBuffer + GWPoint3)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { - - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { - - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - if (2 > 3) { - point = ((int *) (workBuffer + GWPoint4)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + if (!(loadBitBltFrom(fetchPointerofObject(BEBitBltIndex, engine)))) { + return GEFBitBltLoadFailed; + } + if (!(loadFormsFrom(fetchPointerofObject(BEFormsIndex, engine)))) { + return GEFFormLoadFailed; + } + /* Check edgeOop and fillOop */ + if ((slotSizeOf(edgeOop)) < ETBalloonEdgeDataSize) { + return GEFEdgeDataTooSmall; + } + if ((slotSizeOf(fillOop)) < FTBalloonFillDataSize) { + return GEFFillDataTooSmall; + } + /* Note: Rendering can only take place if we're not in one of the intermediate + (e.g., external) states. */ + state = workBuffer[GWState]; + if ((state == GEStateWaitingForEdge) + || ((state == GEStateWaitingForFill) + || (state == GEStateWaitingChange))) { + return GEFWrongState; + } + return 0; +} - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; - } - else { + /* BalloonEnginePlugin>>#loadShapeFromArray:nSegments:fill:lineWidth:lineFill: */ +static sqInt +loadShapeFromArraynSegmentsfilllineWidthlineFill(sqInt points, sqInt nSegments, sqInt fillIndex, sqInt lineWidth, sqInt lineFill) +{ + int *dstPoint1; + sqInt i; + int *point; + sqInt pointOop; + sqInt segs; + float *transform; + sqInt x; + int x0; + int x1; + int x2; + sqInt y; + int y0; + int y1; + int y2; - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); - } - } - loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); - goto l1; + for (i = 0; i < nSegments; i += 1) { + pointOop = fetchPointerofObject(i * 3, points); + loadPointfrom(((int *) (workBuffer + GWPoint1)), pointOop); + pointOop = fetchPointerofObject((i * 3) + 1, points); + loadPointfrom(((int *) (workBuffer + GWPoint2)), pointOop); + pointOop = fetchPointerofObject((i * 3) + 2, points); + loadPointfrom(((int *) (workBuffer + GWPoint3)), pointOop); + if (failed()) { + return null; } - (*((int *) (workBuffer + GWPoint1)) = x0); - (((int *) (workBuffer + GWPoint1)))[1] = y0; - (*((int *) (workBuffer + GWPoint2)) = x1); - (((int *) (workBuffer + GWPoint2)))[1] = y1; - (*((int *) (workBuffer + GWPoint3)) = x2); - (((int *) (workBuffer + GWPoint3)))[1] = y2; /* begin transformPoints: */ if (3 > 0) { @@ -5070,13 +5106,29 @@ loadShapenSegmentsfilllineWidthlineFillpointsShort(int *points, sqInt nSegments, point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } - segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (lineWidth != 0) - && (lineFill != 0)); - if (engineStopped) { - goto l1; + x0 = (*((int *) (workBuffer + GWPoint1))); + y0 = (((int *) (workBuffer + GWPoint1)))[1]; + x1 = (*((int *) (workBuffer + GWPoint2))); + y1 = (((int *) (workBuffer + GWPoint2)))[1]; + x2 = (*((int *) (workBuffer + GWPoint3))); + y2 = (((int *) (workBuffer + GWPoint3)))[1]; + /* Check if we can use a line */ + if (((x0 == y0) + && (x1 == y1)) + || ((x1 == x2) + && (y1 == y2))) { + loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint3)), lineFill, fillIndex, 0); + } + else { + + /* Need bezier */ + segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (lineWidth != 0) + && (lineFill != 0)); + if (engineStopped) { + return null; + } + loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); } - loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); -l1: /* end loadCompressedSegment:from:short:leftFill:rightFill:lineWidth:lineColor: */; if (engineStopped) { return null; } @@ -5097,9 +5149,8 @@ loadSpanBufferFrom(sqInt spanOop) if (!((fetchClassOf(spanOop)) == (classBitmap()))) { return GEFClassMismatch; } - - /* Leave last entry unused to avoid complications */ spanBuffer = firstIndexableField(spanOop); + /* Leave last entry unused to avoid complications */ value = (slotSizeOf(spanOop)) - 1; /* begin spanSizePut: */ @@ -5108,6 +5159,32 @@ loadSpanBufferFrom(sqInt spanOop) } +/* Load a transformation from the given array. */ + + /* BalloonEngineBase>>#loadTransformFromArray:into:length: */ +static sqInt +loadTransformFromArrayintolength(sqInt transformOop, float *destPtr, sqInt n) +{ + sqInt i; + sqInt value; + + for (i = 0; i < n; i += 1) { + value = fetchPointerofObject(i, transformOop); + if (!((isIntegerObject(value)) + || (isFloatObject(value)))) { + return primitiveFail(); + } + if (isIntegerObject(value)) { + destPtr[i] = (((float) (((double) (integerValueOf(value)) )))); + } + else { + destPtr[i] = (((float) (floatValueOf(value)))); + } + } + return 0; +} + + /* Load a transformation from transformOop into the float array defined by destPtr. The transformation is assumed to be either an array or a FloatArray of length n. */ @@ -5116,20 +5193,22 @@ loadSpanBufferFrom(sqInt spanOop) static sqInt loadTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) { + sqInt i; + if (transformOop == (nilObject())) { return 0; } - if (isImmediate(transformOop)) { - return primitiveFail(); - } if (!((slotSizeOf(transformOop)) == n)) { return primitiveFail(); } if (isWords(transformOop)) { - loadWordTransformFromintolength(transformOop, destPtr, n); + /* begin loadTransformFromFloats:into:length: */ + for (i = 0; i < n; i += 1) { + destPtr[i] = ((((float *) (firstIndexableField(transformOop))))[i]); + } } else { - loadArrayTransformFromintolength(transformOop, destPtr, n); + loadTransformFromArrayintolength(transformOop, destPtr, n); } return 1; } @@ -5334,23 +5413,6 @@ loadWideLinefromtolineFillleftFillrightFill(sqInt lineWidth, int *p1, int *p2, s } -/* Load a float array transformation from the given oop */ - - /* BalloonEngineBase>>#loadWordTransformFrom:into:length: */ -static sqInt -loadWordTransformFromintolength(sqInt transformOop, float *destPtr, sqInt n) -{ - sqInt i; - float *srcPtr; - - srcPtr = firstIndexableField(transformOop); - for (i = 0; i < n; i += 1) { - destPtr[i] = (srcPtr[i]); - } - return 0; -} - - /* Load the working buffer from the given oop */ /* BalloonEngineBase>>#loadWorkBufferFrom: */ @@ -5372,17 +5434,18 @@ loadWorkBufferFrom(sqInt wbOop) if (!((workBuffer[GWMagicIndex]) == GWMagicNumber)) { return GEFWorkBufferBadMagic; } + /* Sanity checks */ if (!((workBuffer[GWSize]) == (slotSizeOf(wbOop)))) { return GEFWorkBufferWrongSize; } if (!((workBuffer[GWObjStart]) == GWHeaderSize)) { return GEFWorkBufferStartWrong; } + /* Load buffers */ objBuffer = workBuffer + (workBuffer[GWObjStart]); getBuffer = objBuffer + (workBuffer[GWObjUsed]); - - /* Make sure we don't exceed the work buffer */ aetBuffer = getBuffer + (workBuffer[GWGETUsed]); + /* Make sure we don't exceed the work buffer */ if ((((GWHeaderSize + (workBuffer[GWObjUsed])) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) > (workBuffer[GWSize])) { return GEFWorkTooBig; } @@ -5574,10 +5637,12 @@ primitiveAddBezier(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(5), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* Make sure the fills are okay */ if (!((isFillOkay(leftFill)) && (isFillOkay(rightFill)))) { return primitiveFailFor(GEFWrongFill); } + /* Do a quick check if the fillIndices are equal - if so, just ignore it */ if ((leftFill == rightFill) && 0) { return pop(6); } @@ -5721,16 +5786,38 @@ primitiveAddBezier(void) EXPORT(sqInt) primitiveAddBezierShape(void) { + int *dstPoint1; sqInt failureCode; usqInt fillIndex; + sqInt i; + sqInt index; sqInt length; usqInt lineFill; sqInt lineWidth; sqInt nSegments; + int *point; sqInt points; sqInt pointsIsArray; + sqInt pointsIsShorts; sqInt segSize; - + sqInt segs; + float *transform; + sqInt x; + short x0; + int x0Int; + short x1; + int x1Int; + short x2; + int x2Int; + sqInt y; + short y0; + int y0Int; + short y1; + int y1Int; + short y2; + int y2Int; + + pointsIsShorts = 0; if (!((methodArgumentCount()) == 5)) { return primitiveFailFor(PrimErrBadNumArgs); } @@ -5738,33 +5825,44 @@ primitiveAddBezierShape(void) lineWidth = stackIntegerValue(1); fillIndex = positive32BitValueOf(stackValue(2)); nSegments = stackIntegerValue(3); - points = stackObjectValue(4); + points = stackValue(4); if (failed()) { return primitiveFailFor(PrimErrBadArgument); } if ((failureCode = quickLoadEngineFromrequiredState(stackValue(5), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* First, do a check if the points look okay */ length = slotSizeOf(points); if (isWords(points)) { + /* Either PointArray or ShortPointArray */ pointsIsArray = 0; - if (!((length == (nSegments * 3)) - || (length == (nSegments * 6)))) { - return primitiveFailFor(PrimErrBadArgument); + if (length == (nSegments * 3)) { + pointsIsShorts = 1; + } + else { + if (length == (nSegments * 6)) { + pointsIsShorts = 0; + } + else { + return primitiveFailFor(PrimErrBadArgument); + } } } else { /* Must be Array of points */ - if (!(isArray(points))) { - return primitiveFailFor(PrimErrBadArgument); - } - if (!(length == (nSegments * 3))) { + if (!((isArray(points)) + && (length == (nSegments * 3)))) { return primitiveFailFor(PrimErrBadArgument); } pointsIsArray = 1; } + /* Now check that we have some hope to have enough free space. + Do this by assuming nPoints boundaries of maximum size, + hoping that most of the fills will be colors and many boundaries + will be line segments */ if ((lineWidth == 0) || (lineFill == 0)) { segSize = GLBaseSize; @@ -5781,6 +5879,7 @@ primitiveAddBezierShape(void) engineStopped = 1; return primitiveFailFor(GEFWorkTooBig); } + /* Check the fills */ if (!((isFillOkay(lineFill)) && (isFillOkay(fillIndex)))) { return primitiveFailFor(GEFWrongFill); @@ -5790,23 +5889,499 @@ primitiveAddBezierShape(void) if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } + /* Check if have anything at all to do */ if (((lineFill == 0) || (lineWidth == 0)) && (fillIndex == 0)) { return pop(5); } + /* Transform the lineWidth */ if (lineWidth) { lineWidth = transformWidth(lineWidth); if (lineWidth < 1) { lineWidth = 1; } } - if (pointsIsArray) { - loadArrayShapenSegmentsfilllineWidthlineFill(points, nSegments, fillIndex, lineWidth, lineFill); - } - else { - loadShapenSegmentsfilllineWidthlineFillpointsShort(firstIndexableField(points), nSegments, fillIndex, lineWidth, lineFill, (nSegments * 3) == length); - } + /* And load the actual shape */ + if (pointsIsArray) { + loadShapeFromArraynSegmentsfilllineWidthlineFill(points, nSegments, fillIndex, lineWidth, lineFill); + } + else { + if (pointsIsShorts) { + /* begin loadShapeFromShortPoints:nSegments:fill:lineWidth:lineFill: */ + for (i = 1; i <= nSegments; i += 1) { + /* begin loadCompressedSegment:fromShortPoints:leftFill:rightFill:lineWidth:lineColor: */ + if ((fillIndex == 0) + && ((lineWidth == 0) + || (lineFill == 0))) { + goto l1; + } + + /* 3 points with x/y each */ + index = (i - 1) * 6; + x0 = (((short *) (firstIndexableField(points))))[index]; + y0 = (((short *) (firstIndexableField(points))))[index + 1]; + x1 = (((short *) (firstIndexableField(points))))[index + 2]; + y1 = (((short *) (firstIndexableField(points))))[index + 3]; + x2 = (((short *) (firstIndexableField(points))))[index + 4]; + y2 = (((short *) (firstIndexableField(points))))[index + 5]; + /* Briefly check if can represent the bezier as a line */ + if (((x0 == x1) + && (y0 == y1)) + || ((x1 == x2) + && (y1 == y2))) { + + /* We can use a line from x0/y0 to x2/y2 */ + if ((x0 == x2) + && (y0 == y2)) { + goto l1; + } + (*((int *) (workBuffer + GWPoint1)) = x0); + (((int *) (workBuffer + GWPoint1)))[1] = y0; + (*((int *) (workBuffer + GWPoint2)) = x2); + (((int *) (workBuffer + GWPoint2)))[1] = y2; + + /* begin transformPoints: */ + if (2 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); + goto l1; + } + /* Need bezier curve + Load and transform points */ + (*((int *) (workBuffer + GWPoint1)) = x0); + (((int *) (workBuffer + GWPoint1)))[1] = y0; + (*((int *) (workBuffer + GWPoint2)) = x1); + (((int *) (workBuffer + GWPoint2)))[1] = y1; + (*((int *) (workBuffer + GWPoint3)) = x2); + (((int *) (workBuffer + GWPoint3)))[1] = y2; + + /* begin transformPoints: */ + if (3 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (lineWidth != 0) + && (lineFill != 0)); + if (engineStopped) { + goto l1; + } + loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); +l1: /* end loadCompressedSegment:fromShortPoints:leftFill:rightFill:lineWidth:lineColor: */; + if (engineStopped) { + goto l2; + } + } +l2: /* end loadShapeFromShortPoints:nSegments:fill:lineWidth:lineFill: */; + } + else { + /* begin loadShapeFromIntPoints:nSegments:fill:lineWidth:lineFill: */ + for (i = 1; i <= nSegments; i += 1) { + /* begin loadCompressedSegment:fromIntPoints:leftFill:rightFill:lineWidth:lineColor: */ + if ((fillIndex == 0) + && ((lineWidth == 0) + || (lineFill == 0))) { + goto l3; + } + + /* 3 points with x/y each */ + index = (i - 1) * 6; + x0Int = (((int *) (firstIndexableField(points))))[index]; + y0Int = (((int *) (firstIndexableField(points))))[index + 1]; + x1Int = (((int *) (firstIndexableField(points))))[index + 2]; + y1Int = (((int *) (firstIndexableField(points))))[index + 3]; + x2Int = (((int *) (firstIndexableField(points))))[index + 4]; + y2Int = (((int *) (firstIndexableField(points))))[index + 5]; + /* Briefly check if can represent the bezier as a line */ + if (((x0Int == x1Int) + && (y0Int == y1Int)) + || ((x1Int == x2Int) + && (y1Int == y2Int))) { + + /* We can use a line from x0/y0 to x2/y2 */ + if ((x0Int == x2Int) + && (y0Int == y2Int)) { + goto l3; + } + (*((int *) (workBuffer + GWPoint1)) = x0Int); + (((int *) (workBuffer + GWPoint1)))[1] = y0Int; + (*((int *) (workBuffer + GWPoint2)) = x2Int); + (((int *) (workBuffer + GWPoint2)))[1] = y2Int; + + /* begin transformPoints: */ + if (2 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (2 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); + goto l3; + } + /* Need bezier curve + Load and transform points */ + (*((int *) (workBuffer + GWPoint1)) = x0Int); + (((int *) (workBuffer + GWPoint1)))[1] = y0Int; + (*((int *) (workBuffer + GWPoint2)) = x1Int); + (((int *) (workBuffer + GWPoint2)))[1] = y1Int; + (*((int *) (workBuffer + GWPoint3)) = x2Int); + (((int *) (workBuffer + GWPoint3)))[1] = y2Int; + + /* begin transformPoints: */ + if (3 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + if (3 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { + + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + segs = loadAndSubdivideBezierFromviatoisWide(((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), ((int *) (workBuffer + GWPoint3)), (lineWidth != 0) + && (lineFill != 0)); + if (engineStopped) { + goto l3; + } + loadWideBezierlineFillleftFillrightFilln(lineWidth, lineFill, fillIndex, 0, segs); +l3: /* end loadCompressedSegment:fromIntPoints:leftFill:rightFill:lineWidth:lineColor: */; + if (engineStopped) { + goto l4; + } + } +l4: /* end loadShapeFromIntPoints:nSegments:fill:lineWidth:lineFill: */; + } + } if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } @@ -6031,7 +6606,6 @@ primitiveAddCompressedShape(void) sqInt lineWidths; sqInt nSegments; sqInt points; - int pointsShort; sqInt rightFills; if (!((methodArgumentCount()) == 7)) { @@ -6050,9 +6624,14 @@ primitiveAddCompressedShape(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(7), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* First, do a check if the compressed shape is okay */ if (!(checkCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(points, nSegments, leftFills, rightFills, lineWidths, lineFills, fillIndexList))) { return primitiveFailFor(GEFEntityCheckFailed); } + /* Now check that we have some hope to have enough free space. + Do this by assuming nSegments boundaries of maximum size, + hoping that most of the fills will be colors and many boundaries + will be line segments */ /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + ((((GBBaseSize < GLBaseSize) ? GLBaseSize : GBBaseSize)) * nSegments)) > (workBuffer[GWBufferTop])) { @@ -6062,10 +6641,13 @@ primitiveAddCompressedShape(void) engineStopped = 1; return primitiveFailFor(GEFWorkTooBig); } - - /* Then actually load the compressed shape */ - pointsShort = (slotSizeOf(points)) == (nSegments * 3); - loadCompressedShapesegmentsleftFillsrightFillslineWidthslineFillsfillIndexListpointShort(firstIndexableField(points), nSegments, firstIndexableField(leftFills), firstIndexableField(rightFills), firstIndexableField(lineWidths), firstIndexableField(lineFills), firstIndexableField(fillIndexList), pointsShort); + /* Check if the points are short, and load as appropriate. */ + if ((slotSizeOf(points)) == (nSegments * 3)) { + loadCompressedShapeFromShortPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(((short *) (firstIndexableField(points))), nSegments, ((int *) (firstIndexableField(leftFills))), ((int *) (firstIndexableField(rightFills))), ((int *) (firstIndexableField(lineWidths))), ((int *) (firstIndexableField(lineFills))), ((int *) (firstIndexableField(fillIndexList)))); + } + else { + loadCompressedShapeFromIntPointssegmentsleftFillsrightFillslineWidthslineFillsfillIndexList(((int *) (firstIndexableField(points))), nSegments, ((int *) (firstIndexableField(leftFills))), ((int *) (firstIndexableField(rightFills))), ((int *) (firstIndexableField(lineWidths))), ((int *) (firstIndexableField(lineFills))), ((int *) (firstIndexableField(fillIndexList)))); + } if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } @@ -6166,15 +6748,18 @@ primitiveAddLine(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(4), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* Make sure the fills are okay */ if (!((isFillOkay(leftFill)) && (isFillOkay(rightFill)))) { return primitiveFailFor(GEFWrongFill); } + /* Load the points */ loadPointfrom(((int *) (workBuffer + GWPoint1)), startOop); loadPointfrom(((int *) (workBuffer + GWPoint2)), endOop); if (failed()) { return primitiveFailFor(GEFBadPoint); } + /* Transform points */ /* begin transformPoints: */ if (2 > 0) { @@ -6265,11 +6850,13 @@ primitiveAddLine(void) point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); } } + /* Transform colors */ leftFill = transformColor(leftFill); rightFill = transformColor(rightFill); if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } + /* Load line */ loadWideLinefromtolineFillleftFillrightFill(0, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), 0, leftFill, rightFill); if (engineStopped) { return primitiveFailFor(GEFEngineStopped); @@ -6313,20 +6900,24 @@ primitiveAddOval(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(5), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* Make sure the fills are okay */ if (!((isFillOkay(borderIndex)) && (isFillOkay(fillIndex)))) { return primitiveFailFor(GEFWrongFill); } + /* Transform colors */ fillIndex = transformColor(fillIndex); borderIndex = transformColor(borderIndex); if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } + /* Check if we have anything at all to do */ if ((fillIndex == 0) && ((borderIndex == 0) || (borderWidth <= 0))) { return pop(5); } + /* Make sure we have some space */ /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + (16 * GBBaseSize)) > (workBuffer[GWBufferTop])) { @@ -6336,6 +6927,7 @@ primitiveAddOval(void) engineStopped = 1; return primitiveFailFor(GEFWorkTooBig); } + /* Check if we need a border */ if ((borderWidth > 0) && (borderIndex != 0)) { borderWidth = transformWidth(borderWidth); @@ -6343,6 +6935,7 @@ primitiveAddOval(void) else { borderWidth = 0; } + /* Load the rectangle points */ loadPointfrom(((int *) (workBuffer + GWPoint1)), startOop); loadPointfrom(((int *) (workBuffer + GWPoint2)), endOop); if (failed()) { @@ -6386,21 +6979,22 @@ primitiveAddPolygon(void) sqInt nPoints; int *point; sqInt points; - int *points1; sqInt pointsIsArray; + sqInt pointsIsShorts; sqInt segSize; float *transform; sqInt x; int x0; - sqInt x0SqInt; + short x0Short; int x1; - sqInt x1SqInt; + short x1Short; sqInt y; int y0; - sqInt y0SqInt; + short y0Short; int y1; - sqInt y1SqInt; + short y1Short; + pointsIsShorts = 0; if (!((methodArgumentCount()) == 5)) { return primitiveFailFor(PrimErrBadNumArgs); } @@ -6408,33 +7002,44 @@ primitiveAddPolygon(void) lineWidth = stackIntegerValue(1); fillIndex = positive32BitValueOf(stackValue(2)); nPoints = stackIntegerValue(3); - points = stackObjectValue(4); + points = stackValue(4); if (failed()) { return primitiveFailFor(PrimErrBadArgument); } if ((failureCode = quickLoadEngineFromrequiredState(stackValue(5), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* First, do a check if the points look okay */ length = slotSizeOf(points); if (isWords(points)) { + /* Either PointArray or ShortPointArray */ pointsIsArray = 0; - if (!((length == nPoints) - || ((nPoints * 2) == length))) { - return primitiveFailFor(PrimErrBadArgument); + if (length == nPoints) { + pointsIsShorts = 1; + } + else { + if ((nPoints * 2) == length) { + pointsIsShorts = 0; + } + else { + return primitiveFailFor(PrimErrBadArgument); + } } } else { /* Must be Array of points */ - if (!(isArray(points))) { - return primitiveFailFor(PrimErrBadArgument); - } - if (!(length == nPoints)) { + if (!((isArray(points)) + && (length == nPoints))) { return primitiveFailFor(PrimErrBadArgument); } pointsIsArray = 1; } + /* Now check that we have some hope to have enough free space. + Do this by assuming nPoints boundaries of maximum size, + hoping that most of the fills will be colors and many boundaries + will be line segments */ if ((lineWidth == 0) || (lineFill == 0)) { segSize = GLBaseSize; @@ -6451,6 +7056,7 @@ primitiveAddPolygon(void) engineStopped = 1; return primitiveFail(); } + /* Check the fills */ if (!((isFillOkay(lineFill)) && (isFillOkay(fillIndex)))) { return primitiveFailFor(GEFWrongFill); @@ -6460,16 +7066,19 @@ primitiveAddPolygon(void) if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } + /* Check if have anything at all to do */ if (((lineFill == 0) || (lineWidth == 0)) && (fillIndex == 0)) { return pop(5); } + /* Transform the lineWidth */ if (lineWidth) { lineWidth = transformWidth(lineWidth); } + /* And load the actual polygon */ if (pointsIsArray) { - /* begin loadArrayPolygon:nPoints:fill:lineWidth:lineFill: */ + /* begin loadPolygonFromArray:nPoints:fill:lineWidth:lineFill: */ loadPointfrom(((int *) (workBuffer + GWPoint1)), fetchPointerofObject(0, points)); if (failed()) { goto l1; @@ -6584,131 +7193,229 @@ primitiveAddPolygon(void) x0 = x1; y0 = y1; } -l1: /* end loadArrayPolygon:nPoints:fill:lineWidth:lineFill: */; +l1: /* end loadPolygonFromArray:nPoints:fill:lineWidth:lineFill: */; } else { - points1 = firstIndexableField(points); - - /* begin loadPolygon:nPoints:fill:lineWidth:lineFill:pointsShort: */ - if (nPoints == length) { - x0SqInt = (*((short *) points1)); - y0SqInt = (((short *) points1))[1]; - } - else { - x0SqInt = (*((int *) points1)); - y0SqInt = (((int *) points1))[1]; - } - for (i = 1; i < nPoints; i += 1) { - if (nPoints == length) { - x1SqInt = (((short *) points1))[i * 2]; - y1SqInt = (((short *) points1))[(i * 2) + 1]; - } - else { - x1SqInt = (((int *) points1))[i * 2]; - y1SqInt = (((int *) points1))[(i * 2) + 1]; - } - (*((int *) (workBuffer + GWPoint1)) = x0SqInt); - (((int *) (workBuffer + GWPoint1)))[1] = y0SqInt; - (*((int *) (workBuffer + GWPoint2)) = x1SqInt); - (((int *) (workBuffer + GWPoint2)))[1] = y1SqInt; - - /* begin transformPoints: */ - if (2 > 0) { - point = ((int *) (workBuffer + GWPoint1)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + if (pointsIsShorts) { + /* begin loadPolygonFromShortPoints:nPoints:fill:lineWidth:lineFill: */ + x0Short = (*((short *) (firstIndexableField(points)))); + y0Short = (((short *) (firstIndexableField(points))))[1]; + for (i = 1; i < nPoints; i += 1) { + x1Short = (((short *) (firstIndexableField(points))))[i * 2]; + y1Short = (((short *) (firstIndexableField(points))))[(i * 2) + 1]; + (*((int *) (workBuffer + GWPoint1)) = x0Short); + (((int *) (workBuffer + GWPoint1)))[1] = y0Short; + (*((int *) (workBuffer + GWPoint2)) = x1Short); + (((int *) (workBuffer + GWPoint2)))[1] = y1Short; + + /* begin transformPoints: */ + if (2 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - else { + if (2 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - } - if (2 > 1) { - point = ((int *) (workBuffer + GWPoint2)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + if (2 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - else { + if (2 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } + } + loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); + if (engineStopped) { + goto l2; } + x0Short = x1Short; + y0Short = y1Short; } - if (2 > 2) { - point = ((int *) (workBuffer + GWPoint3)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { +l2: /* end loadPolygonFromShortPoints:nPoints:fill:lineWidth:lineFill: */; + } + else { + /* begin loadPolygonFromIntPoints:nPoints:fill:lineWidth:lineFill: */ + x0 = (*((int *) (firstIndexableField(points)))); + y0 = (((int *) (firstIndexableField(points))))[1]; + for (i = 1; i < nPoints; i += 1) { + x1 = (((int *) (firstIndexableField(points))))[i * 2]; + y1 = (((int *) (firstIndexableField(points))))[(i * 2) + 1]; + (*((int *) (workBuffer + GWPoint1)) = x0); + (((int *) (workBuffer + GWPoint1)))[1] = y0; + (*((int *) (workBuffer + GWPoint2)) = x1); + (((int *) (workBuffer + GWPoint2)))[1] = y1; + + /* begin transformPoints: */ + if (2 > 0) { + point = ((int *) (workBuffer + GWPoint1)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - else { + if (2 > 1) { + point = ((int *) (workBuffer + GWPoint2)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - } - if (2 > 3) { - point = ((int *) (workBuffer + GWPoint4)); - - /* begin transformPoint: */ - if (workBuffer[GWHasEdgeTransform]) { + if (2 > 2) { + point = ((int *) (workBuffer + GWPoint3)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ - /* begin transformPoint:into: */ - dstPoint1 = ((int *) point); - transform = ((float *) (workBuffer + GWEdgeTransform)); - x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); - y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); - dstPoint1[0] = x; - dstPoint1[1] = y; + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } - else { + if (2 > 3) { + point = ((int *) (workBuffer + GWPoint4)); + + /* begin transformPoint: */ + if (workBuffer[GWHasEdgeTransform]) { + + /* Note: AA adjustment is done in #transformPoint: for higher accuracy */ + /* begin transformPoint:into: */ + dstPoint1 = ((int *) point); + transform = ((float *) (workBuffer + GWEdgeTransform)); + x = ((sqInt)(((((transform[0]) * (((double) ((*((int *) point))) ))) + ((transform[1]) * (((double) ((((int *) point))[1]) )))) + (transform[2])) * (((double) (workBuffer[GWAALevel]) )))); + y = ((sqInt)(((((transform[3]) * (((double) ((*((int *) point))) ))) + ((transform[4]) * (((double) ((((int *) point))[1]) )))) + (transform[5])) * (((double) (workBuffer[GWAALevel]) )))); + dstPoint1[0] = x; + dstPoint1[1] = y; + } + else { - /* Multiply each component by aaLevel and add a half pixel */ - point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); - point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + /* Multiply each component by aaLevel and add a half pixel */ + point[0] = (((point[0]) + (workBuffer[GWDestOffsetX])) * (workBuffer[GWAALevel])); + point[1] = (((point[1]) + (workBuffer[GWDestOffsetY])) * (workBuffer[GWAALevel])); + } } + loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); + if (engineStopped) { + goto l3; + } + x0 = x1; + y0 = y1; } - loadWideLinefromtolineFillleftFillrightFill(lineWidth, ((int *) (workBuffer + GWPoint1)), ((int *) (workBuffer + GWPoint2)), lineFill, fillIndex, 0); - if (engineStopped) { - goto l2; - } - x0SqInt = x1SqInt; - y0SqInt = y1SqInt; +l3: /* end loadPolygonFromIntPoints:nPoints:fill:lineWidth:lineFill: */; } -l2: /* end loadPolygon:nPoints:fill:lineWidth:lineFill:pointsShort: */; } if (engineStopped) { return primitiveFailFor(GEFEngineStopped); @@ -6760,20 +7467,24 @@ primitiveAddRect(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(5), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* Make sure the fills are okay */ if (!((isFillOkay(borderIndex)) && (isFillOkay(fillIndex)))) { return primitiveFailFor(GEFWrongFill); } + /* Transform colors */ borderIndex = transformColor(borderIndex); fillIndex = transformColor(fillIndex); if (engineStopped) { return primitiveFailFor(GEFEngineStopped); } + /* Check if we have anything at all to do */ if ((fillIndex == 0) && ((borderIndex == 0) || (borderWidth == 0))) { return pop(5); } + /* Make sure we have some space */ /* begin needAvailableSpace: */ if (((((GWHeaderSize + objUsed) + (workBuffer[GWGETUsed])) + (workBuffer[GWAETUsed])) + (4 * GLBaseSize)) > (workBuffer[GWBufferTop])) { @@ -6783,6 +7494,7 @@ primitiveAddRect(void) engineStopped = 1; return primitiveFailFor(GEFWorkTooBig); } + /* Check if we need a border */ if ((borderWidth > 0) && (borderIndex != 0)) { borderWidth = transformWidth(borderWidth); @@ -6790,6 +7502,7 @@ primitiveAddRect(void) else { borderWidth = 0; } + /* Load the rectangle */ loadPointfrom(((int *) (workBuffer + GWPoint1)), startOop); loadPointfrom(((int *) (workBuffer + GWPoint3)), endOop); if (failed()) { @@ -6799,6 +7512,7 @@ primitiveAddRect(void) (((int *) (workBuffer + GWPoint2)))[1] = ((((int *) (workBuffer + GWPoint1)))[1]); (*((int *) (workBuffer + GWPoint4)) = (*((int *) (workBuffer + GWPoint1)))); (((int *) (workBuffer + GWPoint4)))[1] = ((((int *) (workBuffer + GWPoint3)))[1]); + /* Transform the points */ /* begin transformPoints: */ if (4 > 0) { @@ -6984,33 +7698,38 @@ primitiveCopyBuffer(void) return primitiveFailFor(PrimErrBadNumArgs); } buf2 = stackValue(0); - - /* Make sure the old buffer is properly initialized */ buf1 = stackValue(1); + /* Make sure the old buffer is properly initialized */ if ((failCode = loadWorkBufferFrom(buf1))) { return primitiveFailFor(failCode); } + /* Make sure the buffers are of the same type */ if (!((fetchClassOf(buf1)) == (fetchClassOf(buf2)))) { return primitiveFailFor(GEFClassMismatch); } + /* Make sure buf2 is at least of the size of buf1 */ diff = (slotSizeOf(buf2)) - (slotSizeOf(buf1)); if (diff < 0) { return primitiveFailFor(GEFSizeMismatch); } + /* Okay - ready for copying. First of all just copy the contents up to wbTop */ src = workBuffer; dst = firstIndexableField(buf2); toDoLimit = (workBuffer[GWBufferTop]) - 1; for (i = 0; i <= toDoLimit; i += 1) { dst[i] = (src[i]); } + /* Adjust wbSize and wbTop in the new buffer */ dst[GWBufferTop] = ((workBuffer[GWBufferTop]) + diff); dst[GWSize] = ((workBuffer[GWSize]) + diff); + /* Now copy the entries from wbTop to wbSize */ src += workBuffer[GWBufferTop]; dst = (dst + (workBuffer[GWBufferTop])) + diff; toDoLimit1 = ((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - 1; for (i = 0; i <= toDoLimit1; i += 1) { dst[i] = (src[i]); } + /* Okay, done. Check the new buffer by loading the state from it */ if ((failCode = loadWorkBufferFrom(buf2))) { return primitiveFailFor(failCode); } @@ -7037,6 +7756,7 @@ primitiveDisplaySpanBuffer(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(0), GEStateBlitBuffer))) { return primitiveFailFor(failureCode); } + /* Load span buffer and bitBlt */ if ((failureCode = loadSpanBufferFrom(fetchPointerofObject(BESpanIndex, engine)))) { return primitiveFailFor(failureCode); } @@ -7145,6 +7865,67 @@ primitiveGetAALevel(void) return 0; } + +/* A combination of primitiveGetBezierStats, primitiveGetTimes, & + primitiveGetCounts + */ + + /* BalloonEngineBase>>#primitiveGetAllStats */ +EXPORT(sqInt) +primitiveGetAllStats(void) +{ + sqInt countsOop; + sqInt failureCode; + int *stats; + sqInt statsOop; + sqInt timesOop; + + countsOop = 0; + statsOop = 0; + timesOop = 0; + if (!((methodArgumentCount()) == 3)) { + return primitiveFailFor(PrimErrBadNumArgs); + } + if ((failureCode = quickLoadEngineFrom(stackValue(3)))) { + return primitiveFailFor(failureCode); + } + if (!((isWords((countsOop = stackValue(2)))) + && (((slotSizeOf(countsOop)) >= 9) + && ((isWords((timesOop = stackValue(1)))) + && (((slotSizeOf(timesOop)) >= 9) + && ((isWords((statsOop = stackValue(0)))) + && ((slotSizeOf(statsOop)) >= 4))))))) { + return primitiveFailFor(PrimErrBadArgument); + } + stats = firstIndexableField(countsOop); + stats[0] = ((stats[0]) + (workBuffer[GWCountInitializing])); + stats[1] = ((stats[1]) + (workBuffer[GWCountFinishTest])); + stats[2] = ((stats[2]) + (workBuffer[GWCountNextGETEntry])); + stats[3] = ((stats[3]) + (workBuffer[GWCountAddAETEntry])); + stats[4] = ((stats[4]) + (workBuffer[GWCountNextFillEntry])); + stats[5] = ((stats[5]) + (workBuffer[GWCountMergeFill])); + stats[6] = ((stats[6]) + (workBuffer[GWCountDisplaySpan])); + stats[7] = ((stats[7]) + (workBuffer[GWCountNextAETEntry])); + stats[8] = ((stats[8]) + (workBuffer[GWCountChangeAETEntry])); + stats = firstIndexableField(timesOop); + stats[0] = ((stats[0]) + (workBuffer[GWTimeInitializing])); + stats[1] = ((stats[1]) + (workBuffer[GWTimeFinishTest])); + stats[2] = ((stats[2]) + (workBuffer[GWTimeNextGETEntry])); + stats[3] = ((stats[3]) + (workBuffer[GWTimeAddAETEntry])); + stats[4] = ((stats[4]) + (workBuffer[GWTimeNextFillEntry])); + stats[5] = ((stats[5]) + (workBuffer[GWTimeMergeFill])); + stats[6] = ((stats[6]) + (workBuffer[GWTimeDisplaySpan])); + stats[7] = ((stats[7]) + (workBuffer[GWTimeNextAETEntry])); + stats[8] = ((stats[8]) + (workBuffer[GWTimeChangeAETEntry])); + stats = firstIndexableField(statsOop); + stats[0] = ((stats[0]) + (workBuffer[GWBezierMonotonSubdivisions])); + stats[1] = ((stats[1]) + (workBuffer[GWBezierHeightSubdivisions])); + stats[2] = ((stats[2]) + (workBuffer[GWBezierOverflowSubdivisions])); + stats[3] = ((stats[3]) + (workBuffer[GWBezierLineConversions])); + methodReturnReceiver(); + return 0; +} + /* BalloonEnginePlugin>>#primitiveGetBezierStats */ EXPORT(sqInt) primitiveGetBezierStats(void) @@ -7267,9 +8048,8 @@ primitiveGetFailureReason(void) if (methodArgumentCount()) { return primitiveFailFor(PrimErrBadNumArgs); } - - /* Note -- don't call loadEngineFrom here because this will override the stopReason with Zero */ engine = stackValue(0); + /* Note -- don't call loadEngineFrom here because this will override the stopReason with Zero */ if (isImmediate(engine)) { return primitiveFailFor(GEFEngineIsInteger); } @@ -7442,6 +8222,7 @@ primitiveInitializeProcessing(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(0), GEStateUnlocked))) { return primitiveFailFor(failureCode); } + /* Load span buffer for clear operation */ if ((failureCode = loadSpanBufferFrom(fetchPointerofObject(BESpanIndex, engine)))) { return primitiveFailFor(failureCode); } @@ -7490,20 +8271,22 @@ primitiveMergeFillFrom(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(2), GEStateWaitingForFill))) { return primitiveFailFor(failureCode); } + /* Load span buffer for merging the fill */ if ((failureCode = loadSpanBufferFrom(fetchPointerofObject(BESpanIndex, engine)))) { return primitiveFailFor(failureCode); } fillOop = stackObjectValue(0); - - /* Check bitmap */ bitsOop = stackObjectValue(1); + /* Check bitmap */ if (!((!(failed())) && ((fetchClassOf(bitsOop)) == (classBitmap())))) { return primitiveFailFor(PrimErrBadArgument); } + /* Check fillOop */ if ((slotSizeOf(fillOop)) < FTBalloonFillDataSize) { return primitiveFailFor(GEFFillDataTooSmall); } + /* Check if this was the fill we have exported */ value = fetchIntegerofObject(FTIndexIndex, fillOop); if (!((objBuffer[(workBuffer[GWLastExportedFill]) + GEObjectIndex]) == value)) { return primitiveFailFor(GEFWrongFill); @@ -7522,7 +8305,7 @@ primitiveMergeFillFrom(void) if (failed()) { return null; } - fillBitmapSpanfromto(firstIndexableField(bitsOop), workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX]); + fillBitmapSpanfromto(((int *) (firstIndexableField(bitsOop))), workBuffer[GWLastExportedLeftX], workBuffer[GWLastExportedRightX]); /* statePut: */ workBuffer[GWState] = GEStateScanningAET; @@ -7582,14 +8365,11 @@ primitiveNeedsFlushPut(void) if (failed()) { return primitiveFailFor(PrimErrBadArgument); } - if (needFlush == 1) { - /* needsFlushPut: */ - workBuffer[GWNeedsFlush] = 1; - } - else { - /* needsFlushPut: */ - workBuffer[GWNeedsFlush] = 0; - } + + /* needsFlushPut: */ + workBuffer[GWNeedsFlush] = ((needFlush + ? 1 + : 0)); /* begin storeEngineStateInto: */ /* objUsedPut: */ @@ -7630,6 +8410,8 @@ primitiveNextActiveEdgeEntry(void) if (hasEdge) { edge = aetBuffer[workBuffer[GWAETStart]]; storeEdgeStateFrominto(edge, edgeOop); + /* Do not advance to the next aet entry yet + self aetStartPut: self aetStartGet + 1. */ /* statePut: */ workBuffer[GWState] = GEStateWaitingChange; @@ -7680,12 +8462,14 @@ primitiveNextFillEntry(void) if ((failureCode = quickLoadEngineFromrequiredState(stackValue(1), GEStateScanningAET))) { return primitiveFailFor(failureCode); } + /* Load span buffer for internal handling of fills */ if ((failureCode = loadSpanBufferFrom(fetchPointerofObject(BESpanIndex, engine)))) { return primitiveFailFor(failureCode); } if (!(loadFormsFrom(fetchPointerofObject(BEFormsIndex, engine)))) { return primitiveFailFor(GEFFormLoadFailed); } + /* Check if we have to clear the span buffer before proceeding */ if (workBuffer[GWClearSpanBuffer]) { if (!((workBuffer[GWCurrentY]) & (workBuffer[GWAAScanMask]))) { clearSpanBuffer(); @@ -7834,14 +8618,14 @@ primitiveRegisterExternalEdge(void) if (!(allocateObjEntry(GEBaseEdgeSize))) { return primitiveFailFor(GEFWorkTooBig); } + /* Make sure the fills are okay */ if (!((isFillOkay(leftFillIndex)) && (isFillOkay(rightFillIndex)))) { return primitiveFailFor(GEFWrongFill); } edge = objUsed; - - /* Install type and length */ objUsed = edge + GEBaseEdgeSize; + /* Install type and length */ /* #objectTypeOf:put: #obj:at:put: */ objBuffer[edge + GEObjectType] = GEPrimitiveEdge; @@ -7851,6 +8635,7 @@ primitiveRegisterExternalEdge(void) /* #objectIndexOf:put: #obj:at:put: */ objBuffer[edge + GEObjectIndex] = index; + /* Install remaining stuff */ /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[edge + GEXValue] = initialX; @@ -7900,15 +8685,15 @@ primitiveRegisterExternalFill(void) if (failed()) { return primitiveFailFor(PrimErrBadArgument); } + /* Note: We *must* not allocate any fill with index 0 */ fill = 0; while (fill == 0) { if (!(allocateObjEntry(GEBaseEdgeSize))) { return primitiveFailFor(GEFWorkTooBig); } fill = objUsed; - - /* Install type and length */ objUsed = fill + GEBaseFillSize; + /* Install type and length */ /* #objectTypeOf:put: #obj:at:put: */ objBuffer[fill + GEObjectType] = GEPrimitiveFill; @@ -7930,6 +8715,37 @@ primitiveRegisterExternalFill(void) } +/* Condense the trio of + [self primFinishedProcessing] + whileFalse: + [reason := self primRenderScanline: edge with: fill. + reason = 0 ifFalse: + [self processStopReason: reason edge: edge fill: fill]] + into two primitives: + [(reason := self primRenderAllScanlines: edge with: fill) ~= 0] whileTrue: + [self processStopReason: reason edge: edge fill: fill]. */ + + /* BalloonEngineBase>>#primitiveRenderAllScanlines */ +EXPORT(sqInt) +primitiveRenderAllScanlines(void) +{ + sqInt failCode; + int stopReason; + + if ((failCode = loadRenderingState())) { + return primitiveFailFor(failCode); + } + stopReason = 0; + while (!((stopReason != 0) + || ((workBuffer[GWState]) == GEStateCompleted))) { + proceedRenderingScanline(); + stopReason = workBuffer[GWStopReason]; + } + storeRenderingState(); + return 0; +} + + /* Start/Proceed rendering the entire image */ /* BalloonEngineBase>>#primitiveRenderImage */ @@ -8006,8 +8822,8 @@ primitiveSetBitBltPlugin(void) sqInt pluginName; char *ptr; - /* Must be string to work */ pluginName = stackValue(0); + /* Must be string to work */ if (!(isBytes(pluginName))) { return primitiveFail(); } @@ -8018,13 +8834,12 @@ primitiveSetBitBltPlugin(void) ptr = firstIndexableField(pluginName); needReload = 0; for (i = 0; i < length; i += 1) { - - /* Compare and store the plugin to be used */ if (!((bbPluginName[i]) == (ptr[i]))) { bbPluginName[i] = (ptr[i]); needReload = 1; } } + /* Compare and store the plugin to be used */ if (bbPluginName[length]) { bbPluginName[length] = 0; needReload = 1; @@ -8115,6 +8930,7 @@ primitiveSetColorTransform(void) /* hasColorTransformPut: */ workBuffer[GWHasColorTransform] = 1; + /* Scale transform to be in 0-256 range */ transform[1] = ((transform[1]) * (256.0f)); transform[3] = ((transform[3]) * (256.0f)); transform[5] = ((transform[5]) * (256.0f)); @@ -8647,6 +9463,7 @@ quickSortGlobalEdgeTablefromto(int *array, sqInt i, sqInt j) if (n <= 2) { return 0; } + /* More than two elements. */ /* ij is the midpoint of i and j. */ ij = (i + j) / 2; @@ -8679,6 +9496,9 @@ quickSortGlobalEdgeTablefromto(int *array, sqInt i, sqInt j) if (n <= 3) { return 0; } + /* More than three elements. + Find k>i and lmajorVersion()) == (VM_PROXY_MAJOR)) && ((interpreterProxy->minorVersion()) >= (VM_PROXY_MINOR)); if (ok) { @@ -8908,6 +9730,8 @@ setInterpreter(struct VirtualMachine *anInterpreter) isWords = interpreterProxy->isWords; makePointwithxValueyValue = interpreterProxy->makePointwithxValueyValue; methodArgumentCount = interpreterProxy->methodArgumentCount; + methodReturnInteger = interpreterProxy->methodReturnInteger; + methodReturnReceiver = interpreterProxy->methodReturnReceiver; nilObject = interpreterProxy->nilObject; pop = interpreterProxy->pop; popthenPush = interpreterProxy->popthenPush; @@ -9051,15 +9875,15 @@ stepToFirstBezierInat(sqInt bezier, sqInt yValue) && (yValue >= (objBuffer[bezier + GBEndY]))) { return objBuffer[bezier + GENumLines] = 0; } + /* Now really initialize bezier */ startX = objBuffer[bezier + GEXValue]; startY = objBuffer[bezier + GEYValue]; viaX = objBuffer[bezier + GBViaX]; viaY = objBuffer[bezier + GBViaY]; endX = objBuffer[bezier + GBEndX]; endY = objBuffer[bezier + GBEndY]; - - /* Initialize integer forward differencing */ deltaY = endY - startY; + /* Initialize integer forward differencing */ fwX1 = (viaX - startX) * 2; fwX2 = (startX + endX) - (viaX * 2); fwY1 = (viaY - startY) * 2; @@ -9079,9 +9903,8 @@ stepToFirstBezierInat(sqInt bezier, sqInt yValue) fwDx += fwDDx / 2; fwDy = fwY1 * scaledStepSize; fwDDy = (fwY2 * squaredStepSize) * 2; - - /* Store the values */ fwDy += fwDDy / 2; + /* Store the values */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[bezier + GENumLines] = deltaY; @@ -9092,6 +9915,7 @@ stepToFirstBezierInat(sqInt bezier, sqInt yValue) updateData[GBUpdateDY] = fwDy; updateData[GBUpdateDDX] = fwDDx; updateData[GBUpdateDDY] = fwDDy; + /* And step to the first scan line */ if (!(((startY = objBuffer[bezier + GEYValue])) == yValue)) { /* begin stepToNextBezierIn:at: */ updateData1 = (objBuffer + bezier) + GBUpdateData; @@ -9099,12 +9923,11 @@ stepToFirstBezierInat(sqInt bezier, sqInt yValue) lastY = updateData1[GBUpdateY]; fwDxInt = updateData1[GBUpdateDX]; fwDyInt = updateData1[GBUpdateDY]; - + minY = yValue * 0x100; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ - minY = yValue * 0x100; while ((minY > lastY) && (fwDyInt >= 0)) { lastX += (((sqInt)((fwDxInt + 0x8000))) >> 16); @@ -9120,6 +9943,7 @@ stepToFirstBezierInat(sqInt bezier, sqInt yValue) /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[bezier + GEXValue] = xValue; + /* Adjust number of lines remaining */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[bezier + GENumLines] = (deltaY - (yValue - startY)); @@ -9153,9 +9977,8 @@ stepToFirstLineInat(sqInt line, sqInt yValue) return objBuffer[line + GENumLines] = 0; } deltaX = (objBuffer[line + GLEndX]) - (objBuffer[line + GEXValue]); - - /* Check if edge goes left to right */ deltaY = (objBuffer[line + GLEndY]) - (objBuffer[line + GEYValue]); + /* Check if edge goes left to right */ if (deltaX >= 0) { xDir = 1; widthX = deltaX; @@ -9166,6 +9989,9 @@ stepToFirstLineInat(sqInt line, sqInt yValue) widthX = 0 - deltaX; error = 1 - deltaY; } + /* Check if deltaY is zero. + Note: We could actually get out here immediately + but wide lines rely on an accurate setup in this case */ if (deltaY) { /* Check if edge is y-major */ @@ -9188,12 +10014,15 @@ stepToFirstLineInat(sqInt line, sqInt yValue) xInc = deltaX; errorAdjUp = 0; } + /* Store the values */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[line + GENumLines] = deltaY; /* #lineXDirectionOf:put: #obj:at:put: */ objBuffer[line + GLXDirection] = xDir; + /* self lineYDirectionOf: line put: yDir. + <-- Already set */ /* #lineXIncrementOf:put: #obj:at:put: */ objBuffer[line + GLXIncrement] = xInc; @@ -9206,6 +10035,7 @@ stepToFirstLineInat(sqInt line, sqInt yValue) /* #lineErrorAdjDownOf:put: #obj:at:put: */ objBuffer[line + GLErrorAdjDown] = deltaY; + /* And step to the first scan line */ if (!(((startY = objBuffer[line + GEYValue])) == yValue)) { for (i = startY; i < yValue; i += 1) { /* begin stepToNextLineIn:at: */ @@ -9222,6 +10052,7 @@ stepToFirstLineInat(sqInt line, sqInt yValue) /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[line + GEXValue] = x; } + /* Adjust number of lines remaining */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[line + GENumLines] = (deltaY - (yValue - startY)); @@ -9249,18 +10080,17 @@ stepToFirstWideBezierInat(sqInt bezier, sqInt yValue) /* Get some values */ lineWidth = objBuffer[bezier + GBWideExtent]; - - /* Compute the incremental values of the bezier */ lineOffset = lineWidth / 2; + /* Compute the incremental values of the bezier */ endX = objBuffer[bezier + GBEndX]; startY = objBuffer[bezier + GEYValue]; stepToFirstBezierInat(bezier, startY); - - /* Copy the incremental update data */ nLines = objBuffer[bezier + GENumLines]; + /* Copy the incremental update data */ for (i = 0; i <= 5; i += 1) { ((objBuffer + bezier) + GBWideUpdateData)[i] = (((objBuffer + bezier) + GBUpdateData)[i]); } + /* Compute primary x direction of curve (e.g., 1: left to right; -1: right to left). */ xDir = ((objBuffer + bezier) + GBUpdateData)[GBUpdateDX]; if (!xDir) { xDir = ((objBuffer + bezier) + GBUpdateData)[GBUpdateDDX]; @@ -9271,18 +10101,22 @@ stepToFirstWideBezierInat(sqInt bezier, sqInt yValue) else { xDir = -1; } + /* Adjust the curve to start/end at the right position */ if (xDir < 0) { adjustWideBezierLeftwidthoffsetendX(bezier, lineWidth, lineOffset, endX); } else { adjustWideBezierRightwidthoffsetendX(bezier, lineWidth, lineOffset, endX); } + /* Adjust the last value for horizontal lines */ if (!nLines) { ((objBuffer + bezier) + GBUpdateData)[GBUpdateX] = ((objBuffer[bezier + GBFinalX]) * 0x100); } + /* Adjust the number of lines to include the lineWidth */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[bezier + GENumLines] = (nLines + lineWidth); + /* Compute the points where we have to turn on/off the fills */ /* turned on at lineOffset */ yEntry = 0; @@ -9295,6 +10129,7 @@ stepToFirstWideBezierInat(sqInt bezier, sqInt yValue) /* #wideBezierExitOf:put: #obj:at:put: */ objBuffer[bezier + GBWideExit] = yExit; + /* Turn the fills on/off as necessary */ if ((yEntry >= lineOffset) && (yExit < 0)) { /* #edgeFillsValidate: #objectTypeOf:put: #obj:at:put: */ @@ -9305,12 +10140,14 @@ stepToFirstWideBezierInat(sqInt bezier, sqInt yValue) objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } computeFinalWideBezierValueswidth(bezier, lineWidth); + /* And step to the first scan line */ if (!(startY == yValue)) { /* Note: Must single step here so that entry/exit works */ for (i = startY; i < yValue; i += 1) { stepToNextWideBezierInat(bezier, i); } + /* Adjust number of lines remaining */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[bezier + GENumLines] = ((objBuffer[bezier + GENumLines]) - (yValue - startY)); @@ -9346,22 +10183,22 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* Get some values */ lineWidth = objBuffer[line + GLWideExtent]; - - /* Compute the incremental values of the line */ lineOffset = lineWidth / 2; + /* Compute the incremental values of the line */ startX = objBuffer[line + GEXValue]; startY = objBuffer[line + GEYValue]; stepToFirstLineInat(line, startY); nLines = objBuffer[line + GENumLines]; - - /* Adjust the line to start at the correct X position */ xDir = objBuffer[line + GLXDirection]; + /* Adjust the line to start at the correct X position */ /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[line + GEXValue] = (startX - lineOffset); + /* Adjust the number of lines to include the lineWidth */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[line + GENumLines] = (nLines + lineWidth); + /* Adjust the values for x-major lines */ if (xDir > 0) { /* #wideLineWidthOf:put: #obj:at:put: */ objBuffer[line + GLWideWidth] = ((objBuffer[line + GLXIncrement]) + lineWidth); @@ -9373,6 +10210,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[line + GEXValue] = ((objBuffer[line + GEXValue]) + (objBuffer[line + GLXIncrement])); } + /* Compute the points where we have to turn on/off the fills */ /* turned on at lineOffset */ yEntry = 0; @@ -9385,6 +10223,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #wideLineExitOf:put: #obj:at:put: */ objBuffer[line + GLWideExit] = yExit; + /* Turn the fills on/off as necessary */ if ((yEntry >= lineOffset) && (yExit < 0)) { /* #edgeFillsValidate: #objectTypeOf:put: #obj:at:put: */ @@ -9394,6 +10233,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #edgeFillsInvalidate: #objectTypeOf:put: #obj:at:put: */ objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } + /* And step to the first scan line */ if (!(startY == yValue)) { for (i = startY; i < yValue; i += 1) { /* begin stepToNextWideLineIn:at: */ @@ -9405,6 +10245,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #wideLineExitOf:put: #obj:at:put: */ objBuffer[line + GLWideExit] = yExitInt; + /* Turn fills on/off */ lineWidthInt = objBuffer[line + GLWideExtent]; lineOffsetSqInt = lineWidthInt / 2; if (yEntryInt >= lineOffsetSqInt) { @@ -9415,6 +10256,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #edgeFillsInvalidate: #objectTypeOf:put: #obj:at:put: */ objBuffer[line + GEObjectType] = (((objBuffer[line + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } + /* Step to the next scan line */ lastX = objBuffer[line + GEXValue]; /* begin stepToNextLineIn:at: */ @@ -9430,9 +10272,8 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) /* #edgeXValueOf:put: #obj:at:put: */ objBuffer[line + GEXValue] = x; - - /* Check for special start/end adjustments */ nextX = objBuffer[line + GEXValue]; + /* Check for special start/end adjustments */ if ((yEntryInt <= lineWidthInt) || ((yExitInt + lineOffsetSqInt) >= 0)) { @@ -9440,6 +10281,7 @@ stepToFirstWideLineInat(sqInt line, sqInt yValue) adjustWideLineafterSteppingFromto(line, lastX, nextX); } } + /* Adjust number of lines remaining */ /* #edgeNumLinesOf:put: #obj:at:put: */ objBuffer[line + GENumLines] = ((objBuffer[line + GENumLines]) - (yValue - startY)); @@ -9485,6 +10327,7 @@ stepToNextWideBezierInat(sqInt bezier, sqInt yValue) /* #edgeFillsInvalidate: #objectTypeOf:put: #obj:at:put: */ objBuffer[bezier + GEObjectType] = (((objBuffer[bezier + GEObjectType]) & GEPrimitiveTypeMask) | GEEdgeFillsInvalid); } + /* Check if we have to step the upper curve */ if ((yExit + lineOffset) < 0) { updateData = (objBuffer + bezier) + GBUpdateData; @@ -9493,12 +10336,11 @@ stepToNextWideBezierInat(sqInt bezier, sqInt yValue) lastY = updateData[GBUpdateY]; fwDx = updateData[GBUpdateDX]; fwDy = updateData[GBUpdateDY]; - + minY = yValue * 0x100; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ - minY = yValue * 0x100; while ((minY > lastY) && (fwDy >= 0)) { lastX += (((sqInt)((fwDx + 0x8000))) >> 16); @@ -9517,6 +10359,7 @@ stepToNextWideBezierInat(sqInt bezier, sqInt yValue) /* Adjust the last x value to the final x recorded previously */ ((objBuffer + bezier) + GBUpdateData)[GBUpdateX] = ((objBuffer[bezier + GBFinalX]) * 0x100); } + /* Step the lower curve */ updateData = (objBuffer + bezier) + GBWideUpdateData; /* begin stepToNextBezierForward:at: */ @@ -9524,12 +10367,11 @@ stepToNextWideBezierInat(sqInt bezier, sqInt yValue) lastY = updateData[GBUpdateY]; fwDx = updateData[GBUpdateDX]; fwDy = updateData[GBUpdateDY]; - + minY = yValue * 0x100; /* Step as long as we haven't yet reached minY and also as long as fwDy is greater than zero thus stepping down. Note: The test for fwDy should not be necessary in theory but is a good insurance in practice. */ - minY = yValue * 0x100; while ((minY > lastY) && (fwDy >= 0)) { lastX += (((sqInt)((fwDx + 0x8000))) >> 16); @@ -9618,14 +10460,15 @@ storeRenderingState(void) if (reason == GErrorAETEntry) { edge = aetBuffer[workBuffer[GWAETStart]]; storeEdgeStateFrominto(edge, edgeOop); + /* Do not advance to the next aet entry yet + self aetStartPut: self aetStartGet + 1. */; } } /* begin storeEngineStateInto: */ /* objUsedPut: */ workBuffer[GWObjUsed] = objUsed; - pop(3); - pushInteger(workBuffer[GWStopReason]); + methodReturnInteger(workBuffer[GWStopReason]); return 0; } @@ -9675,12 +10518,14 @@ subdivideBezier(sqInt index) int startY; startY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 1)]; - - /* If the receiver is horizontal, don't do anything */ endY = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 5)]; + /* If the receiver is horizontal, don't do anything */ if (endY == startY) { return index; } + /* TODO: If the curve can be represented as a line, then do so + If the height of the curve exceeds 256 pixels, subdivide + (forward differencing is numerically not very stable) */ deltaY = endY - startY; if (deltaY < 0) { deltaY = 0 - deltaY; @@ -9690,6 +10535,7 @@ subdivideBezier(sqInt index) workBuffer[GWBezierHeightSubdivisions] = ((workBuffer[GWBezierHeightSubdivisions]) + 1); return computeBezierSplitAtHalf(index); } + /* Check if the incremental values could possibly overflow the scaled integer range */ startX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index))]; endX = workBuffer[(workBuffer[GWBufferTop]) + ((((workBuffer[GWSize]) - (workBuffer[GWBufferTop])) - index) + 4)]; deltaX = endX - startX; @@ -9730,6 +10576,7 @@ subdivideToBeMonotonInX(sqInt index) /* incrementStat:by: */ workBuffer[GWBezierMonotonSubdivisions] = ((workBuffer[GWBezierMonotonSubdivisions]) + 1); + /* Compute split value */ denom = dx2 - dx1; num = dx1; if (num < 0) { @@ -9767,6 +10614,7 @@ subdivideToBeMonotonInY(sqInt index) /* incrementStat:by: */ workBuffer[GWBezierMonotonSubdivisions] = ((workBuffer[GWBezierMonotonSubdivisions]) + 1); + /* Compute split value */ denom = dy2 - dy1; num = dy1; if (num < 0) { @@ -10252,6 +11100,7 @@ void* B2DPlugin_exports[][3] = { {(void*)_m, "primitiveDoProfileStats\000\000\003", (void*)primitiveDoProfileStats}, {(void*)_m, "primitiveFinishedProcessing\000\002\003", (void*)primitiveFinishedProcessing}, {(void*)_m, "primitiveGetAALevel\000\002\003", (void*)primitiveGetAALevel}, + {(void*)_m, "primitiveGetAllStats\000\002\003", (void*)primitiveGetAllStats}, {(void*)_m, "primitiveGetBezierStats\000\002\003", (void*)primitiveGetBezierStats}, {(void*)_m, "primitiveGetClipRect\000\002\003", (void*)primitiveGetClipRect}, {(void*)_m, "primitiveGetCounts\000\002\003", (void*)primitiveGetCounts}, @@ -10269,6 +11118,7 @@ void* B2DPlugin_exports[][3] = { {(void*)_m, "primitiveNextGlobalEdgeEntry\000\002\003", (void*)primitiveNextGlobalEdgeEntry}, {(void*)_m, "primitiveRegisterExternalEdge\000\002\003", (void*)primitiveRegisterExternalEdge}, {(void*)_m, "primitiveRegisterExternalFill\000\002\003", (void*)primitiveRegisterExternalFill}, + {(void*)_m, "primitiveRenderAllScanlines\000\377\000", (void*)primitiveRenderAllScanlines}, {(void*)_m, "primitiveRenderImage\000\377\000", (void*)primitiveRenderImage}, {(void*)_m, "primitiveRenderScanline\000\377\000", (void*)primitiveRenderScanline}, {(void*)_m, "primitiveSetAALevel\000\002\003", (void*)primitiveSetAALevel}, @@ -10302,6 +11152,7 @@ EXPORT(signed short) primitiveDisplaySpanBufferMetadata = 0x200; EXPORT(signed short) primitiveDoProfileStatsMetadata = 3; EXPORT(signed short) primitiveFinishedProcessingMetadata = 515; EXPORT(signed short) primitiveGetAALevelMetadata = 515; +EXPORT(signed short) primitiveGetAllStatsMetadata = 515; EXPORT(signed short) primitiveGetBezierStatsMetadata = 515; EXPORT(signed short) primitiveGetClipRectMetadata = 515; EXPORT(signed short) primitiveGetCountsMetadata = 515; diff --git a/src/plugins/FilePlugin/FilePlugin.c b/src/plugins/FilePlugin/FilePlugin.c index 35007fa9ad..9e26441e6b 100644 --- a/src/plugins/FilePlugin/FilePlugin.c +++ b/src/plugins/FilePlugin/FilePlugin.c @@ -1,9 +1,10 @@ /* Automatically generated by - VMPluginCodeGenerator VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 + VMPluginCodeGenerator VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c + (Compiler-eem.508) from - FilePlugin VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 + FilePlugin VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c */ -static char __buildInfo[] = "FilePlugin VMMaker.oscog-eem.3456 uuid: e316760f-1758-4b6b-aa08-f84bc7c44ef3 " __DATE__ ; +static char __buildInfo[] = "FilePlugin VMMaker.oscog-eem.3461 uuid: a28f832c-aec3-49ea-855b-750565b69a4c " __DATE__ ; #include "config.h" @@ -38,6 +39,7 @@ static char __buildInfo[] = "FilePlugin VMMaker.oscog-eem.3456 uuid: e316760f-17 #define DirBadPath 2 #define DirNoMoreEntries 1 #define DisownVMForThreading 32 +#define MaxPathLen 0x800 /*** Function Prototypes ***/ @@ -78,7 +80,9 @@ EXPORT(sqInt) primitiveFileStdioHandles(void); EXPORT(sqInt) primitiveFileSync(void); EXPORT(sqInt) primitiveFileTruncate(void); EXPORT(sqInt) primitiveFileWrite(void); +EXPORT(sqInt) primitiveGetWorkingDirectory(void); EXPORT(sqInt) primitiveHasFileAccess(void); +EXPORT(sqInt) primitiveSetWorkingDirectory(void); EXPORT(sqInt) setInterpreter(struct VirtualMachine *anInterpreter); EXPORT(sqInt) setMacFileTypeAndCreator(char *fileName, char *typeString, char *creatorString); EXPORT(sqInt) shutdownModule(void); @@ -112,6 +116,7 @@ static sqInt (*isPinned)(sqInt anObject); static sqInt (*isWordsOrBytes)(sqInt oop); static sqInt (*methodReturnBool)(sqInt boolean); static sqInt (*methodReturnInteger)(sqInt integer); +static sqInt (*methodReturnReceiver)(void); static sqInt (*methodReturnValue)(sqInt oop); static sqInt (*nilObject)(void); static sqInt (*ownVM)(void *handle); @@ -171,6 +176,7 @@ extern sqInt isPinned(sqInt anObject); extern sqInt isWordsOrBytes(sqInt oop); extern sqInt methodReturnBool(sqInt boolean); extern sqInt methodReturnInteger(sqInt integer); +extern sqInt methodReturnReceiver(void); extern sqInt methodReturnValue(sqInt oop); extern sqInt nilObject(void); extern sqInt ownVM(void *handle); @@ -199,7 +205,7 @@ extern sqInt trueObject(void); extern #endif struct VirtualMachine* interpreterProxy; -static const char *moduleName = "FilePlugin VMMaker.oscog-eem.3456 " INT_EXT; +static const char *moduleName = "FilePlugin VMMaker.oscog-eem.3461 " INT_EXT; static void * sCCPfn; static void * sCDFfn; static void * sCDPfn; @@ -398,6 +404,7 @@ makeDirEntryNamesizecreateDatemodDateisDirfileSize(char *entryName, sqInt entryN nameString = popRemappableOop(); results = popRemappableOop(); #endif /* SPURVM */ + /* copy name into Smalltalk string */ stringPtr = firstIndexableField(nameString); for (i = 0; i < entryNameSize; i += 1) { stringPtr[i] = (entryName[i]); @@ -454,6 +461,7 @@ makeDirEntryNamesizecreateDatemodDateisDirfileSizeposixPermissionsisSymlink(char nameString = popRemappableOop(); results = popRemappableOop(); #endif /* SPURVM */ + /* copy name into Smalltalk string */ stringPtr = firstIndexableField(nameString); for (i = 0; i < entryNameSize; i += 1) { stringPtr[i] = (entryName[i]); @@ -589,10 +597,9 @@ primitiveDirectoryCreate(void) return primitiveFail(); } dirNameIndex = firstIndexableField(dirName); - + dirNameSize = byteSizeOf(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ - dirNameSize = byteSizeOf(dirName); if (sCCPfn) { okToCreate = ((sqInt (*)(char *, sqInt))sCCPfn)(dirNameIndex, dirNameSize); if (!okToCreate) { @@ -620,10 +627,9 @@ primitiveDirectoryDelete(void) return primitiveFail(); } dirNameIndex = firstIndexableField(dirName); - + dirNameSize = byteSizeOf(dirName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ - dirNameSize = byteSizeOf(dirName); if (sCDPfn) { okToDelete = ((sqInt (*)(char *, sqInt))sCDPfn)(dirNameIndex, dirNameSize); if (!okToDelete) { @@ -671,7 +677,7 @@ primitiveDirectoryEntry(void) { sqInt createDate; sqInt dirFlag; - char entryName[256]; + char entryName[MaxPathLen]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt modifiedDate; @@ -697,10 +703,13 @@ primitiveDirectoryEntry(void) if (!(isBytes(pathName))) { return primitiveFail(); } + /* Outbound string parameters */ pathNameIndex = firstIndexableField(pathName); pathNameSize = byteSizeOf(pathName); reqNameIndex = firstIndexableField(requestedName); reqNameSize = byteSizeOf(requestedName); + /* If the security plugin can be loaded, use it to check for permission. + If not, assume it's ok */ okToList = (sCLPfn ? ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize) : 1); @@ -760,10 +769,9 @@ primitiveDirectoryGetMacTypeAndCreator(void) creatorStringIndex = firstIndexableField(creatorString); typeStringIndex = firstIndexableField(typeString); fileNameIndex = firstIndexableField(fileName); - + fileNameSize = byteSizeOf(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ - fileNameSize = byteSizeOf(fileName); if (sCGFTfn) { okToGet = ((sqInt (*)(char *, sqInt))sCGFTfn)(fileNameIndex, fileNameSize); if (!okToGet) { @@ -803,7 +811,7 @@ primitiveDirectoryLookup(void) { sqInt createDate; sqInt dirFlag; - char entryName[256]; + char entryName[MaxPathLen]; sqInt entryNameSize; squeakFileOffsetType fileSize; sqInt index; @@ -829,6 +837,8 @@ primitiveDirectoryLookup(void) } pathNameIndex = firstIndexableField(pathName); pathNameSize = byteSizeOf(pathName); + /* If the security plugin can be loaded, use it to check for permission. + If not, assume it's ok */ okToList = (sCLPfn ? ((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize) : 1); @@ -884,10 +894,9 @@ primitiveDirectorySetMacTypeAndCreator(void) creatorStringIndex = firstIndexableField(creatorString); typeStringIndex = firstIndexableField(typeString); fileNameIndex = firstIndexableField(fileName); - + fileNameSize = byteSizeOf(fileName); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ - fileNameSize = byteSizeOf(fileName); if (sCSFTfn) { okToSet = ((sqInt (*)(char *, sqInt))sCSFTfn)(fileNameIndex, fileNameSize); if (!okToSet) { @@ -984,10 +993,9 @@ primitiveFileDelete(void) return primitiveFailFor(PrimErrBadArgument); } nameIndex = firstIndexableField(namePointer); - + nameSize = byteSizeOf(namePointer); /* If the security plugin can be loaded, use it to check for permission. If not, assume it's ok */ - nameSize = byteSizeOf(namePointer); if (sCDFfn) { okToDelete = ((sqInt (*)(char *, sqInt))sCDFfn)(nameIndex, nameSize); if (!okToDelete) { @@ -1179,6 +1187,7 @@ primitiveFileRead(void) if (isPinned(array)) { vmHandle = disownVM(DisownVMForThreading); } + /* Note: adjust startIndex for zero-origin byte indexing */ bytesRead = sqFileReadIntoAt(file, count * elementSize, ((char *) (firstIndexableField(array))), (startIndex - 1) * elementSize); if (vmHandle) { ownVM(vmHandle); @@ -1218,9 +1227,8 @@ primitiveFileRead(void) methodReturnInteger(0); goto l4; } - - /* Note: adjust startIndex for zero-origin byte indexing */ elementSize = (byteSizeOf(array)) / slotSize; + /* Note: adjust startIndex for zero-origin byte indexing */ bytesRead = sqFileReadIntoAt(file, count * elementSize, ((char *) (firstIndexableField(array))), (startIndex - 1) * elementSize); if (!(failed())) { methodReturnInteger(bytesRead / elementSize); @@ -1255,9 +1263,8 @@ primitiveFileRead(void) primitiveFailFor(PrimErrBadIndex); goto l6; } - - /* Note: adjust startIndex for zero-origin indexing */ elementSize = bytesPerElement(array); + /* Note: adjust startIndex for zero-origin indexing */ bytesRead = sqFileReadIntoAt(file, count * elementSize, ((char *) (firstIndexableField(array))), (startIndex - 1) * elementSize); if (!(failed())) { methodReturnInteger(bytesRead / elementSize); @@ -1289,10 +1296,9 @@ primitiveFileRename(void) newNameIndex = firstIndexableField(newNamePointer); newNameSize = byteSizeOf(newNamePointer); oldNameIndex = firstIndexableField(oldNamePointer); - + oldNameSize = byteSizeOf(oldNamePointer); /* If the security plugin can be loaded, use it to check for rename permission. If not, assume it's ok */ - oldNameSize = byteSizeOf(oldNamePointer); if (sCRFfn) { okToRename = ((sqInt (*)(char *, sqInt))sCRFfn)(oldNameIndex, oldNameSize); if (!okToRename) { @@ -1407,6 +1413,9 @@ primitiveFileStdioHandles(void) memcpy(firstIndexableField(result), (&(fileRecords[index])), sizeof(SQFile)); } } + /* In the non-Spur threaded VM ensure the handles are old, so that sqFileReadIntoAt is unaffected + by incremental GCs. See platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c. The Spur + VM uses pinning, so it doesn't need the GC. */ # if COGMTVM # if !SPURVM fullGC(); @@ -1524,9 +1533,8 @@ primitiveFileWrite(void) if (!slotSize) { return methodReturnInteger(0); } - - /* Note: adjust startIndex for zero-origin byte indexing */ elementSize = (byteSizeOf(array)) / slotSize; + /* Note: adjust startIndex for zero-origin byte indexing */ bytesWritten = sqFileWriteFromAt(file, count * elementSize, ((char *) (firstIndexableField(array))), (startIndex - 1) * elementSize); if (!(failed())) { methodReturnInteger(bytesWritten / elementSize); @@ -1534,6 +1542,25 @@ primitiveFileWrite(void) return 0; } + +/* Answer the VM process's working directory as a UTF8 string. */ + + /* FilePlugin>>#primitiveGetWorkingDirectory */ +EXPORT(sqInt) +primitiveGetWorkingDirectory(void) +{ + char buffer[MaxPathLen + 1]; + sqInt nBytesOrError; + + nBytesOrError = dir_GetPathToWorkingDirAsUTF8(buffer, MaxPathLen); + if (nBytesOrError <= 0) { + return primitiveFailForOSError(-nBytesOrError); + } + buffer[nBytesOrError] = 0; + methodReturnString(buffer); + return 0; +} + /* FilePlugin>>#primitiveHasFileAccess */ EXPORT(sqInt) primitiveHasFileAccess(void) @@ -1554,6 +1581,47 @@ primitiveHasFileAccess(void) } +/* Set the VM process's working directory from a UTF8 string. */ + + /* FilePlugin>>#primitiveSetWorkingDirectory */ +EXPORT(sqInt) +primitiveSetWorkingDirectory(void) +{ + char *dstPtr; + sqInt errorCode; + sqInt obj; + char *path; + sqInt sz; + + /* begin stackEphemeralStringValue: */ + obj = stackValue(0); + if (!(isBytes(obj))) { + primitiveFailFor(PrimErrBadArgument); + path = null; + goto l1; + } + sz = byteSizeOf(obj); + dstPtr = alloca(sz + 1); + if (!dstPtr) { + primitiveFailFor(PrimErrNoCMemory); + path = null; + goto l1; + } + memcpy(dstPtr, firstIndexableField(obj), sz); + dstPtr[sz] = 0; + path = dstPtr; +l1: /* end stackEphemeralStringValue: */; + if (path) { + errorCode = dir_SetPathToWorkingDirAsUTF8(path); + if (!errorCode) { + return methodReturnReceiver(); + } + return primitiveFailForOSError(errorCode); + } + return 0; +} + + /* Note: This is coded so that it can be run in Squeak. */ /* InterpreterPlugin>>#setInterpreter: */ @@ -1562,9 +1630,9 @@ setInterpreter(struct VirtualMachine *anInterpreter) { sqInt ok; + interpreterProxy = anInterpreter; /* This may seem tautological, but in a real plugin it checks that the VM provides the version the plugin was compiled against which is the version the plugin expects. */ - interpreterProxy = anInterpreter; ok = ((interpreterProxy->majorVersion()) == (VM_PROXY_MAJOR)) && ((interpreterProxy->minorVersion()) >= (VM_PROXY_MINOR)); if (ok) { @@ -1613,6 +1681,7 @@ setInterpreter(struct VirtualMachine *anInterpreter) isWordsOrBytes = interpreterProxy->isWordsOrBytes; methodReturnBool = interpreterProxy->methodReturnBool; methodReturnInteger = interpreterProxy->methodReturnInteger; + methodReturnReceiver = interpreterProxy->methodReturnReceiver; methodReturnValue = interpreterProxy->methodReturnValue; nilObject = interpreterProxy->nilObject; ownVM = interpreterProxy->ownVM; @@ -1701,7 +1770,9 @@ void* FilePlugin_exports[][3] = { {(void*)_m, "primitiveFileSync\000\001\000", (void*)primitiveFileSync}, {(void*)_m, "primitiveFileTruncate\000\001\000", (void*)primitiveFileTruncate}, {(void*)_m, "primitiveFileWrite\000\001\000", (void*)primitiveFileWrite}, + {(void*)_m, "primitiveGetWorkingDirectory\000\377\000", (void*)primitiveGetWorkingDirectory}, {(void*)_m, "primitiveHasFileAccess\000\377\000", (void*)primitiveHasFileAccess}, + {(void*)_m, "primitiveSetWorkingDirectory\000\000\000", (void*)primitiveSetWorkingDirectory}, {(void*)_m, "setInterpreter", (void*)setInterpreter}, {(void*)_m, "setMacFileTypeAndCreator", (void*)setMacFileTypeAndCreator}, {(void*)_m, "shutdownModule", (void*)shutdownModule}, @@ -1733,6 +1804,7 @@ EXPORT(signed short) primitiveFileSizeMetadata = 0x100; EXPORT(signed short) primitiveFileSyncMetadata = 0x100; EXPORT(signed short) primitiveFileTruncateMetadata = 0x100; EXPORT(signed short) primitiveFileWriteMetadata = 0x100; +EXPORT(signed short) primitiveSetWorkingDirectoryMetadata = 0; #endif // SPURVM #endif // ifdef SQ_BUILTIN_PLUGIN