home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************\
- * *
- * IFS Lab, Copyright (C) 1992 by N. Zeldes. All rights reserved. *
- * *
- * Version 1.0, April 9, 1992 *
- * *
- * An interactive program for exploring the IFS Code method of Fractal Image *
- * representation and reconstruction. *
- * *
- * Requires the Fox/Dawson freeware req.library in libs: directory. *
- * *
- * Compile under Aztec C 5.0, with -ff option (Fast floating point) *
- * and -safmnpsu options (code optimization). *
- * Link with +cd option (forces sprite and image data to load in CHIP RAM). *
- * Link with IFF files (from CBM IFF Disk, Fish disk #185), and with the glue *
- * module for the Fox/Dawson requester library, thus: *
- * *
- * cc -ff -safmnpsu -i IFF -i req IFSLab.c *
- * ln +cd IFSLab.o IFF/putpict.o IFF/ilbmw.o IFF/packer.o *
- * IFF/iffw.o IFF/readpict.o IFF/ilbmr.o IFF/unpacker.o IFF/iffr.o *
- * IFF/remalloc.o req/myreqglue.o mf.lib c.lib *
- * *
- \******************************************************************************/
-
- #include <intuition/intuition.h>
- #include <exec/memory.h>
- /* exec/memory.h required to use AllocMem() */
- #include <graphics/text.h>
- /* graphics/text.h required for font TextAttr structure */
- #include <stdio.h>
- #include <math.h> /* Floating point math: sqrt, fabs, trig functions */
- #include <errno.h> /* Required by myatan2() */
- #include <graphics/display.h> /* needed for definition of INTERLACE */
- #include <stdlib.h> /* stdlib.h needed for rand() */
- #include <time.h> /* time.h needed for time() */
- #include <string.h> /* needed for memset */
-
- #include <ilbm.h> /* Header file from IFF Disk (Note that */
- /* ilbm.h #includes compiler.h and iff.h) */
- #include <readpict.h> /* From IFF Disk */
- #include <remalloc.h> /* From IFF Disk; For ChipAlloc(), RemFree() */
- #include <libraries/dos.h> /* For IFF file I/O stuff */
- #include <libraries/dosextens.h> /* For the Process structure definition. */
- #include <reqbase.h> /* Fox/Dawson file requester header file */
- #include "IFSLab.h" /* PowerWindows-generated structures and defines */
-
- #define INTUITION_REV 31L
- #define GRAPHICS_REV 31L
-
- #define OUTLINE 0 /* parameters for SetMode() */
- #define COLLAGE 1
-
- #define FREEHAND 0 /* drawmode values */
- #define LINES 1
- #define ERASE 2
- #define FILL 3
- #define VECTOR 4
-
- #define CODES 0 /* parameters for AboutText() */
- #define IFS_THEORY 1
- #define HELP1 2
- #define HELP2 3
- #define AUTHOR 4
- #define DEMOTEXT 5
-
- #define WIDTH Window->Width
- #define HEIGHT Window->Height
- #define GZZWIDTH Window->GZZWidth
- #define GZZHEIGHT Window->GZZHeight
-
- #define MAX_N 19 /* max permitted piece index */
-
- struct Screen *Screen = NULL, *ImageScreen;
- struct RastPort *scrp; /* Pointer to Screen RastPort */
- struct Window *Window = NULL, *NumWindow;
- struct RastPort *r; /* Pointer to RastPort of main editing window */
- struct Window *ImageWindow; /* Window for rendering Image */
- struct RastPort *Textrp; /* Rastport of Text Window */
- struct IntuitionBase *IntuitionBase = NULL;
- struct GfxBase *GfxBase = NULL;
- void *MathBase = NULL;
- void *MathTransBase = NULL;
- struct ReqLib *ReqBase = NULL; /* Fox/Dawson Requester Library */
- int drawmode = FREEHAND;
- /* Current mode - FREEHAND,LINES,ERASE,FILL (outline) or VECTOR (Collage) */
- int exists_outline = 0, exists_image = 0, exists_numwindow = 0;
- int renderwidth = 640, renderheight = 400; /* initialize to default */
- int renderdepth = 1; /* initialize to default */
- long mx, my; /* Current Mouse coordinates in editing */
-
- struct pixel {
- long x;
- long y;
- };
- struct piece {
- double a, b, c, d, e, f;
- double s1, s2, r1, r2;
- double dens;
- double p;
- double det;
- UBYTE *piecemap;
- struct pixel boxo, boxx, boxy, boxz;
- };
- struct piece *pieceptr[MAX_N + 1]; /* Array of pointers to piece structures */
- int N = -1; /* Index of highest existing Piece Initialized to zero pieces */
- int selpiece; /* Index of currently selected Piece */
- char curcor; /* Currently dragged Box corner ('o','x','y','z') or none ('0') */
- struct pixel ghboxo, ghboxx, ghboxy, ghboxz; /* Current corners of ghost Box */
- struct pixel tmpboxo, tmpboxx, tmpboxy, tmpboxz;
- struct piece *AllocPiece();
- double myatan2(); /* My version of atan2() which is missing in Manx mf.lib */
- char *fname, *GetFileName();
- struct Library *OpenLibrary();
- void *AllocMem(), *AllocRaster();
- UBYTE *outlinebufptr=NULL; /* ptr to buffer holding outline in collage mode */
- long i; /* handy as a loop index */
-
- /*** IFF error messages (external) */
-
- char MsgOkay[] = { "(IFF_OKAY) A good IFF file" };
- char MsgEndMark[] = { "(END_MARK) IFF Loader Error" };
- char MsgDone[] = { "(IFF_DONE) Well Done!" };
- char MsgDos[] = { "DOS Error - Aborting Load!" };
- char MsgNot[] = { "Not an IFF file - Aborting Load!" };
- char MsgNoFile[] = { "No such file found - Aborting Load!" };
- char MsgClientError[] = { "(CLIENT_ERROR) IFF Checker bug"};
- char MsgForm[] = { "(BAD_FORM) IFF Loader Error" };
- char MsgShort[] = { "(SHORT_CHUNK) IFF Loader Error" };
- char MsgBad[] = { "A mangled IFF file - Aborting Load!" };
-
- /* MUST GET THESE IN RIGHT ORDER!!*/
- char *IFFPMessages[-LAST_ERROR+1] = {
- /*IFF_OKAY*/ MsgOkay,
- /*END_MARK*/ MsgEndMark,
- /*IFF_DONE*/ MsgDone,
- /*DOS_ERROR*/ MsgDos,
- /*NOT_IFF*/ MsgNot,
- /*NO_FILE*/ MsgNoFile,
- /*CLIENT_ERROR*/ MsgClientError,
- /*BAD_FORM*/ MsgForm,
- /*SHORT_CHUNK*/ MsgShort,
- /*BAD_IFF*/ MsgBad
- };
-
- struct FileRequester MyFileReqStruct; /* File Requester stuff */
- char filename[FCHARS+1];
- char directoryname[DSIZE+1];
- char pathname[FCHARS+DSIZE+2+4]; /* +4 to permit space for appending '.ifs' */
-
- /*==========================================================================*/
-
- main()
- {
- struct Message * GetMsg();
- void ReplyMsg();
- struct IntuiMessage *message;
- ULONG class;
- USHORT code, MenuNumber, menuid, itemid, subitemid;
- struct MenuItem *ItemAddress(), *ItemAddr;
- long labs();
- int w; /* temporary int variable */
- int hitgadget; /* GadgetID # of last gadget hit by mouse */
- struct Gadget *hitgadstruct; /* Gadget Structure of last hit gadget */
- int numgadgpending; /* GadgetID of unserviced coeff gadget, or -1 if none */
- struct piece tmppiece; /* will be used to hold temporary trans' coeffs */
- long mx0,my0, mx1,my1; /* coords of endpoints of ghost line in Lines mode */
- int pendown = 0;
- /* 0 if mouse SELECT button is currently pressed in window */
- SHORT WindowBdrArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- /* will be filled later to corners of inner GZZ Window */
- struct Gadget *gad; /* used as a temporary variable */
-
- /**** Initialize stuff, set up edit window in custom screen etc. ****/
-
- OpenLibraries();
- OpenDisplay(); /* Open Outline Sketch window in custom screen */
-
- SetAPen(r, 2L);
- WindowBdrArray[2] = WindowBdrArray[4] = GZZWIDTH - 1;
- WindowBdrArray[5] = WindowBdrArray[7] = GZZHEIGHT - 1;
-
- /*** Allocate memory for Outline buffer bitmap */
- if ((outlinebufptr =
- (UBYTE *)AllocMem((long)RASSIZE(WIDTH,HEIGHT), MEMF_CHIP)) == NULL) {
- ShowError("Can't allocate Outline Buffer Memory!");
- CloseAll();
- }
- /**** Main Loop ****/
-
- while(1) {
-
- mx = (long)Window->GZZMouseX;
- my = (long)Window->GZZMouseY;
-
- if (pendown == 1) {
-
- /*** Do Mouse editing to board per drawmode and mouse coords */
- switch (drawmode) {
-
- case FREEHAND:
- Draw(r, mx, my);
- break;
-
- case LINES:
- SetDrMd(r, JAM1|COMPLEMENT); /* COMPLEMENT used for ghost line */
- Move(r, mx0, my0);
- Draw(r, mx1,my1); /* Undraw previous ghost line */
- Move(r, mx0, my0);
- Draw(r, mx1 = mx, my1 = my); /* Draw a new ghost line */
- SetDrMd(r, JAM1);
- break;
-
- case ERASE:
- RectFill(r, mx - 2, my - 2, mx + 2, my + 2);
- break;
-
- case FILL:
- break;
-
- case VECTOR: /* Change the Ghost Vector Box */
- if (exists_numwindow || curcor == '0')
- break;
-
- /* Check for attempt to size box to a point */
- if ( (mx==pieceptr[selpiece]->boxo.x && my==pieceptr[selpiece]->boxo.y)
- && ( (curcor == 'z') ||
- (curcor == 'x' &&
- pieceptr[selpiece]->boxy.x == pieceptr[selpiece]->boxo.x &&
- pieceptr[selpiece]->boxy.y == pieceptr[selpiece]->boxo.y) ||
- (curcor == 'y' &&
- pieceptr[selpiece]->boxx.x == pieceptr[selpiece]->boxo.x &&
- pieceptr[selpiece]->boxx.y == pieceptr[selpiece]->boxo.y)
- )
- )
- mx = (mx == 0) ? 1 : mx - 1; /* If attempted, tweak mx to avoid */
-
- ComputeNewBox(); /* Compute New Ghost Box from mouse coords */
- ToggleGhostBox(); /* Undraw old ghost box */
- ghboxo = tmpboxo; /* Update ghost box variables */
- ghboxx = tmpboxx;
- ghboxy = tmpboxy;
- ghboxz = tmpboxz;
- ToggleGhostBox(); /* Draw new ghost box */
- break;
- } /* End Switch */
- } /* end if pendown == 1 */
-
- /* Get an IDCMP event, if any, from Window */
- if (message = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
- class = message->Class;
- code = message->Code;
- ReplyMsg(message);
- }
- else /* no message */
- class = code = NULL; /* so event routines below will be skipped */
-
- /*** Go case by case over possible events from port */
-
- if (class == MOUSEBUTTONS) { /*** Respond to user mousebutton clicks */
- if (code == SELECTDOWN) {
- pendown = 1;
- if (drawmode != ERASE)
- exists_outline = 1;
- switch (drawmode) {
-
- case FREEHAND:
- case ERASE:
- Move(r, mx, my);
- break;
-
- case LINES:
- mx0 = mx1 = mx; /* Attach both ends of line to pixel */
- my0 = my1 = my;
- break;
-
- case FILL:
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
- SetAPen(r, 2L);
- Move(r, 0L, 0L);
- PolyDraw(r,5L,WindowBdrArray); /* temporary border to prevent */
- Flood(r, 0L, mx, my); /* messes on flood fill to edge */
- SetAPen(r, 0L);
- Move(r, 0L, 0L);
- PolyDraw(r,5L,WindowBdrArray);
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- break;
-
- case VECTOR:
- if (exists_numwindow)
- break;
- /*** Decide which corner, if any, the user clicked on */
- curcor = '0';
- w = selpiece; /* Just to keep source lines shorter... */
- if (labs(mx-pieceptr[w]->boxo.x)<5&&labs(my-pieceptr[w]->boxo.y)<5)
- curcor = 'o';
- if (labs(mx-pieceptr[w]->boxx.x)<5&&labs(my-pieceptr[w]->boxx.y)<5)
- curcor = 'x';
- if (labs(mx-pieceptr[w]->boxy.x)<5&&labs(my-pieceptr[w]->boxy.y)<5)
- curcor = 'y';
- if (labs(mx-pieceptr[w]->boxz.x)<5&&labs(my-pieceptr[w]->boxz.y)<5)
- curcor = 'z';
- if (curcor != '0') { /* Set up ghost box for starters */
-
- /*** Update ghost box variables by calling ComputeNewBox() */
- ComputeNewBox();
- ghboxo = tmpboxo; /* Structure Assignments */
- ghboxx = tmpboxx;
- ghboxy = tmpboxy;
- ghboxz = tmpboxz;
-
- ToggleGhostBox(); /* Draw initial ghost box */
- }
- break;
- } /* End switch */
- } /* End if SELECTDOWN */
-
- else if (code == SELECTUP) {
- pendown = 0;
- switch (drawmode) {
-
- case FREEHAND:
- case ERASE:
- case FILL:
- break;
-
- case LINES:
- SetAPen(r, 2L); /* Draw final line (Jam onto last Ghost line) */
- Move(r,mx0, my0);
- Draw(r, mx1, my1);
- break;
-
- case VECTOR:
- if (exists_numwindow || curcor == '0')
- break;
- ToggleGhostBox(); /* Undraw Ghost Box */
- /*** Compute all coeffs from ghbox corners, put into tmppiece */
- tmppiece = *pieceptr[selpiece]; /* Structure assignment */
- tmppiece.s1 =
- sqrt((double)((ghboxx.x-ghboxo.x)*(ghboxx.x-ghboxo.x) +
- (ghboxx.y-ghboxo.y)*(ghboxx.y-ghboxo.y)))/GZZWIDTH;
- tmppiece.s2 =
- sqrt((double)((ghboxy.x-ghboxo.x)*(ghboxy.x-ghboxo.x) +
- (ghboxy.y-ghboxo.y)*(ghboxy.y-ghboxo.y)))/GZZHEIGHT;
- tmppiece.r1 = myatan2((double)(ghboxx.y-ghboxo.y),
- (double)(ghboxx.x-ghboxo.x));
- tmppiece.r2 = myatan2((double)(ghboxo.x-ghboxy.x),
- (double)(ghboxy.y-ghboxo.y));
- tmppiece.a = tmppiece.s1*cos(tmppiece.r1);
- tmppiece.b = -tmppiece.s2*sin(tmppiece.r2);
- tmppiece.c = tmppiece.s1*sin(tmppiece.r1);
- tmppiece.d = tmppiece.s2*cos(tmppiece.r2);
- tmppiece.e = (double)(ghboxo.x)/GZZWIDTH;
- tmppiece.f = (double)(ghboxo.y)/GZZWIDTH;
-
- /*** Erase Plane 3 before transformation delay */
- SetWrMsk(r,0xFFF8); /* Write-protect planes 0,1,2 */
- SetRast(r, 0L);
- SetWrMsk(r,0xFFFF);
- /* Transform the selected piece per user drag of vector box */
- TransformPiece(outlinebufptr,
- pieceptr[selpiece]->piecemap, &tmppiece);
- /*** Erase Plane 2, then Blit Selected Piece from piecemap to it */
- SetWrMsk(r,0xFFF4); /* Write-protect planes 0,1,3 */
- SetRast(r, 0L);
- SetAPen(r, 4L);
- BltTemplate((char*)pieceptr[selpiece]->piecemap,
- (long)Window->BorderLeft,(long)WIDTH/8, r, 0L, 0L,
- (long)GZZWIDTH, (long)GZZHEIGHT);
- /* Rastport WrMask will be restored in DrawBox() called below */
-
- /*** Recompute probabilities and update piece structures */
- tmppiece.boxo = ghboxo; /* structure assignment */
- tmppiece.boxx = ghboxx; /* structure assignment */
- tmppiece.boxy = ghboxy; /* structure assignment */
- tmppiece.boxz = ghboxz; /* structure assignment */
- *pieceptr[selpiece] = tmppiece; /* structure assignment */
- pieceptr[selpiece]->det =
- fabs(tmppiece.a * tmppiece.d - tmppiece.b * tmppiece.c);
- if (pieceptr[selpiece]->det == 0.0)
- pieceptr[selpiece]->det = 0.01;
- ComputeProbs(); /* Adjust all piece probabilities */
- DrawBox(); /* Redraw Vector Box for modified selected piece */
- curcor = '0';
- break;
- } /* End switch */
- } /* End else if SELECTUP */
- } /* End if MOUSEBUTTONS */
-
- else if (class == GADGETUP) { /*** Respond to Gadget clicked in Window */
-
- hitgadget = ((struct Gadget *)(message->IAddress))->GadgetID;
- /* ID# of just-selected gadget structure */
- if (hitgadget <= 3) /* a draw mode gadget in Outline mode */
- HiliteGadget(hitgadget);
- switch(hitgadget) {
-
- case 0:
- drawmode = FREEHAND;
- SetAPen(r,2L);
- break;
-
- case 1:
- drawmode = LINES;
- SetAPen(r,2L);
- break;
-
- case 2:
- drawmode = ERASE;
- SetAPen(r, 0L);
- SetOPen(r, 0L);
- break;
-
- case 3:
- drawmode = FILL;
- SetOPen(r, 2L); /* (A Pen defined before doing the flood fill) */
- break;
-
- case 4: /* CLROUT (Clear Outline) gadget */
- SetRast(r, 0L);
- exists_outline = 0;
- if(drawmode == ERASE || drawmode == FILL) {
- drawmode = FREEHAND;
- SetAPen(r,2L);
- HiliteGadget(0);
- }
- break;
-
- case 5: /* DONE gadget */
- SetMode(COLLAGE);
- AddDefPiece();
- DrawCollage();
- break;
-
- case 6: /* ADD gadget */
- AddDefPiece();
- DrawCollage();
- if (exists_numwindow)
- UpdateNumStrings();
- break;
-
- case 7: /* DUP gadget */
- DupSelPiece();
- DrawCollage();
- if (exists_numwindow)
- UpdateNumStrings();
- break;
-
- case 8: /* SELECT gadget */
- if (--selpiece < 0)
- selpiece = N;
- DrawCollage();
- if (exists_numwindow)
- UpdateNumStrings();
- break;
-
- case 9: /* DELETE gadget */
- DeleteSelPiece();
- DrawCollage();
- ComputeProbs();
- if (exists_numwindow)
- UpdateNumStrings();
- break;
-
- case 10: /* CLRIFS gadget */
- ClearIFS();
- AddDefPiece();
- DrawCollage();
- if (exists_numwindow)
- UpdateNumStrings();
- break;
-
- case 11: /* NUMBERS Gadget */
- if (!exists_numwindow) {
- UpdateNumStrings();
- OpenNumWindow();
- numgadgpending = -1;
- }
-
- break;
- } /* end switch hitgadget */
- } /* End else if GADGETUP */
-
- else if (class == MENUPICK) { /*** Respond to menu selections */
-
- MenuNumber = code; /* (First) item selection returned by IDCMP */
- while (MenuNumber != MENUNULL) { /*** service multiply chosen items */
- /* (if any) */
- ItemAddr = ItemAddress(&MenuList1, (long)MenuNumber);
-
- menuid = MENUNUM(MenuNumber); /* Extract menu, item from IDCMP code */
- itemid = ITEMNUM(MenuNumber);
- subitemid = SUBNUM(MenuNumber);
-
- if (menuid == 0) { /* PROJECT Menu */
- switch (itemid) {
-
- case 0: /* NEW */
- if (SetMode(OUTLINE) == 1) {
- SetRast(r, 0L);
- exists_outline = 0;
- if (exists_image)
- CloseImageScreen();
- }
- break;
-
- case 1: /* EDIT OUTLINE */
- SetMode(OUTLINE);
- break;
-
- case 2: /* LOAD FILE (with subitems) */
- if(ReqBase == NULL) { /* req.library missing - no file I/O */
- ShowError("req.library not found!");
- break;
- }
- fname = GetFileName("File to Load:");
- if (*fname != '\0') {
-
- switch (subitemid) {
-
- case 0: /* Load Outline */
- if (SetMode(OUTLINE) == 1)
- LoadILBM(fname, 0);
- break;
-
- case 1: /* Load IFS */
- SetMode(COLLAGE);
- if (LoadIFS(fname) == NULL) { /* If load failed */
- ClearIFS();
- AddDefPiece();
- DrawCollage();
- }
- break;
-
- case 2: /* Load Image */
- LoadILBM(fname, 1);
- break;
- } /* end switch subitemid */
- } /* end if *fname etc */
- break;
-
- case 3: /* SAVE FILE (with subitems) */
- if(ReqBase == NULL) { /* req.library missing - no file I/O */
- ShowError("req.library not found!");
- break;
- }
- switch (subitemid) {
-
- case 0: /* Save IFS */
- SaveIFS();
- break;
-
- case 1: /* Save Image */
- SaveILBM();
- break;
- } /* end switch subitemid */
- break;
-
- case 4: /* OPTIMIZE */
- if (drawmode != VECTOR)
- ShowError("No IFS to Optimize!");
- else
- Optimize(1);
- break;
-
- case 5: /* QUIT */
- CloseAll();
- break;
- } /* end switch itemid */
- } /* end if menuid == 0) */
-
- else if (menuid == 1) { /* DISPLAY Menu */
- switch (itemid) {
-
- case 0: /* SHOW CODES */
- if (drawmode != VECTOR)
- ShowError("No IFS!");
- else
- AboutText(CODES);
- break;
-
- case 1: /* SHOW IMAGE */
- if (exists_image) {
- MoveScreen(ImageScreen, 0L, (long)(-1*ImageScreen->TopEdge));
- ScreenToFront(ImageScreen);
- }
- else
- ShowError("No Image!");
- break;
- } /* end switch itemid */
- } /* end else if menuid == 1) */
-
- else if (menuid == 2) { /* RENDER Menu */
- switch (itemid) {
-
- case 0: /* RESOLUTION (with subitems) */
- renderwidth = (subitemid > 0) ? 640 : 320;
- renderheight = (subitemid > 1) ? 400 : 200;
- break;
-
- case 1: /* GRAY LEVELS (with subitems) */
- renderdepth = subitemid + 1;
- break;
-
- case 2: /* START */
- while(message = (struct IntuiMessage *)GetMsg(Window->UserPort))
- ReplyMsg(message); /* Clean out IDCMP port before closing it */
- ModifyIDCMP(Window, NULL); /* Disable IDCMP during rendering */
- ClearMenuStrip(Window); /* remove main window menus during render*/
- RenderImage(0); /* render the attractor in Image Screen */
- SetMenuStrip(Window, &MenuList1);
- ModifyIDCMP(Window, MOUSEBUTTONS|GADGETUP|MENUPICK);
- break;
- } /* end switch itemid */
- } /* end else if menuid == 2) */
-
- else if (menuid == 3) { /* ABOUT Menu */
- switch (itemid) {
-
- case 0: /* IFS THEORY */
- AboutText(IFS_THEORY);
- break;
-
- case 1: /* HELP */
- AboutText(HELP1);
- AboutText(HELP2);
- break;
-
- case 2: /* AUTHOR */
- AboutText(AUTHOR);
- break;
-
- case 3: /* DEMO */
- DoDemo();
- break;
- } /* end switch itemid */
- } /* end else if menuid == 3) */
-
- MenuNumber = ItemAddr->NextSelect;
- /* Loop back for next multiply selected item, if any */
- } /* end while MenuNumber != MENUNULL */
- } /* end else if MENUPICK */
-
- /*** Get & serve an IDCMP event, if any, from Coefficients Window */
-
- if (exists_numwindow) {
- if (message = (struct IntuiMessage *)GetMsg(NumWindow->UserPort)) {
- ReplyMsg(message);
-
- /* Note that all events in this window are GADGETUP, GADGETDOWN */
- /* or CLOSEWINDOW */
-
- if (message->Class == CLOSEWINDOW) {
- CloseWindow(NumWindow);
- exists_numwindow = 0;
- numgadgpending = -1;
- SetMenuStrip(Window, &MenuList1);
- }
- else if (message->Class == GADGETDOWN) { /* ENTER or string gadget */
- if (numgadgpending != -1)
- RecomputeCoeffs(numgadgpending);
- hitgadstruct = (struct Gadget *)(message->IAddress);
- /* pointer to just-hit gadget */
- numgadgpending = hitgadstruct->GadgetID;
- /* ID# of just-selected gadget structure */
-
- /**** Refresh all string gadgets except just-hit one */
- for(gad = &NumAcoeffGadg; gad != NULL; gad = gad->NextGadget)
- if (gad->GadgetID != numgadgpending)
- RefreshGList(gad, NumWindow, NULL, 1L);
- if (numgadgpending == 12)
- numgadgpending = -1; /* It was only the ENTER Gadget */
- }
- else if (message->Class == GADGETUP) {
- hitgadget = ((struct Gadget *)(message->IAddress))->GadgetID;
- /* ID# of just-selected gadget structure */
- switch (hitgadget) {
-
- case 12: /* ENTER */
-
- tmppiece = *pieceptr[selpiece]; /* Structure assignment */
-
- /* Copy all coeffs from string gadgets to tmppiece */
-
- sscanf((char*)NumNumR2coeffGadgSIBuff, "%lf", &tmppiece.r2);
- sscanf((char*)NumNumR1coeffGadgSIBuff, "%lf", &tmppiece.r1);
- sscanf((char*)NumNumS2coeffGadgSIBuff, "%lf", &tmppiece.s2);
- sscanf((char*)NumNumS1coeffGadgSIBuff, "%lf", &tmppiece.s1);
- sscanf((char*)NumNumPcoeffGadgSIBuff, "%lf", &tmppiece.p);
- sscanf((char*)NumNumDenscoeffGadgSIBuff, "%lf",
- &tmppiece.dens);
- sscanf((char*)NumNumFcoeffGadgSIBuff, "%lf", &tmppiece.f);
- sscanf((char*)NumNumEcoeffGadgSIBuff, "%lf", &tmppiece.e);
- sscanf((char*)NumNumDcoeffGadgSIBuff, "%lf", &tmppiece.d);
- sscanf((char*)NumNumCcoeffGadgSIBuff, "%lf", &tmppiece.c);
- sscanf((char*)NumNumBcoeffGadgSIBuff, "%lf", &tmppiece.b);
- sscanf((char*)NumNumAcoeffGadgSIBuff, "%lf", &tmppiece.a);
-
- tmppiece.r1 = tmppiece.r1*0.017453293; /* convert degs to radians*/
- tmppiece.r2 = tmppiece.r2*0.017453293;
-
- /*** Erase Plane 3 before transformation delay */
- SetWrMsk(r,0xFFF8); /* Write-protect planes 0,1,2 */
- SetRast(r, 0L);
- SetWrMsk(r, 0xFFFF);
-
- /* Transform the selected piece per user-entered coefficients */
- TransformPiece(outlinebufptr,
- pieceptr[selpiece]->piecemap, &tmppiece);
- /*** Erase Plane 2, then Blit Selected Piece from piecemap to it */
- SetWrMsk(r,0xFFF4); /* Write-protect planes 0,1,3 */
- SetRast(r, 0L);
- SetAPen(r, 4L);
- BltTemplate((char*)pieceptr[selpiece]->piecemap,
- (long)Window->BorderLeft,(long)WIDTH/8, r, 0L, 0L,
- (long)GZZWIDTH, (long)GZZHEIGHT);
- /* Rastport WrMask will be restored in DrawBox() called below */
-
- /*** Compute new Box corners from new coeffs */
- tmppiece.boxo.x = tmppiece.e * GZZWIDTH;
- tmppiece.boxo.y = tmppiece.f * GZZWIDTH; /* sic! */
- tmppiece.boxx.x = (tmppiece.a + tmppiece.e) * GZZWIDTH;
- tmppiece.boxx.y = (tmppiece.c + tmppiece.f) * GZZWIDTH;
- tmppiece.boxy.x = (tmppiece.b*GZZHEIGHT/GZZWIDTH + tmppiece.e) *
- GZZWIDTH;
- tmppiece.boxy.y = (tmppiece.d*GZZHEIGHT/GZZWIDTH + tmppiece.f) *
- GZZWIDTH;
- tmppiece.boxz.x =
- tmppiece.boxy.x + tmppiece.boxx.x - tmppiece.boxo.x;
- tmppiece.boxz.y =
- tmppiece.boxy.y + tmppiece.boxx.y - tmppiece.boxo.y;
-
- *pieceptr[selpiece] = tmppiece; /* structure assignment */
- /*** Recompute probabilities and update piece structures */
- pieceptr[selpiece]->det =
- fabs(tmppiece.a * tmppiece.d - tmppiece.b * tmppiece.c);
- if (pieceptr[selpiece]->det == 0.0)
- pieceptr[selpiece]->det = 0.01;
- ComputeProbs(); /* Adjust all piece probabilities */
- DrawBox(); /* Redraw Vector Box for modified selected piece */
- break;
-
- default: /* GADGETUP on any coefficient string gadget */
- numgadgpending = -1;
- RecomputeCoeffs(hitgadget);
- RefreshGadgets(&NumGadgetList3, NumWindow, NULL);
- break;
- } /* end switch hitgadget */
- } /* end else if ... GADGETUP */
- } /* end if message etc of coeffs window */
- } /* end if exists_numwindow */
-
- /*** Get & serve an IDCMP event, if any, from Image Window */
- /* Note that all events in this window are MOUSEBUTTONS */
-
- if (exists_image) {
- if (message = (struct IntuiMessage *)GetMsg(ImageWindow->UserPort)) {
- ReplyMsg(message);
- if (message->Code == SELECTUP) { /* User clicked - push Image to back*/
- ScreenToBack(ImageScreen);
- MoveScreen(ImageScreen, 0L, (long)(-1*ImageScreen->TopEdge));
- ScreenToFront(Screen);
- ActivateWindow(Window);
- }
- }
- } /* End if exists_image */
- } /* End while of main loop */
- } /* End main() */
- /*=========================================================================*/
-
- char * GetFileName(prompt) /* Returns pointer to a filename selected from */
- char *prompt; /* a file requester. Prompt appears at top of requester */
- /* window. If user selected CANCEL,returns a nullstring */
- /* Places the requester in a custom 640x200 screen. */
-
- /* Uses the Fox/Dawson File Requester; you must link */
- /* with glue module myreqglue.o. You need to include */
- /* reqbase.h and also libraries/dosextens.h (for the */
- /* Process structure). */
- {
- struct Screen *ReqScreen;
- struct Window *ReqWindow;
- struct NewScreen ns;
- struct Screen *OpenScreen();
- struct NewWindow nw;
- struct Window *OpenWindow();
-
- struct Task *FindTask();
- struct Process *myprocess;
- APTR oldwindowptr;
-
- /* Link the buffers to the FileRequester struct (all declared as globals) */
-
- MyFileReqStruct.File = filename;
- MyFileReqStruct.Dir = directoryname;
- MyFileReqStruct.PathName = pathname;
-
- /*** Open a window in a custom Hires screen for requester display */
-
- ns.LeftEdge = 0; /*** Initialize a NewScreen structure */
- ns.TopEdge = 0;
- ns.Width = 640;
- ns.Height = 200;
- ns.Depth = 2;
- ns.DetailPen = 0; /* Colour of text in screen title bar */
- ns.BlockPen = 1; /* Colour of screen Title Bar */
- ns.ViewModes = HIRES;
- ns.Type = CUSTOMSCREEN;
- ns.Font = &TOPAZ80;
- ns.DefaultTitle = NULL;
- ns.Gadgets = NULL;
- ns.CustomBitMap = NULL;
-
- nw.LeftEdge = 0; /*** Initialize a NewWindow structure */
- nw.TopEdge = 0;
- nw.Width = 640;
- nw.Height = 200;
- nw.DetailPen = 0; /* Menu title text color */
- nw.BlockPen = 1; /* Menu item box and title bar background */
- nw.IDCMPFlags = NULL;
- nw.Flags = ACTIVATE|NOCAREREFRESH;
- nw.FirstGadget = NULL;
- nw.CheckMark = NULL;
- nw.Title = (UBYTE*)" ";
- nw.Screen = NULL; /* Will set it to ReqScreen after the screen is opened */
- nw.BitMap = NULL;
- nw.MinWidth = 0;
- nw.MinHeight = 0;
- nw.MaxWidth = 0;
- nw.MaxHeight = 0;
- nw.Type = CUSTOMSCREEN;
-
-
- /*** Open a Hires screen to place the requester in */
-
- if ((ReqScreen = (struct Screen *) OpenScreen(&ns)) == NULL) {
- ShowError("Couldn't open Requester screen!!!");
- pathname[0] = '\0'; /* make returned buffer a nullstring */
- return(pathname);
- }
-
- /*** Open the Window to place the requester in */
- nw.Screen = ReqScreen;
- if ((ReqWindow = (struct Window *) OpenWindow(&nw)) == NULL) {
- CloseScreen(ReqScreen);
- ShowError("Couldn't open Requester window!!!");
- pathname[0] = '\0'; /* make returned buffer a nullstring */
- return(pathname);
- }
-
- /* Set pointer to tell req.library requesters where to appear */
- myprocess = (struct Process *)FindTask((char *)0);
- oldwindowptr = myprocess->pr_WindowPtr;
- myprocess->pr_WindowPtr = (APTR)ReqWindow;
-
- /*** Set up file requester structure fields to customize requester */
-
- MyFileReqStruct.Title = prompt; /* Text at top of requester */
- MyFileReqStruct.dirnamescolor = 3; /* colours of requester elements */
- MyFileReqStruct.devicenamescolor = 3;
- MyFileReqStruct.WindowLeftEdge = 0;
- MyFileReqStruct.WindowTopEdge = 0;
- MyFileReqStruct.Flags = FRQCACHINGM | /* Directory Caching */
- FRQABSOLUTEXYM | /* Fix requester position in screen */
- FRQNOHALFCACHEM| /* Don't cache half-read directories */
- FRQNODRAGM; /* No drag bar on requester */
-
- if (FileRequester(&MyFileReqStruct) == NULL) /* Call the File Requester */
- pathname[0] = '\0'; /* If user selected no file, return a nullstring*/
-
- /* restore pr_WindowPtr before closing the window! */
- myprocess->pr_WindowPtr = oldwindowptr;
-
- CloseWindow(ReqWindow); /*** Close requester screen stuff and return */
- CloseScreen(ReqScreen);
-
- return(pathname); /* Will be the pointer to a string which now contains the */
- /* full file name selected, or a NULL string if the user */
- /* selected CANCEL or no filename */
- }
- /*===========================================================================*/
-
- OpenLibraries() /* Open needed libraries */
- {
- IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library",INTUITION_REV);
- if (IntuitionBase == NULL) {
- printf("Can't open Intuition library!!!!!!\n");
- CloseAll();
- }
-
- GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library",GRAPHICS_REV);
- if (GfxBase == NULL) {
- printf("Can't open graphics library!!!!!!\n");
- CloseAll();
- }
-
- MathBase = (void *)OpenLibrary("mathffp.library",0L);
- if (MathBase == NULL) {
- printf("Can't open mathffp library!!!!!!\n");
- CloseAll();
- }
-
- MathTransBase = (void *)OpenLibrary("mathtrans.library",0L);
- if (MathTransBase == NULL) {
- printf("Can't open mathtrans library!!!!!!\n");
- CloseAll();
- }
- ReqBase = (struct ReqLib *)OpenLibrary("req.library", 0L);
- if (ReqBase == NULL) {
- printf("Couldn't open req.library!!!!!!\n");
- printf("IFSlab requires req.library in libs: to be able to do file I/O\n");
- }
- }
- /*=========================================================================*/
-
- OpenDisplay() /* Open Outline Sketch window in custom screen */
-
- {
- /* NEWSCREENSTRUCTURE, PALETTE and NewWindowStructure1 are in IFSLab.h */
- /* and, along with pointers Window, Screen, have been declared externally */
-
- struct Screen *OpenScreen();
- struct Window *OpenWindow();
- struct ViewPort *vp;
-
- /*** Open the screen */
- if ((Screen = (struct Screen *) OpenScreen(&NEWSCREENSTRUCTURE)) == NULL) {
- printf("\nCouldn't open screen!!!!\n");
- CloseAll();
- }
- /*** Link Custom colours defined in PALETTE to screen's ViewPort */
- vp = &(Screen->ViewPort);/* ptr to viewport structure assoc'd with screen */
- LoadRGB4(vp,PALETTE,16L); /* Change to custom colors defined above */
-
- /*** Open the Window */
-
- NewWindowStructure1.Screen = Screen;
- if ((Window = (struct Window *) OpenWindow(&NewWindowStructure1)) == NULL) {
- printf("\nCouldn't open window!!!!\n");
- CloseAll();
- }
-
- scrp = &(Screen->RastPort); /* Screen RastPort,used to draw in outer window*/
- SetDrMd(scrp, JAM1);
- SetAPen(scrp, 1L);
- r = (Window->RPort); /* Window's rastport, used for drawing in GZZ bitmap */
- SetDrMd(r, JAM1);
- HiliteGadget(0);
- SetMenuStrip(Window,&MenuList1);
- OffMenu(Window, NOITEM<<5 | 2); /* disable render menu and its items */
- }
- /*===========================================================================*/
-
- OpenNumWindow() /* Open Coefficients Window and disable menus */
- {
- /* Assumes window is not open already */
-
- NumNewWindowStructure3.Screen = Screen;
- if ((NumWindow = (struct Window *)OpenWindow(&NumNewWindowStructure3))
- == NULL) {
- ShowError("Error - Couldn't open coeffs window");
- return;
- }
- ClearMenuStrip(Window); /* remove main window menus while Coeffs window on */
- SetWindowTitles(NumWindow, -1L, (char *)" Collage Editor");
- exists_numwindow = 1;
- }
- /*===========================================================================*/
-
- CloseAll() /* Close everything neatly and exit program */
- {
- if (exists_image)
- CloseImageScreen();
- for (i = 0; i <= N; i++) /* Dealocate Pieces' struct and piecemap memory */
- FreePiece(pieceptr[i]);
- if (outlinebufptr)
- FreeMem(outlinebufptr, (long)RASSIZE(WIDTH, HEIGHT));
- if (Window) {
- ClearMenuStrip(Window);
- CloseWindow(Window);
- }
- if (exists_numwindow)
- CloseWindow(NumWindow);
- if (Screen)
- CloseScreen(Screen);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (GfxBase)
- CloseLibrary(GfxBase);
- if (MathBase)
- CloseLibrary(MathBase);
- if (MathTransBase)
- CloseLibrary(MathTransBase);
- if (ReqBase) {
- PurgeFiles(&MyFileReqStruct); /* function in req.library */
- CloseLibrary(ReqBase);
- }
-
- exit(0);
- }
- /*===========================================================================*/
-
- int SetMode(newmode) /* Sets up and enters requested mode */
- int newmode; /* newmode can be OUTLINE or COLLAGE */
- { /* returns 1 normally; returns 0 if user chose CANCEL in */
- /* "IFS will be LOST" requester */
- BOOL AutoRequest();
- static struct IntuiText Cancel = {
- 3,0, /* FrontPen, BackPen */
- JAM1, /* DrawMode */
- 6,3, /* LeftEdge, TopEdge */
- &TOPAZ80, /* ITextFont */
- (UBYTE*)"Cancel", /* IText */
- NULL /* NextText */
- };
- static struct IntuiText Doit, ReqBodyText;
- Doit = ReqBodyText = Cancel; /* structure assignment */
- ReqBodyText.IText = (UBYTE *)" IFS will be LOST!";
- ReqBodyText.TopEdge = 8;
- Doit.IText = (UBYTE *)"Do it!";
-
- switch (newmode) {
-
- case OUTLINE:
- if (drawmode != VECTOR) /* already in desired mode! */
- return(1);
- if (AutoRequest(Window, &ReqBodyText, &Doit, &Cancel,
- NULL, NULL, 180L, 56L) == FALSE) {
- /* Set IDCMP flags right in case AutoRequest() messed 'em up */
- ModifyIDCMP(Window, MOUSEBUTTONS|GADGETUP|MENUPICK);
- return(0);
- }
- ModifyIDCMP(Window, MOUSEBUTTONS|GADGETUP|MENUPICK); /* After AutoReq. */
- ClearIFS();
- RemoveGList(Window, &CollageGadgetList2, 6L);
- AddGList(Window, &GadgetList1, 0L, 6L, NULL); /* change gadgets */
- SetDrMd(scrp, JAM1);
- SetAPen(scrp, 0L);
- RectFill(scrp, 280L, 12L, 316L, 117L); /* Blot out old gadget images */
- RefreshGadgets(&GadgetList1, Window, NULL);
- OffMenu(Window, NOITEM<<5 | 2); /* disable render menu and its items */
- SetWindowTitles(Window, -1L, " Outline Editor");
- drawmode = FREEHAND;
- HiliteGadget(0);
- SetAPen(r, 2L);
- break;
-
- case COLLAGE:
- if (drawmode == VECTOR) /* already in desired mode! */
- return(1);
- if (exists_outline == 0)
- PutDefOutline();
-
- CopyMem((char*)Window->RPort->BitMap->Planes[1],
- (char*)outlinebufptr, (long)RASSIZE(WIDTH,HEIGHT));
-
- RemoveGList(Window, &GadgetList1, 6L);
- AddGList(Window, &CollageGadgetList2, 0L, 6L, NULL);
- SetDrMd(scrp, JAM1);
- SetAPen(scrp, 0L);
- RectFill(scrp, 280L, 12L, 316L, 117L); /* Blot out old gadget images */
- RefreshGadgets(&CollageGadgetList2, Window, NULL);
- OnMenu(Window, NOITEM<<5 | 2); /* Enable render menu and its items */
- SetWindowTitles(Window, -1L, " Collage Editor");
- drawmode = VECTOR;
- curcor = '0';
- break;
- } /* end switch newmode */
- return(1);
- }
- /*===========================================================================*/
-
- DupSelPiece() /* Generate a copy of Selected Piece, make it highest */
- { /* numbered and Selected. Increment N. */
- if (N >= MAX_N) {
- ShowError("Too many transformations");
- return;
- }
- /*** Allocate and fill piece structure, make it Selected */
-
- if ((pieceptr[++N] = AllocPiece()) == NULL) { /* Allocate Piece */
- N--; /* if couldn't allocate piece */
- if (N == -1) { /* No memory for even one Piece - Quit program */
- ShowError("Re-run with more free memory!");
- CloseAll();
- }
- return;
- }
- pieceptr[N]->a = pieceptr[selpiece]->a;
- pieceptr[N]->b = pieceptr[selpiece]->b;
- pieceptr[N]->c = pieceptr[selpiece]->c;
- pieceptr[N]->d = pieceptr[selpiece]->d;
- pieceptr[N]->e = pieceptr[selpiece]->e;
- pieceptr[N]->f = pieceptr[selpiece]->f;
- pieceptr[N]->s1 = pieceptr[selpiece]->s1;
- pieceptr[N]->s2 = pieceptr[selpiece]->s2;
- pieceptr[N]->r1 = pieceptr[selpiece]->r1;
- pieceptr[N]->r2 = pieceptr[selpiece]->r2;
- pieceptr[N]->dens = 1.0;
- pieceptr[N]->det = pieceptr[selpiece]->det;
- pieceptr[N]->boxo = pieceptr[selpiece]->boxo; /* Structure assignment! */
- pieceptr[N]->boxx = pieceptr[selpiece]->boxx; /* Structure assignment! */
- pieceptr[N]->boxy = pieceptr[selpiece]->boxy; /* Structure assignment! */
- pieceptr[N]->boxz = pieceptr[selpiece]->boxz; /* Structure assignment! */
-
- ComputeProbs(); /* Adjust all Piece probabilities */
- /* Copy selected piece's piecemap to the new piece's piecemap */
- CopyMem((char*)pieceptr[selpiece]->piecemap, (char*)pieceptr[N]->piecemap,
- (long)RASSIZE(WIDTH,GZZHEIGHT));
- selpiece = N; /* make this Piece Selected */
- }
- /*===========================================================================*/
-
- AddDefPiece() /* Generate a default Piece of current Outline, make */
- { /* it highest numbered and Selected. Increment N. */
- if (N >= MAX_N) {
- ShowError("Too many transformations");
- return;
- }
- /*** Allocate and fill piece structure, make it Selected */
-
- if ((pieceptr[++N] = AllocPiece()) == NULL) { /* Allocate Piece */
- N--; /* if couldn't allocate piece */
- if (N == -1) { /* No memory for even one Piece - Quit program */
- ShowError("Re-run with more free memory!");
- CloseAll();
- }
- return;
- }
- pieceptr[N]->a = 0.5;
- pieceptr[N]->b = 0.0;
- pieceptr[N]->c = 0.0;
- pieceptr[N]->d = 0.5;
- pieceptr[N]->e = 0.25;
- pieceptr[N]->f = 0.16938406; /* = 0.25*GZZHEIGHT/GZZWIDTH */
- pieceptr[N]->s1 = 0.5;
- pieceptr[N]->s2 = 0.5;
- pieceptr[N]->r1 = 0.0;
- pieceptr[N]->r2 = 0.0;
- pieceptr[N]->dens = 1.0;
- pieceptr[N]->det = 0.25;
- pieceptr[N]->boxo.x = 0.25 * GZZWIDTH;
- pieceptr[N]->boxo.y = 0.25 * GZZHEIGHT;
- pieceptr[N]->boxx.x = 0.75 * GZZWIDTH;
- pieceptr[N]->boxx.y = 0.25 * GZZHEIGHT;
- pieceptr[N]->boxy.x = 0.25 * GZZWIDTH;
- pieceptr[N]->boxy.y = 0.75 * GZZHEIGHT;
- pieceptr[N]->boxz.x = 0.75 * GZZWIDTH;
- pieceptr[N]->boxz.y = 0.75 * GZZHEIGHT;
-
- ComputeProbs(); /* Adjust all Piece probabilities */
- /* Transform Outline by this piece's transformation into its piecemap */
- TransformPiece(outlinebufptr, pieceptr[N]->piecemap, pieceptr[N]);
- selpiece = N; /* make this Piece Selected */
- }
- /*===========================================================================*/
-
- ComputeProbs() /* Recompute all piece probabilities */
- {
- double sum = 0;
-
- for (i = 0; i <= N; i++)
- sum = sum + pieceptr[i]->dens * pieceptr[i]->det;
-
- for (i = 0; i <= N; i++)
- pieceptr[i]->p = (pieceptr[i]->dens * pieceptr[i]->det)/sum;
- }
- /*===========================================================================*/
-
- DrawBox() /* Erase bitplane 3, and draw Vector Box of Selected Piece in it */
- {
- SetWrMsk(r,0xFFF8); /* Write-protect planes 0,1,2 */
- SetRast(r, 0L); /* Erase plane 3 */
-
- SetAPen(r, 8L); /*** Draw Vector Box */
- Move(r, pieceptr[selpiece]->boxo.x, pieceptr[selpiece]->boxo.y);
- Draw(r, pieceptr[selpiece]->boxx.x, pieceptr[selpiece]->boxx.y);
- Draw(r, pieceptr[selpiece]->boxz.x, pieceptr[selpiece]->boxz.y);
- Draw(r, pieceptr[selpiece]->boxy.x, pieceptr[selpiece]->boxy.y);
- Draw(r, pieceptr[selpiece]->boxo.x, pieceptr[selpiece]->boxo.y);
-
- SetDrMd(r, JAM2|INVERSVID); /*** Draw Corner "gadgets" */
- SetBPen(r, 0L);
- Move(r, pieceptr[selpiece]->boxo.x - 3L, pieceptr[selpiece]->boxo.y + 3L);
- Text(r, "O", 1L);
- Move(r, pieceptr[selpiece]->boxx.x - 3L, pieceptr[selpiece]->boxx.y + 3L);
- Text(r, "x", 1L);
- Move(r, pieceptr[selpiece]->boxz.x - 3L, pieceptr[selpiece]->boxz.y + 3L);
- Text(r, " ", 1L);
- Move(r, pieceptr[selpiece]->boxy.x - 3L, pieceptr[selpiece]->boxy.y + 3L);
- Text(r, "y", 1L);
-
- SetDrMd(r, JAM1);
- SetWrMsk(r,0xFFFF);
- }
- /*===========================================================================*/
-
- ToggleGhostBox() /* Draw or undraw current ghost box, as given in */
- { /* ghbox? variables, in COMPLEMENT mode */
- SetDrMd(r, JAM1|COMPLEMENT);
- Move(r, ghboxo.x, ghboxo.y);
- Draw(r, ghboxx.x, ghboxx.y);
- Draw(r, ghboxz.x, ghboxz.y);
- Draw(r, ghboxy.x, ghboxy.y);
- Draw(r, ghboxo.x, ghboxo.y);
- SetDrMd(r, JAM1);
-
- }
- /*===========================================================================*/
-
- ComputeNewBox() /* Compute New Ghost Box from mouse coords, put in tmpbox */
- { /* variables. */
- long dx, dy; /* increments of mouse position from corner's previous pos */
- double s, a; /* Scaling and Rotation components of change in vector Z */
- double cosa, sina; /* cosine and sine of angle a */
- double Qx, Qy;
- double tmp;
-
- switch (curcor) {
-
- case 'o':
- dx = mx - pieceptr[selpiece]->boxo.x;
- dy = my - pieceptr[selpiece]->boxo.y;
- tmpboxo.x = mx;
- tmpboxo.y = my;
- tmpboxx.x = pieceptr[selpiece]->boxx.x + dx;
- tmpboxx.y = pieceptr[selpiece]->boxx.y + dy;
- tmpboxy.x = pieceptr[selpiece]->boxy.x + dx;
- tmpboxy.y = pieceptr[selpiece]->boxy.y + dy;
- tmpboxz.x = pieceptr[selpiece]->boxz.x + dx;
- tmpboxz.y = pieceptr[selpiece]->boxz.y + dy;
- break;
-
- case 'x':
- dx = mx - pieceptr[selpiece]->boxx.x;
- dy = my - pieceptr[selpiece]->boxx.y;
- tmpboxo = pieceptr[selpiece]->boxo; /* Structure Assignment */
- tmpboxx.x = mx;
- tmpboxx.y = my;
- tmpboxy = pieceptr[selpiece]->boxy; /* Structure Assignment */
- tmpboxz.x = pieceptr[selpiece]->boxz.x + dx;
- tmpboxz.y = pieceptr[selpiece]->boxz.y + dy;
- break;
-
- case 'y':
- dx = mx - pieceptr[selpiece]->boxy.x;
- dy = my - pieceptr[selpiece]->boxy.y;
- tmpboxo = pieceptr[selpiece]->boxo; /* Structure Assignment */
- tmpboxx = pieceptr[selpiece]->boxx; /* Structure Assignment */
- tmpboxy.x = mx;
- tmpboxy.y = my;
- tmpboxz.x = pieceptr[selpiece]->boxz.x + dx;
- tmpboxz.y = pieceptr[selpiece]->boxz.y + dy;
- break;
-
- case 'z':
- s = sqrt((double)((mx-pieceptr[selpiece]->boxo.x)*
- (mx-pieceptr[selpiece]->boxo.x)+(my-pieceptr[selpiece]->boxo.y)*
- (my-pieceptr[selpiece]->boxo.y))/
- (double)((pieceptr[selpiece]->boxz.x-pieceptr[selpiece]->boxo.x)*
- (pieceptr[selpiece]->boxz.x-pieceptr[selpiece]->boxo.x)+
- (pieceptr[selpiece]->boxz.y-pieceptr[selpiece]->boxo.y)*
- (pieceptr[selpiece]->boxz.y-pieceptr[selpiece]->boxo.y)));
-
- a = myatan2((double)(my - pieceptr[selpiece]->boxo.y), (double)(mx -
- pieceptr[selpiece]->boxo.x)) - myatan2((double)
- (pieceptr[selpiece]->boxz.y - pieceptr[selpiece]->boxo.y),
- (double)(pieceptr[selpiece]->boxz.x - pieceptr[selpiece]->boxo.x));
-
- cosa = cos(a);
- sina = sin(a);
-
- Qx = pieceptr[selpiece]->boxo.x + s * (pieceptr[selpiece]->boxo.y * sina -
- pieceptr[selpiece]->boxo.x * cosa);
- Qy = pieceptr[selpiece]->boxo.y - s * (pieceptr[selpiece]->boxo.y * cosa +
- pieceptr[selpiece]->boxo.x * sina);
-
- tmpboxo = pieceptr[selpiece]->boxo; /* Structure Assignment */
-
- /* Below, the conditional assignments assure rounding on the */
- /* double-to-int conversion rather than truncation */
- tmp = s * (pieceptr[selpiece]->boxx.x * cosa -
- pieceptr[selpiece]->boxx.y * sina) + Qx;
- tmpboxx.x = (tmp - floor(tmp) > 0.5) ? tmp + 1. : tmp;
- tmp = s * (pieceptr[selpiece]->boxx.x * sina +
- pieceptr[selpiece]->boxx.y * cosa) + Qy;
- tmpboxx.y = (tmp - floor(tmp) > 0.5) ? tmp + 1. : tmp;
- tmp = s * (pieceptr[selpiece]->boxy.x * cosa -
- pieceptr[selpiece]->boxy.y * sina) + Qx;
- tmpboxy.x = (tmp - floor(tmp) > 0.5) ? tmp + 1. : tmp;
- tmp = s * (pieceptr[selpiece]->boxy.x * sina +
- pieceptr[selpiece]->boxy.y * cosa) + Qy;
- tmpboxy.y = (tmp - floor(tmp) > 0.5) ? tmp + 1. : tmp;
- tmpboxz.x = tmpboxy.x + tmpboxx.x - tmpboxo.x;
- tmpboxz.y = tmpboxx.y + tmpboxy.y - tmpboxo.y;
- break;
- } /* End switch curcor */
- }
- /*===========================================================================*/
-
- DeleteSelPiece() /* Delete the Selected Piece. If it was the only piece, */
- { /* replace it with a Default Piece. Rearrange Piece list */
- FreePiece(pieceptr[selpiece]); /* free memory associated with the piece */
- for (i = selpiece; i < N; i++) /* close gap in pointer array */
- pieceptr[i] = pieceptr[i+1];
- if (selpiece == N)
- selpiece--;
- N--;
-
- if (N == -1) /* if deleted last piece, place a default piece */
- AddDefPiece();
- }
- /*==========================================================================*/
-
- ClearIFS() /* Clear IFS variables, memory, and Collage image */
- {
- /* Clear all GZZ bitplanes except Outline plane */
- SetWrMsk(r,0xFFFD); /* Write-protect plane 1, Outline */
- SetRast(r, 0L);
- SetWrMsk(r,0xFFFF);
-
- for(i = 0; i <= N; i++)
- FreePiece(pieceptr[i]);
- N = -1;
- }
- /*==========================================================================*/
-
- HiliteGadget(gadgetid) /* frame gadget of given ID# in Red */
- /* Implements in software Gadget Mutual Exclude */
- /* Because window is GZZ and gadgets are in its border, this routine */
- /* Draws the frame directly on the Screen,not in Window. It is quite */
- /* non-generic because gadget coordinates are coded in numerically */
- int gadgetid;
- {
- long i;
- /*** Define frames as border structures ***/
-
- static SHORT Frame_data[10] = { 0,0, 36,0, 36,15, 0,15, 0,0 };
- /* Gadget select frame data */
-
- static struct Border OnFrame_Bdr = { /* Red (Selected) Gadget border */
- 0,0, /* LeftEdge, TopEdge */
- 4,0,JAM1, /* FrontPen, BackPen, DrawMode */
- 5, /* Count */
- Frame_data, /* XY */
- NULL /* Next Border */
- };
-
- static struct Border OffFrame_Bdr = { /* Lt Green (deselected) Gadg border */
- 0,0, /* LeftEdge, TopEdge */
- 3,0,JAM1, /* FrontPen, BackPen, DrawMode */
- 5, /* Count */
- Frame_data, /* XY */
- NULL /* Next Border */
- };
-
- /*** Unframe all gadgets, then frame selected one */
- for (i = 0; i <= 3; i++)
- DrawBorder(scrp, &OffFrame_Bdr, 280L, i*18L+12L);
- DrawBorder(scrp, &OnFrame_Bdr, 280L, gadgetid*18L+12L);
- }
- /*==========================================================================*/
-
- DrawCollage() /* Draw the current IFS as a collage image with */
- { /* vector Box of Selected Piece (wipe out old box)*/
- /*** Erase all bitplanes except Outline plane */
- SetWrMsk(r,0xFFFD); /* Write-protect plane 1, Outline */
- SetRast(r, 0L);
-
- /* Blit Deselected pieces from piecemaps to plane 0 */
- SetWrMsk(r,0x0001); /* Write protect all planes except plane 0 */
- SetAPen(r, 1L);
- for (i = 0; i <= N; i++)
- if (i != selpiece) /* skip Selected piece */
- BltTemplate((char*)pieceptr[i]->piecemap,(long)Window->BorderLeft,
- (long)WIDTH/8, r, 0L, 0L, (long)GZZWIDTH, (long)GZZHEIGHT);
- /* Blit Selected Piece from piecemap to plane 2 */
- SetWrMsk(r,0x0004); /* Write protect all planes except plane 2 */
- SetAPen(r, 4L);
- BltTemplate((char*)pieceptr[selpiece]->piecemap,(long)Window->BorderLeft,
- (long)WIDTH/8, r, 0L, 0L, (long)GZZWIDTH, (long)GZZHEIGHT);
-
- DrawBox(); /* Draw Vector Box of Selected Piece */
- /* Note that Rastport's WrMask is restored within DrawBox() */
- }
- /*==========================================================================*/
-
- double myatan2(y,x) /* atan2() as defined in Aztec C but missing from mf.lib */
- double x, y; /* returns arctangent of y/x in range -pi to pi. */
- { /* If x=y=0, returns 0, sets errno=EDOM. */
- /* Requires #include of errno.h and math.h */
-
- #define PI 3.141592654
- if (x == 0.0) {
- if (y == 0.0) {
- errno = EDOM;
- return(0.0);
- }
- else
- x = 1.0e-10;
- }
-
- if (y >= 0.0) {
- if (x >= 0.0)
- return(atan(y/x)); /* Quadrant I */
- else
- return(PI - atan(-y/x)); /* Quadrant II */
- }
- else {
- if (x >= 0.0)
- return(-atan(-y/x)); /* Quadrant IV */
- else
- return(atan(y/x) - PI); /* Quadrant III */
- }
- }
- /*==========================================================================*/
-
- ModifyMousePtr(Wind, n)
- /* Change to custom mouse pointer in Window if n=1, or restore default */
- /* arrow and free CHIP RAM if n=-1. Use in only one window at a time! */
- struct Window *Wind;
- int n;
- {
- static short *ChipPtr;
- static struct ViewPort *vprt;
- static long color17, color18, color19;
- long GetRGB4();
-
- /*** Define Custom mouse pointer sprite data */
-
- #define ROWS 14 /* Number of Pixel rows in pointer */
-
- static USHORT Mouseptr[] = {
- 0x0000, 0x0000,
- /* ++++++++++++++++++ */
- 0x00f0, 0x00f0, /* + 3333 + */
- 0x03f8, 0x03f8, /* + 3333333 + */
- 0x07fc, 0x079c, /* + 333311333 + */
- 0x0ffe, 0x0e0e, /* + 33311111333 + */
- 0x0ffe, 0x0c06, /* + 33111111133 + */
- 0xafff, 0x0c73, /* +1 1 331113331133+ */
- 0xafff, 0x0cfb, /* +1 1 331133333133+ */
- 0xafff, 0x0ccb, /* +1 1 331133113133+ */
- 0xcfff, 0x0cdb, /* +11 331133133133+ */
- 0xdfff, 0x18c3, /* +11 3311133111133+ */
- 0xffff, 0x1ce7, /* +1113331133311333+ */
- 0xfffe, 0x07fe, /* +111113333333333 + */
- 0x7ffe, 0x003c, /* + 11111111133331 + */
- 0x1fff, 0x0000, /* + 1111111111111+ */
- /* ++++++++++++++++++ */
- 0x0000, 0x0000
- };
-
- if (n == 1 && ChipPtr == NULL) {
-
- /*** Get colors of default pointer in Window's screen */
- vprt = &(Wind->WScreen->ViewPort); /* ptr to viewport of screen */
- color17 = GetRGB4(vprt->ColorMap, 17L);
- color18 = GetRGB4(vprt->ColorMap, 18L);
- color19 = GetRGB4(vprt->ColorMap, 19L);
-
- /*** Copy sprite data into chip RAM to be accessible to graphic chips */
- ChipPtr =(short*)AllocMem((long)((ROWS+2)*4),MEMF_CHIP); /* Alloc block */
- CopyMem((char*)Mouseptr,(char*)ChipPtr,(long)((ROWS+2)*4)); /* Copy data*/
- /*** Attach custom pointer to window */
- SetPointer(Wind, ChipPtr, (long)ROWS, 16L, -1L, -1L);
-
- /*** Change custom pointer colors */
- SetRGB4(vprt, 17L, 15L, 12L, 10L);
- SetRGB4(vprt, 18L, 13L, 2L, 2L);
- SetRGB4(vprt, 19L, 15L, 0L, 0L);
- }
- else if (n == -1 && ChipPtr != NULL) {
- ClearPointer(Wind); /* Reset default pointer and its original colors */
- SetRGB4(vprt, 17L, color17>>8, (color17>>4L)&15, color17&15);
- SetRGB4(vprt, 18L, color18>>8, (color18>>4L)&15, color18&15);
- SetRGB4(vprt, 19L, color19>>8, (color19>>4L)&15, color19&15);
- FreeMem(ChipPtr, (long)((ROWS+2)*4)); /* release memory of pointer data */
- ChipPtr = NULL;
- }
- else
- DisplayBeep(NULL); /* Illegal call (called twice in a row with same n */
- }
- /*===========================================================================*/
-
- UpdateNumStrings() /* Update values of Coeff window string gadgets from */
- { /* selected piece structure. Redraw gadgets if the window is open */
- double degr1, degr2;
-
- degr1 = pieceptr[selpiece]->r1 / 0.017453293; /* convert radians to degrees*/
- degr2 = pieceptr[selpiece]->r2 / 0.017453293;
-
- sprintf((char*)NumNumT2coeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->f);
- sprintf((char*)NumNumT1coeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->e);
- sprintf((char*)NumNumR2coeffGadgSIBuff, "%5.lf", degr2);
- sprintf((char*)NumNumR1coeffGadgSIBuff, "%5.lf", degr1);
- sprintf((char*)NumNumS2coeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->s2);
- sprintf((char*)NumNumS1coeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->s1);
- sprintf((char*)NumNumPcoeffGadgSIBuff, "%5.3lf", pieceptr[selpiece]->p);
- sprintf((char*)NumNumDenscoeffGadgSIBuff,"%4.1lf", pieceptr[selpiece]->dens);
- sprintf((char*)NumNumFcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->f);
- sprintf((char*)NumNumEcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->e);
- sprintf((char*)NumNumDcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->d);
- sprintf((char*)NumNumCcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->c);
- sprintf((char*)NumNumBcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->b);
- sprintf((char*)NumNumAcoeffGadgSIBuff, "%5.2lf", pieceptr[selpiece]->a);
- if (exists_numwindow)
- RefreshGadgets(&NumGadgetList3, NumWindow, NULL);
- }
- /*===========================================================================*/
-
- RecomputeCoeffs(gadgetid) /* Re-Calculate 13 coefficients based on */
- int gadgetid; /* change in value of the one in the string gadget with */
- { /* the given gadgetid; put new values in string gadgets */
- /* Does range checking on entered coefficients; If user */
- /* entered an illegal value, will restore previous */
- /* value and inform user before returning. */
- double a, b, c, d, e, f, s1, s2, r1, r2, t1, t2, dens, p;
- double sum, p0, det, olddet, olddens;
-
- /* Put current coefficient values into temporary variables */
- sscanf((char*)NumNumT2coeffGadgSIBuff, "%lf", &t2);
- sscanf((char*)NumNumT1coeffGadgSIBuff, "%lf", &t1);
- sscanf((char*)NumNumR2coeffGadgSIBuff, "%lf", &r2);
- sscanf((char*)NumNumR1coeffGadgSIBuff, "%lf", &r1);
- sscanf((char*)NumNumS2coeffGadgSIBuff, "%lf", &s2);
- sscanf((char*)NumNumS1coeffGadgSIBuff, "%lf", &s1);
- sscanf((char*)NumNumPcoeffGadgSIBuff, "%lf", &p);
- sscanf((char*)NumNumDenscoeffGadgSIBuff, "%lf", &dens);
- sscanf((char*)NumNumFcoeffGadgSIBuff, "%lf", &f);
- sscanf((char*)NumNumEcoeffGadgSIBuff, "%lf", &e);
- sscanf((char*)NumNumDcoeffGadgSIBuff, "%lf", &d);
- sscanf((char*)NumNumCcoeffGadgSIBuff, "%lf", &c);
- sscanf((char*)NumNumBcoeffGadgSIBuff, "%lf", &b);
- sscanf((char*)NumNumAcoeffGadgSIBuff, "%lf", &a);
-
- while (r1 > 180. || r1 < -180.) /* Get angles to range -180 => +180 */
- r1 = (r1 > 0.) ? r1 - 360. : r1 + 360.;
- while (r2 > 180. || r2 < -180.)
- r2 = (r2 > 0.) ? r2 - 360. : r2 + 360.;
-
- r1 = r1*0.017453293; /* convert degrees to radians*/
- r2 = r2*0.017453293;
-
- /*** Check that all coefficients are in legal ranges */
- if (a < -1. || a > 1. || b < -1. || b > 1. || c < -1. || c > 1. ||
- d < -1. || d > 1. || e < -0.25 || e > 1. || f < -0.25 || f > 1. ||
- s1 < -1. || s1 > 1. || s2 < -1. || s2 > 1. || dens <= 0. ||
- t1 < -0.25 || t1 > 1. || t2 < -0.25 || t2 > 1. || p <= 0. || p > 1.) {
- ShowError("Coefficient out of Range!");
- a = pieceptr[selpiece]->a; /*** Undo the error */
- b = pieceptr[selpiece]->b;
- c = pieceptr[selpiece]->c;
- d = pieceptr[selpiece]->d;
- e = pieceptr[selpiece]->e;
- f = pieceptr[selpiece]->f;
- p = pieceptr[selpiece]->p;
- dens = pieceptr[selpiece]->dens;
- s1 = pieceptr[selpiece]->s1;
- s2 = pieceptr[selpiece]->s2;
- r1 = pieceptr[selpiece]->r1;
- r2 = pieceptr[selpiece]->r2;
- t1 = pieceptr[selpiece]->e;
- t2 = pieceptr[selpiece]->f;
- }
-
- det = fabs(a * d - b * c);
- if (det == 0.0)
- det = 0.01;
- sum = -(pieceptr[selpiece]->dens * pieceptr[selpiece]->det) + dens * det;
- for (i = 0; i <= N; i++)
- sum = sum + pieceptr[i]->dens * pieceptr[i]->det;
-
- if (gadgetid <= 26) { /* id's 21 thru 26, matrix coeffs a - f */
- s1 = sqrt(a*a + c*c);
- s2 = sqrt(b*b + d*d);
- r1 = myatan2(c, a);
- r2 = myatan2(-b, d);
- t1 = e;
- t2 = f;
- p = (dens * det)/sum;
- }
-
- if (gadgetid == 27) { /* density coefficient */
- p = (dens * det)/sum;
- }
-
- if (gadgetid == 28) { /* probability coefficient */
- olddens = dens;
- p0 = det / (sum - olddens*det + det); /* What p SHOULD be with dens == 1 */
- dens = p / p0;
- p = (dens * det)/(sum - olddens*det + dens*det);
- }
-
- if (gadgetid >= 29) { /* id's 29 thru 34, geometrical coeffs s1 thru t2 */
- olddet = fabs(a * d - b * c);
- if (olddet == 0.0)
- olddet = 0.01;
- a = s1 * cos(r1);
- b = -s2 * sin(r2);
- c = s1 * sin(r1);
- d = s2 * cos(r2);
- e = t1;
- f = t2;
- det = fabs(a * d - b * c); /*** recompute det and probability */
- if (det == 0.0)
- det = 0.01;
- sum = sum - olddet*dens + det*dens;
- p = (dens * det)/sum;
- }
-
- r1 = r1 / 0.017453293; /* convert radians to degrees */
- r2 = r2 / 0.017453293;
-
- /* Put resultant coefficient values into their string gadgets */
- sprintf((char*)NumNumT2coeffGadgSIBuff, "%5.2lf", f);
- sprintf((char*)NumNumT1coeffGadgSIBuff, "%5.2lf", e);
- sprintf((char*)NumNumR2coeffGadgSIBuff, "%5.lf", r2);
- sprintf((char*)NumNumR1coeffGadgSIBuff, "%5.lf", r1);
- sprintf((char*)NumNumS2coeffGadgSIBuff, "%5.2lf", s2);
- sprintf((char*)NumNumS1coeffGadgSIBuff, "%5.2lf", s1);
- sprintf((char*)NumNumPcoeffGadgSIBuff, "%5.3lf", p);
- sprintf((char*)NumNumDenscoeffGadgSIBuff, "%4.1lf", dens);
- sprintf((char*)NumNumFcoeffGadgSIBuff, "%5.2lf", f);
- sprintf((char*)NumNumEcoeffGadgSIBuff, "%5.2lf", e);
- sprintf((char*)NumNumDcoeffGadgSIBuff, "%5.2lf", d);
- sprintf((char*)NumNumCcoeffGadgSIBuff, "%5.2lf", c);
- sprintf((char*)NumNumBcoeffGadgSIBuff, "%5.2lf", b);
- sprintf((char*)NumNumAcoeffGadgSIBuff, "%5.2lf", a);
-
- return;
- }
- /*==========================================================================*/
-
- ShowError(text) /* Show error message in a Window, return on user */
- /* clicking in the OK gadget. Text string must not */
- /* exceed Window's width minus two characters. */
- /* Window is used and not a requester so it is in front */
- /* of coeffs window & GZZ Border of main Window */
- char *text; /* The message to be displayed */
- {
- struct Message * GetMsg();
- void ReplyMsg();
- struct IntuiMessage *message;
- int gadgetid;
- struct Window *ErrWindow, *OpenWindow();
-
- #define TEXTCOLOR 3 /* Text color for message and "OK" */
- #define BGCOLOR 14 /* Color for Window and Gadget background */
- #define GADGBDRCOLOR 3 /* Color for border of "OK" Gadget */
- #define BDRCOLOR 3 /* Color for border of Error-window */
-
- /*** Initialize Error-window structures */
-
- static struct IntuiText OKGadgetMsg = {
- TEXTCOLOR, BGCOLOR, /* FrontPen, BackPen */
- JAM1, /* DrawMode */
- 4,3, /* LeftEdge, TopEdge */
- NULL, /* ITextFont */
- (UBYTE*)"OK", /* IText */
- NULL /* NextText */
- };
-
- static SHORT OKGadgetCoord[18] = { 0,0, 23,0, 23,12, 0,12, 0,0,
- 24,0, 24,12, -1,12, -1,0 };
- /* NOTE: Second line above gives 2-pixel-wide border for hires screen */
-
- static struct Border OKGadgetBdr = {
- 0,0, /* LeftEdge, TopEdge */
- GADGBDRCOLOR, BGCOLOR, JAM1, /* FrontPen, BackPen, DrawMode */
- 9, /* Count */
- &OKGadgetCoord[0], /* XY */
- NULL /* NextBorder */
- };
-
- static struct Gadget OKGadget = {
- NULL, /* NextGadget */
- -40,35,24,13, /* LeftEdge, TopEdge, Width, Height */
- GADGHCOMP | GRELRIGHT, /* Flags */
- ENDGADGET |
- RELVERIFY, /* Activation */
- BOOLGADGET, /* GadgetType */
- (APTR)&OKGadgetBdr, /* GadgetRender */
- NULL, /* SelectRender */
- &OKGadgetMsg, /* GadgetText */
- 0, /* MutualExclude */
- NULL, /* SpecialInfo */
- 99, /* GadgetID */
- NULL /* UserData */
- };
-
- static SHORT BdrCoords[10] = { 2,2, 0,2, 0,57, 2,57, 2,2 };
- /* 0's to be replaced later */
- static struct Border Bdr = {
- 0, 0, /* LeftEdge, TopEdge */
- BDRCOLOR, BGCOLOR, JAM1, /* FrontPen, BackPen, DrawMode */
- 5, /* Count */
- &BdrCoords[0], /* XY */
- NULL /* NextBorder */
- };
-
- static struct IntuiText ErrText = {
- TEXTCOLOR, BGCOLOR, JAM1, /* FrontPen, BackPen, DrawMode */
- 8, 18, /* LeftEdge, TopEdge */
- NULL, /* ITextFont */
- NULL, /* IText -- Will be filled later */
- NULL, /* NextText */
- };
-
- static struct Image ErrWinBgnd = { /* Just a filled rectangle */
- 0, 0, /* LeftEdge, TopEdge */
- 0, 60, 0, /* Width,Height, Depth */
- NULL, /* ImageData */
- 0x0, 0xE, /* PlanePick, PlaneOnOff */
- NULL /* NextImage */
- };
-
- static struct NewWindow ErrNewWindow = {
- 0,60, /* window XY origin relative to TopLeft of screen */
- 0,60, /* window width and height */
- TEXTCOLOR,BDRCOLOR, /* detail and block pens */
- GADGETUP, /* IDCMP flags */
- ACTIVATE|SIMPLE_REFRESH|BORDERLESS, /* other window flags */
- &OKGadget, /* first gadget in gadget list */
- NULL, /* custom CHECKMARK imagery */
- NULL, /* window title */
- NULL, /* custom screen pointer */
- NULL, /* custom bitmap */
- 5,5, /* minimum width and height */
- -1,-1, /* maximum width and height */
- CUSTOMSCREEN /* destination screen type */
- };
-
- /*** Compute and fill in text and window-dependent stuff */
-
- ErrNewWindow.Screen = Screen;
- ErrNewWindow.Width = strlen(text) * 8 + 16;
- if (ErrNewWindow.Width < 44)
- ErrNewWindow.Width = 44;
- ErrWinBgnd.Width = ErrNewWindow.Width;
-
- ErrNewWindow.LeftEdge = (320 - ErrNewWindow.Width)/2;
- if (ErrNewWindow.LeftEdge < 0)
- ErrNewWindow.LeftEdge = 0;
-
- BdrCoords[2] = BdrCoords[4] = ErrNewWindow.Width - 3;
-
- ErrText.IText = (UBYTE*)text;
-
- if (Window->WScreen->Width = 320) /* If Lo-res -- remove vert. double line */
- OKGadgetBdr.Count = 5;
- else
- OKGadgetBdr.Count = 9;
-
- /*** Display the Error-Window */
-
-
- if ((ErrWindow = OpenWindow(&ErrNewWindow)) == NULL) {
- printf("\nCouldn't open Error Message window!!!\n");
- CloseAll();
- }
- DrawImage(ErrWindow->RPort, &ErrWinBgnd, 0L, 0L);
- PrintIText(ErrWindow->RPort, &ErrText, 0L, 0L);
- DrawBorder(ErrWindow->RPort, &Bdr, 0L, 0L);
- RefreshGadgets(&OKGadget, ErrWindow, NULL);
- /* Because DrawImage() obscured the OK Gadget image */
-
- /*** Wait until user clicks the Error-window's "OK" Gadget */
- gadgetid = 9999;
- while (gadgetid != 99) {
- if (message = (struct IntuiMessage *)GetMsg(ErrWindow->UserPort)) {
- gadgetid = ((struct Gadget *)(message->IAddress))->GadgetID;
- ReplyMsg(message);
- }
- }
- CloseWindow(ErrWindow);
- }
- /*===========================================================================*/
-
- OpenImageScreen(width, height, depth) /* Open a Custom screen & window for */
- /* the Image; Set exists_image flag */
- int width, height, depth;
- {
- struct NewScreen ns;
- struct Screen *OpenScreen();
- struct NewWindow nw;
- struct Window *OpenWindow();
- long numcols; /* # of colors in screen */
- UWORD *colortableptr[5]; /* Array of Pointers to screen colortables */
- /* Note: element 0 is not used! */
-
- static UWORD colortable1[] = /*** Colors for 1-bitplane screen */
- {0x000, 0x068, 0x0AF, 0x5CF};
- static UWORD colortable2[] = /*** Colors for 2-bitplane screen */
- {0x000, 0x057, 0x07B, 0xAF};
- static UWORD colortable3[] = /*** Colors for 3-bitplane screen */
- {0x000, 0x034, 0x046, 0x068, 0x06A, 0x08C, 0x09E, 0x0AF};
- static UWORD colortable4[] = /*** Colors for 4-bitplane screen */
- {0x000, 0x011, 0x012, 0x023, 0x034, 0x045, 0x046, 0x057,
- 0x068, 0x069, 0x06A, 0x07B, 0x08C, 0x08D, 0x09E, 0x0AF};
-
- colortableptr[1] = colortable1;
- colortableptr[2] = colortable2;
- colortableptr[3] = colortable3;
- colortableptr[4] = colortable4;
-
- ns.LeftEdge = 0; /*** Initialize NewScreen structure */
- ns.TopEdge = 0;
- ns.Width = width;
- ns.Height = height;
- ns.Depth = (depth == 1) ? 2 : depth;
- ns.DetailPen = 3; /* Colour of text in screen title bar */
- ns.BlockPen = 1; /* Colour of screen Title Bar */
- ns.ViewModes = ((width == 640) ? HIRES:0) | ((height == 400) ? INTERLACE:0);
- ns.Type = CUSTOMSCREEN;
- ns.Font = &TOPAZ80;
- ns.DefaultTitle = (UBYTE*)" Click in screen to stop rendering";
- ns.Gadgets = NULL;
- ns.CustomBitMap = NULL;
-
- switch (depth) { /* Customize Image Title and Border colors to depth */
- case (1):
- ns.DetailPen = 3;
- ns.BlockPen = 1;
- break;
- case (2):
- ns.DetailPen = 3;
- ns.BlockPen = 1;
- break;
- case (3):
- ns.DetailPen = 7;
- ns.BlockPen = 3;
- break;
- case (4):
- ns.DetailPen = 15;
- ns.BlockPen = 7;
- break;
- }
-
- nw.LeftEdge = 0; /*** Initialize NewWindow structure */
- nw.TopEdge = 0;
- nw.Width = width;
- nw.Height = height;
- nw.DetailPen = ns.DetailPen; /* Title text color */
- nw.BlockPen = ns.BlockPen; /* Title bar background */
- nw.IDCMPFlags = MOUSEBUTTONS;
- nw.Flags = ACTIVATE|GIMMEZEROZERO|SIMPLE_REFRESH|BACKDROP;
- nw.FirstGadget = NULL;
- nw.CheckMark = NULL;
- nw.Title = (UBYTE*)" "; /* Never seen - stays behind screen title bar */
- nw.Screen = NULL; /* Will set it to ImageScreen after the screen is opened */
- nw.BitMap = NULL;
- nw.MinWidth = 0;
- nw.MinHeight = 0;
- nw.MaxWidth = 0;
- nw.MaxHeight = 0;
- nw.Type = CUSTOMSCREEN;
-
- /*** Open the screen */
- if ((ImageScreen = (struct Screen *) OpenScreen(&ns)) == NULL) {
- ShowError("Couldn't open Image screen!");
- return;
- }
-
- /* Link Custom colours defined above to screen's ViewPort */
- numcols = 1 << ns.Depth;
- LoadRGB4(&(ImageScreen->ViewPort), colortableptr[depth], numcols);
-
- /*** Open the Window */
- nw.Screen = ImageScreen;
- if ((ImageWindow = (struct Window *) OpenWindow(&nw)) == NULL) {
- CloseScreen(ImageScreen);
- ShowError("Couldn't open Image window!");
- return;
- }
- SetWindowTitles(ImageWindow,-1L,
- (char *)" Click in screen to stop rendering");
- exists_image = 1;
- }
- /*===========================================================================*/
-
- CloseImageScreen() /* Close image screen & Window, reset exists_image flag */
- {
- struct Message * GetMsg();
- void ReplyMsg();
- struct IntuiMessage *message;
-
- /* Empty ImageWindow IDCMP queue if any */
- while (message = (struct IntuiMessage *)GetMsg(ImageWindow->UserPort))
- ReplyMsg(message);
-
- CloseWindow(ImageWindow);
- CloseScreen(ImageScreen);
- exists_image = 0;
- }
- /*===========================================================================*/
-
- DoDemo() /* Demonstrate IFS process, then NEW and return */
- {
- if (SetMode(OUTLINE) == 1) {
- SetRast(r, 0L);
- exists_outline = 0;
- }
- else /* User clicked CANCEL in IFS WILL BE LOST requester - Abort demo */
- return;
- ModifyIDCMP(Window, NULL); /* Disable Editor Window IDCMP during Demo */
- ClearMenuStrip(Window); /* remove main window menus during demo */
- AboutText(DEMOTEXT); /* Show explanation of demo in text screen */
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
-
- /* Draw outline of Sierpinski Triangle */
- SetDrMd(r, JAM1);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Move(r, 138L, 24L);
- Draw(r, 24L, 172L);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Draw(r, 238L, 131L);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Draw(r, 138L, 24L);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Move(r, 82L, 98L);
- Draw(r, 188L, 77L);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Draw(r, 130L, 152L);
- for (i = 0; i < 100000; i++) ; /* Delay */
- Draw(r, 82L, 98L);
- exists_outline = 1;
- for (i = 0; i < 150000; i++) /* Delay before entering Collage Editor */
- ;
-
- /*** Place 3 Pieces to form Collage */
-
- SetMode(COLLAGE);
- for (i = 0; i < 100000; i++) ; /* Delay */
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- AddDefPiece();
- DrawCollage();
- pieceptr[0]->e = 0.25;
- pieceptr[0]->f = 0.045;
- pieceptr[0]->dens = 1.0;
- ComputeBoxCorners(pieceptr[0]);
- ComputeProbs();
- for (i = 0; i < 100000; i++) ; /* Delay */
- TransformPiece(outlinebufptr, pieceptr[0]->piecemap, pieceptr[0]);
- DrawCollage();
-
- for (i = 0; i < 100000; i++) ; /* Delay */
- AddDefPiece();
- DrawCollage();
- pieceptr[1]->e = 0.045;
- pieceptr[1]->f = 0.315;
- pieceptr[1]->dens = 0.4;
- ComputeBoxCorners(pieceptr[1]);
- ComputeProbs();
- for (i = 0; i < 100000; i++) ; /* Delay */
- TransformPiece(outlinebufptr, pieceptr[1]->piecemap, pieceptr[1]);
- DrawCollage();
-
- for (i = 0; i < 100000; i++) ; /* Delay */
- AddDefPiece();
- DrawCollage();
- pieceptr[2]->e = 0.43;
- pieceptr[2]->f = 0.24;
- pieceptr[2]->dens = 0.7;
- ComputeBoxCorners(pieceptr[2]);
- ComputeProbs();
- for (i = 0; i < 100000; i++) ; /* Delay */
- TransformPiece(outlinebufptr, pieceptr[2]->piecemap, pieceptr[2]);
- DrawCollage();
-
- for (i = 0; i < 300000; i++) /* Delay before rendering */
- ;
- RenderImage(0); /* Render, until user clicks in image screen */
-
- /*** After rendering ended, do a NEW (without IFS WILL BE LOST requester) */
- ClearIFS();
- RemoveGList(Window, &CollageGadgetList2, 6L);
- AddGList(Window, &GadgetList1, 0L, 6L, NULL); /* change gadgets */
- SetDrMd(scrp, JAM1);
- SetAPen(scrp, 0L);
- RectFill(scrp, 280L, 12L, 316L, 117L); /* Blot out old gadget images */
- RefreshGadgets(&GadgetList1, Window, NULL);
- OffMenu(Window, NOITEM<<5 | 2); /* disable render menu and its items */
- SetWindowTitles(Window, -1L, " Outline Editor");
- drawmode = FREEHAND;
- HiliteGadget(0);
- SetAPen(r, 2L);
- SetRast(r, 0L);
- exists_outline = 0;
- CloseImageScreen();
- ModifyIDCMP(Window, MOUSEBUTTONS|GADGETUP|MENUPICK); /* Restore IDCMP */
- SetMenuStrip(Window, &MenuList1); /* Restore menu strip */
- }
- /*===========================================================================*/
-
- ComputeBoxCorners(pcptr) /* Compute Vector Box corners from Piece coeffs */
- struct piece *pcptr;
- {
- pcptr->boxo.x = pcptr->e * GZZWIDTH;
- pcptr->boxo.y = pcptr->f * GZZWIDTH; /* sic! */
- pcptr->boxx.x = (pcptr->a + pcptr->e) * GZZWIDTH;
- pcptr->boxx.y = (pcptr->c + pcptr->f) * GZZWIDTH;
- pcptr->boxy.x = (pcptr->b*GZZHEIGHT/GZZWIDTH + pcptr->e) * GZZWIDTH;
- pcptr->boxy.y = (pcptr->d*GZZHEIGHT/GZZWIDTH + pcptr->f) * GZZWIDTH;
- pcptr->boxz.x = pcptr->boxy.x + pcptr->boxx.x - pcptr->boxo.x;
- pcptr->boxz.y = pcptr->boxy.y + pcptr->boxx.y - pcptr->boxo.y;
- }
- /*===========================================================================*/
-
- LoadILBM(fnam, dest) /* Load an Image from IFF file; If dest = 1, */
- char *fnam; /* put image and colormap in Image Screen; */
- int dest; /* if dest = 0, put plane 0 of image in Outline */
- {
- struct BitMap picbitmap = {0}; /* Empty BitMap structure to "Fill" */
- ILBMFrame iFrame; /* ILBM Frame to be used by Reader Routines */
- LONG file; /* File handle [we use AmigaDOS Open(), not Manx open()] */
- LONG iffp;
- char *blitbuffer; /* Needed for the Blit operation only */
- struct BitMap tmpbitmap; /* used for 2-step blit to Outline */
-
- #define MIN(a,b) ((a)<(b)?(a):(b))
-
- /* Open the File to read */
- if ((file = Open(fnam, MODE_OLDFILE)) == NULL) {
- ShowError("Can't open file!");
- return;
- }
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
-
- /* Use EA IFF routine ReadPicture() to Read image from ILBM file into */
- /* memory, modify picbitmap accordingly */
-
- iffp = ReadPicture(file,&picbitmap,&iFrame,ChipAlloc);
-
- Close(file);
-
- if (iffp != IFF_DONE) { /* React to error message from EA routine, if any */
- ShowError(IFFPMessages[-iffp]);
- if (picbitmap.Planes[0]) /* free planes allocated by ReadPicture, if any */
- RemFree(picbitmap.Planes[0]);
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- return;
- }
-
- /*** Now image is in memory; copy it to the proper destination bitmap */
-
- switch (dest) {
-
- case 0: /*** Copy plane 0 of loaded image to Outline (plane 1 in Window) */
-
- SetRast(r, 0L); /* Erase old outline, set drawmode to FREEHAND */
- if(drawmode == ERASE || drawmode == FILL) {
- drawmode = FREEHAND;
- SetAPen(r,2L);
- HiliteGadget(0);
- }
-
- /* NOTE: Must use 2 steps because must blit (possibly part of) loaded */
- /* image of arbitrary size, adjusting for GZZ borders, and from plane 0 */
- /* to plane 1. Neither BltBitMap nor BltTemplate can do this in 1 step */
-
- /* Step 1: Blit plane 0 of loaded image to temp bitmap */
- /* (uses outline buffer as its single bitplane) */
- InitBitMap(&tmpbitmap, 1L, WIDTH, HEIGHT);
- tmpbitmap.Planes[0] = (PLANEPTR)outlinebufptr;
-
- blitbuffer = (char *)AllocMem(80L,MEMF_CHIP); /* Allocate temp buffer */
- BltBitMap(&picbitmap, 0L, 0L, &tmpbitmap, 0L, 0L,
- MIN(WIDTH, picbitmap.BytesPerRow*8L),
- MIN(HEIGHT, picbitmap.Rows), 192L, 0x1, blitbuffer);
- /* 192L is minterm for Direct Copy; 0x1 is mask, will copy plane 0 */
- FreeMem(blitbuffer, 80L);
-
- /* Step 2: Blit the temporary bitplane from Outline Buffer to plane 1 */
- /* of GZZ Window */
-
- SetAPen(r, 2L);
- SetDrMd(r, JAM1);
- SetWrMsk(r,0x0002); /* Write protect all planes except plane 1 */
- BltTemplate((char*)outlinebufptr, 0L, WIDTH/8L, Window->RPort, 0L, 0L,
- MIN(GZZWIDTH, picbitmap.BytesPerRow*8L), MIN(GZZHEIGHT, picbitmap.Rows));
- SetWrMsk(r,0xFFFF);
-
- exists_outline = 1;
- break;
-
- case 1: /*** Set up a (new) Image Screen and blit loaded image into it */
- if (exists_image)
- CloseImageScreen();
- OpenImageScreen(iFrame.bmHdr.pageWidth, iFrame.bmHdr.pageHeight,
- picbitmap.Depth);
-
- /* Link colours read in from file to screen's ViewPort */
- LoadRGB4(&(ImageScreen->ViewPort), iFrame.colorMap, 1<<picbitmap.Depth);
-
- SetWindowTitles(ImageWindow,
- (char *)" ", (char *)" Click in screen to push it back");
- blitbuffer = (char *)AllocMem(80L,MEMF_CHIP); /* Allocate temp buffer */
- BltBitMap(&picbitmap, 2L, 11L, ImageWindow->RPort->BitMap, 2L, 11L,
- MIN(ImageWindow->Width-4L,picbitmap.BytesPerRow*8L-2L),
- MIN(ImageWindow->Height-13L,picbitmap.Rows-11L), 192L, 0xFF, blitbuffer);
- /* 192L is minterm for Direct Copy; 0xFF is mask, will copy all planes */
- /* 2L, 11L, 4L, 13L cause The blit to skip the window borders */
- FreeMem(blitbuffer, 80L);
- exists_image = 1;
- break;
- } /* End switch dest */
-
- if (picbitmap.Planes[0]) /* free planes allocated by ReadPicture, if any */
- RemFree(picbitmap.Planes[0]);
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- }
- /*==========================================================================*/
-
- AboutText(whichtext) /* Opens the text screen and displays in it */
- int whichtext; /* the selected About text or IFS code table */
- /* according to whichtext. Closes on click in screen */
- /* whichtext can be: CODES, IFS_THEORY, HELP1, HELP2, AUTHOR, DEMOTEXT*/
- {
- struct Screen *TextScreen;
- struct Window *TextWindow;
- struct NewScreen ns;
- struct Screen *OpenScreen();
- struct NewWindow nw;
- struct Window *OpenWindow();
- struct Message * GetMsg();
- struct IntuiMessage *message;
- static struct IntuiText RedText = {
- 3, 0, JAM1, /* FrontPen, BackPen, DrawMode */
- 0, 0, /* LeftEdge, TopEdge */
- &TOPAZ80, /* ITextFont */
- (UBYTE*)"Click Mouse to Continue", NULL /* IText, NextText */
- };
- char codelinebuf[78]; /* Buffer for line of codes in CODES display */
- static struct IntuiText CodesText = { /* Codes line for display */
- 1, 0, JAM1, /* FrontPen, BackPen, DrawMode */
- 0, 0, /* LeftEdge, TopEdge */
- &TOPAZ80, /* ITextFont */
- NULL, NULL /* IText, NextText */
- };
-
- /*** Open a window in a custom Hires screen for text display */
-
- ns.LeftEdge = 0; /*** Initialize NewScreen structure */
- ns.TopEdge = 0;
- ns.Width = 640;
- ns.Height = 200;
- ns.Depth = 2;
- ns.DetailPen = 0; /* Colour of text in screen title bar */
- ns.BlockPen = 1; /* Colour of screen Title Bar */
- ns.ViewModes = HIRES;
- ns.Type = CUSTOMSCREEN;
- ns.Font = &TOPAZ80;
- ns.DefaultTitle = NULL;
- ns.Gadgets = NULL;
- ns.CustomBitMap = NULL;
-
- nw.LeftEdge = 0; /*** Initialize NewWindow structure */
- nw.TopEdge = 0;
- nw.Width = 640;
- nw.Height = 200;
- nw.DetailPen = 0; /* Menu title text color */
- nw.BlockPen = 1; /* Menu item box and title bar background */
- nw.IDCMPFlags = MOUSEBUTTONS;
- nw.Flags = ACTIVATE|SIMPLE_REFRESH;
- nw.FirstGadget = NULL;
- nw.CheckMark = NULL;
- nw.Title = (UBYTE*)" ";
- nw.Screen = NULL; /* Will set it to TextScreen after the screen is opened */
- nw.BitMap = NULL;
- nw.MinWidth = 0;
- nw.MinHeight = 0;
- nw.MaxWidth = 0;
- nw.MaxHeight = 0;
- nw.Type = CUSTOMSCREEN;
-
- /*** Open the screen */
- if ((TextScreen = (struct Screen *) OpenScreen(&ns)) == NULL) {
- ShowError("Couldn't open Text screen!!!");
- return;
- }
-
- /*** Open the Window */
- nw.Screen = TextScreen;
- if ((TextWindow = (struct Window *) OpenWindow(&nw)) == NULL) {
- CloseScreen(TextScreen);
- ShowError("Couldn't open Text window!!!");
- return;
- }
- Textrp = (TextWindow->RPort); /* Window's rastport, used by p() */
-
- p(NULL); /* reset screen print routine to top of screen */
- p(" "); /* skip 2 lines to clear text window title bar */
- p(" ");
-
- switch (whichtext) { /**** Print appropreiate text into window */
-
- case IFS_THEORY:
- SetWindowTitles(TextWindow, " IFS Theory Background", -1L);
-
- p(" IFS is a method developed by Michael F. Barnsley that allows one to en\
- code a");
- p(" Fractal as a small set of numbers, the coefficients of an Iterated Funct\
- ion");
- p(" System (IFS) Code, and later to reconstruct it from those numbers. An IF\
- S Code");
- p(" is a set of Contractive Affine Transformations, which are transformation\
- s of");
- p(" the plane that combine a Linear Transformation (consisting of combinatio\
- ns of");
- p(" stretching and rotation) and a Translation of the origin. Each such affi\
- ne");
- p(" transformation can be represented by six real numbers. In addition, with\
- each");
- p(" transformation is associated a probability value.");
- p(" ");
- p(" To derive the IFS Code for a given Fractal image, one must find a set \
- of");
- p(" transformations of the image - reduced, deformed copies of it - that whe\
- n");
- p(" taken together cover the original image. To reconstruct the image, one \
- starts");
- p(" with any point in the plane, picks at random one of the transformations");
- p(" defined above, applies it to the point, and draws the resulting point. T\
- o this");
- p(" new point one applies the same procedure, and so on. The probabilities d\
- efine");
- p(" how often each transformation will be picked. The 'Collage Theorem' assu\
- res");
- p(" that this process will in fact reconstruct the original Fractal.");
- p(" ");
- p(" For more detailed information on the theory and use of IFS, refer to:");
- p(" - Barnsley and Sloan: A Better Way to Compress Images, BYTE, Jan. 88\
- .");
- p(" - Peitgen and Saupe, eds.: The Science of Fractal Images, Chapter 5.");
-
- break;
-
- case HELP1:
- SetWindowTitles(TextWindow, " A Summary of Program Operation", -1L);
-
- p(" This program requires two steps to generate an IFS Code for a Fractal:");
- p(" ");
- p(" a. OUTLINE EDITOR: This step allows you to draw the approximate Outline \
- of");
- p(" the planned Fractal. The user interface is a simple Paint program, with");
- p(" Freestyle, Lines, Erase (XXX), Fill and Clear gadgets. Note that the le\
- ss");
- p(" pixels you draw, the faster things will move later, in the Collage Edit\
- or");
- p(" phase. When your Outline is finished, click DONE to enter the Collage E\
- ditor.");
- p(" ");
- p(" b. COLLAGE EDITOR: Here you create the Collage, by defining the affine");
- p(" transformations ('Pieces') to cover the Outline with. When you enter th\
- is");
- p(" mode, you see your Outline, and one Default transformation - a half-siz\
- ed");
- p(" copy of this Outline, drawn in red. The box around it is the image of t\
- he");
- p(" screen boundary under the transformation. You can modify the Piece by");
- p(" dragging any corner of this box with the mouse. The corner marked 'O' w\
- ill");
- p(" translate the Origin; 'X' and 'Y' will stretch and rotate these axes; T\
- he");
- p(" last corner will enlarge and rotate the Piece without deforming it. Cli\
- ck");
- p(" ADD to add a new Default Piece, or DUP to add a duplicate of the curren\
- t");
- p(" Piece. The Piece drawn in red is the 'Selected' one; all editing action\
- s");
- p(" apply to it. Clicking SEL repeatedly will make one Piece after another \
- the");
- p(" Selected one, allowing you to modify (or delete, by clicking DEL) previ\
- ously");
- p(" defined Pieces.");
-
- break;
-
- case HELP2:
- SetWindowTitles(TextWindow, " A Summary of Program Operation (Continued)",
- -1L);
-
- p(" You can click the NUM gadget to get a numeric display of the Selected");
- p(" transformation's coefficients (a-f, p), as well as the associated Proba\
- bility");
- p(" Density (probability per unit area) and Scalings, Rotations and Transla\
- tions.");
- p(" You can modify any one of these values in their string gadgets, and cli\
- ck");
- p(" ENTER to make the changes take effect. To quit the numeric window, clic\
- k its");
- p(" Close gadget.");
- p(" ");
- p(" When you've covered the Outline fully with Pieces, use the Render men\
- u");
- p(" to generate the Attractor of the IFS in the resolution and gray level c\
- ount");
- p(" of your choice.");
- p(" ");
- p(" The Optimize menu item will modify the current IFS so that its Attrac\
- tor");
- p(" will fill the screen; it will also generate an exact Collage for it, by\
- using");
- p(" the Attractor itself as an Outline.");
- p(" ");
- p(" File I/O menuitems allow you to save the IFS codes or the Image to d\
- isk,");
- p(" to load IFS Codes from files saved by IFSLab and by most other IFS prog\
- rams,");
- p(" and to load any Non-HAM IFF image file into the Image screen or as the");
- p(" Outline.");
- break;
-
- case AUTHOR:
- SetWindowTitles(TextWindow, " Author Information", -1L);
- p(" ");
- p(" ");
- p(" ");
- p(" ");
- p(" IFS Lab written by Nathan Zeldes");
- p(" ");
- p(" ");
- p(" Copyright (C) 1992 by N. Zeldes. All Rights Reserved. ");
- p(" ");
- p(" Thanks to C.W. Fox and Bruce Dawson for the File Requester");
- p(" ");
- p(" ");
- p(" ");
- p(" ");
- p(" ");
- p(" ");
-
- break;
-
- case DEMOTEXT:
- SetWindowTitles(TextWindow, " A Demonstration of IFS in Action", -1L);
-
- p(" ");
- p(" This demo will define and render the Sierpinski Triangle, a well known");
- p(" fractal.");
- p(" ");
- p(" The program will first enter the Outline Editor and draw an Outline of\
- the");
- p(" Sierpinski triangle. After a brief delay it will switch to the Collage E\
- ditor");
- p(" and show how the Outline can be covered by three half-sized copies of it\
- self.");
- p(" When it has built this Collage, the program will initiate rendering of t\
- he");
- p(" fractal. Note that this demo intentionally assigns unequal probabilities\
- to");
- p(" the three transformations, which causes the uneven 'shading' effect in t\
- he");
- p(" rendered image.");
- p(" ");
- p(" To start the demo, click the left mouse button. Do no more until the");
- p(" rendering begins. When you've had your fill of the beauty of the emergin\
- g");
- p(" image, click twice in the Image screen to exit the demo.");
-
- break;
-
- case CODES: /* Display Codes Table */
- SetWindowTitles(TextWindow, " IFS Code Coefficients", -1L);
-
- p(" A B C D E F P Dens S1 S2\
- R1 R2 ");
- if (N < MAX_N)
- p(" ------ ------ ------ ------ ----- ----- ----- ------- ----- -----\
- ----- ----- "); /* The underline is omitted to allow display of 20 pieces */
-
- for(i = 0; i <= N; i++) { /* Put lines of coefficients in text window */
-
- sprintf(codelinebuf, " % 6.3lf % 6.3lf % 6.3lf % 6.3lf %5.3lf %5.3lf\
- %5.3lf %7.3lf% 5.3lf %5.3lf % 4.0lf % 4.0lf", pieceptr[i]->a, pieceptr[i]->b,
- pieceptr[i]->c, pieceptr[i]->d, pieceptr[i]->e, pieceptr[i]->f,
- pieceptr[i]->p, pieceptr[i]->dens, pieceptr[i]->s1, pieceptr[i]->s2,
- pieceptr[i]->r1/0.017453293, pieceptr[i]->r2/0.017453293);
-
- CodesText.FrontPen = (i == selpiece) ? 3 : 1; /* Selected piece in red */
- CodesText.IText = (UBYTE*)codelinebuf;
- CodesText.TopEdge = (N < MAX_N) ? 8L * i + 32L : 8L * i + 24L;
- PrintIText(Textrp, &CodesText, 0L, 0L);
- }
- break;
-
- } /* End switch */
-
- PrintIText(Textrp, &RedText, 450L, 190L); /* 'Click Mouse...' text */
-
- /*** Wait with text displayed, poll IDCMP until you get a SELECTDOWN */
- while (!(message = (struct IntuiMessage *)GetMsg(TextWindow->UserPort)))
- ; /* here any event must be a SELECTDOWN due to IDCMP flag definition */
- ReplyMsg(message);
- while (!(message = (struct IntuiMessage *)GetMsg(TextWindow->UserPort)))
- ; /* get rid of SELECTUP message following the SELECTDOWN */
- ReplyMsg(message);
-
- CloseWindow(TextWindow); /* Close text display and return */
- CloseScreen(TextScreen);
- }
- /*===========================================================================*/
-
- PutDefOutline() /* Place default Outline in Outline Bitmap */
- {
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
- SetDrMd(r, JAM1);
- SetAPen(r, 2L);
- SetOPen(r, 2L);
- SetWrMsk(r,0x0002); /* Write protect all planes except plane 1 */
- SetRast(r, 0L);
-
- DrawCircle(r, 138L, 93L, 22L); /* Face outline */
- DrawCircle(r, 138L, 93L, 13L); /* To become mouth outline */
- SetAPen(r, 0L);
- SetOPen(r, 0L);
- RectFill(r, 124L, 80L, 152L, 100L); /* Blot out top part of mouth circle */
- SetAPen(r, 2L);
- SetOPen(r, 2L);
- DrawCircle(r, 129L, 85L, 3L); /* Left Eye */
- DrawCircle(r, 147L, 85L, 3L); /* Right Eye */
-
- exists_outline = 1;
- SetWrMsk(r,0xFFFF);
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- }
- /*===========================================================================*/
-
- TransformPiece(source, dest, pc) /* Apply transformation of Piece */
- /* To image in source bitplane, put result in dest piecemap. */
- /* Return 1 if done OK, return 0 if a pixel overflowed plane boudary. */
- /* Any overflow pixels are not put into the destination piecemap. */
- /* Skips title bar and borders of source bitplane properly. */
- /* Replaces doubles with scaled-up integers for speed. */
-
- UBYTE *source; /* Pointer to 1st byte in a single Window-sized Bitplane */
- UBYTE *dest; /* Pointer to first byte in target piecemap */
- struct piece *pc; /* pointer to piece structure containing trans' coeffs */
- {
- #define LEFTBDRBITS 4 /* Width in BITS of left border of Window */
- #define TOPBDRBYTES 440 /* bytes within Top Border of Window */
- #define RIGHTBDRBYTES 5 /* bytes within right Border (must be integral) */
- #define MAPROWBYTES 35 /* Number of bytes in a net row of piecemap */
- #define MAPROWBYTESPLUS 40 /* Number of bytes in a gross row of piecemap */
- #define PIECEMAPWIDTH GZZWIDTH+Window->BorderLeft
-
- UBYTE *srcbyte; /* address of current byte in source bitplane */
- int bitpos; /* bit position in byte (leftmost bit = 0) */
- int rowbyte; /* number of current source byte within row */
- int srcx, srcy, destx, desty; /* Source and destination pixel X-Y coords */
- long ai, bi, ci, di, ei, fi; /* Scaled integer transformation coefficients */
- long lbdri; /* Scaled LEFTBDRBITS */
- int overflowflag = 0;
-
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
- /* Erase piecemap */
- BltClear((char*)dest, (long)RASSIZE(WIDTH,GZZHEIGHT), 1L);
-
- /*** Convert coefficients to scaled integers */
-
- ai = (long)(pc->a * 1000000);
- bi = (long)(pc->b * 1000000);
- ci = (long)(pc->c * 1000000);
- di = (long)(pc->d * 1000000);
- ei = (long)(pc->e * 1000000 * GZZWIDTH);
- fi = (long)(pc->f * 1000000 * GZZWIDTH);
- lbdri = (long)(LEFTBDRBITS * 1000000);
-
- srcbyte = source + TOPBDRBYTES; /* Initialize srcbyte to after Top Border */
-
- for (srcy = 0; srcy < GZZHEIGHT; srcy++) { /* Loop on source plane rows */
- /* Loop on bytes in source row - up to right border only */
- for (rowbyte = 0; rowbyte < MAPROWBYTES; rowbyte++) {
-
- if (*srcbyte != 0) { /* If Source byte not empty */
-
- for(bitpos = 0; bitpos < 8; bitpos++) { /* loop on bits in byte */
- if ((*srcbyte & (128>>bitpos)) != 0) { /* current src pixel is '1' */
-
- srcx = rowbyte * 8 + bitpos - LEFTBDRBITS;
-
- /* do transformation */
- destx = (ai * srcx + bi * srcy + ei + lbdri) / 1000000;
- desty = (ci * srcx + di * srcy + fi) / 1000000;
-
- if(destx < LEFTBDRBITS || destx >= PIECEMAPWIDTH ||
- desty < 0 || desty >= GZZHEIGHT) /* Don't write transformed */
- overflowflag = 1; /* pixel to dest - it is outside bitplane! */
- else
- /* write '1' pixel to destination. Expression to left of |= */
- /* is destination byte address; 128>>bitpos is the bitmask. */
- *( dest + desty*MAPROWBYTESPLUS + destx/8 ) |= 128>>(destx % 8);
- } /* End if current source pixel is '1' */
- } /* End loop on bits in byte */
- } /* End If source byte not empty */
- srcbyte++;
- } /* End loop on bytes in source row */
- srcbyte += RIGHTBDRBYTES; /* skip right border */
- } /* End loop on source rows */
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- return(!overflowflag);
- }
- /*===========================================================================*/
-
- SaveIFS() /* Save IFS coefficients, if any, to a disk file */
- {
- FILE *fopen(), *fp;
- char *fnam, *p;
- char *GetFileName();
- int strcmp();
- char *strcat();
- long k;
-
- if (drawmode != VECTOR) {
- ShowError("No IFS to Save!");
- return;
- }
- /*** Open disk file,deleting prev rev if any; if error, exit function */
-
- fnam = GetFileName("Save to File:");
- if (*fnam == '\0') {
- return; /* do nothing - user selected CANCEL or no filename */
- }
-
- k = 0; /* Set k to 1 if filename ends with .ifs */
- for (p = fnam; *p != '\0'; p++)
- if (strcmp(p, ".ifs") == 0)
- k = 1;
- if (k == 0) /* Add .ifs to filename if needed */
- strcat(fnam, ".ifs");
-
- if ((fp = fopen(fnam, "w")) == NULL) {
- ShowError(" Cannot open file!!!");
- return;
- }
-
- /*** Save the current IFS codes to a disk file */
-
- fprintf(fp, " A B C D E F P Dens S1\
- S2 R1 R2\n");
- for(i = 0; i <= N; i++)
- fprintf(fp, " % 6.3lf % 6.3lf % 6.3lf % 6.3lf %5.3lf %5.3lf\
- %5.3lf %7.3lf% 5.3lf %5.3lf % 4.0lf % 4.0lf\n", pieceptr[i]->a,
- pieceptr[i]->b, pieceptr[i]->c, pieceptr[i]->d, pieceptr[i]->e,
- pieceptr[i]->f, pieceptr[i]->p, pieceptr[i]->dens, pieceptr[i]->s1,
- pieceptr[i]->s2, pieceptr[i]->r1/0.017453293,
- pieceptr[i]->r2/0.017453293);
-
- fclose(fp); /* close disk file */
- }
- /*===========================================================================*/
-
- int LoadIFS(fnam) /* Load IFS Code variables from disk file */
- char *fnam; /* Returns 1 if done OK, 0 if failed to load */
- /* Skips lines of wrong form (e.g. text headers) */
- /* and ignores excess info on a line (e.g. Geom. Coeffs) */
- /* Calls Optimize() to create a Collage and assure */
- { /* Attractor will not overflow window */
- FILE *fopen(), *fp;
- int c, eofread, scan;
- char linebuf[161]; /* Input lines will be truncated after 160 chars */
- double mindens;
- long xmin, xmax, ymin, ymax;
- /* GZZ PIXEL coords of boundary rect of old (as-loaded) attractor*/
- int j;
-
- /*** Open disk file for reading */
- if ((fp = fopen(fnam,"r")) == NULL) {
- ShowError(" Cannot open file!!!");
- return(0);
- }
-
- ClearIFS(); /* Erase old IFS (if any), set N to -1 */
-
- /*** Load the IFS codes line by line */
-
- eofread = 0;
- while (N < MAX_N && !eofread) { /* Loop on lines in file */
-
- if ((pieceptr[++N] = AllocPiece()) == NULL) { /* Allocate Piece */
- N--; /* if couldn't allocate piece */
- ShowError("Couldn't allocate memory!");
- if (N == -1) { /* No memory for even one Piece - Quit program */
- ShowError("Re-run with more free memory!");
- CloseAll();
- }
- ShowError(" Aborting Load! ");
- fclose(fp);
- return(0);
- }
-
- /*** Read in a single line from file into memory, then sscanf it */
- /* (Don't use fscanf from file because it ignores end of line */
- for (i = 0; i < 160 && (c = getc(fp)) != EOF && c != '\n'; i++)
- linebuf[i] = c;
- linebuf[i] = '\0';
- if (c != EOF && c != '\n') /* Line has been truncated after 160 chars */
- while ((c = getc(fp)) != '\n' && c != EOF)
- ; /* Remove any other stuff on the file line */
- if (c == EOF)
- eofread = 1;
-
- /* Now a null-terminated line is in linebuf & the file is positioned at */
- /* start of next file line or past EOF;eofread is set if EOF was reached */
-
- scan = sscanf(linebuf, "%lf %lf %lf %lf %lf %lf %lf", &pieceptr[N]->a,
- &pieceptr[N]->b, &pieceptr[N]->c, &pieceptr[N]->d, &pieceptr[N]->e,
- &pieceptr[N]->f, &pieceptr[N]->p);
-
- if (scan == 7) { /* converted successfully 7 coeffs of one IFS */
-
- /*** Check that coefficients a - d and p are in legal ranges */
- if (pieceptr[N]->a < -1. || pieceptr[N]->a > 1. || pieceptr[N]->b < -1.||
- pieceptr[N]->b > 1. || pieceptr[N]->c < -1. || pieceptr[N]->c > 1. ||
- pieceptr[N]->d < -1. || pieceptr[N]->d > 1. ||
- pieceptr[N]->p <= 0. || pieceptr[N]->p > 1.) {
- ShowError("Coefficient out of Range!");
- ShowError(" Aborting Load! ");
- fclose(fp);
- return(0);
- }
-
- /*** compute the geometrical coeffs from matrix coeffs read from file */
- pieceptr[N]->s1 = sqrt(pieceptr[N]->a*pieceptr[N]->a +
- pieceptr[N]->c*pieceptr[N]->c);
- pieceptr[N]->s2 = sqrt(pieceptr[N]->b*pieceptr[N]->b +
- pieceptr[N]->d*pieceptr[N]->d);
- pieceptr[N]->r1 = myatan2(pieceptr[N]->c, pieceptr[N]->a);
- pieceptr[N]->r2 = myatan2(-pieceptr[N]->b, pieceptr[N]->d);
- pieceptr[N]->det = fabs(pieceptr[N]->a * pieceptr[N]->d -
- pieceptr[N]->b * pieceptr[N]->c);
- if (pieceptr[N]->det == 0.0)
- pieceptr[N]->det = 0.01;
- pieceptr[N]->dens = pieceptr[N]->p / pieceptr[N]->det;
-
- /*** Compute new Box corners from new coeffs */
- pieceptr[N]->boxo.x = pieceptr[N]->e * GZZWIDTH;
- pieceptr[N]->boxo.y = pieceptr[N]->f * GZZWIDTH; /* sic! */
- pieceptr[N]->boxx.x = (pieceptr[N]->a + pieceptr[N]->e) * GZZWIDTH;
- pieceptr[N]->boxx.y = (pieceptr[N]->c + pieceptr[N]->f) * GZZWIDTH;
- pieceptr[N]->boxy.x = (pieceptr[N]->b * GZZHEIGHT/GZZWIDTH +
- pieceptr[N]->e) * GZZWIDTH;
- pieceptr[N]->boxy.y = (pieceptr[N]->d * GZZHEIGHT/GZZWIDTH +
- pieceptr[N]->f) * GZZWIDTH;
- pieceptr[N]->boxz.x = pieceptr[N]->boxy.x + pieceptr[N]->boxx.x -
- pieceptr[N]->boxo.x;
- pieceptr[N]->boxz.y = pieceptr[N]->boxy.y + pieceptr[N]->boxx.y -
- pieceptr[N]->boxo.y;
- }
-
- else /* scanf failed to match 7 doubles on line - skip it! */
- FreePiece(pieceptr[N--]);
-
- } /* End while loop on lines */
-
- selpiece = N;
-
- if (N == MAX_N && !eofread && getc(fp) != EOF) /* Exited loop at N==MAX_N */
- ShowError("File too long; IFS may be truncated");
-
- if (N == -1) { /* Not a single transformation was found! */
- ShowError("No IFS found in File - Aborting Load!");
- fclose(fp);
- return(0);
- }
-
- /*** If probabilities read from file were cumulative, convert to non-cum */
- if (pieceptr[N]->p == 1.000) {
- for (i = N; i > 0; i--) {
- pieceptr[i]->p = pieceptr[i]->p - pieceptr[i-1]->p;
- pieceptr[i]->dens = pieceptr[i]->p / pieceptr[i]->det;
- }
- }
-
- /*** Normalize Piece densities so smallest one is 1.000 */
- mindens = 1000000.;
- for (i = 0; i <= N; i++)
- if (pieceptr[i]->dens < mindens)
- mindens = pieceptr[i]->dens;
- for (i = 0; i <= N; i++)
- pieceptr[i]->dens /= mindens;
-
- ComputeProbs(); /* Adjust all probabilities in case rounding errors in */
- /* file made their sum != 1.000 */
-
- fclose(fp); /* close disk file */
-
- /* Transform loaded IFS to fit in window if it exceeds it, */
- /* and generate Collage */
- Optimize(0);
-
- return(1);
- }
- /*===========================================================================*/
- int Optimize(mode) /* Creates an Outline from current Attractor, creates */
- int mode; /* a Collage from it and displays it. If mode==1, also */
- /* modifies the IFS so its attractor fills the window. */
- /* If mode==0, does this only if current Attractor would */
- /* overflow the window. */
- /* Returns 1 if successful and 0 if it failed (because */
- { /* not in Collage Editor) and no modifications were done.*/
- long xmin, xmax, ymin, ymax; /* GZZ PIXEL coords of old boundary rect */
- int px1, py1; /* GZZ PIXEL coords of Topleft corner of new boundary rect */
- double x0,y0; /* REAL plane coords of Topleft corner of old boundary rect */
- double x1,y1; /* REAL plane coords of Topleft corner of new boundary rect */
- double m; /* Magnification to apply to attractor so it fills window */
- double attrw, attrh; /* PIXEL Width & Height of old boundary rect */
- struct piece tmppiece; /* will be used to hold temporary trans' coeffs */
- int j;
-
- if (drawmode != VECTOR) { /* Abort if not in Collage Editor! */
- ShowError("No IFS!");
- return(0);
- }
-
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
-
- SetRast(r, 0L); /* Erase Old Outline and Collage */
-
- FindBoundary(&xmin, &xmax, &ymin, &ymax); /* Identify old boundary rect */
-
- /*** If mode is 1, or mode is 0 but attractor exceeds window, modify IFS ***/
-
- if (mode==1 || xmin<0 || xmax >= GZZWIDTH || ymin<0 || ymax >= GZZHEIGHT) {
- /*** Compute required magnification and relocation of attractor */
-
- attrw = (double)((xmax - xmin) + 1);
- attrh = (double)((ymax - ymin) + 1);
-
- if ((double)attrw/(double)attrh >= (double)GZZWIDTH/(double)GZZHEIGHT) {
- m = 0.95 * (double)GZZWIDTH / attrw;
- px1 = 0.025 * (double)GZZWIDTH;
- py1 = 0.025 * (double)GZZHEIGHT +
- (0.95 * (double)GZZHEIGHT - m * attrh) / 2.0;
- }
- else {
- m = 0.95 * (double)GZZHEIGHT / attrh;
- px1 = 0.025 * (double)GZZWIDTH +
- (0.95 * (double)GZZWIDTH - m * attrw) / 2.0;
- py1 = 0.025 * (double)GZZHEIGHT;
- }
- x0 = (double)xmin / (double)GZZWIDTH;
- y0 = (double)ymin / (double)GZZWIDTH;
- x1 = (double)px1 / (double)GZZWIDTH;
- y1 = (double)py1 / (double)GZZWIDTH;
-
- /*** Modify all piece coefficients to make new attractor fill window */
-
- for (i = 0; i <= N; i++) { /* Loop on pieces */
- pieceptr[i]->e = m * pieceptr[i]->e +
- (pieceptr[i]->a - 1) * (m * x0 - x1) + pieceptr[i]->b * (m * y0 - y1);
- pieceptr[i]->f = m * pieceptr[i]->f +
- pieceptr[i]->c * (m * x0 - x1) + (pieceptr[i]->d - 1) * (m * y0 - y1);
-
- /*** Recompute new Box corners from new coeffs */
- pieceptr[i]->boxo.x = pieceptr[i]->e * GZZWIDTH;
- pieceptr[i]->boxo.y = pieceptr[i]->f * GZZWIDTH; /* sic! */
- pieceptr[i]->boxx.x = (pieceptr[i]->a + pieceptr[i]->e) * GZZWIDTH;
- pieceptr[i]->boxx.y = (pieceptr[i]->c + pieceptr[i]->f) * GZZWIDTH;
- pieceptr[i]->boxy.x = (pieceptr[i]->b * GZZHEIGHT/GZZWIDTH +
- pieceptr[i]->e) * GZZWIDTH;
- pieceptr[i]->boxy.y = (pieceptr[i]->d * GZZHEIGHT/GZZWIDTH +
- pieceptr[i]->f) * GZZWIDTH;
- pieceptr[i]->boxz.x = pieceptr[i]->boxy.x + pieceptr[i]->boxx.x -
- pieceptr[i]->boxo.x;
- pieceptr[i]->boxz.y = pieceptr[i]->boxy.y + pieceptr[i]->boxx.y -
- pieceptr[i]->boxo.y;
- } /* End loop on pieces */
- } /* End if mode==1... */
-
- RenderImage(1); /* Render new attractor in OUTLINE Bitplane */
- CopyMem((char*)Window->RPort->BitMap->Planes[1],
- (char*)outlinebufptr, (long)RASSIZE(WIDTH,HEIGHT));
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
-
- /*** Transform the new Outline (=attractor) into all pieces' piecemaps */
- /*** Draw each piece into the collage as you go */
-
- selpiece = N;
- for (i = 0; i <= N-1; i++) { /* Loop on deselected pieces */
-
- TransformPiece(outlinebufptr, pieceptr[i]->piecemap, pieceptr[i]);
-
- /* Blit this piece from its piecemap to plane 0 */
- SetWrMsk(r,0x0001); /* Write protect all planes except plane 0 */
- SetAPen(r, 1L);
- BltTemplate((char*)pieceptr[i]->piecemap,(long)Window->BorderLeft,
- (long)WIDTH/8, r, 0L, 0L, (long)GZZWIDTH, (long)GZZHEIGHT);
- }
-
- /* Now transform Selected Piece & Blit it from piecemap to plane 2 */
- TransformPiece(outlinebufptr, pieceptr[i]->piecemap, pieceptr[i]);
- SetWrMsk(r,0x0004); /* Write protect all planes except plane 2 */
- SetAPen(r, 4L);
- BltTemplate((char*)pieceptr[selpiece]->piecemap,(long)Window->BorderLeft,
- (long)WIDTH/8, r, 0L, 0L, (long)GZZWIDTH, (long)GZZHEIGHT);
-
- DrawBox(); /* Draw Vector Box of Selected Piece */
- /* Note that Rastport's WrMask is restored within DrawBox() */
-
- return(1);
- }
- /*===========================================================================*/
-
- RenderImage(z) /* If z == 0, Render the Attractor in Image Screen at current */
- int z; /* resolution & depth settings; stop and return on click in Image */
- /* screen. If z == 1, render it in Outline bitplane. */
- /* Probabilities and coefficients are scaled to integers so can use */
- /* faster integer math */
- {
- struct Message * GetMsg();
- struct IntuiMessage *message;
- int randprob; /* Random probability value */
- double sum; /* cum probability */
- int k;
- long unitwidth, unitheight;
- /* width, height in image screen pixels of unit square in the plane */
- long iter; /* Iteration counter */
- struct RastPort *imagerp; /* Pointer to rastport of Image window */
- long pix; /* Color (Pen #) of a pixel */
- long ReadPixel();
- long ai[MAX_N+1], bi[MAX_N+1], ci[MAX_N+1],
- di[MAX_N+1], ei[MAX_N+1], fi[MAX_N+1]; /* Scaled integer coefficients */
- long xi, yi, tmpxi; /* Scaled integer pixel coordinates */
- int cumprobi[MAX_N+2]; /* Scaled integer Cum Probabilities */
- /* cumprobi array has MAX_N+2 elements because using MAX_N+1 caused a */
- /* Crash for unclear reasons ?!?! */
-
- /*** Prepare stuff for iteration loop ***/
-
- if (z == 0) { /* Rendering is in Image Screen */
- /*** Open Image Window in its screen (Closing any previous image screen) */
- if (exists_image)
- CloseImageScreen();
- OpenImageScreen(renderwidth, renderheight, renderdepth);
- /* OpenImageScreen() also opens ImageWindow */
- imagerp = ImageWindow->RPort;
- SetAPen(imagerp,2L); /* Will be modified in loop for Greyscale rendering */
- SetDrMd(imagerp, JAM1);
-
- SetWindowTitles(ImageWindow, -1L,
- (char *)" Click in screen to stop rendering");
-
- unitwidth = GZZWIDTH*(renderwidth/320); /* GZZWIDTH is of Collage window!*/
- unitheight = GZZWIDTH * (renderheight/200);
-
- }
- else { /* Rendering in Outline plane */
- SetWrMsk(r, 0x0002); /* Write protect all planes except plane 1 */
- SetAPen(r, 2L);
- SetDrMd(r, JAM1);
-
- unitwidth = unitheight = GZZWIDTH;
- }
-
- srand((unsigned int)(time(NULL)%10000L)); /* seed random gen from sys time*/
-
- sum = 0;
- for (k = 0; k <= N; k++) { /* Scale Coefficients as longs */
- ai[k] = (long)(pieceptr[k]->a * 1000000);
- bi[k] = (long)(pieceptr[k]->b * 1000000);
- ci[k] = (long)(pieceptr[k]->c * 1000000);
- di[k] = (long)(pieceptr[k]->d * 1000000);
- ei[k] = (long)(pieceptr[k]->e * 1000000 * unitwidth);
- fi[k] = (long)(pieceptr[k]->f * 1000000 * unitwidth);
-
- sum = sum + pieceptr[k]->p; /* Compute scaled Cum Probabilities */
- cumprobi[k] = (int)(sum * (double)RAND_MAX);
- }
-
- xi = unitwidth / 3; /* Initial coordinates */
- yi = unitwidth / 3;
-
- /*** Iterate until user clicks in Image window or until 1000 points ***/
- /*** (depending on z) ***/
-
- for (iter = 0; 1; iter++) { /* endless loop */
-
- /*** Select a Piece at random */
- randprob = rand();
- /* rand() returns a random # (between 0 - RAND_MAX) */
- for (k = 0; cumprobi[k] < randprob; k++) {
- /* the following IF is to trap problem case when randprob = RAND_MAX */
- /* exactly and cum probability is RAND_MAX minus slight delta due to */
- /* rounding errors */
- if (k > N) {
- k--;
- break;
- }
- }
-
- /* Apply transformation #k to previous (x,y) */
- tmpxi = (ai[k] * xi + bi[k] * yi + ei[k]) / 1000000;
- yi = (ci[k] * xi + di[k] * yi + fi[k]) / 1000000;
- xi = tmpxi;
-
- if (iter > 19) { /* Render the pixel (except 1st 20 points) */
-
- if (z == 0) { /*** draw in Image Screen, quit on mouseclick in it */
-
- if (renderdepth > 1) { /* Grayscale rendering */
- pix = ReadPixel(imagerp, xi, yi * unitheight / unitwidth);
- if (++pix < (1<<renderdepth)) {
- SetAPen(imagerp, pix);
- WritePixel(imagerp, xi, yi * unitheight / unitwidth);
- }
- }
- else /* B&W rendering - A Pen was set outside main loop */
- WritePixel(imagerp, xi, yi * unitheight / unitwidth);
-
- /*** Quit rendering loop if user clicked in ImageWindow */
- if (message = (struct IntuiMessage *)GetMsg(ImageWindow->UserPort)) {
- ReplyMsg(message);
- if (message->Code == SELECTUP) {
- SetWindowTitles(ImageWindow,
- (char *)" Click in screen to push it back", -1L);
- ShowTitle(ImageScreen, FALSE); /* Hide screen depth gadgets! */
- break; /* From for iter */
- }
- }
- }
-
- else { /* z == 1, draw in outline plane, quit after 1000 iters */
-
- WritePixel(r, xi, yi);
- if (iter > 999)
- break; /* From for iter */
- }
- } /* End if iter > 19 */
- } /* End for iter */
-
- if (z == 0) { /*** Wait for user click in Image screen to push it to back */
- while (!(message = (struct IntuiMessage*)GetMsg(ImageWindow->UserPort)))
- ; /* Wait for a message */
- ReplyMsg(message);
- SetWindowTitles(ImageWindow,
- (char *)" ", (char *)" Click in screen to push it back");
- ShowTitle(ImageScreen, TRUE); /* OK to have depth gadgets now */
- ScreenToBack(ImageScreen);
- MoveScreen(ImageScreen, 0L, (long)(-1*ImageScreen->TopEdge));
- ScreenToFront(Screen);
- ActivateWindow(Window);
- }
- else /* z == 1, unprotect Outline window planes */
- SetWrMsk(r, 0xFFFF);
- }
- /*===========================================================================*/
-
- SaveILBM() /* Saves the current Image to an IFF disk file */
- {
- LONG file; /* File handle [we use AmigaDOS Open(), not Manx open()] */
- UBYTE *savebuffer;
- char *fnam;
-
- if (exists_image == 0) {
- ShowError("No Image to save!");
- return;
- }
-
- fnam = GetFileName("Save to File:"); /* Get the filename */
- if (*fnam == '\0') /* User selected CANCEL or gave no filename */
- return;
-
- if ((file = Open(fnam, MODE_NEWFILE)) == NULL) {
- ShowError("Can't open file!");
- return;
- }
- if ((savebuffer = (UBYTE *)AllocMem(8000L, MEMF_CHIP|MEMF_PUBLIC)) == NULL) {
- ShowError("Can't allocate Save Buffer Memory!");
- return;
- }
-
- /* Use EA IFF routine PutPict() to save the image to file */
- ModifyMousePtr(Window, 1); /* Bring up 'ZZ' pointer */
- SetWindowTitles(ImageWindow,-1L,
- (char *)"");
- ShowTitle(ImageScreen, FALSE); /* Hide screen depth gadgets! */
- ActivateWindow(ImageWindow); /* To make title change take effect */
- ActivateWindow(Window);
- PutPict(file, ImageWindow->RPort->BitMap, ImageScreen->Width, ImageScreen->Height,
- (WORD *)(&(ImageScreen->ViewPort))->ColorMap->ColorTable, savebuffer,8000L);
- SetWindowTitles(ImageWindow,-1L,
- (char *)" Click in screen to push it back");
- ShowTitle(ImageScreen, TRUE); /* OK to have depth gadgets now */
- ActivateWindow(ImageWindow); /* To make title change take effect */
- ActivateWindow(Window);
- FreeMem(savebuffer, 8000L);
- Close(file);
- ModifyMousePtr(Window, -1); /* Remove 'ZZ' pointer */
- }
- /*===========================================================================*/
-
- struct piece *AllocPiece() /* Allocate memory for a piece structure and */
- { /* its piecemap. Return pointer to the piece structure */
- /* Or NULL if can't allocate memory */
- struct piece *tmppieceptr;
- UBYTE *mapptr;
-
- /* Allocate memory for piece structure */
- if ((tmppieceptr =
- (struct piece *)AllocMem((long)sizeof(struct piece), NULL)) == NULL) {
- ShowError("Can't allocate Memory!");
- return(NULL);
- }
- /* Allocate piecemap CHIP RAM */
- if ((mapptr = (UBYTE*)AllocRaster((long)WIDTH, (long)GZZHEIGHT)) == NULL) {
- FreeMem((void*)tmppieceptr, (long)sizeof(struct piece));
- ShowError("Can't allocate Memory!");
- return(NULL);
- }
- /* Clear piecemap */
- BltClear((char*)mapptr, (long)RASSIZE(WIDTH,GZZHEIGHT), 1L);
- tmppieceptr->piecemap = mapptr; /* Link bitplane to piece structure */
- return(tmppieceptr);
- }
- /*===========================================================================*/
-
- FreePiece(piecepntr) /* Frees the memory used for a piece structure */
- struct piece *piecepntr; /* and its piecemap. */
- {
- /* Deallocate CHIP RAM of piecemap bitplane */
- FreeRaster((void*)(piecepntr->piecemap), (long)WIDTH, (long)GZZHEIGHT);
-
- /* Deallocate memory of piece structure */
- FreeMem((void*)piecepntr, (long)sizeof(struct piece));
- }
- /*===========================================================================*/
-
- p(text) /* screen text output routine, similar to BASIC's PRINT */
- /* puts text in consecutive lines in rastport pointed at by the */
- /* external pointer Textrp. Line position is maintained between */
- /* calls, but is reset to top if text==NULL. No overflow check */
- char *text; /* is done -- text should fit in rastport area! */
- {
- static struct IntuiText Textline = {
- 1, 0, JAM1, /* FrontPen, BackPen, DrawMode */
- 0, NULL, /* LeftEdge, TopEdge */
- NULL, /* ITextFont */
- NULL, NULL /* IText, NextText */
- };
- static int line = 0; /* vert. position of line to be printed next (0 - 24) */
-
- if (text == NULL) /* reset to top line of rastport */
- line = 0;
- else {
- Textline.TopEdge = 8 * line; /* Put text into line on screen */
- Textline.IText = (UBYTE*)text;
- PrintIText(Textrp, &Textline, 0L, 0L);
- line++; /* increment line for next call */
- }
- }
- /*===========================================================================*/
-
- FindBoundary(xminp, xmaxp, yminp, ymaxp) /* Iterates IFS without drawing */
- /* and returns PIXEL coords of boundary rectangle of attractor */
- /* in variables pointed at by its arguments */
- /* Uses float math, not scaled int, to avoid overflow on very */
- /* large coeffs of loaded IFS files from other programs */
- long *xminp, *xmaxp, *yminp, *ymaxp; /* Pointers! */
- {
- int randprob; /* Random probability value */
- double sum; /* cum probability */
- int k;
- long iter; /* Iteration counter */
- double xd, yd, tmpxd; /* Real pixel coordinates */
- double xdmin, ydmin, xdmax, ydmax; /* Real boundary rect coords */
- int cumprobi[MAX_N+2]; /* Scaled integer Cum Probabilities */
- /* cumprobi array has MAX_N+2 elements because using MAX_N+1 caused a */
- /* Crash for unclear reasons in RenderImage() ?!?! */
-
- /*** Prepare stuff for iteration loop ***/
-
- srand((unsigned int)(time(NULL)%10000L)); /* seed random gen from sys time*/
-
- sum = 0;
- for (k = 0; k <= N; k++) { /* Scale Coefficients as longs */
- sum = sum + pieceptr[k]->p; /* Compute scaled Cum Probabilities */
- cumprobi[k] = (int)(sum * (double)RAND_MAX);
- }
-
- xdmin = 1000000000.; /* Initialize boundary rectangle coords */
- xdmax = -1000000000.;
- ydmin = 1000000000.;
- ydmax = -1000000000.;
-
- xd = 0.3; /* Initial coordinates */
- yd = 0.3;
-
- /*** Iterate 1000 times without drawing ***/
-
- for (iter = 0; iter < 1000; iter++) {
-
- /*** Select a Piece at random */
- randprob = rand();
- /* rand() returns a random # (between 0 - RAND_MAX) */
- for (k = 0; cumprobi[k] < randprob; k++) {
- /* the following IF is to trap problem case when randprob = RAND_MAX */
- /* exactly and cum probability is RAND_MAX minus slight delta due to */
- /* rounding errors */
- if (k > N) {
- k--;
- break;
- }
- }
-
- /* Apply transformation #k to previous (x,y) */
- tmpxd = pieceptr[k]->a * xd + pieceptr[k]->b * yd + pieceptr[k]->e;
- yd = pieceptr[k]->c * xd + pieceptr[k]->d * yd + pieceptr[k]->f;
- xd = tmpxd;
-
- if (iter > 19) { /* Adjust rectangle (except 1st 20 points) */
- if (xd < xdmin)
- xdmin = xd;
- if (xd > xdmax)
- xdmax = xd;
- if (yd < ydmin)
- ydmin = yd;
- if (yd > ydmax)
- ydmax = yd;
- }
-
- } /* End for iter */
-
- /*** Convert real coords to pixel coords for returned values */
-
- *xminp = (long)(xdmin * GZZWIDTH);
- *xmaxp = (long)(xdmax * GZZWIDTH);
- *yminp = (long)(ydmin * GZZWIDTH);
- *ymaxp = (long)(ydmax * GZZWIDTH);
- }
- /*===========================================================================*/
-