/* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.

This file is part of Ghostscript.

Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.  Refer
to the Ghostscript General Public License for full details.

Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License.  A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities.  It should be in a file named COPYING.  Among other
things, the copyright notice and this notice must be preserved on all
copies.  */

/* ega.c */
/* EGA graphics hacks */
#define interrupt			/* patch ANSI incompatibility */
#include <dos.h>
#include "math_.h"
#include "stdio_.h"
#include "gstypes.h"
#include "gsmatrix.h"			/* for gxdevice.h */
#include "gxdevice.h"

/* Stuff in gdevpcfb.c */
#define pcfb_device gs_vga_device
extern struct gx_device_s pcfb_device;
#define the_device (&pcfb_device)

/* Stubs for other GS stuff */
int
gx_device_adjust_resolution(gx_device *dev,
  int actual_width, int actual_height, int fit)
{	return 0;
}

float yDx = 35.0/48.0;			/* aspect ratio */
#define black (gx_color_index)0
#define green (gx_color_index)2
#define blue (gx_color_index)9
#define red (gx_color_index)12
#define yellow (gx_color_index)14
#define white (gx_color_index)15

main(int argc, char *argv[])
{	return real_main(argc, argv);
}
real_main(int argc, char *argv[])
{	/* Display all kinds of stuff */
	(*the_device->procs->open_device)(the_device);
	if ( !kbhit() ) paint1();
	if ( !kbhit() ) paint2();
	if ( !kbhit() ) paint3();
	if ( !kbhit() ) paint4();
	if ( !kbhit() ) test2();
	while ( !kbhit() ) ;
	(*the_device->procs->close_device)(the_device);
}

/* Stubs for gx procedures */
int gx_default_draw_line() { return -1; }
void gx_default_get_initial_matrix() { }
int gx_default_output_page() { return 0; }
int gx_default_sync_output() { return 0; }
int gx_default_tile_rectangle() { return -1; }
int gx_default_get_props() { return 0; }
int gx_default_put_props() { return 0; }

/* Display color samples */
paint1()
{	ushort r, g, b;
	ushort m = the_device->color_info.max_rgb;
	for ( r = 0; r <= m; r++ )
	 for ( g = 0; g <= m; g++ )
	  for ( b = 0; b <= m; b++ )
	{	int x = r * 30, y = (g*(m+1)+b) * 24;
		gx_color_index color =
		  (*the_device->procs->map_rgb_color)(the_device,
			(ushort)(r * 0xffffL / m),
			(ushort)(g * 0xffffL / m),
			(ushort)(b * 0xffffL / m));
		static unsigned char map[16] = {
			0xaa, 0xaa, 0xaa, 0, 0x55, 0x55, 0x55, 0,
			0xaa, 0xaa, 0xaa, 0, 0x55, 0x55, 0x55, 0
		   };
		(*the_device->procs->fill_rectangle)(the_device, x, y, 21, 8, color);
		(*the_device->procs->copy_mono)(the_device, map, 0, 4, gx_no_bitmap_id, x, y + 8, 21, 4, white, color);
		(*the_device->procs->copy_mono)(the_device, map, 0, 4, gx_no_bitmap_id, x, y + 12, 21, 4, black, color);
	}
	   {	int c;
		for ( c = 0; c <= 15; c++ )
		   {	(*the_device->procs->fill_rectangle)(the_device, 320+c*20, 0, 14, 11, (gx_color_index)c);
		   }
	   }
}

/* Tile with different color combinations */
paint2()
{	static byte pattern[] = {
	  0xaa,0xcc, 0x55,0xcc, 0xaa,0x33, 0x55,0x33,
	  0xaa,0xcc, 0x55,0xcc, 0xaa,0x33, 0x55,0x33,
	  0xf0,0xcc, 0xf0,0x66, 0xf0,0x33, 0xf0,0x99,
	  0x0f,0xcc, 0x0f,0x66, 0x0f,0x33, 0x0f,0x99
	};
	static gx_color_index colors[5] = { 0, 2, 6, 12, 0xf };
	gx_bitmap tile;
	int i, j;
	tile.data = pattern;
	tile.raster = 2;
	tile.size.x = tile.rep_width = 16;
	tile.size.y = tile.rep_height = 16;
	tile.id = gx_no_bitmap_id;
	for ( i = 0; i < 5; i++ )
	 for ( j = 0; j < 5; j++ )
		(*the_device->procs->tile_rectangle)(the_device, &tile, 212+i*44, 20+j*44, 32, 32, colors[i], colors[j], 0, 0);
}

