[gnu.ghostscript.bug] Suntools support for ghostscript 1.2

ek@PRINCETON.EDU (Eleftherios Koutsofios) (03/14/89)

I just finished getting ghostscript 1.2 to run under suntools.

Here's file gdevsv.c, which can be used in place of gdevx.c,
or gdevega*. (you also need to change gsmain.c to use 'sv_device'
instead of x_device or whatever). Link with -lsuntool -lsunwindow -lpixrect.

It was tested on a sun3/60 running SunOS 4.0.1 and on a 3/50 running
SunOS 3.2.

Since there's no documentation describing things like the bitmap
format, or the exact semantics of arguments like 'one' and 'zero',
I had to make assumptions about them, which could of course be wrong,
so I would appreciate any feedback.

In this version of the code, suntools events are handled only when
the sv_sync function is called, which means that when gs is waiting
for input from the user (ie. when the GS> prompt is displayed), the only
way to get gs to respond to events (like resize, move, close, etc.)
is to press a few <CR>'s.

Lefteris Koutsofios  (ek@princeton.edu)

---------------------- cut here -------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	gdevsv.c
# This archive created: Mon Mar 13 16:02:41 1989
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'gdevsv.c'
then
	echo shar: "will not over-write existing file 'gdevsv.c'"
else
cat << \SHAR_EOF > 'gdevsv.c'
/* Copyright (C) 1989 Aladdin Enterprises.  All rights reserved.
   Distributed by Free Software Foundation, Inc.

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.  */

/* gdevsv.c */
/* SunView driver for GhostScript library */
/* Written by Lefteris Koutsofios (ek@princeton.edu) 3/12/89 */

#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <stdio.h>
#include <malloc.h>
#include <math.h>

/* defines uint and ushort.... */
#  define uint _uint
#  define ushort _ushort
#include "gx.h"			/* for gx_bitmap; includes std.h */
#  undef _uint
#  undef _ushort
#include "gxdevice.h"

/* Procedures */

int sv_open(P1(gx_device *));

int sv_close(P1(gx_device *));

int sv_map_rgb_color(P4(gx_device *, ushort, ushort, ushort));

int sv_map_color_rgb(P3(gx_device *, int, ushort *));

int sv_sync(P1(gx_device *));

int sv_fill_rectangle(P6(gx_device *, int, int, int, int, int));

int sv_tile_rectangle(P8(gx_device *, gx_bitmap *, int, int, int, int, int, int));

int sv_copy_mono(P10(gx_device *, byte *, int, int, int, int, int, int, int, int));

int sv_copy_color(P9(gx_device *, byte *, int, int, int, int, int, int, int));

int sv_draw_line(P6(gx_device *, int, int, int, int, int));

int sv_fill_trapezoid(P8(gx_device *, int, int, int, int, int, int, int));

/* The device descriptor */

static gx_device_procs sv_procs = {
  sv_open,
  sv_close,
  sv_map_rgb_color,
  sv_map_color_rgb,
  sv_sync,
  sv_fill_rectangle,
  sv_tile_rectangle,
  sv_copy_mono,
  sv_copy_color,
  sv_draw_line,
  sv_fill_trapezoid,
  gx_default_tile_trapezoid
};

/* Define the SunView device */

typedef struct gx_device_SV_s {
  gx_device_common;
  Frame   frame;
  Canvas  canvas;
  Pixwin *pw;
  int     depth;

  unsigned char   red[256], green[256], blue[256];
} gx_device_SV;

/* The instance is public. */

gx_device_SV sv_device = {
  sizeof(gx_device_SV),
  &sv_procs,
  612, 792,		/* x and y extent */

  /* Following parameters are initialized for color */

  1,			/* has color */
  255,			/* max r-g-b value */
  8,			/* bits per color pixel */

  /* End of monochrome/color parameters */

  1,			/* bit-big-endian (for now) */
};

/* Macro for casting gx_device argument */
#define svdev ((gx_device_SV *)dev)

static struct pixrect *pr1, *pr2, *pr3, *pr4, *pr5;

int
sv_open (gx_device *dev)
{
  int winW = svdev->width, winH = svdev->height;

  if (!(svdev->frame = window_create(NULL, FRAME, WIN_X, 0, WIN_Y, 0,
				     FRAME_LABEL, "Ghostscript", 0))) {
    fprintf(stderr, "Cannot open frame\n");
    exit(1);
  }
  if (!(svdev->canvas = window_create(svdev->frame, CANVAS,
				      WIN_WIDTH, winW, WIN_HEIGHT, winH, 
				      CANVAS_RETAINED, TRUE, 0))) {
    fprintf(stderr, "Cannot open canvas\n");
    exit(1);
  }
  svdev->pw = canvas_pixwin (svdev->canvas);
  svdev->depth = svdev->pw->pw_pixrect->pr_depth;

  if (svdev->depth == 1) {
    svdev->has_color = 0, svdev->max_rgb_value = 1;
    svdev->bits_per_color_pixel;
  } else
    setcmap (dev);

  window_fit (svdev->frame);
  window_set (svdev->frame, WIN_SHOW, TRUE, 0);

  if ((pr1 = mem_create (10, 10, 1)) == NULL ||
      (pr2 = mem_create (10, 10, svdev->depth)) == NULL ||
      (pr3 = mem_create (10, 10, 1)) == NULL ||
      (pr4 = mem_create (10, 10, 1)) == NULL ||
      (pr5 = mem_create (10, 10, svdev->depth)) == NULL) {
    fprintf (stderr, "Cannot allocate temporary pixrects\n");
    exit (1);
  }
  notify_dispatch ();
  return 0;
}

