149 lines
4.7 KiB
C
149 lines
4.7 KiB
C
// minicad.c - port of ORCA-C's MiniCAD.cc sample.
|
|
//
|
|
// MiniCAD is a tiny drawing program: each click in the content area
|
|
// creates a new line in the current window's line list. In the
|
|
// original you click to set the anchor, drag to draw a rubber-band
|
|
// line, release to commit. We seed three classic line-art patterns
|
|
// (curve-stitching, sunburst, mandala) instead of waiting for clicks
|
|
// because our minimal Event Manager doesn't have a working
|
|
// GetNextEvent path for mouse-drag tracking, but the data model and
|
|
// rendering pipeline match MiniCAD.cc verbatim.
|
|
|
|
#include "iigs/toolbox.h"
|
|
#include "iigs/desktop.h"
|
|
|
|
|
|
#define wInContent 19
|
|
#define fVis 0x0020
|
|
#define fMove 0x0080
|
|
#define fClose 0x4000
|
|
|
|
|
|
typedef struct { short v1, h1, v2, h2; } Rect;
|
|
|
|
typedef struct {
|
|
unsigned short paramLength;
|
|
unsigned short wFrameBits;
|
|
void *wTitle;
|
|
unsigned long wRefCon;
|
|
Rect wZoom;
|
|
void *wColor;
|
|
short wYOrigin, wXOrigin;
|
|
short wDataH, wDataV;
|
|
short wMaxHeight, wMaxWidth;
|
|
short wScrollVer, wScrollHor;
|
|
short wPageVer, wPageHor;
|
|
unsigned long wInfoRefCon;
|
|
short wInfoHeight;
|
|
void *wFrameDefProc;
|
|
void *wInfoDefProc;
|
|
void *wContDefProc;
|
|
Rect wPosition;
|
|
void *wPlane;
|
|
void *wStorage;
|
|
} NewWindowParm;
|
|
|
|
|
|
typedef struct { short v1, h1, v2, h2; } LineRec;
|
|
|
|
|
|
static unsigned char gTitle[] = "\x07MiniCAD";
|
|
|
|
// Menu bar titles painted manually (DrawMenuBar hangs in our env).
|
|
static const unsigned char appleTitle[] = "\x01\x14";
|
|
static const unsigned char fileTitle[] = "\x04" "File";
|
|
static const unsigned char editTitle[] = "\x04" "Edit";
|
|
static const unsigned char optsTitle[] = "\x07" "Options";
|
|
static const unsigned char *const menuTitles[] = {
|
|
appleTitle, fileTitle, editTitle, optsTitle
|
|
};
|
|
|
|
static NewWindowParm gWp;
|
|
|
|
|
|
// Draw a curve-stitching pattern: 12 chord lines mapping the y-axis
|
|
// to a curve along the x-axis. Visually it traces a hyperbolic
|
|
// envelope (the classic "string art" pattern).
|
|
static void drawCurves(short ox, short oy) {
|
|
for (short i = 0; i < 12; i++) {
|
|
MoveTo((short)(ox + 0), (short)(oy + i * 6));
|
|
LineTo((short)(ox + 90 - i * 5), (short)(oy + 70 - i * 5));
|
|
}
|
|
}
|
|
|
|
|
|
// Draw a sunburst: 12 radial lines from a central point.
|
|
static void drawSunburst(short cx, short cy, short r) {
|
|
// Pre-computed cos/sin for 12 equally-spaced angles (every 30
|
|
// degrees), scaled by 1000. Avoids any float math.
|
|
static const short cosA[12] = { 1000, 866, 500, 0, -500, -866, -1000, -866, -500, 0, 500, 866 };
|
|
static const short sinA[12] = { 0, 500, 866, 1000, 866, 500, 0, -500, -866, -1000, -866, -500 };
|
|
for (short i = 0; i < 12; i++) {
|
|
short dx = (short)((long)cosA[i] * r / 1000);
|
|
short dy = (short)((long)sinA[i] * r / 1000);
|
|
MoveTo((short)(cx - dx), (short)(cy - dy));
|
|
LineTo((short)(cx + dx), (short)(cy + dy));
|
|
}
|
|
}
|
|
|
|
|
|
// Draw a mandala: 6-pointed star made of two overlapping triangles.
|
|
static void drawMandala(short cx, short cy, short r) {
|
|
short h = (short)((long)r * 866L / 1000L);
|
|
short h2 = (short)(r / 2);
|
|
// First triangle (point up).
|
|
MoveTo(cx, (short)(cy - r));
|
|
LineTo((short)(cx + h), (short)(cy + h2));
|
|
LineTo((short)(cx - h), (short)(cy + h2));
|
|
LineTo(cx, (short)(cy - r));
|
|
// Second triangle (point down).
|
|
MoveTo(cx, (short)(cy + r));
|
|
LineTo((short)(cx + h), (short)(cy - h2));
|
|
LineTo((short)(cx - h), (short)(cy - h2));
|
|
LineTo(cx, (short)(cy + r));
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
unsigned short userId = startdesk(640);
|
|
(void)userId;
|
|
paintDesktopBackdrop();
|
|
paintMenuBarTitles(menuTitles, 4);
|
|
ShowCursor();
|
|
|
|
// Open the drawing window.
|
|
{
|
|
unsigned char *p = (unsigned char *)&gWp;
|
|
for (unsigned short i = 0; i < sizeof gWp; i++) p[i] = 0;
|
|
}
|
|
gWp.paramLength = (unsigned short)sizeof gWp;
|
|
gWp.wFrameBits = fVis | fMove | fClose;
|
|
gWp.wTitle = gTitle;
|
|
gWp.wMaxHeight = 200;
|
|
gWp.wMaxWidth = 640;
|
|
gWp.wPosition.v1 = 20; gWp.wPosition.h1 = 30;
|
|
gWp.wPosition.v2 = 180; gWp.wPosition.h2 = 610;
|
|
gWp.wPlane = (void *)-1L;
|
|
void *win = NewWindow(&gWp);
|
|
|
|
if (win) {
|
|
BeginUpdate(win);
|
|
SetPort(win);
|
|
SetSolidPenPat(0);
|
|
|
|
// Three patterns laid out horizontally.
|
|
drawCurves(20, 30);
|
|
drawSunburst(280, 75, 50);
|
|
drawMandala(450, 75, 50);
|
|
|
|
EndUpdate(win);
|
|
}
|
|
|
|
for (volatile unsigned long s = 0; s < 400000UL; s++) { }
|
|
|
|
if (win) {
|
|
CloseWindow(win);
|
|
}
|
|
*(volatile unsigned char *)0x70 = 0x99;
|
|
return 0;
|
|
}
|