AmendHub

pfuentes69

/

FractalViewer

/

amendments

/

1

First commit


pfp made amendment 1 about 1 year ago
--- FractalViewer.cp Sun Oct 31 18:00:22 2021 +++ FractalViewer.cp Sun Oct 31 18:00:22 2021 @@ -0,0 +1,158 @@ +/***** + * FractalViewer.c + * + * Simple object-oriented application to draw 2D CGI, + * mostly fractals, using QuickDraw + * + *****/ + +/* MacHeaders Included */ + +#include <oops.h> +#include "FractalViewerMenus.h" +#include "TFractalViewerWindow.h" + + +/**** + * InitMacintosh() + * + * Initialize all the managers & memory + * + ****/ + +static void InitMacintosh(void) + +{ + MaxApplZone(); + + InitGraf(&thePort); + InitFonts(); + FlushEvents(everyEvent, 0); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(0L); + InitCursor(); +} +/* end InitMacintosh */ + + +/**** + * HandleMouseDown (theEvent) + * + * Take care of mouseDown events. + * + ****/ + +static void HandleMouseDown(EventRecord *theEvent) +{ + WindowPeek wp; + short windowPart = FindWindow (theEvent->where, (WindowPtr*) &wp); + + switch (windowPart) + { + case inSysWindow: + SystemClick (theEvent, (WindowPtr) wp); + break; + + case inMenuBar: + HandleMenu(MenuSelect(theEvent->where)); + break; + + case inDrag: + if (wp->windowKind == TWINDOWKIND) + OBJ(wp)->Drag(theEvent->where); + break; + + case inContent: + if (wp->windowKind == TWINDOWKIND) { + if (wp != (WindowPeek) FrontWindow()) + OBJ(wp)->Select(); + else + OBJ(wp)->Hit(theEvent->where); + } + break; + + case inGoAway: + if (wp->windowKind == TWINDOWKIND) + OBJ(wp)->TrackClose(theEvent->where); + break; + + case inGrow: + if (wp->windowKind == TWINDOWKIND) + OBJ(wp)->Grow(theEvent->where); + break; + + case inZoomIn: + case inZoomOut: + if (wp->windowKind == TWINDOWKIND) + OBJ(wp)->TrackZoom(theEvent->where, windowPart); + } +} +/* end HandleMouseDown */ + + +/**** + * HandleEvent() + * + * The main event dispatcher. This routine should be called + * repeatedly (it handles only one event). + * + *****/ + +static void HandleEvent(void) +{ + short ok; + EventRecord theEvent; + + HiliteMenu(0); + SystemTask (); /* Handle desk accessories */ + AdjustMenus(); + + ok = GetNextEvent (everyEvent, &theEvent); + if (ok) + { + switch (theEvent.what) + { + case mouseDown: + HandleMouseDown(&theEvent); + break; + + case keyDown: + case autoKey: + if ((theEvent.modifiers & cmdKey) != 0) + HandleMenu(MenuKey((char) (theEvent.message & charCodeMask))); + break; + + case updateEvt: + if (((WindowPeek) theEvent.message)->windowKind == TWINDOWKIND) + OBJ(theEvent.message)->Update(); + break; + + case activateEvt: + if (((WindowPeek) theEvent.message)->windowKind == TWINDOWKIND) + OBJ(theEvent.message)->Activate(theEvent.modifiers & 0x01); + break; + } + } +} +/* end HandleEvent */ + + +/***** + * main() + * + * This is where everything happens + * + *****/ + + +void main(void) +{ + InitMacintosh(); + SetUpMenus(); + + for (;;) + HandleEvent(); +} +/* end main */ --- FractalViewerMenus.cp Sun Oct 31 18:04:19 2021 +++ FractalViewerMenus.cp Sun Oct 31 18:04:19 2021 @@ -0,0 +1,296 @@ +/***** + * FractalViewerMenus.cp + * + * Menu handling routines for the program + * + *****/ + +#include <oops.h> +#include "FractalViewerMenus.h" +#include "FractalViewerPrefs.h" +#include "TFractalViewerWindow.h" +#include "TMandelbrot.h" +#include "TJulia.h" +#include "TPlasma.h" + + + // prototypes for utility routines +static void enable (MenuHandle menu, short item, Boolean enableMenu); +static findColorItem (long color); + +MenuHandle appleMenu, + fileMenu, + editMenu, + styleMenu, + viewMenu; + +enum { // Menu ids + appleID = 1, + fileID, + editID, + styleID, + viewID +}; + +enum { // items in the File menu + mandelItem = 1, + juliaItem, + plasmaItem, + closeItem, + prefsItem = closeItem+2, // leave space for the dashed line before Preferences + quitItem = prefsItem+2 // leave space for the dashed line before Quit +}; + + +enum { // items in the File menu + restoreItem = 1, + zoomInItem, + zoomOutItem, + separatorItem, + FastModeItem, + NormalModeItem, + FineModeItem +}; + + + +/**** + * SetUpMenus() + * + * Set up the menus. + * + ****/ + +void SetUpMenus(void) + +{ + InsertMenu(appleMenu = GetMenu(appleID), 0); + AddResMenu(appleMenu, 'DRVR'); + + InsertMenu(fileMenu = GetMenu(fileID), 0); + InsertMenu(editMenu = GetMenu(editID), 0); + InsertMenu(styleMenu = GetMenu(styleID), 0); + InsertMenu(viewMenu = GetMenu(viewID), 0); + + DrawMenuBar(); +} +/* end SetUpMenus */ + + +/**** + * AdjustMenus() + * + * Enable or disable the items in the Edit menu if a DA window + * comes up or goes away. Our application doesn't do anything with + * the Edit menu. If one of our windows is frontmost, adjust the + * Width and color menus to reflect the proper values for the + * windows. + * + ****/ + +#define isEnabled(mH) ((**mH).enableFlags & 0x01) + +void AdjustMenus(void) +{ + register WindowPeek wp = (WindowPeek) FrontWindow(); + short kind = wp ? wp->windowKind : 0; + short i; + short max; + static short redrawForEdit = true; // did the Edit menu change? + static short redrawForWidth = true; // did the Width menu change? + + if (kind < 0) { // enable Edit for desk accessories + redrawForEdit = !isEnabled(editMenu); + enable(editMenu, 0, true); + } + else { // disable it for all others + redrawForEdit = isEnabled(editMenu); + enable(editMenu, 0, false); + } + + // enable the Close command for DAs and our windows + enable(fileMenu, closeItem, kind < 0 || kind == TWINDOWKIND); + + // disable the Width and color menus if our window isn't frontmost + if (kind != TWINDOWKIND) { + redrawForWidth = isEnabled(styleMenu); + enable(styleMenu, 0, false); + enable(viewMenu, 0, false); + } + else { + redrawForWidth = !isEnabled(styleMenu); + enable(styleMenu, 0, true); + enable(viewMenu, 0, true); + + max = CountMItems(styleMenu); // uncheck all the widths + for (i = 1; i <= max; i++) + CheckItem(styleMenu, i, false); + + max = CountMItems(viewMenu); // uncheck all the colors + for (i = 1; i <= max; i++) { + CheckItem(viewMenu, i, false); + } + + // check the style for the frontmost window + CheckItem(styleMenu, OBJ(wp)->GetStyle(), true); + // check the drawMode for the frontmost window + CheckItem(viewMenu, separatorItem + OBJ(wp)->GetDrawMode(), true); + } + + if (redrawForEdit || redrawForWidth) { + DrawMenuBar(); + redrawForEdit = redrawForWidth = false; + } +} + +/** + * enable or disable a menu + * + **/ + +static void enable (MenuHandle menu, short item, Boolean enableMenu) +{ + if (enableMenu) + EnableItem(menu, item); + else + DisableItem(menu, item); +} + +/** + * given an old QuickDraw color, find its menu item number + * + **/ + +/* +static findColorItem (long color) +{ + short i; + short max = sizeof(colorTable) / sizeof(long); + + for (i= 1; i <= max; i++) + if (colorTable[i] == color) + return i; + else return 0; + DebugStr("\pBAD COLOR!"); +} +*/ + + + +/***** + * HandleMenu(mSelect) + * + * Handle the menu selection. mSelect is what MenuSelect() and + * MenuKey() return: the high word is the menu ID, the low word + * is the menu item + * + *****/ + +void HandleMenu (long mSelect) +{ + short menuID = HiWord(mSelect); + short menuItem = LoWord(mSelect); + Str255 name; + GrafPtr savePort; + TFractalViewerWindow *fractalWindow; + WindowPeek wp; + + switch (menuID) + { + case appleID: + if (menuItem == 1) + { + Alert(128, 0L); + break; + } + + GetPort(&savePort); + GetItem(appleMenu, menuItem, name); + OpenDeskAcc(name); + SetPort(savePort); + break; + + case fileID: + switch (menuItem) + { + case mandelItem: + fractalWindow = new(TMandelbrot); + break; + + case juliaItem: + fractalWindow = new(TJulia); + break; + + case plasmaItem: + fractalWindow = new(TPlasma); + break; + + case closeItem: + if ((wp = (WindowPeek) FrontWindow()) == NULL) + break; + + if (wp->windowKind < 0) + CloseDeskAcc(wp->windowKind); + else if (wp->windowKind == TWINDOWKIND) + OBJ(wp)->Close(); + break; + + case prefsItem: + HandlePrefs(); + break; + + case quitItem: + ExitToShell(); + break; + } + break; + + case editID: + if (!SystemEdit(menuItem-1)) + SysBeep(5); + break; + + case styleID: + if ((wp = (WindowPeek) FrontWindow()) == 0L || + wp->windowKind != TWINDOWKIND) + break; + + OBJ(wp)->SetStyle(menuItem); + break; + + case viewID: + if ((wp = (WindowPeek) FrontWindow()) == 0L || + wp->windowKind != TWINDOWKIND) + break; + + switch (menuItem) { + case restoreItem: + OBJ(wp)->ZoomContent(0); + break; + + case zoomInItem: + OBJ(wp)->ZoomContent(+1); + break; + + case zoomOutItem: + OBJ(wp)->ZoomContent(-1); + break; + + case FastModeItem: + OBJ(wp)->SetDrawMode(1); + break; + + case NormalModeItem: + OBJ(wp)->SetDrawMode(2); + break; + + case FineModeItem: + OBJ(wp)->SetDrawMode(3); + break; + + } + break; + } +} +/* end HandleMenu */ + --- FractalViewerMenus.h Sun Oct 31 18:02:11 2021 +++ FractalViewerMenus.h Sun Oct 31 18:02:11 2021 @@ -0,0 +1,14 @@ +/***** + * objBullMenus.h + * + * Public interfaces for FractalViewerMenus.cp + * + *****/ + +#pragma once // include this header + // only once per source file + + +void HandleMenu (long mSelect); +void AdjustMenus(void); +void SetUpMenus(void); --- FractalViewerPrefs.cp Wed Oct 20 22:22:50 2021 +++ FractalViewerPrefs.cp Wed Oct 20 22:22:50 2021 @@ -0,0 +1,52 @@ +#include "FractalViewerPrefs.h" + +enum { // Preferences Dialog Items + iPrefsOK = 1, + iPrefsCancel, + iPrefsBW, + iPrefsJuliaX = iPrefsBW + 3, + iPrefsJuliaY = iPrefsJuliaX + 2 +}; + +FractalViewerPrefs GlobalPrefs; + +/***** + * HandlePrefs(void) + * + * Handle the preferences dialog + * + *****/ + +void HandlePrefs(void) +{ + Boolean dlgDone = false; + short itemHit, itemType; + Handle itemHandle; + Rect itemRect; + + DialogPtr dlgPrefs = GetNewDialog(128, nil, (WindowPtr)-1L); + SetDialogDefaultItem(dlgPrefs, iPrefsOK); + SetDialogCancelItem(dlgPrefs, iPrefsCancel); + ShowWindow(dlgPrefs); + + while (!dlgDone) { + ModalDialog(nil, &itemHit); + + switch (itemHit) { + case iPrefsOK: + case iPrefsCancel: + dlgDone = true; + break; + case iPrefsBW: + GetDItem(dlgPrefs, itemHit, &itemType, &itemHandle, &itemRect); + SetCtlValue((ControlHandle)itemHandle, !GetCtlValue((ControlHandle)itemHandle)); + break; + default: + SysBeep(5); + break; + } + + } + + DisposeDialog(dlgPrefs); +} --- FractalViewerPrefs.h Wed Oct 20 21:40:14 2021 +++ FractalViewerPrefs.h Wed Oct 20 21:40:14 2021 @@ -0,0 +1,18 @@ +/***** + * FractalViewerPrefs.h + * + * Public interfaces for FractalViewerPrefs.c + * + *****/ + +#pragma once // include this header + // only once per source file + + +struct FractalViewerPrefs { + Boolean BW; + double JuliaX; + double JuliaY; +}; + +void HandlePrefs(void); --- TFractalViewerWindow.cp Sun Oct 31 18:06:04 2021 +++ TFractalViewerWindow.cp Sun Oct 31 18:06:04 2021 @@ -0,0 +1,169 @@ +/***** + * TFractalViewerWindow.c + * + * The window methods for the application. + * + * TFractalViewerWindow inherits its Draw method from TWindow. + * TMandelbrot, TJulia, and others override DrawShape to draw their own kind of CGI. + * + *****/ + +#include <Packages.h> // for NumToString prototype +#include "TFractalViewerWindow.h" +#include <stdlib.h> +#include "Utils.h" + + +/**** + * TFractalViewerWindow constructor + * + * Create a bullseye window. This constructor relies + * on the TWindow constructor to place the window in + * in attractive place. Then it appends a number to the + * window title. + * + ****/ + +TFractalViewerWindow::TFractalViewerWindow(void) +{ + Str15 numStr; + Str255 title; + long windowNumber; + + + // Set the title of the window to be + // the title in the resource + // plus the window counter. + // The window counter is a class variable + // declared in the TWindow class. + + + GetWindowTitle(title); + windowNumber = GetWindowNumber(); + NumToString(GetWindowNumber(), numStr); + concat(title, numStr); + SetWindowTitle(title); + +} + + +/**** + * Hit + * + * Handle a mouse down in the window. + * Bullseye window just force a refresh. + * + ****/ + +void TFractalViewerWindow::Hit(Point where) +{ + RefreshWindow(false); // preserve the scroll bars +} + + +/**** + * GetStyle + * SetStyle + * + * Get and set the color style + * + ****/ + +short TFractalViewerWindow::GetStyle() +{ + return style; +} + + +void TFractalViewerWindow::SetStyle(short w) +{ + style = w; + RefreshWindow(true); +} + + + +short TFractalViewerWindow::GetDrawMode() +{ + return drawMode; +} + + +void TFractalViewerWindow::SetDrawMode(short m) +{ + if (drawMode != m) { + drawMode = m; + RefreshWindow(true); + } +} + + + +/**** + * Draw + * + * Draw the bullseye figures. + * Repeatedly call DrawShape with a smaller drawing area. + * The drawing area gets smaller by 2 * the width. + * + ****/ + +void TFractalViewerWindow::Draw(void) + +{ + RgnHandle saveClip = NewRgn(); + PenState pen; + Rect drawingRect; + + + GetPenState(&pen); + GetClip(saveClip); + + inherited::Draw(); + + GetWindowRect(&drawingRect, false); // Don't draw in the scroll + // bar areas. Note that it's + // ok to pass the address of + // drawingRect because + // GetWindowRect won't move + // memory. + + sTop = drawingRect.top; + sLeft = drawingRect.left; + + DrawShape(&drawingRect); + + SetClip(saveClip); + DisposeRgn(saveClip); + SetPenState(&pen); + +} + + +/**** + * DrawShape methods + * + * These are the DrawShape methods for + * TBullWindow: does nothing + * TCircleBull: Circles + * TSquareBull: Squares + * TPlasma: "Triangles" + * + * All the DrawShape methods take a drawingRect + * as a parameter. The pen width + * is already set to the appropriate width. + * + ****/ + +void TFractalViewerWindow::DrawShape(Rect *drawingRect) +{ +} + +// +// ZOOM CONTENT +// + +void TFractalViewerWindow::ZoomContent(short z) +{ + RefreshWindow(false); // preserve the scroll bars +} --- TFractalViewerWindow.h Tue Oct 12 16:16:42 2021 +++ TFractalViewerWindow.h Tue Oct 12 16:16:42 2021 @@ -0,0 +1,39 @@ +/***** + * TFractalViewerWindow.h + * + * Object definitions for window to draw a fractal in. + * + *****/ + +#pragma once // include this header + // only once per source file + +#include "TWindow.h" + +class TFractalViewerWindow : public TWindow { +protected: + short style; + short drawMode; + short sWidth, sHeigth, sLeft, sTop; +public: + TFractalViewerWindow(void); // constructor + + virtual void Hit(Point where); + virtual void Draw(void); + virtual void DrawShape(Rect *drawingRect); + virtual void SetStyle(short s); + virtual short GetStyle(); + virtual void SetDrawMode(short m); + virtual short GetDrawMode(); + virtual void ZoomContent(short z); + +}; + + + + // This macro gets the object that stored in + // the refCon of the window and casts is so we + // can send messages to it + +#define OBJ(win) ((TFractalViewerWindow *)(((WindowPeek) win)->refCon)) + --- TJulia.cp Sun Oct 31 18:06:43 2021 +++ TJulia.cp Sun Oct 31 18:06:43 2021 @@ -0,0 +1,227 @@ +/***** + * TJulia.cp + * + * TJulia draws a Julia set + * + *****/ + +#include <Packages.h> // for NumToString prototype +#include "TFractalViewerWindow.h" +#include "TJulia.h" +#include <stdlib.h> + + +/**** + * TFractalViewerWindow constructor + * + * Create a bullseye window. This constructor relies + * on the TWindow constructor to place the window in + * in attractive place. Then it appends a number to the + * window title. + * + ****/ + + +TJulia::TJulia(void) +{ + // Set the width, and show the window. + PrepareStyles(); + SetStyle(1); + SetDrawMode(2); + // Set the default plane + DefaultPlane(); + + Show(); +} + + +/**** + * Hit + * + * Handle a mouse down in the window. + * Bullseye window just force a refresh. + * + ****/ + +void TJulia::DefaultPlane() +{ + pWidth = 5; + pHeigth = 5; + pCX = 0.0; + pCY = 0.0; +} + + +void TJulia::Hit(Point where) +{ + Point mouse; + double sCX, sCY, tX, tY, hX, hY; + Rect drawingRect; + + // Recalculate center + GlobalToLocal(&where); + hX = where.h; // - sLeft; + hY = where.v; // - sTop; + + sCX = sWidth / 2.0; + sCY = sHeigth / 2.0; + tX = sCX - hX; + tY = hY - sCY; + pCX = pCX - pWidth * tX / (double)sWidth; + pCY = pCY - pHeigth * tY / (double)sHeigth; + RefreshWindow(false); // preserve the scroll bars +} + + +/**** + * DrawShape methods + * + * These are the DrawShape methods for + * TBullWindow: does nothing + * TCircleBull: Circles + * TSquareBull: Squares + * TPlasma: "Triangles" + * + * All the DrawShape methods take a drawingRect + * as a parameter. The pen width + * is already set to the appropriate width. + * + ****/ + +int TJulia::Julia(double real, double imag, short maxiterations) { + double zReal = real; + double zImag = imag; + + for (int i = 0; i < maxiterations; ++i) { + double r2 = zReal * zReal; + double i2 = zImag * zImag; + if (r2 + i2 > 4.0) + return i; + zImag = 2.0 * zReal * zImag + 0.70882; + zReal = r2 - i2 - 0.28625; + } + return maxiterations; +} + + +void TJulia::DrawShape(Rect *drawingRect) +{ + RGBColor colPix; + short maxiterations; + + switch (drawMode) { + case 1: + maxiterations = 20; + break; + case 2: + maxiterations = 100; + break; + case 3: + maxiterations = 200; + break; + } + + short st = GetStyle() - 1; + + sWidth = drawingRect->right - drawingRect->left + 1; + sHeigth = drawingRect->bottom - drawingRect->top + 1; + + pHeigth = (double)sHeigth * pWidth / (double)sWidth; + + double x_start = pCX - pWidth / 2.0; + double x_fin = x_start + pWidth; + double y_start = pCY - pHeigth / 2.0; + double y_fin = y_start + pHeigth; + + double dx = (x_fin - x_start)/(sWidth - 1); + double dy = (y_fin - y_start)/(sHeigth - 1); + + for (int i = 0; i < sHeigth; i++) { + for (int j = 0; j < sWidth; j++) { + double x = x_start + j*dx; // current real value + double y = y_fin - i*dy; // current imaginary value + + int value = Julia(x, y, maxiterations); + if (value == maxiterations) { + colPix.red = 0; + colPix.green = 0; + colPix.blue = 0; + } + else { + value = 255 * value / maxiterations; + colPix = spec[st][value % 255]; + } + SetCPixel(j, i, &colPix); + } + } + +} + + + +// +// PREPARE STYLES METHODS +// + +void TJulia::PrepareStyles() +{ + short ci; + // Style 1 + for(ci=0; ci < 256; ci++) { + spec[0][ci].red = 65536 - ci * 256; + spec[0][ci].green = 65536 - ci * 256; + spec[0][ci].blue = 65536 - ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[1][ci].red = ci * 256; + spec[1][ci].green = ci * 256; + spec[1][ci].blue = ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[2][ci].red = 65535 - ci * 256; + spec[2][ci].green = 32768 + ci * 128; + spec[2][ci].blue = ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[3][ci].red = ci * 256; + spec[3][ci].green = 32768 + ci * 128; + spec[3][ci].blue = 65535 - ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[4][ci].red = 32768 - ci * 128; + spec[4][ci].green = ci * 256; + spec[4][ci].blue = 65535 - ci * 256; + } +} + + +// +// ZOOM CONTENT +// + + +void TJulia::ZoomContent(short z) +{ + switch (z) { + case -1: + pWidth = pWidth * 1.333; + pHeigth = pHeigth * 1.333; + break; + case 1: + pWidth = pWidth * 0.666; + pHeigth = pHeigth * 0.666; + break; + break; + default: + DefaultPlane(); + break; + } + + RefreshWindow(false); // preserve the scroll bars +} + + --- TJulia.h Sun Oct 31 18:02:44 2021 +++ TJulia.h Sun Oct 31 18:02:44 2021 @@ -0,0 +1,28 @@ +/***** + * TJulia.h + * + * Object definitions for window to draw a Julia set in. + * + *****/ + +#pragma once // include this header + // only once per source file + +#include "TFractalViewerWindow.h" + + +class TJulia : public TFractalViewerWindow { +protected: + virtual void DefaultPlane(); + RGBColor spec[5][256]; + int Julia(double real, double imag, short maxiterations); + virtual void PrepareStyles(); + double pWidth, pHeigth; + double pXMin, pXMax, pYMin, pYMax; + double pCX, pCY; +public: + TJulia(void); + virtual void Hit(Point where); + virtual void DrawShape(Rect *drawingRect); + virtual void ZoomContent(short z); +}; --- TMandelbrot.cp Fri Aug 26 13:26:48 2022 +++ TMandelbrot.cp Fri Aug 26 13:26:48 2022 @@ -0,0 +1,227 @@ +/***** + * TMandelbrot.cp + * + * The window methods to draw a Mandelbrot set + * + *****/ + +#include <Packages.h> // for NumToString prototype +#include "TFractalViewerWindow.h" +#include "TMandelbrot.h" +#include <stdlib.h> + + +/**** + * TFractalViewerWindow constructor + * + * Create a bullseye window. This constructor relies + * on the TWindow constructor to place the window in + * in attractive place. Then it appends a number to the + * window title. + * + ****/ + + +TMandelbrot::TMandelbrot(void) +{ + // Set the width, and show the window. + PrepareStyles(); + SetStyle(1); + SetDrawMode(2); + // Set the default plane + DefaultPlane(); + + Show(); +} + + +/**** + * Hit + * + * Handle a mouse down in the window. + * Bullseye window just force a refresh. + * + ****/ + +void TMandelbrot::DefaultPlane() +{ + pWidth = 3.0; + pHeigth = 3.0; + pCX = -0.6; + pCY = 0.0; +} + + +void TMandelbrot::Hit(Point where) +{ + Point mouse; + double sCX, sCY, tX, tY, hX, hY; + Rect drawingRect; + + // Recalculate center + GlobalToLocal(&where); + hX = where.h; // - sLeft; + hY = where.v; // - sTop; + + sCX = sWidth / 2.0; + sCY = sHeigth / 2.0; + tX = sCX - hX; + tY = hY - sCY; + pCX = pCX - pWidth * tX / (double)sWidth; + pCY = pCY - pHeigth * tY / (double)sHeigth; + RefreshWindow(false); // preserve the scroll bars +} + + +/**** + * DrawShape methods + * + * These are the DrawShape methods for + * TBullWindow: does nothing + * TCircleBull: Circles + * TSquareBull: Squares + * TPlasma: "Triangles" + * + * All the DrawShape methods take a drawingRect + * as a parameter. The pen width + * is already set to the appropriate width. + * + ****/ + +int TMandelbrot::Mandelbrot(double real, double imag, short maxiterations) { + double zReal = real; + double zImag = imag; + + for (int i = 0; i < maxiterations; ++i) { + double r2 = zReal * zReal; + double i2 = zImag * zImag; + if (r2 + i2 > 8.0) + return i; + zImag = 2.0 * zReal * zImag + imag; + zReal = r2 - i2 + real; + } + return maxiterations; +} + + +void TMandelbrot::DrawShape(Rect *drawingRect) +{ + RGBColor colPix; + short maxiterations; + + switch (drawMode) { + case 1: + maxiterations = 20; + break; + case 2: + maxiterations = 100; + break; + case 3: + maxiterations = 200; + break; + } + + short st = GetStyle() - 1; + + sWidth = drawingRect->right - drawingRect->left + 1; + sHeigth = drawingRect->bottom - drawingRect->top + 1; + + pHeigth = (double)sHeigth * pWidth / (double)sWidth; + + double x_start = pCX - pWidth / 2.0; + double x_fin = x_start + pWidth; + double y_start = pCY - pHeigth / 2.0; + double y_fin = y_start + pHeigth; + + double dx = (x_fin - x_start)/(sWidth - 1); + double dy = (y_fin - y_start)/(sHeigth - 1); + + for (int i = 0; i < sHeigth; i++) { + for (int j = 0; j < sWidth; j++) { + double x = x_start + j*dx; // current real value + double y = y_fin - i*dy; // current imaginary value + + int value = Mandelbrot(x, y, maxiterations); + if (value == maxiterations) { + colPix.red = 0; + colPix.green = 0; + colPix.blue = 0; + } + else { + value = 255 * value / maxiterations; + colPix = spec[st][value % 255]; + } + SetCPixel(j, i, &colPix); + } + } + +} + + + +// +// PREPARE STYLES METHODS +// + +void TMandelbrot::PrepareStyles() +{ + short ci; + // Style 1 + for(ci=0; ci < 256; ci++) { + spec[0][ci].red = 65536 - ci * 256; + spec[0][ci].green = 65536 - ci * 256; + spec[0][ci].blue = 65536 - ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[1][ci].red = ci * 256; + spec[1][ci].green = ci * 256; + spec[1][ci].blue = ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[2][ci].red = 65535 - ci * 256; + spec[2][ci].green = 32768 + ci * 128; + spec[2][ci].blue = ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[3][ci].red = ci * 256; + spec[3][ci].green = 32768 + ci * 128; + spec[3][ci].blue = 65535 - ci * 256; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[4][ci].red = 32768 - ci * 128; + spec[4][ci].green = ci * 256; + spec[4][ci].blue = 65535 - ci * 256; + } +} + + +// +// ZOOM CONTENT +// + + +void TMandelbrot::ZoomContent(short z) +{ + switch (z) { + case -1: + pWidth = pWidth * 1.333; + pHeigth = pHeigth * 1.333; + break; + case 1: + pWidth = pWidth * 0.666; + pHeigth = pHeigth * 0.666; + break; + break; + default: + DefaultPlane(); + break; + } + + RefreshWindow(false); // preserve the scroll bars +} + + --- TMandelbrot.h Tue Oct 12 17:03:39 2021 +++ TMandelbrot.h Tue Oct 12 17:03:39 2021 @@ -0,0 +1,28 @@ +/***** + * TMandelbrot.h + * + * Object definitions for window to draw a Mandelbrot set in. + * + *****/ + +#pragma once // include this header + // only once per source file + +#include "TFractalViewerWindow.h" + + +class TMandelbrot : public TFractalViewerWindow { +protected: + virtual void DefaultPlane(); + RGBColor spec[5][256]; + int Mandelbrot(double real, double imag, short maxiterations); + virtual void PrepareStyles(); + double pWidth, pHeigth; + double pXMin, pXMax, pYMin, pYMax; + double pCX, pCY; +public: + TMandelbrot(void); + virtual void Hit(Point where); + virtual void DrawShape(Rect *drawingRect); + virtual void ZoomContent(short z); +}; --- TPlasma.cp Mon Nov 15 21:01:19 2021 +++ TPlasma.cp Mon Nov 15 21:01:19 2021 @@ -0,0 +1,301 @@ +/***** + * TPlasma.cp + * + * Drawing clouds (Perlin noise?) + * + *****/ + +#include <Packages.h> // for NumToString prototype +#include "TFractalViewerWindow.h" +#include "TPlasma.h" +#include <stdlib.h> +#include <math.h> + + +/**** + * TFractalViewerWindow constructor + * + * Create a bullseye window. This constructor relies + * on the TWindow constructor to place the window in + * in attractive place. Then it appends a number to the + * window title. + * + ****/ + + +TPlasma::TPlasma(void) +{ + PrepareStyles(); + // Set the width, and show the window. + SetStyle(2); + Show(); +} + + +/**** + * Hit + * + * Handle a mouse down in the window. + * Bullseye window just force a refresh. + * + ****/ + + + + +/**** + * Noise calculations + * + * + ****/ + + +// This code is adapted from a Javascript example found at perlin.mydevelops.com (unknown author) + +int p[] = { + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, + 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, + 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, + 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, + 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, + 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, + 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, + 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, + 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, + 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, + 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, + 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, + 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, + 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, + 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 + }; + + +int round(float f) +{ + int fl = floor(f); + float d = f - (float)fl; + if (d > 0.5) + return fl + 1; + else + return fl; +} + +int Perm(int x) +{ + return p[(x & 255)]; +} + + +int Index(int x, int y) +{ + return Perm(x + Perm(y)); +} + + +float Gradient(int vector,float x,float y) +{ + //we will find the right gradient + float val = 0; + switch (vector % 4) + { + case 0: + val = x + y; + break; + case 1: + val = -x + y; + break; + case 2: + val = x - y; + break; + case 3: + val = -x - y; + break; + } + + return val; +} + + +float Smooth(float t) +{ + return t * t * t * (6 * t * t - 15.0 * t + 10.0); +} + + +float Interpolate(float t,float a,float b) +{ + return a + t * ( b - a); +} + +float Perlin2D(float x,float y) +{ + float hX = floor(x); + float hY = floor(y); + + float dX = x - hX; + float dY = y - hY; + + //field for gradients + float gradients[4]; + + //now let's go through the vertices of the creator and their vectors + for (int i = 0; i < 4; i++) { + // 00, 01, 10, 11 + int tmpX = (i & 2) ? 1: 0; + int tmpY = (i & 1); + int vector = Index(hX + tmpX, hY + tmpY); + + gradients[i] = Gradient(vector, dX - tmpX, dY - tmpY); + + } + + //let's use the smoothing function + float smoothX = Smooth(dX); + float smoothY = Smooth(dY); + + //we make a bilinear interpolation of the gradient of vectors first two and two + // and finally the results from the first and the second and we get the result + float x_prva = Interpolate(smoothX, gradients[0], gradients[2]); + double x_druha = Interpolate(smoothX, gradients[1], gradients[3]); + + return Interpolate(smoothY, x_prva, x_druha); +} + +int PerlinMapped(double value) +{ + //we will scale it from -1 1 to 0 1 and then from it to 0 255 + return round( ((value + 1.0) / 2.0) * 255.0); +} + +int PerlinOctFrec(int x, int y, int oct, double frec) +{ + double together = 0; +// int amp = 0; + double frek = 0; + + for(int i = 1; i <= oct; i++) { + frek = frec * (double)i; + together += Perlin2D((double)x * frek, (double)y * frek); + } + + return PerlinMapped((double)(together / oct)); +} + + + +/**** + * DrawShape methods + * + * + ****/ + + + +void TPlasma::DrawShape(Rect *drawingRect) +{ + RGBColor colPix; + double frekvencia = 0.004; + int oktava = 3; + + short st = GetStyle() - 1; + + sWidth = drawingRect->right - drawingRect->left + 1; + sHeigth = drawingRect->bottom - drawingRect->top + 1; + + for(int x=0; x<sWidth; x++) { + for (int y=0; y<sHeigth; y++) { + int shade = PerlinOctFrec(x, y, oktava, frekvencia); + colPix = spec[st][shade]; + SetCPixel(x, y, &colPix); + } + } + + + +/* Test code to draw stuff using DrawPicture. It crashes for complex images (memory issues?) + OpenCPicParams myOpenCPicParams; + PicHandle myPic; + Rect rect; + + rect.left = drawingRect->left; + rect.right = drawingRect->right; + rect.top = drawingRect->top; + rect.bottom = drawingRect->bottom; + + myOpenCPicParams.srcRect = rect; + myOpenCPicParams.hRes = 0x00480000; + myOpenCPicParams.vRes = 0x00480000; + myOpenCPicParams.version = -2; + myOpenCPicParams.reserved1 = 0; + myOpenCPicParams.reserved2 = 0; + + myPic = OpenCPicture(&myOpenCPicParams); + + PenSize(style, style); + ClipRect(drawingRect); + + while (drawingRect->left < drawingRect->right && + drawingRect->top < drawingRect->bottom) { + MoveTo(drawingRect->left, drawingRect->bottom); + LineTo(drawingRect->right, drawingRect->bottom); + LineTo(drawingRect->left, drawingRect->top); + LineTo(drawingRect->left, drawingRect->bottom); + InsetRect(drawingRect, style*2, style*2); + } + + ClosePicture(); + + DrawPicture(myPic, &rect); +*/ + +} + + +// +// PREPARE STYLES METHODS +// + + +void TPlasma::PrepareStyles() +{ + short ci; + // Style 1 + for(ci=0; ci < 256; ci++) { + spec[0][ci].red = ci * 256; + spec[0][ci].green = ci * 256; + spec[0][ci].blue = 65535; + } + // Style 2 + for(ci=0; ci < 256; ci++) { + spec[1][ci].red = 65535 - ci * 256; + spec[1][ci].green = 65535 - ci * 256; + spec[1][ci].blue = 65535; + } + // Style 3 + for(ci=0; ci < 256; ci++) { + spec[2][ci].red = 65535 - ci * 256; + spec[2][ci].green = 65535 - ci * 256; + spec[2][ci].blue = 65535 - ci * 256; + } + // Style 4 + for(ci=0; ci < 256; ci++) { + spec[3][ci].red = ci * 256; + spec[3][ci].green = ci * 256; + spec[3][ci].blue = ci * 256; + } + // Style 4 + for(ci=0; ci < 256; ci++) { + spec[4][ci].red = 32768 - ci * 128; + spec[4][ci].green = ci * 256; + spec[4][ci].blue = 65535 - ci * 256; + } +} + + + +// +// ZOOM CONTENT +// + + --- TPlasma.h Mon Nov 15 20:43:08 2021 +++ TPlasma.h Mon Nov 15 20:43:08 2021 @@ -0,0 +1,23 @@ +/***** + * TPlasma.h + * + * Object definitions for window to draw a Plasma Fractal in. + * + *****/ + +#pragma once // include this header + // only once per source file + +#define PI 3.1415927; + +#include "TFractalViewerWindow.h" + + +class TPlasma : public TFractalViewerWindow { +protected: + RGBColor spec[5][256]; + virtual void PrepareStyles(); +public: + TPlasma(void); + virtual void DrawShape(Rect *drawingRect); +}; --- TWindow.cp Tue Aug 16 13:53:05 2022 +++ TWindow.cp Tue Aug 16 13:53:05 2022 @@ -0,0 +1,405 @@ +/***** + * TWindow.cp + * + * Copyright © 1991 Symantec Corporation. All rights reserved. + * + * Generic window class to handle most window actions. + * This class is intended to demonstrate the new + * object-oriented features of THINK C 5.0. It is not + * intended to be a general purpose window class for use + * in commerical-quality applications. + * + * We store the object in the window's refCon and set + * the windowKind to TWINDOWKIND so we can tell whether + * there's an object in it. + * + *****/ + +#include <oops.h> +#include "TWindow.h" + + // Prototypes for utility functions. + +static void EraseScrollBars (WindowPtr theWindow); +static void InvalScrollBars (WindowPtr theWindow); +static void ValidScrollBars (WindowPtr theWindow); + +short TWindow::windowCounter = 0; // the window counter that this class uses to + // stack its windows + + +/**** + * TWindow constructor + * + * Create a new window and place it in an + * attractive place on the screen. + * + ****/ + +TWindow::TWindow(void) +{ + Rect myRect; + short offset; + Point originPt; + + theWindow = GetNewCWindow(TWinRSRC, NULL, (void *) -1L); + drag = screenBits.bounds; + SetRect(&smallest, 60, 60, 9999, 9999); + + ((WindowPeek) theWindow)->windowKind = TWINDOWKIND; + SetWRefCon(theWindow, (long) this); + SetPort(theWindow); + + // Place this window in some attractive place + // on the screen. TWindow uses the class variable + // windowCounter to keep track of how many windows it + // has stacked, but subclasses can access this variable + // through the GetWindowNumber() method to create + // numbered windows. + + originPt = topLeft(theWindow->portRect); + LocalToGlobal(&originPt); + offset = ((windowCounter) % 7) * 20; + MoveWindow(theWindow, originPt.h+offset, originPt.v+offset, true); + windowCounter++; +} + + +/**** + * TWindow destructor + * + * Dispose of the window. + * + ****/ + +TWindow::~TWindow(void) +{ + DisposeWindow(theWindow); +} + + +/**** + * Close + * + * Close a window. + * This method merely deletes the object. + * + ****/ + +void TWindow::Close() +{ + delete this; +} + + + +/**** + * GetWindowCounter + * + * Return the current value of the windowCounter + * instance variable. + * + ****/ + +short TWindow::GetWindowNumber (void) + +{ + return windowCounter; +} + +/**** + * Draw + * + * Draw the contents of the window. + * This method sets the foreground and background + * color, erases the window, draws the scroll area + * in white, and finally draws the grow icon. + * + ****/ + +void TWindow::Draw() +{ + EraseRect(&theWindow->portRect); + BackColor(whiteColor); + EraseScrollBars(theWindow); + DrawGrowIcon(theWindow); + +} + + +void TWindow::Hit(Point where) +{ + // Subclasses must do something here +} + +/**** + * Grow + * + * Grow the window. + * If the window actually changed size, erase the + * scroll bar areas. Return the new size of the window. + * + ****/ + +long TWindow::Grow (Point where) +{ + long size; + Rect smallest; + + smallest = this->smallest; // can't pass the address of + // and instance variable to + // a Toolbox routine that may + // move memory. + + SetPort(theWindow); + size = GrowWindow(theWindow, where, &smallest); + + if (size) { + EraseScrollBars(theWindow); + RefreshWindow(true); // force whoe window to be redrawn + // the "true" param to SizeWindow + // accumulates the new area into + // the update region + + SizeWindow(theWindow, LoWord(size), HiWord(size), true); + } + + return (size); +} + +/**** + * Zoom + * + * Zoom a window in reponse to a click in the zoom box. + * + ****/ + +void TWindow::Zoom (short part) +{ + Rect myRect; + + SetPort(theWindow); + EraseRect(&theWindow->portRect); + ZoomWindow(theWindow, part, true); +} + + +/**** + * Update + * + * Update a window. + * The usual thing to do here is to call the Draw() + * method. + * + ****/ + +void TWindow::Update(void) +{ + WindowPtr savePort; + + GetPort(&savePort); + SetPort(theWindow); + BeginUpdate(theWindow); + Draw(); + EndUpdate(theWindow); + SetPort(savePort); +} + + +/**** + * Activate + * + * Respond to activate events. + * All we really have to do is make sure that the + * grow icon is drawn correctly. Subclasses that + * want to do something special when deactivate should + * override this method. + * + ****/ + +void TWindow::Activate (short active) +{ + DrawGrowIcon(theWindow); // DrawGrowIcon knows how to draw the icon + // for inactive & active windows + + if (active) + SetPort(theWindow); +} + + + +/**** + * Draw + * Select + * Show + * Hide + * TrackClose + * TrackZoom + * IsVisible + * GetWindowTitle + * SetWindowTitle + * + * Various OOP interfaces to the Toolbox routines. + * + ****/ + + +void TWindow::Drag(Point where) +{ + DragWindow(theWindow, where, &drag); +} + + +void TWindow::Select(void) +{ + SelectWindow(theWindow); +} + + +void TWindow::Show(void) +{ + ShowWindow(theWindow); +} + + +void TWindow::Hide(void) +{ + HideWindow(theWindow); +} + + +void TWindow::TrackClose (Point where) +{ + if (TrackGoAway(theWindow, where)) + Close(); +} + + +void TWindow::TrackZoom(Point where, short part) +{ + if (TrackBox(theWindow, where, part)) + Zoom(part); +} + + +short TWindow::IsVisible() +{ + return ((WindowPeek) theWindow)->visible; +} + + + +void TWindow::GetWindowTitle (Str255 theTitle) +{ + GetWTitle(theWindow, theTitle); +} + + +void TWindow::SetWindowTitle (Str255 theTitle) +{ + SetWTitle(theWindow, theTitle); +} + + +/**** + * GetWindowRect + * + * Return the windows rectangle. + * This method is provided so subclasses don't have + * to go poking into the instance variables. + * + ****/ + +void TWindow::GetWindowRect (Rect *theRect, Boolean entireWindow) +{ + *theRect = theWindow->portRect; + if (!entireWindow) { + theRect->top += 1; + theRect->left += 1; + theRect->right -= 16; + theRect->bottom -= 16; + } +} + + +/**** + * RefreshWindow + * + * Force a window to be redrawn on the next udpate event. + * The Boolean parameter determines whether the scroll bars + * should be redrawn or not. + * + ****/ + +void TWindow::RefreshWindow (Boolean wholeWindow) +{ + InvalRect(&theWindow->portRect); + if (!wholeWindow) + ValidScrollBars(theWindow); +} + + + +/**** + * Zoom + * + ****/ + +void TWindow::ZoomContent(short z) +{ + // Child will do +} + + +/*** + * Utility routines to validate & inval the scroll bar rectangles. + * + ***/ + + +typedef enum { kInval, kValid, kErase } sbarAction; + +static void xScrollBars (WindowPtr theWindow, sbarAction action) +{ + Rect botRect; + Rect rightRect; + + rightRect = botRect = theWindow->portRect; + + botRect.top = botRect.bottom-15; // The bottom scroll area + + rightRect.left = rightRect.right-15; // The right scroll area + + switch (action) { + case kInval: InvalRect(&botRect); + InvalRect(&rightRect); + break; + + case kValid: ValidRect(&botRect); + ValidRect(&rightRect); + break; + + case kErase: EraseRect(&botRect); + EraseRect(&rightRect); + break; + } +} + +static void InvalScrollBars (WindowPtr theWindow) +{ + xScrollBars(theWindow, kInval); +} + +static void ValidScrollBars (WindowPtr theWindow) +{ + xScrollBars(theWindow, kValid); +} + + +static void EraseScrollBars (WindowPtr theWindow) +{ + xScrollBars(theWindow, kErase); +} + + + --- TWindow.h Mon Oct 11 15:04:27 2021 +++ TWindow.h Mon Oct 11 15:04:27 2021 @@ -0,0 +1,66 @@ +/***** + * TWindow.h + * + * Copyright © 1991 Symantec Corporation + * + * Class definition of window class. + * This class is intended to demonstrate the new + * object-oriented features of THINK C 5.0. It is not + * intended to be a general purpose window class for use + * in commerical-quaility applications. + * + *****/ + +#pragma once // include this header + // only once per source file + +#define TWINDOWKIND 'TW' // Windows whose windowKind is + // TWINDOWKIND have a TWindow + // object stored in their refCon. + // If it's any other windowKind, + // it's not one of ours. + +#define TWinRSRC 128 // Resource ID of WIND resource + // for TWindow windows + +#if __cplusplus +class TWindow { // Using Symantec C++ +#else +class TWindow : indirect { // ...or THINK C's oop extensions +#endif + +private: + Rect drag; + Rect smallest; + WindowPtr theWindow; // the window record + + static short windowCounter; // counter for the stacker + + +public: + TWindow(void); // constructor + ~TWindow(void); // destructor + + virtual void Close(void); + short GetWindowNumber(void); + virtual void Draw(void); + virtual void Hit(Point where); + virtual long Grow(Point where); + virtual void Zoom(short part); + virtual void Update(void); + virtual void Activate(short active); + virtual void Drag(Point where); + virtual void Select(void); + virtual void Show(void); + virtual void Hide(void); + virtual void TrackClose(Point where); + virtual void TrackZoom(Point where, short part); + virtual short IsVisible(void); + virtual void GetWindowTitle (Str255 theTitle); + virtual void SetWindowTitle (Str255 theTitle); + virtual void GetWindowRect(Rect *theRect, Boolean entireWindow); + virtual void RefreshWindow(Boolean entireWindow); + virtual void ZoomContent(short z); + +}; + --- Utils.cp Fri Oct 15 11:22:31 2021 +++ Utils.cp Fri Oct 15 11:22:31 2021 @@ -0,0 +1,15 @@ +#include <Packages.h> // for NumToString prototype +#include <stdlib.h> +#include "Utils.h" + +/*** + * concatenate two Pascal strings + * + ***/ + +void concat (StringPtr s, StringPtr p) +{ + BlockMove(p+1, s+1+s[0], (long) p[0]); + s[0] += p[0]; +} + --- Utils.h Fri Oct 15 11:22:51 2021 +++ Utils.h Fri Oct 15 11:22:51 2021 @@ -0,0 +1,12 @@ +/***** + * Utils.h + * + * several utilities + * + *****/ + +#pragma once // include this header + // only once per source file + +void concat (StringPtr s, StringPtr p); +