/* Draw a turkey */
paint3()
{	static byte turkey[] = {
	  0x00,0x3b,0x00,0, 0x00,0x27,0x00,0, 0x00,0x24,0x80,0,
	  0x0e,0x49,0x40,0, 0x11,0x49,0x20,0, 0x14,0xb2,0x20,0,
	  0x3c,0xb6,0x50,0, 0x75,0xfe,0x88,0, 0x17,0xff,0x8c,0,
	  0x17,0x5f,0x14,0, 0x1c,0x07,0xe2,0, 0x38,0x03,0xc4,0,
	  0x70,0x31,0x82,0, 0xf8,0xed,0xfc,0, 0xb2,0xbb,0xc2,0,
	  0xbb,0x6f,0x84,0, 0x31,0xbf,0xc2,0, 0x18,0xea,0x3c,0,
	  0x0e,0x3e,0x00,0, 0x07,0xfc,0x00,0, 0x03,0xf8,0x00,0,
	  0x1e,0x18,0x00,0, 0x1f,0xf8,0x00,0
	};
	(*the_device->procs->fill_rectangle)(the_device, 0, 250, 30, 30, yellow);
	(*the_device->procs->copy_mono)(the_device, turkey, 0, 4, gx_no_bitmap_id, 0, 250, 24, 23, white, red);
	(*the_device->procs->copy_color)(the_device, turkey, 0, 4, gx_no_bitmap_id, 0, 280, 6, 23);
}

/* Copy patterns to the screen */
paint4()
{	static unsigned char box[] =
		{ 0xff,0xff,0,0, 0xc0,0x0c,0,0, 0xc0,0x0c,0,0, 0xc0,0x0c,0,0, 0xff,0xff,0,0
		};
	int i, j;
	(*the_device->procs->fill_rectangle)(the_device, 432 - 4, 20 - 4, 4 + 8 * 17 + 8, 4 + 8 * 17, green);
	for ( i = 0; i < 8; i++ )
	  for ( j = 0; j < 8; j++ )
		(*the_device->procs->copy_mono)(the_device, box, i, 4,
			gx_no_bitmap_id, 432 + (j * 17) + i, 20 + (i * 17),
			j + 1, 5, black, red);
}

/* Plot a circle 2 different ways */
plot_arc(P9(floatp, floatp, floatp, floatp, floatp, floatp, int, gx_color_index, floatp));
test2()
{	float kx = 200.0;
	float ky = -kx * yDx;
	float ox = 320.0, oy = 175.0;
	float x0 = ox - kx, y0 = oy - ky;
	float x1 = ox + kx, y1 = oy + ky;
	/* Plot a real circle */
	float i;
	for ( i = 0; i <= 360; i += 5 )
	   {	float theta = i * M_PI / 180.0;
		int x = ox + kx * cos(theta);
		int y = oy + ky * sin(theta);
		ega_write_dot(the_device, x, y, red);
	   }
	/* Plot with 90 degree arcs */
	   {	static float mar[] = { 0.5, 0.45, 0.4 };
		static gx_color_index car[] = { white, green, yellow };
		int j;
		for ( j = 0; j < 3; j++ )
		   {	float magic = mar[j];
			gx_color_index color = car[j];
			plot_arc(x1, oy, x1, y1, ox, y1, 40, color, magic);
			plot_arc(ox, y1, x0, y1, x0, oy, 40, color, magic);
			plot_arc(x0, oy, x0, y0, ox, y0, 40, color, magic);
			plot_arc(ox, y0, x1, y0, x1, oy, 40, color, magic);
		   }
	   }
}

/* Approximate an arc */
plot_curve(P10(floatp, floatp, floatp, floatp, floatp, floatp, floatp, floatp, int, gx_color_index));
plot_arc(floatp x0, floatp y0, floatp xi, floatp yi, floatp x3, floatp y3,
  int nsteps, gx_color_index color, floatp magic)
{	float cmagic = 1 - magic;
	float xic = xi * cmagic, yic = yi * cmagic;
	plot_curve(x0, y0, x0 * magic + xic, y0 * magic + yic,
		x3 * magic + xic, y3 * magic + yic, x3, y3,
		nsteps, color);
}

/* Plot a Bezier curve */
plot_curve(floatp x0, floatp y0, floatp x1, floatp y1,
  floatp x2, floatp y2, floatp x3, floatp y3,
  int nsteps, gx_color_index color)
{	float dt = 1.0 / nsteps;
	float cx = 3.0 * (x1 - x0);
	float bx = 3.0 * (x2 - x1) - cx;
	float ax = x3 - (x0 + cx + bx);
	float cy = 3.0 * (y1 - y0);
	float by = 3.0 * (y2 - y1) - cy;
	float ay = y3 - (y0 + cy + by);
	float t = 0.0;
	while ( t <= 1.0 )
	   {	int x = ((ax * t + bx) * t + cx) * t + x0;
		int y = ((ay * t + by) * t + cy) * t + y0;
		ega_write_dot(the_device, x, y, color);
		t += dt;
	   }
}