#define INVGAMMA  0.4
#define COLORINT 51.0

#define COLORSEG1  6
#define COLORSEG2 36

static int igm[256];

/* setcmap installs a gamma corrected colormap */
/* However, when the calling function asks for information about
   a color, (from functions: sv_map_rgb_color and sv_map_color_rgb)
   we respond as if a non gamma corrected colormap was used.
   If this isn't done the calling function seems to get confused. */

setcmap (gx_device *dev)
{
  int i, j, k, l;

  for (i = 0; i < 256; i++) {
    igm[i] = (int) (0.5 + 255 * pow (i / 255.0, INVGAMMA));
  }
  for (i = 0; i < COLORSEG1; i++)
    for (j = 0; j < COLORSEG1; j++)
      for (k = 0; k < COLORSEG1; k++) {
	l = i * COLORSEG2 + j * COLORSEG1 + k;
	svdev->red[l]   = igm[(int) (COLORINT * (COLORSEG1 - i - 1) + 0.5)];
	svdev->green[l] = igm[(int) (COLORINT * (COLORSEG1 - j - 1) + 0.5)];
	svdev->blue[l]  = igm[(int) (COLORINT * (COLORSEG1 - k - 1) + 0.5)];
      }
  pw_setcmsname (svdev->pw, "ghostscript");
  pw_putcolormap (svdev->pw, 0, 256, svdev->red, svdev->green, svdev->blue);
  for (i = 0; i < COLORSEG1; i++)
    for (j = 0; j < COLORSEG1; j++)
      for (k = 0; k < COLORSEG1; k++) {
	l = i * COLORSEG2 + j * COLORSEG1 + k;
	svdev->red[l]   = COLORINT * (COLORSEG1 - i - 1) + 0.5;
	svdev->green[l] = COLORINT * (COLORSEG1 - j - 1) + 0.5;
	svdev->blue[l]  = COLORINT * (COLORSEG1 - k - 1) + 0.5;
      }
}

/* Close the device. */

int
sv_close (gx_device *dev)
{
  window_destroy (svdev->canvas);
  window_destroy (svdev->frame);
  return 0;
}

/* Map a color.  The "device colors" are just r,g,b packed together. */

int
sv_map_rgb_color (register gx_device *dev, ushort r, ushort g, ushort b)
{
  int foo;
  if (svdev->has_color) {
    foo = ((COLORSEG1 - (int) (r / COLORINT) - 1) * COLORSEG2 +
	   (COLORSEG1 - (int) (g / COLORINT) - 1) * COLORSEG1 +
	   (COLORSEG1 - (int) (b / COLORINT) - 1));
  } else {
    if ((.3 * b + .59 * r + .11 * g) >= .5)
      foo = 0;
    else
      foo = 1;
  }

  return foo;
}

/* Map a "device color" back to r-g-b. */

int
sv_map_color_rgb (register gx_device *dev, int color, ushort *prgb)
{
  if (svdev->has_color) {
    prgb[0] = svdev->red[color];
    prgb[1] = svdev->green[color];
    prgb[2] = svdev->blue[color];
  } else {
    if (color == 1)
      prgb[0] = prgb[1] = prgb[2] = 0;
    else
      prgb[0] = prgb[1] = prgb[2] = 1;
  }
}

/* Synchronize the display with the commands already given */

int
sv_sync (register gx_device *dev)
{	
  notify_dispatch ();
  return 0;
}

/* Fill a rectangle with a color. */

int
sv_fill_rectangle (register gx_device *dev, 
		   int x, int y, int w, int h, int color)
{
  pw_rop (svdev->pw, x, y, w, h,
	  (color ? PIX_SRC | PIX_COLOR (color) : PIX_CLR), NULL, x, y);
  return 0;
}

/* Tile a rectangle. */

