view.c - A Mandlebrot set viewer for Apollos.
John W Peterson
peterson at utah-cs.UUCP
Mon Oct 7 12:10:41 AEST 1985
/*
* view.c - View mandlebrot sets on an Apollo display
*
* Author: J. W. Peterson,
* based on "ibmcg4" by Bennett Todd @ Duke University.
*
* Computer Science Dept.
* University of Utah
* Date: Fri Sep 20 1985
* Copyright (c) 1985 J. W. Peterson
*
*/
/* View the mandlebrot set on a Color apollo (assumes 8 bit display) */
/*
* view [name]
* Display file name.pic created by "compute" on an Apollo color display
* Works best with 8 bit color, but can produce interesting results on
* bitmapped displays.
*
* This version is extended to you to use the mouse to find new regions
* for "exploration". The program will print out the coordinates
* and the "scale" of the box defined by the last two mouse selections
* (bottom left and top right).
*
* The "c" mouse key (whatever that is on your particular mouse)
* exits the program.
*/
#include <stdio.h>
#include "/sys/ins/base.ins.c"
#include "/sys/ins/gpr.ins.c"
#include "/sys/ins/pad.ins.c"
#include "/sys/ins/streams.ins.c"
status_$t status;
stream_$id_t out_stream;
gpr_$pixel_value_t scanline[2000];
int hpix, vpix;
#define MAXNAMELEN 64 /* max filename length for MS-DOS */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef EOF
#define EOF (-1)
#endif
#define ISSUFFIX(s1, s2) !strcmp((s1), (s2)+strlen(s2)-strlen(s1))
main(argc, argv)
int argc;
char **argv;
{
char name[MAXNAMELEN];
char ch;
FILE *fp, *fopen();
int i, j, n;
double center_r,
center_i,
scale_r,
scale_i,
new_r, new_i, last_r, last_i;
char colormax[4];
int npix, count[256], temp_l;
if (argc == 2)
if (ISSUFFIX(".pic", argv[1]))
strncpy(name, argv[1], MAXNAMELEN);
else {
strncpy(name, argv[1], MAXNAMELEN-4);
strcat(name, ".pic");
}
else {
printf("syntax: view [name]\n");
printf("Name: ");
gets(name);
}
if (!ISSUFFIX(".pic", name))
strcat(name, ".pic");
while ((fp = fopen(name, "r")) == NULL) {
fprintf(stderr, "view: cannot open %s\n", name);
printf("Name: ");
gets(name);
if (!ISSUFFIX(".pic", name))
strcat(name, ".pic");
}
if (fscanf(fp, "Centered at %lf+%lfi, scale %lf+%lfi, %dx%d\n\032",
¢er_r, ¢er_i, &scale_r, &scale_i, &hpix, &vpix) != 6) {
fprintf(stderr, "view: cannot parse header of %s\n", name);
exit(1);
}
npix = hpix*vpix;
printf("Reading %s centered at %lf+%lfi, scale %lf+%lfi, %dx%d\n",
name, center_r, center_i, scale_r, scale_i, hpix, vpix);
setup_scr(hpix,vpix);
for (i=0; i<vpix; i++) {
for (j=0; j<hpix; j++) {
if ((n=getc(fp)) == EOF) {
fprintf(stderr, "view: too few pixels!\n");
exit(1);
}
putpoint(j, i, (n==255) ? 0 : n ); /* 255 = Black */
}
flushline(i);
}
/* Allow the user to interactivly select points on the grid. Code
* will print out the center & scale of the box defined by the
* last two points (lower left, upper right) selected. */
last_r = 0.0; last_i = 0.0;
do {
get_cursor( &i, &j, &ch );
new_r = (center_r - scale_r) + i * (2*scale_r/hpix);
new_i = (center_i + scale_i) - j * (2*scale_i/vpix);
printf("center=%lf+%lfi scale=%lf+%lfi\n",
(new_r + last_r)/2.0, (new_i + last_i)/2.0,
(new_r-last_r)/2.0, (new_i-last_i)/2.0 );
last_r = new_r; last_i = new_i;
} while (ch != 'c');
}
/* Apollo dependant code (warning - status codes aren't checked) */
/* Initialize the display, by popping up a new window to draw the picture
* in. */
setup_scr(hsize,vsize)
int hsize,vsize;
{
gpr_$offset_t size;
gpr_$color_vector_t colmap;
gpr_$attribute_desc_t hidden_desc;
unsigned int value;
int i;
name_$pname_t output_file;
short len;
gpr_$window_t dest_box;
pad_$window_desc_t window_shape;
static gpr_$bitmap_desc_t main_bitmap;
short fontid;
/* Open a separate window to display the results */
window_shape.top = 0;
window_shape.left = 0;
window_shape.width = (short)hsize + 5;
window_shape.height = (short)vsize + 5;
pad_$create_window( "", (short) 0, pad_$transcript, (short) 1,
window_shape, out_stream, status );
pad_$set_auto_close( out_stream, (short) 1, true, status );
size.x_size = 1024; /* GPR will shrink to fit */
size.y_size = 1024;
/* Initialize the graphics primitives package */
gpr_$init(gpr_$direct,
out_stream, /* "unit" */
size, /* size of the initial bitmap */
7, /* identifier of the heightest
numbered bitmap plane */
main_bitmap, /* resulting bitmap descriptor */
status);
gpr_$set_auto_refresh( true, status ); /* all yours, DM. */
gpr_$acquire_display( status ) ;
/* set the new bitmap descriptor to be the 'current bitmap' */
gpr_$set_bitmap(main_bitmap,status);
gpr_$clear( gpr_$black, status );
gpr_$release_display( status );
/* Set up the color map. I like the results this produces, however
* there's an awful lot of room available for creative tweaking here.
* (Note pixels between 255-16 and 254 may wrap around...)
*/
for(i = 0; i < 256; i++) {
colmap[i] = ((i * 4) % 128) + 127;
colmap[i] |= i << 9;
colmap[i] |= ((i * 2) & 0xFF) << 16 ;
}
colmap[0] = gpr_$black; /* assure 0 is black */
gpr_$acquire_display( status ) ;
/* 16 is offset from DM window colors */
gpr_$set_color_map( (int) 16, 255 - 16 , colmap, status );
gpr_$release_display( status );
init_cursor();
}
/*
* Pixels are buffered on a Scanline basis - this increases the drawing
* speed by an order of magnitude or so...
*/
putpoint(x, y, c)
int x, y, c;
{
scanline[x] = c + 16; /* "+16" avoids DM colors, but can wrap around.. */
}
flushline(y)
int y;
{
gpr_$window_t dest_box;
dest_box.window_base.x_coord = 0;
dest_box.window_base.y_coord = y;
dest_box.window_size.x_size = hpix;
dest_box.window_size.y_size = 1;
gpr_$acquire_display(status);
gpr_$write_pixels( scanline, dest_box, status);
gpr_$release_display( status );
}
/* Cursor handling code (translated from an old Pascal program...) */
/* Do all the grunge to initialize a cross-hair cursor */
init_cursor()
{
static gpr_$bitmap_desc_t CursorBitmap;
static gpr_$attribute_desc_t AttribBlock;
static gpr_$keyset_t keyset;
gpr_$position_t Pos; /* Cursor offset */
gpr_$offset_t Size; /* Cursor bitmap size */
gpr_$bitmap_desc_t Bitmap; /* System bitmap */
Size.x_size = 15; Size.y_size = 15;
gpr_$inq_bitmap(Bitmap, status); /* save the original bitmap */
gpr_$allocate_attribute_block(AttribBlock,status);
/*Now that we have a set of attributes, make a bitmap to store the cursor*/
gpr_$allocate_bitmap(Size, (gpr_$plane_t) 0, /*Plane ID*/
AttribBlock, /*Attribute block*/
CursorBitmap,
status);
gpr_$set_bitmap(CursorBitmap,status); /*Set graphics to cursor bitmap*/
/*Draw cross-hair pattern*/
gpr_$move((gpr_$coordinate_t) 0, (gpr_$coordinate_t) 7, status);
gpr_$line((gpr_$coordinate_t) 15, (gpr_$coordinate_t) 7, status);
gpr_$move((gpr_$coordinate_t) 7, (gpr_$coordinate_t) 0, status);
gpr_$line((gpr_$coordinate_t) 7, (gpr_$coordinate_t) 15, status);
gpr_$set_cursor_pattern(CursorBitmap, status); /*Assign bitmap to cursor*/
Pos.x_coord = 7;
Pos.y_coord = 7;
gpr_$set_cursor_origin(Pos, status); /*Center the origin*/
gpr_$set_bitmap(Bitmap, status); /*Reset the graphics to main bitmap*/
{ int i; /* Kludge for pascal sets */
for (i=0; i <= 7; i++)
{ keyset[i] = 0xFFFFFFFF; }}
gpr_$enable_input( gpr_$buttons, keyset, status );
gpr_$enable_input( gpr_$locator, keyset, status );
}
/* Read the cursor */
get_cursor( px, py, c )
int * px, * py;
char * c;
{
gpr_$position_t pos;
gpr_$event_t event;
char eventdata;
gpr_$acquire_display( status );
do {
gpr_$event_wait( event, eventdata, pos, status );
gpr_$set_cursor_active( false, status ); /* avoid cursor smear */
gpr_$set_cursor_position( pos, status );
gpr_$set_cursor_active( true, status );
} while ((event != gpr_$buttons) ||
((eventdata >= 'A') && (eventdata <= 'D'))); /* ignore 'up's */
gpr_$release_display( status );
*px = pos.x_coord;
*py = pos.y_coord;
*c = eventdata;
}
More information about the Comp.sources.unix
mailing list