summaryrefslogtreecommitdiffstats
path: root/maccaml/graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'maccaml/graph.c')
-rw-r--r--maccaml/graph.c1179
1 files changed, 0 insertions, 1179 deletions
diff --git a/maccaml/graph.c b/maccaml/graph.c
deleted file mode 100644
index 1bf03d9a3..000000000
--- a/maccaml/graph.c
+++ /dev/null
@@ -1,1179 +0,0 @@
-/***********************************************************************/
-/* */
-/* Objective Caml */
-/* */
-/* Damien Doligez, projet Para, INRIA Rocquencourt */
-/* */
-/* Copyright 1998 Institut National de Recherche en Informatique et */
-/* en Automatique. All rights reserved. This file is distributed */
-/* under the terms of the GNU Library General Public License, with */
-/* the special exception on linking described in file ../LICENSE. */
-/* */
-/***********************************************************************/
-
-/* $Id$ */
-
-#include "alloc.h"
-#include "callback.h"
-#include "fail.h"
-#include "memory.h"
-#include "mlvalues.h"
-#include "signals.h"
-
-#include "main.h" /* Include main.h last or Assert will not work. */
-
-
-/* The off-screen buffer that holds the contents of the graphics arena. */
-static GWorldPtr gworld = NULL;
-
-/* An arbitrarily large rectangle (for clipping). */
-static Rect maxrect = { -SHRT_MAX, -SHRT_MAX, SHRT_MAX, SHRT_MAX };
-
-/* Coordinates (relative to the window) of the top-left corner
- of the graphics arena. */
-long x0, y0;
-
-/* Width and height of the graphics arena. */
-long w0, h0;
-
-RGBColor fgcolor;
-
-/* Convert from Caml coordinates to QD coordinates in the off-screen buffer. */
-/* Note: these conversions are self-inverse (see gr_current_point). */
-#define Bx(x) (x)
-#define By(y) (h0-1 - (y))
-
-/* Convert from Caml coordinates to QD coordinates in the window. */
-#define Wx(x) (Bx(x) + x0)
-#define Wy(y) (By(y) + y0)
-
-/* Convert from QD window coordinates to Caml coordinates. */
-#define Cx(x) ((x) - x0)
-#define Cy(y) (h0-1 - ((y) - y0))
-
-
-/***********************************************************************/
-/* User interface functions */
-/***********************************************************************/
-
-static void GraphUpdateGW (void)
-{
- Rect r;
- WStatusH st = WinGetStatus (winGraphics);
-
- Assert (st != NULL);
- Assert (gworld != NULL);
- WELongRectToRect (&(*st)->destrect, &r);
- OffsetRect (&r, winGraphics->portRect.left, winGraphics->portRect.top);
- UpdateGWorld (&gworld, 0, &r, NULL, NULL, clipPix);
-}
-
-void GraphNewSizePos (void)
-{
- GraphUpdateGW ();
-}
-
-/* The current port must be winGraphics when this function is called. */
-void GraphUpdate (void)
-{
- Rect r, src, dst;
- Boolean good;
- WStatusH st = WinGetStatus (winGraphics);
- RGBColor forecolor, backcolor;
-
- Assert (st != NULL);
- GraphUpdateGW ();
- good = LockPixels (GetGWorldPixMap (gworld)); Assert (good);
- WELongRectToRect (&(*st)->destrect, &r);
- WELongRectToRect (&(*st)->viewrect, &dst);
- src = dst;
- OffsetRect (&src, -r.left, -r.top);
- GetBackColor (&backcolor);
- GetForeColor (&forecolor);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyBits (&((GrafPtr) gworld)->portBits, &((GrafPtr) winGraphics)->portBits,
- &src, &dst, srcCopy, NULL);
- RGBBackColor (&backcolor);
- RGBForeColor (&forecolor);
- UnlockPixels (GetGWorldPixMap (gworld));
-}
-
-/* All scrolling of the graphics window must go through this function
- so it can update the coordinates x0 and y0, and the pen location. */
-void GraphScroll (long dx, long dy)
-{
- Rect r;
- RgnHandle update = NewRgn ();
- WStatusH st = WinGetStatus (winGraphics);
- Point p;
- GrafPtr port;
-
- Assert (st != NULL);
- GetPort (&port);
- SetPort (winGraphics);
- WELongRectToRect (&(*st)->viewrect, &r);
- ScrollRect (&r, dx, dy, update);
- WEOffsetLongRect (&(*st)->destrect, dx, dy);
- SetClip (update);
- GraphUpdate ();
- ClipRect (&maxrect);
- DisposeRgn (update);
-
- x0 += dx;
- y0 += dy;
- GetPen (&p);
- MoveTo (p.h + dx, p.v + dy);
- SetPort (port);
-}
-
-/* Graphics event queue */
-#define GraphQsize 15
-static EventRecord graphQ[GraphQsize];
-static int graphQlen = 0;
-
-#define Succ(x) ((x) >= GraphQsize ? 0 : (x)+1)
-
-void GraphGotEvent (EventRecord *evt)
-{
- GrafPort *saveport;
-
- if (graphQlen < GraphQsize) ++ graphQlen;
- memmove (&(graphQ[1]), &(graphQ[0]), (graphQlen - 1) * sizeof (graphQ[0]));
-
- graphQ[0] = *evt;
-
- PushWindowPort (winGraphics);
- GlobalToLocal (&(graphQ[0].where));
- PopPort;
-}
-static void DequeueEvent (int i)
-{
- -- graphQlen;
- memmove (&(graphQ[i]), &(graphQ[i+1]), (graphQlen - i) * sizeof (graphQ[0]));
-}
-
-/***********************************************************************/
-/* Primitives for the graphics library */
-/***********************************************************************/
-
-value gr_open_graph (value vgeometry);
-value gr_close_graph (value unit);
-value gr_sigio_signal (value unit);
-value gr_sigio_handler (value unit);
-value gr_display_mode (value flag);
-value gr_remember_mode (value flag);
-value gr_synchronize (value unit);
-value gr_clear_graph (value unit);
-value gr_size_x (value unit);
-value gr_size_y (value unit);
-value gr_set_color (value vrgb);
-value gr_plot (value vx, value vy);
-value gr_point_color (value vx, value vy);
-value gr_moveto (value vx, value vy);
-value gr_current_x (value unit);
-value gr_current_y (value unit);
-value gr_lineto (value vx, value vy);
-value gr_draw_rect (value vx, value vy, value vw, value vh);
-value gr_draw_arc (value *argv, int argc);
-value gr_draw_arc_nat (value, value, value, value, value, value);
-value gr_set_line_width (value vwidth);
-value gr_fill_rect (value vx, value vy, value vw, value vh);
-value gr_fill_poly (value vpoints);
-value gr_fill_arc (value *argv, int argc);
-value gr_fill_arc_nat (value, value, value, value, value, value);
-value gr_draw_char (value vchr);
-value gr_draw_string (value vstr);
-value gr_set_font (value vfontname);
-value gr_set_text_size (value vsz);
-value gr_text_size (value vstr);
-value gr_make_image (value varray);
-value gr_dump_image (value vimage);
-value gr_draw_image (value vimage, value vx, value vy);
-value gr_create_image (value vw, value vh);
-value gr_blit_image (value vimage, value vx, value vy);
-value gr_wait_event (value veventlist);
-value gr_sound (value vfreq, value vdur);
-value gr_set_window_title (value title);
-
-#define UNIMPLEMENTED(f, args) \
-value f args; \
-value f args \
-{ \
- failwith ("not implemented: " #f); \
- return Val_unit; /* not reached */ \
-}
-
-UNIMPLEMENTED (gr_window_id, (value unit))
-UNIMPLEMENTED (gr_open_subwindow, (value x, value y, value w, value h))
-UNIMPLEMENTED (gr_close_subwindow, (value id))
-
-
-/**** Ancillary macros and function */
-
-/* double-buffer or write-through */
-static int grdisplay_mode;
-static int grremember_mode;
-
-/* Current state */
-static long cur_x, cur_y;
-static short cur_width, cur_font, cur_size;
-/* see also fgcolor */
-
-
-/* Drawing off-screen and on-screen simultaneously. The following three
- macros must always be used together and in this order.
-*/
-/* 1. Begin drawing in the off-screen buffer. */
-#define BeginOff { \
- CGrafPtr _saveport_; \
- GDHandle _savegdev_; \
- Rect _cliprect_; \
- if (grremember_mode) { \
- GetGWorld (&_saveport_, &_savegdev_); \
- LockPixels (GetGWorldPixMap (gworld)); \
- SetGWorld ((CGrafPtr) gworld, NULL);
-
-/* 2. Continue with on-screen drawing. */
-#define On \
- SetGWorld (_saveport_, _savegdev_); \
- UnlockPixels (GetGWorldPixMap (gworld)); \
- } \
- if (grdisplay_mode) { \
- SetPort (winGraphics); \
- ScrollCalcGraph (winGraphics, &_cliprect_); \
- ClipRect (&_cliprect_);
-
-/* 3. Clean up after drawing. */
-#define EndOffOn \
- ClipRect (&maxrect); \
- SetPort ((GrafPtr) _saveport_); \
- } \
-}
-
-/* Set up the current port unconditionally. This is for functions that
- don't draw (measurements and setting the graphport state).
- Usage: BeginOffAlways / EndOffAlways
- or BeginOffAlways / OnAlways / EndOffOnAlways
- */
-#define BeginOffAlways { \
- CGrafPtr _saveport_; \
- GDHandle _savegdev_; \
- GetGWorld (&_saveport_, &_savegdev_); \
- LockPixels (GetGWorldPixMap (gworld)); \
- SetGWorld ((CGrafPtr) gworld, NULL);
-
-#define EndOffAlways \
- SetGWorld (_saveport_, _savegdev_); \
- UnlockPixels (GetGWorldPixMap (gworld)); \
-}
-
-#define OnAlways \
- SetGWorld (_saveport_, _savegdev_); \
- UnlockPixels (GetGWorldPixMap (gworld)); \
- SetPort (winGraphics); \
-
-#define EndOffOnAlways \
- SetPort ((GrafPtr) _saveport_); \
-}
-
-/* Convert a red, green, or blue value from 8 bits to 16 bits. */
-#define RGB8to16(x) ((x) | ((x) << 8))
-
-/* Declare and convert x and y from vx and vy. */
-#define XY long x = Long_val (vx), y = Long_val (vy)
-
-
-static value * graphic_failure_exn = NULL;
-
-static void gr_fail(char *fmt, void *arg)
-{
- char buffer[1024];
-
- if (graphic_failure_exn == NULL) {
- graphic_failure_exn = caml_named_value("Graphics.Graphic_failure");
- if (graphic_failure_exn == NULL){
- invalid_argument("Exception Graphics.Graphic_failure not initialized,"
- " you must load graphics.cma");
- }
- }
- sprintf(buffer, fmt, arg);
- raise_with_string(*graphic_failure_exn, buffer);
-}
-
-static void gr_check_open (void)
-{
- if (winGraphics == NULL) gr_fail("graphic screen not opened", NULL);
-}
-
-/* Max_image_mem is the number of image pixels that can be allocated
- in one major GC cycle. The GC will speed up to match this allocation
- speed.
-*/
-#define Max_image_mem 1000000 /*FIXME Should use user pref. */
-
-#define Transparent (-1)
-
-struct grimage {
- final_fun f; /* Finalization function */
- long width, height; /* Dimensions of the image */
- GWorldPtr data; /* Pixels */
- GWorldPtr mask; /* Mask for transparent points, or NULL */
-};
-
-#define Grimage_wosize \
- ((sizeof (struct grimage) + sizeof (value) - 1) / sizeof (value))
-
-static void free_image (value vimage)
-{
- struct grimage *im = (struct grimage *) Bp_val (vimage);
-
- if (im->data != NULL) DisposeGWorld (im->data);
- if (im->mask != NULL) DisposeGWorld (im->mask);
-}
-
-static value alloc_image (long w, long h)
-{
- value res = alloc_final (Grimage_wosize, free_image, w*h, Max_image_mem);
- struct grimage *im = (struct grimage *) Bp_val (res);
- Rect r;
- QDErr err;
-
- im->width = w;
- im->height = h;
- im->mask = NULL;
- SetRect (&r, 0, 0, w, h);
- err = NewGWorld (&im->data, 32, &r, NULL, NULL, 0);
- if (err != noErr){
- im->data = NULL;
- gr_fail ("Cannot allocate image (error code %ld)", (void *) err);
- }
- return res;
-}
-
-static value gr_alloc_int_vect(mlsize_t size)
-{
- value res;
- mlsize_t i;
-
- if (size <= Max_young_wosize) {
- res = alloc(size, 0);
- } else {
- res = alloc_shr(size, 0);
- }
- for (i = 0; i < size; i++) {
- Field(res, i) = Val_long(0);
- }
- return res;
-}
-
-/***********************************************************************/
-
-value gr_open_graph (value vgeometry)
-{
- int i;
- short err;
- Rect r;
- WStatusH st;
-
- if (winGraphics == NULL){
- Assert (gworld == NULL);
-
- i = sscanf (String_val (vgeometry), "%ldx%ld", &w0, &h0);
- if (i < 2){
- w0 = 640;
- h0 = 480;
- }
- if (w0 < kMinWindowWidth - kScrollBarWidth - 1){
- w0 = kMinWindowWidth - kScrollBarWidth - 1;
- }
- if (h0 < kMinWindowHeight - kScrollBarWidth - 1){
- h0 = kMinWindowHeight - kScrollBarWidth - 1;
- }
-
- err = WinOpenGraphics (w0, h0);
- if (err != noErr) goto failed;
-
- x0 = y0 = 0;
-
- st = WinGetStatus (winGraphics); Assert (st != NULL);
- WELongRectToRect (&(*st)->destrect, &r);
- OffsetRect (&r, winGraphics->portRect.left, winGraphics->portRect.top);
- err = NewGWorld (&gworld, 0, &r, NULL, NULL, 0);
- if (err != noErr) goto failed;
-
- fgcolor.red = fgcolor.green = fgcolor.blue = 0;
- }
- /* Synchronise off-screen and on-screen by initialising everything. */
- grremember_mode = 1;
- grdisplay_mode = 1;
- gr_clear_graph (Val_unit);
- gr_moveto (Val_long (0), Val_long (0));
- gr_set_color (Val_long (0));
- gr_set_line_width (Val_long (0));
- gr_set_font ((value) "geneva"); /* XXX hack */
- gr_set_text_size (Val_long (12));
-
- return Val_unit;
-
- failed:
- if (gworld != NULL){
- DisposeGWorld (gworld);
- gworld = NULL;
- }
- if (winGraphics != NULL) WinCloseGraphics ();
- gr_fail ("open_graph failed (error %d)", (void *) (long) err);
- return Val_unit; /* not reached */
-}
-
-value gr_close_graph (value unit)
-{
-#pragma unused (unit)
- gr_check_open ();
- WinCloseGraphics ();
- DisposeGWorld (gworld);
- gworld = NULL;
- return Val_unit;
-}
-
-value gr_sigio_signal (value unit) /* Not used on MacOS */
-{
-#pragma unused (unit)
- return Val_unit;
-}
-
-value gr_sigio_handler (value unit) /* Not used on MacOS */
-{
-#pragma unused (unit)
- return Val_unit;
-}
-
-value gr_synchronize (value unit)
-{
-#pragma unused (unit)
- GrafPtr saveport;
-
- gr_check_open ();
- PushWindowPort (winGraphics);
- GraphUpdate ();
- PopPort;
- return Val_unit;
-}
-
-value gr_display_mode (value flag)
-{
- grdisplay_mode = Bool_val (flag);
- return Val_unit;
-}
-
-value gr_remember_mode (value flag)
-{
- grremember_mode = Bool_val (flag);
- return Val_unit;
-}
-
-value gr_clear_graph (value unit)
-{
-#pragma unused (unit)
- gr_check_open ();
- BeginOff
- EraseRect (&maxrect);
- On
- EraseRect (&maxrect);
- EndOffOn
- return unit;
-}
-
-value gr_size_x (value unit)
-{
-#pragma unused (unit)
- gr_check_open ();
- return Val_long (w0);
-}
-
-value gr_size_y (value unit)
-{
-#pragma unused (unit)
- gr_check_open ();
- return Val_long (h0);
-}
-
-value gr_set_color (value vrgb)
-{
- long rgb = Long_val (vrgb);
-
- gr_check_open ();
- fgcolor.red = RGB8to16 ((rgb >> 16) & 0xFF);
- fgcolor.green = RGB8to16 ((rgb >> 8) & 0xFF);
- fgcolor.blue = RGB8to16 (rgb & 0xFF);
- BeginOffAlways
- RGBForeColor (&fgcolor);
- OnAlways
- RGBForeColor (&fgcolor);
- EndOffOnAlways
- return Val_unit;
-}
-
-value gr_plot (value vx, value vy)
-{
- XY;
-
- gr_check_open ();
- BeginOff
- SetCPixel (Bx (x), By (y) - 1, &fgcolor);
- On
- SetCPixel (Wx (x), Wy (y) - 1, &fgcolor);
- EndOffOn
- return Val_unit;
-}
-
-value gr_point_color (value vx, value vy)
-{
- XY;
- RGBColor c;
-
- gr_check_open ();
- if (x < 0 || x >= w0 || y < 0 || y >= h0) return Val_long (-1);
- BeginOffAlways
- GetCPixel (Bx (x), By (y) - 1, &c);
- EndOffAlways
- return Val_long (((c.red & 0xFF00) << 8)
- | (c.green & 0xFF00)
- | ((c.blue & 0xFF00) >> 8));
-}
-
-value gr_moveto (value vx, value vy)
-{
- XY;
-
- gr_check_open ();
- cur_x = x; cur_y = y;
- return Val_unit;
-}
-
-value gr_current_x (value unit)
-{
-#pragma unused (unit)
-
- gr_check_open ();
- return Val_long (cur_x);
-}
-
-value gr_current_y (value unit)
-{
-#pragma unused (unit)
-
- gr_check_open ();
- return Val_long (cur_y);
-}
-
-value gr_lineto (value vx, value vy)
-{
- XY;
- int delta = cur_width / 2;
-
- gr_check_open ();
- BeginOff
- MoveTo (Bx (cur_x) - delta, By (cur_y) - delta);
- LineTo (Bx (x) - delta, By (y) - delta);
- On
- MoveTo (Wx (cur_x) - delta, Wy (cur_y) - delta);
- LineTo (Wx (x) - delta, Wy (y) - delta);
- EndOffOn
- cur_x = x; cur_y = y;
- return Val_unit;
-}
-
-value gr_draw_rect (value vx, value vy, value vw, value vh)
-{
- XY;
- long w = Long_val (vw), h = Long_val (vh);
- Rect r;
- int d1 = cur_width / 2;
- int d2 = cur_width - d1;
-
- gr_check_open ();
- BeginOff
- SetRect (&r, Bx (x) - d1, By (y+h) - d1, Bx (x+w) + d2, By (y) + d2);
- FrameRect (&r);
- On
- SetRect (&r, Wx (x) - d1, Wy (y+h) - d1, Wx (x+w) + d2, Wy (y) + d2);
- FrameRect (&r);
- EndOffOn
- return Val_unit;
-}
-
-value gr_draw_arc (value *argv, int argc)
-{
-#pragma unused (argc)
- return gr_draw_arc_nat (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
-}
-
-value gr_draw_arc_nat (value vx, value vy, value vrx, value vry, value va1,
- value va2)
-{
- XY;
- long rx = Long_val (vrx), ry = Long_val (vry);
- long a1 = Long_val (va1), a2 = Long_val (va2);
- Rect r;
- long qda1 = 90 - a1, qda2 = 90 - a2;
- int d1 = cur_width / 2;
- int d2 = cur_width - d1;
-
- gr_check_open ();
- BeginOff
- SetRect (&r, Bx(x-rx) - d1, By(y+ry) - d1, Bx(x+rx) + d2, By(y-ry) + d2);
- FrameArc (&r, qda1, qda2 - qda1);
- On
- SetRect (&r, Wx(x-rx) - d1, Wy(y+ry) - d1, Wx(x+rx) + d2, Wy(y-ry) + d2);
- FrameArc (&r, qda1, qda2 - qda1);
- EndOffOn
- return Val_unit;
-}
-
-value gr_set_line_width (value vwidth)
-{
- short width = Int_val (vwidth);
-
- if (width == 0) width = 1;
- gr_check_open ();
- BeginOffAlways
- PenSize (width, width);
- OnAlways
- PenSize (width, width);
- EndOffOnAlways
- cur_width = width;
- return Val_unit;
-}
-
-value gr_fill_rect (value vx, value vy, value vw, value vh)
-{
- XY;
- long w = Long_val (vw), h = Long_val (vh);
- Rect r;
-
- gr_check_open ();
- BeginOff
- SetRect (&r, Bx (x), By (y+h), Bx (x+w), By (y));
- PaintRect (&r);
- On
- SetRect (&r, Wx (x), Wy (y+h), Wx (x+w), Wy (y));
- PaintRect (&r);
- EndOffOn
- return Val_unit;
-}
-
-value gr_fill_poly (value vpoints)
-{
- long i, n = Wosize_val (vpoints);
- PolyHandle p;
-
- #define Bxx(i) Bx (Int_val (Field (Field (vpoints, (i)), 0)))
- #define Byy(i) By (Int_val (Field (Field (vpoints, (i)), 1)))
-
- gr_check_open ();
- if (n < 1) return Val_unit;
-
- p = OpenPoly ();
- MoveTo (Bxx (0), Byy (0));
- for (i = 1; i < n; i++) LineTo (Bxx (i), Byy (i));
- ClosePoly ();
- BeginOff
- PaintPoly (p);
- On
- OffsetPoly (p, x0, y0);
- PaintPoly (p);
- EndOffOn
- KillPoly (p);
- return Val_unit;
-}
-
-value gr_fill_arc (value *argv, int argc)
-{
-#pragma unused (argc)
- return gr_fill_arc_nat (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
-}
-
-value gr_fill_arc_nat (value vx, value vy, value vrx, value vry, value va1,
- value va2)
-{
- XY;
- long rx = Long_val (vrx), ry = Long_val (vry);
- long a1 = Long_val (va1), a2 = Long_val (va2);
- Rect r;
- long qda1 = 90 - a1, qda2 = 90 - a2;
-
- gr_check_open ();
- BeginOff
- SetRect (&r, Bx (x-rx), By (y+ry), Bx (x+rx), By (y-ry));
- PaintArc (&r, qda1, qda2 - qda1);
- On
- SetRect (&r, Wx (x-rx), Wy (y+ry), Wx (x+rx), Wy (y-ry));
- PaintArc (&r, qda1, qda2 - qda1);
- EndOffOn
- return Val_unit;
-}
-
-static void draw_text (char *txt, unsigned long len)
-{
- FontInfo info;
- unsigned long w;
-
- if (len > 32767) len = 32767;
-
- BeginOffAlways
- GetFontInfo (&info);
- w = TextWidth (txt, 0, len);
- EndOffAlways
-
- gr_check_open ();
- BeginOff
- MoveTo (Bx (cur_x), By (cur_y) - info.descent);
- DrawText (txt, 0, len);
- On
- MoveTo (Wx (cur_x), Wy (cur_y) - info.descent);
- DrawText (txt, 0, len);
- EndOffOn
- cur_x += w;
-}
-
-value gr_draw_char (value vchr)
-{
- char c = Int_val (vchr);
-
- draw_text (&c, 1);
- return Val_unit;
-}
-
-value gr_draw_string (value vstr)
-{
- mlsize_t len = string_length (vstr);
- char *str = String_val (vstr);
-
- draw_text (str, len);
- return Val_unit;
-}
-
-value gr_set_font (value vfontname)
-{
- Str255 pfontname;
- short fontnum;
-
- gr_check_open ();
- CopyCStringToPascal (String_val (vfontname), pfontname);
- GetFNum (pfontname, &fontnum);
- BeginOffAlways
- TextFont (fontnum);
- OnAlways
- TextFont (fontnum);
- EndOffOnAlways
- cur_font = fontnum;
- return Val_unit;
-}
-
-value gr_set_text_size (value vsz)
-{
- short sz = Int_val (vsz);
-
- gr_check_open ();
- BeginOffAlways
- TextSize (sz);
- OnAlways
- TextSize (sz);
- EndOffOnAlways
- cur_size = sz;
- return Val_unit;
-}
-
-value gr_text_size (value vstr)
-{
- mlsize_t len = string_length (vstr);
- char *str = String_val (vstr);
- value result = alloc_tuple (2);
- FontInfo info;
- long w, h;
-
- BeginOffAlways
- GetFontInfo (&info);
- w = TextWidth (str, 0, len);
- h = info.ascent + info.descent;
- EndOffAlways
- Field (result, 0) = Val_long (w);
- Field (result, 1) = Val_long (h);
- return result;
-}
-
-value gr_make_image (value varray)
-{
- long height = Wosize_val (varray);
- long width;
- long x, y;
- GWorldPtr w;
- value result, line;
- long color;
- RGBColor qdcolor;
- int has_transp = 0;
- CGrafPtr saveport;
- GDHandle savegdev;
-
- gr_check_open ();
- if (height == 0) return alloc_image (0, 0);
- width = Wosize_val (Field (varray, 0));
- for (y = 1; y < height; y++){
- if (Wosize_val (Field (varray, y)) != width){
- gr_fail("make_image: lines of different lengths", NULL);
- }
- }
-
- result = alloc_image (width, height);
- w = ((struct grimage *) Bp_val (result))->data;
-
- LockPixels (GetGWorldPixMap (w));
- GetGWorld (&saveport, &savegdev);
- SetGWorld ((CGrafPtr) w, NULL);
- for (y = 0; y < height; y++){
- line = Field (varray, y);
- for (x = 0; x < width; x++){
- color = Long_val (Field (line, x));
- if (color == Transparent) has_transp = 1;
- qdcolor.red = ((color >> 16) & 0xFF) | ((color >> 8) & 0xFF00);
- qdcolor.green = ((color >> 8) & 0xFF) | (color & 0xFF00);
- qdcolor.blue = (color & 0xFF) | ((color << 8) & 0xFF00);
- SetCPixel (x, y, &qdcolor);
- }
- }
- UnlockPixels (GetGWorldPixMap (w));
-
- if (has_transp){
- Rect r;
- QDErr err;
-
- SetRect (&r, 0, 0, width, height);
- err = NewGWorld (&w, 1, &r, NULL, NULL, 0);
- if (err != noErr){
- SetGWorld (saveport, savegdev);
- gr_fail ("Cannot allocate image (error code %d)", (void *) err);
- }
- LockPixels (GetGWorldPixMap (w));
- SetGWorld ((CGrafPtr) w, NULL);
- EraseRect (&maxrect);
- qdcolor.red = qdcolor.green = qdcolor.blue = 0;
- for (y = 0; y < height; y++){
- line = Field (varray, y);
- for (x = 0; x < width; x++){
- color = Long_val (Field (line, x));
- if (color != Transparent) SetCPixel (x, y, &qdcolor);
- }
- }
- UnlockPixels (GetGWorldPixMap (w));
- ((struct grimage *) Bp_val (result))->mask = w;
- }
-
- SetGWorld (saveport, savegdev);
-
- return result;
-}
-
-value gr_dump_image (value vimage)
-{
- value result = Val_unit;
- struct grimage *im = (struct grimage *) Bp_val (vimage);
- long width = im->width;
- long height = im->height;
- long x, y;
- GWorldPtr wdata = im->data;
- GWorldPtr wmask = im->mask;
- CGrafPtr saveport;
- GDHandle savegdev;
- RGBColor qdcolor;
- value line;
-
- gr_check_open ();
- Begin_roots2 (vimage, result);
- result = gr_alloc_int_vect (height);
- for (y = 0; y < height; y++){
- value v = gr_alloc_int_vect (width);
- modify (&Field (result, y), v);
- }
- End_roots ();
- GetGWorld (&saveport, &savegdev);
- LockPixels (GetGWorldPixMap (wdata));
- SetGWorld (wdata, NULL);
- for (y = 0; y < height; y++){
- line = Field (result, y);
- for (x = 0; x < width; x++){
- GetCPixel (x, y, &qdcolor);
- Field (line, x) = Val_long (((qdcolor.red & 0xFF00) << 8)
- | (qdcolor.green & 0xFF00)
- | ((qdcolor.blue & 0xFF00) >> 8));
- }
- }
- UnlockPixels (GetGWorldPixMap (wdata));
- if (wmask != NULL){
- LockPixels (GetGWorldPixMap (wmask));
- SetGWorld (wmask, NULL);
- for (y = 0; y < height; y++){
- line = Field (result, y);
- for (x = 0; x < width; x++){
- if (!GetPixel (x, y)) Field (line, x) = Val_long (Transparent);
- }
- }
- UnlockPixels (GetGWorldPixMap (wmask));
- }
- SetGWorld (saveport, savegdev);
- return result;
-}
-
-value gr_draw_image (value vimage, value vx, value vy)
-{
- XY;
- struct grimage *im = (struct grimage *) Bp_val (vimage);
- RGBColor forecolor, backcolor;
- Rect srcrect, dstrect;
-
- SetRect (&srcrect, 0, 0, im->width, im->height);
- if (im->mask != NULL){
- LockPixels (GetGWorldPixMap (im->data));
- LockPixels (GetGWorldPixMap (im->mask));
- BeginOff
- SetRect (&dstrect, Bx (x), By (y+im->height), Bx (x+im->width), By (y));
- GetBackColor (&backcolor);
- GetForeColor (&forecolor);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyMask (&((GrafPtr) im->data)->portBits,
- &((GrafPtr) im->mask)->portBits,
- &((GrafPtr) gworld)->portBits,
- &srcrect, &srcrect, &dstrect);
- RGBBackColor (&backcolor);
- RGBForeColor (&forecolor);
- On
- SetRect (&dstrect, Wx (x), Wy (y+im->height), Wx (x+im->width), Wy (y));
- GetBackColor (&backcolor);
- GetForeColor (&forecolor);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyMask (&((GrafPtr) im->data)->portBits,
- &((GrafPtr) im->mask)->portBits,
- &((GrafPtr) winGraphics)->portBits,
- &srcrect, &srcrect, &dstrect);
- RGBBackColor (&backcolor);
- RGBForeColor (&forecolor);
- EndOffOn
- UnlockPixels (GetGWorldPixMap (im->data));
- UnlockPixels (GetGWorldPixMap (im->mask));
- }else{
- LockPixels (GetGWorldPixMap (im->data));
- BeginOff
- SetRect (&dstrect, Bx (x), By (y+im->height), Bx (x+im->width), By (y));
- GetBackColor (&backcolor);
- GetForeColor (&forecolor);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyBits (&((GrafPtr) im->data)->portBits, &((GrafPtr) gworld)->portBits,
- &srcrect, &dstrect, srcCopy, NULL);
- RGBBackColor (&backcolor);
- RGBForeColor (&forecolor);
- On
- SetRect (&dstrect, Wx (x), Wy (y+im->height), Wx (x+im->width), Wy (y));
- GetBackColor (&backcolor);
- GetForeColor (&forecolor);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyBits (&((GrafPtr) im->data)->portBits,
- &((GrafPtr) winGraphics)->portBits, &srcrect, &dstrect, srcCopy,
- NULL);
- RGBBackColor (&backcolor);
- RGBForeColor (&forecolor);
- EndOffOn
- UnlockPixels (GetGWorldPixMap (im->data));
- }
- return Val_unit;
-}
-
-value gr_create_image (value vw, value vh)
-{
- return alloc_image (Long_val (vw), Long_val (vh));
-}
-
-value gr_blit_image (value vimage, value vx, value vy)
-{
- XY;
- struct grimage *im = (struct grimage *) Bp_val (vimage);
- Rect srcrect, dstrect, worldrect;
- CGrafPtr saveport;
- GDHandle savegdev;
-
- SetRect (&worldrect, 0, 0, w0, h0);
- SetRect (&srcrect, Bx (x), By (y+im->height), Bx (x+im->width), By (y));
- SectRect (&srcrect, &worldrect, &srcrect);
- dstrect = srcrect;
- OffsetRect (&dstrect, -Bx (x), -By (y+im->height));
-
- LockPixels (GetGWorldPixMap (im->data));
- LockPixels (GetGWorldPixMap (gworld));
- GetGWorld (&saveport, &savegdev);
- SetGWorld (im->data, NULL);
- BackColor (whiteColor);
- ForeColor (blackColor);
- CopyBits (&((GrafPtr) gworld)->portBits, &((GrafPtr) im->data)->portBits,
- &srcrect, &dstrect, srcCopy, NULL);
- SetGWorld (saveport, savegdev);
- UnlockPixels (GetGWorldPixMap (im->data));
- UnlockPixels (GetGWorldPixMap (gworld));
- return Val_unit;
-}
-
-int motion_requested = 0;
-short motion_oldx, motion_oldy;
-/* local coord versions of motion_oldx, motion_oldy */
-static Point lastpt = {SHRT_MAX - 1, SHRT_MAX - 1};
-
-#define Button_down_val 0
-#define Button_up_val 1
-#define Key_pressed_val 2
-#define Mouse_motion_val 3
-#define Poll_val 4
-
-value gr_wait_event (value veventlist)
-{
- int askmousedown = 0, askmouseup = 0, askkey = 0, askmotion = 0, askpoll = 0;
- GrafPtr saveport;
- value result;
- int mouse_x, mouse_y, button, keypressed, key;
- Point pt;
- int i;
-
- gr_check_open();
- PushWindowPort (winGraphics);
-
- while (veventlist != Val_int (0)) {
- switch (Int_val(Field (veventlist, 0))) {
- case Button_down_val: askmousedown = 1; break;
- case Button_up_val: askmouseup = 1; break;
- case Key_pressed_val: askkey = 1; break;
- case Mouse_motion_val: askmotion = 1; break;
- case Poll_val: askpoll = 1; break;
- default: Assert (0);
- }
- veventlist = Field (veventlist, 1);
- }
-
- enter_blocking_section ();
-
- while (1){
- while (graphQlen > 0 && graphQ[0].when + 300 < TickCount ()){
- DequeueEvent (0);
- }
- for (i = graphQlen - 1; i >= 0; i--){
- int what = graphQ[i].what;
- if (askpoll){
- if (what == keyDown || what == autoKey){
- GetMouse (&pt);
- mouse_x = pt.h;
- mouse_y = pt.v;
- button = Button ();
- keypressed = 1;
- key = graphQ[i].message & charCodeMask;
- goto gotevent;
- }
- }else if ( askmousedown && what == mouseDown
- || askmouseup && what == mouseUp){
- mouse_x = graphQ[i].where.h;
- mouse_y = graphQ[i].where.v;
- button = graphQ[i].what == mouseDown;
- keypressed = 0;
- DequeueEvent (i);
- goto gotevent;
- }else if (askkey && (what == keyDown || what == autoKey)){
- mouse_x = graphQ[i].where.h;
- mouse_y = graphQ[i].where.v;
- button = Button ();
- keypressed = 1;
- key = graphQ[i].message & charCodeMask;
- DequeueEvent (i);
- goto gotevent;
- }
- }
- GetMouse (&pt);
- if (askpoll || askmotion && (pt.h != lastpt.h || pt.v != lastpt.v)){
- mouse_x = pt.h;
- mouse_y = pt.v;
- button = Button ();
- keypressed = 0;
- goto gotevent;
- }
- if (askmotion){
- motion_requested = 1;
- pt = lastpt;
- LocalToGlobal (&pt);
- motion_oldx = pt.h;
- motion_oldy = pt.v;
- }
- GetAndProcessEvents (askmotion ? waitMove : waitEvent,
- motion_oldx, motion_oldy);
- }
-
- gotevent:
- PopPort;
- leave_blocking_section (); /* acquire master lock, handle signals */
- lastpt.h = mouse_x;
- lastpt.v = mouse_y;
- motion_requested = 0;
-
- result = alloc_tuple (5);
- Field (result, 0) = Val_int (Cx (mouse_x));
- Field (result, 1) = Val_int (Cy (mouse_y));
- Field (result, 2) = Val_bool (button);
- Field (result, 3) = Val_bool (keypressed);
- Field (result, 4) = Val_int (key);
- return result;
-}
-
-value gr_sound (value vfreq, value vdur)
-{
- long freq = Long_val (vfreq);
- long dur = Long_val (vdur);
- long scale;
- Handle h;
- OSErr err;
-
- if (dur <= 0 || freq <= 0) return Val_unit;
- if (dur > 5000) dur = 5000;
- if (freq > 20000) gr_fail ("sound: frequency is too high", NULL);
-
- if (freq > 11025) scale = 2;
- else if (freq > 5513) scale = 4;
- else if (freq > 1378) scale = 8;
- else if (freq > 345) scale = 32;
- else if (freq > 86) scale = 128;
- else scale = 512;
-
- h = GetResource ('snd ', 1000 + scale);
- if (h == NULL){
- gr_fail ("sound: resource error (code = %ld)", (void *) (long) ResError ());
- }
- err = HandToHand (&h);
- if (err != noErr) gr_fail ("sound: out of memory", NULL);
- *(unsigned short *)((*h)+kDurationOffset) = dur * 2;
- Assert (scale * freq < 0x10000);
- *(unsigned short *)((*h)+kSampleRateOffset) = scale * freq;
- HLock (h);
- err = SndPlay (NULL, (SndListHandle) h, false);
- HUnlock (h);
- if (err != noErr){
- gr_fail ("sound: cannot play sound (error code %ld)", (void *) (long) err);
- }
-
- return Val_unit;
-}
-
-value gr_set_window_title (value title)
-{
- Str255 ptitle;
-
- strcpy ((char *) ptitle, String_val (title));
- c2pstr ((char *) ptitle);
- SetWTitle (winGraphics, ptitle);
- return Val_unit;
-}