int
sv_tile_rectangle (register gx_device *dev, gx_bitmap *tile,
		   int x, int y, int w, int h, int zero, int one)
{
  char *data;

  int w0, w1, i, j;

  w0 = (tile->width + 7) / 8;
  w1 = ((tile->width + 15) / 16) * 2;
  if (pr1->pr_size.x != tile->width || pr1->pr_size.y != tile->height) {
    pr_destroy (pr1);
    pr1 = mem_create (tile->width, tile->height, 1);
  }
  data = (char *) mpr_d(pr1)->md_image;
  for (j = 0; j < tile->height; j++)
    for (i = 0; i < w0; i++)
      *(data + j * w1 + i) = *(tile->data + w0 * j + i);

  if (pr2->pr_size.x != w || pr2->pr_size.y != h) {
    pr_destroy (pr2);
    pr2 = mem_create (w, h, svdev->depth);
  } else
    pr_rop (pr2, 0, 0, w, h, PIX_CLR, pr2, 0, 0);

  if (pr3->pr_size.x != w || pr3->pr_size.y != h) {
    pr_destroy (pr3);
    pr3 = mem_create (w, h, 1);
  }

  if (one != -1) {
    if (one)
      pr_replrop (pr2, 0, 0, w, h, PIX_SRC | PIX_COLOR (one), pr1, 0, 0);
    pr_replrop (pr3, 0, 0, w, h, PIX_SRC, pr1, 0, 0);
    pw_stencil (svdev->pw, x, y, w, h, PIX_SRC, pr3, 0, 0, pr2, 0, 0);
  }

  pr_rop (pr2, 0, 0, w, h, PIX_CLR, pr2, 0, 0);
  if (zero != -1) {
    pr_rop (pr1, 0, 0, tile->width, tile->height, 
	    PIX_NOT (PIX_SRC), pr1, 0, 0);
    if (zero)
      pr_replrop (pr2, 0, 0, w, h, PIX_SRC | PIX_COLOR (zero), pr1, 0, 0);
    pr_replrop (pr3, 0, 0, w, h, PIX_SRC, pr1, 0, 0);
    pw_stencil (svdev->pw, x, y, w, h, PIX_SRC, pr3, 0, 0, pr2, 0, 0);
  }
  return 0;
}

/* Copy a monochrome bitmap. */

int
sv_copy_mono (register gx_device *dev, byte *base, int sourcex, int raster,
	      int x, int y, int w, int h, int zero, int one)
{
  char *data;

  int w0, w1, i, j;

  w0 = (w + 7) / 8;
  w1 = ((w + 15) / 16) * 2;
  if (pr4->pr_size.x != w || pr4->pr_size.y != h) {
    pr_destroy (pr4);
    pr4 = mem_create (w, h, 1);
  }
  data = (char *) mpr_d(pr4)->md_image;
  for (j = 0; j < h; j++)
    for (i = 0; i < w0; i++)
      *(data + j * w1 + i) = *(base + w0 * j + i);

  if (pr5->pr_size.x != w || pr5->pr_size.y != h) {
    pr_destroy (pr5);
    pr5 = mem_create (w, h, svdev->depth);
  } else
    pr_rop (pr5, 0, 0, w, h, PIX_CLR, pr5, 0, 0);

  if (one != -1) {
    if (one)
      pr_rop (pr5, 0, 0, w, h, PIX_SRC | PIX_COLOR (one), pr4, sourcex, 0);
    pw_stencil (svdev->pw, x, y, w, h, PIX_SRC, pr4, 0, 0, pr5, 0, 0);
  }

  if (zero != -1) {
    pr_rop (pr4, 0, 0, w, h, PIX_NOT (PIX_SRC), pr4, 0, 0);
    if (zero)
      pr_rop (pr5, 0, 0, w, h, PIX_SRC | PIX_COLOR (zero), pr4, sourcex, 0);
    pw_stencil (svdev->pw, x, y, w, h, PIX_SRC, pr4, 0, 0, pr5, 0, 0);
  }
  return 0;
}

/* Copy a "color" bitmap.  Since "color" is the same as monochrome, */
/* this just reduces to copying a monochrome bitmap. */

int
sv_copy_color (register gx_device *dev, byte *base, int sourcex, int raster,
	       int x, int y, int w, int h, int color_transparent)
{
  int zero = 0, one = 1;

  switch (color_transparent) {
    case 0: zero = -1; break;
    case 1: one  = -1; break;
  }
  return sv_copy_mono (dev, base, sourcex, raster, x, y, w, h, zero, one);
}

/* Draw a line */

int
sv_draw_line (register gx_device *dev,
	      int x0, int y0, int x1, int y1, int color)
{
  pw_vector (svdev->pw, x0, y0, x1, y1, PIX_SRC, color);
  return 0;
}

/* Fill a trapezoid */

int
sv_fill_trapezoid (register gx_device *dev,
		   int x0, int y0, int w0, int x1, int y1, int w1, int color)
{
  struct pr_pos vlist[4];
  int n = 4;

  vlist[0].x = x0, vlist[0].y = y0;
  vlist[1].x = x0 + w0, vlist[1].y = y0;
  vlist[2].x = x1 + w1, vlist[2].y = y1;
  vlist[3].x = x1, vlist[3].y = y1;

  pw_polygon_2 (svdev->pw, 0, 0, 1, &n, vlist,
		(color ? PIX_SRC | PIX_COLOR (color) : PIX_CLR), NULL, 0, 0);
  return 0;
}
SHAR_EOF
fi
exit 0
#	End of shell archive