emo@iuvax.cs.indiana.edu (07/19/88)
I am seeking information concerning a PostScript previewer that will run under X version 11. Any and all pointers would be very much appreciated! eric
dana@dino.bellcore.com (Dana A. Chee) (07/19/88)
Yes, one does exist. It is called xps and is available from the
comp.sources.unix archives (vol 12 issues 50-68, 18 files in all).
The patches to make it work in X11 (originally done for X10) are
below.
This package was written by:
Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
and updated to X11 by:
Terry Weissman weissman@decwrl.dec.com
It works OK for me on a Sun 3/75.
Remove my signature from the end, the shar file for the patches
follows.
Enjoy!!
==================== x11ps.SHAR ====================
#!/bin/sh
#
# This is the source for my X11 interface to the postscript previewer.
# This source did get posted, but not to comp.sources.unix; it ended up
# in (I believe) comp.sources.bugs. Anyway, here it is, along with the
# makefile I use (which you'll probably have to modify somewhat).
#
# - Terry Weissman weissman@decwrl.dec.com ...!decwrl!weissman
#
#
# to extract, remove the header and type "sh filename"
if `test ! -s ./X11.c`
then
echo "writing ./X11.c"
cat > ./X11.c << '\Rogue\Monster\'
/*
* Copyright (C) Rutherford Appleton Laboratory 1987
*
* This source may be copied, distributed, altered or used, but not sold for profit
* or incorporated into a product except under licence from the author.
* It is not in the public domain.
* This notice should remain in the source unaltered, and any changes to the source
* made by persons other than the author should be marked as such.
*
* Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
*/
#include "main.h"
#include "graphics.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include "canon.h"
static void Punt(str)
char *str;
{
fprintf(stderr, "%s\n", str);
exit(1);
}
static Display *dpy;
typedef struct _HardwareRec {
Drawable w;
} HardwareRec, *Hardware;
#ifdef CANON
struct hardware
{
/*
* Each driver is expected to provide its own definition of this
* structure. It is only ever used as a pointer and is never dereferenced
* outside the driver.
*/
int pad;
};
#endif CANON
/*
* This file describes the interface that PostScript requires to the graphics
* system at Version 1.4.
*
* ''Hardware'' in this context refers to a pointer to windows and/or bitmaps
* and is the lowest level of access that PostScript is interested in. Any
* Hardware parameter may be expected to be NULL.
*/
/********************* CREATION OF WINDOWS AND BITMAPS *******************/
#define SCREEN 0 /* What to use as our screen number. */
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
static GC fillgc[16];
struct hardware *InitHardware ()
{
XGCValues values;
int i;
if ((dpy = XOpenDisplay(dpy)) == NULL)
Punt("Could not open display");
InitTransfer(DisplayHeight(dpy, SCREEN) / 11);
/* This defines our screen as being 11 inches high, no matter what its */
/* real size. What a hack. */
values.foreground = AllPlanes;
for (i=0 ; i<16 ; i++) {
values.function = i;
fillgc[i] = XCreateGC(dpy, RootWindow(dpy, SCREEN),
GCFunction | GCForeground, &values);
}
}
/*
* InitHardware () returns a default device which PostScript may use
* immediately (or NULL if not appropriate). Its size and shape are not
* defined. Most typically the user will want to start up another device
* before it is used anyway. No attempt will be made by PostScript to Destroy
* the resulting device.
*/
static struct hardware *NewHardware(width, height)
int width, height;
{
struct hardware *to;
Hardware hard;
to = (struct hardware *) malloc(sizeof(struct hardware));
hard = (Hardware) malloc(sizeof(HardwareRec));
to->hard.addr = (char *) hard;
to->flags = 0;
to->aux = to->clip = NULL;
to->extent = NewDevicePoint(width, height);
hard->w = NULL;
return to;
}
struct hardware *NewBitmapHardware (width, height)
int width, height;
{
struct hardware *to = NewHardware(width, height);
Hardware hard = (Hardware) to->hard.addr;
to->flags = NULL;
hard->w = XCreatePixmap(dpy, RootWindow(dpy, SCREEN), width, height,
DefaultDepth(dpy, SCREEN));
XFillRectangle(dpy, hard->w, fillgc[GXclear], 0, 0, width, height);
/* {
static int y = 0;
XSetWindowAttributes attributes;
hard->w = XCreateSimpleWindow(dpy, RootWindow(dpy, SCREEN), 700, y,
width, height, 1, BlackPixel(dpy, SCREEN),
WhitePixel(dpy, SCREEN));
attributes.override_redirect = TRUE;
XChangeWindowAttributes(dpy, hard->w, CWOverrideRedirect, &attributes);
XMapWindow(dpy, hard->w);
y+=30;
}*/
return to;
}
struct hardware *NewWindowHardware (width, height)
int width, height;
{
struct hardware *to = NewHardware(width, height);
Hardware hard = (Hardware) to->hard.addr;
XEvent event;
to->flags = ISWIN;
hard->w = XCreateSimpleWindow(dpy, RootWindow(dpy, SCREEN), 0, 0,
width, height, 1, BlackPixel(dpy, SCREEN),
0);
XSelectInput(dpy, hard->w, ExposureMask);
XMapWindow(dpy, hard->w);
XNextEvent(dpy, &event);
XSelectInput(dpy, hard->w, 0);
return to;
}
/*
* NewBitmapHardware () is expected to create a new bitmap. Only one plane
* will be needed.
*
* NewWindowHardware () is expected to create a window on the screen. On a
* colour system this will be expected to support full colour.
*/
#ifdef CANON
int IsWindowHardware (h)
struct hardware *h;
{}
#endif CANON
/*
* IsWindowHardware () should return TRUE if the hardware is a window, FALSE
* otherwise. NULL is a window.
*/
void DestroyHardware (h)
struct hardware *h;
{
if (h) {
Hardware hard = (Hardware) h->hard.addr;
if (IsWindowHardware(h))
XDestroyWindow(dpy, hard->w);
else
XFreePixmap(dpy, hard->w);
}
}
/*
*
* DestroyHardware () should release the resources required by the hardware,
* bitmap or window. This should cause a window device to vanish. NULL is not
* an error (does nothing).
*/
#ifdef CANON
Matrix DeviceMatrix (width, height)
int width, height;
{}
#endif CANON
/*
*
* DeviceMatrix () should return a matrix appropriate to a device of the given
* height and width. For a typical display with a graphics origin at the top
* left of a window, an appropriate definition would be:
*
* Matrix DeviceMatrix (width, height)
* int width, height;
* {
* return NewMatrix (PIXELS_PER_INCH / 72.0, 0.0, 0.0,
* -PIXELS_PER_INCH / 72.0, 0.0, (float) height);
* }
*/
#ifdef CANON
DevicePoint HardwareExtent (h)
struct hardware *h;
{}
#endif
/*
* HardwareExtent () returns a DevicePoint describing the width and height of
* the argument. NULL has extent NewDevicePoint (0, 0).
*/
/*************************** OUTPUT PRIMITIVES ******************************/
void BitBlt (from, to, fromPoint, toPoint, extent, rop)
struct hardware *from, *to;
DevicePoint toPoint, fromPoint, extent;
int rop;
{
Hardware fromhard, tohard;
static int count = 0;
if (to == NULL) return;
tohard = (Hardware) to->hard.addr;
if (from == NULL) {
XFillRectangle(dpy, tohard->w, fillgc[rop], toPoint.dx, toPoint.dy,
extent.dx, extent.dy);
} else {
fromhard = (Hardware) from->hard.addr;
XCopyArea(dpy, fromhard->w, tohard->w, fillgc[rop], fromPoint.dx,
fromPoint.dy, extent.dx, extent.dy, toPoint.dx, toPoint.dy);
}
if (count++ % 50 == 0) XSync(dpy, 0);
}
#ifdef CANON
void Paint (from, to, fromPoint, toPoint, extent, colour)
struct hardware *from, *to;
DevicePoint toPoint, fromPoint, extent;
Colour colour;
{}
#endif
/*
*
* BitBlt () is a full function RasterOp. The 'rop' argument will have values
* as described in the header file hard.h. If the from argument is NULL it is
* taken to be a bitmap full of ones the shape of the fromPoint and extent. If
* the to argument is NULL, this is a no-op.
*
* Paint () is an addition to BitBlt. Bits that are set in the source are
* Painted into the destination in the given colour with a copying rasterop so
* that they replace pixels previously there. If the machine does not support
* colour windows, half-toning should be performed. Colour values have hue,
* saturation and brightness components. on a black and white or greyscale
* system the brightness value will be a FP value between 0.0 (black) and 1.1
* (white), which can be used as a grey level.
*
* Paint is expected to mask with the clip mask. BitBlt is not,
*/
#ifdef CANON
void BitBltTrapezoid(to, lefttop, leftbottom, righttop, rightbottom,
top, bottom, rop)
struct hardware *to;
DevicePoint lefttop, leftbottom, righttop, rightbottom;
int top, bottom, rop;
{}
#endif CANON
#ifdef CANON
void PaintTrapezoid (to, lefttop, leftbottom, righttop, rightbottom,
top, bottom, colour)
struct hardware *to;
DevicePoint lefttop, leftbottom, righttop, rightbottom;
int top, bottom;
Colour colour;
{}
#endif CANON
/*
* BitBltTrapezoid () and PaintTrapezoid () render a complete trapezoidal
* shape. The corners of the trapezoid may lie far outside the range of
* interesting scan-lines, but the slope of the line should be clipped by the
* top and bottom. The coordinates are half-open.
*/
void BitBltLine (h, fromPoint, toPoint, rop)
struct hardware *h;
DevicePoint fromPoint, toPoint;
int rop;
{
if (h) {
Hardware hard = (Hardware) h->hard.addr;
XDrawLine(dpy, hard->w, fillgc[rop], fromPoint.dx, fromPoint.dy,
toPoint.dx, toPoint.dy);
}
}
#ifdef CANON
void PaintLine (h, fromPoint, toPoint, colour)
struct hardware *h;
DevicePoint fromPoint, toPoint;
Colour colour;
{}
#endif CANON
/*
*
* BitBltLine () is expected to draw a line between the given points
* with the given RasterOp and colour masking.
* The line should be one pixel wide and half-open.
* [Thicker lines are done with BitBlt.]
*
* PaintLine () is expected to Paint a line by analogy with Paint
* and BitBlt.
*/
void BitBltBlob (to, top, height, left, right, rop)
struct hardware *to;
int top, height, *left, *right, rop;
{
int i;
DevicePoint p1, p2;
for (i=0 ; i<height ; i++) {
p1.dx = left[i];
p2.dx = right[i];
p1.dy = p2.dy = top + i;
BitBltLine(to, p1, p2, rop);
}
}
/*
* BitBltBlob () takes a set of pixel coordinates and fills the trapezon
* figure half open.
*/
#ifdef SLOWANDWRONG
void RasterTile (from, to, toPoint, extent, rop)
struct hardware *from, *to;
DevicePoint toPoint, extent;
int rop;
{
Hardware fromhard, tohard;
DevicePoint p1, p2, p3;
int x, y;
if (to == NULL) return;
if (from == NULL)
Punt("Can only RasterTile from Hardware.");
fromhard = (Hardware) from->hard.addr;
tohard = (Hardware) to->hard.addr;
p1.dx = p1.dy = 0;
for (x=toPoint.dx ; x < toPoint.dx + extent.dx ; x+=from->extent.dx) {
for (y=toPoint.dy ; y < toPoint.dy + extent.dy ; y+=from->extent.dy) {
p2.dx = x;
p2.dy = y;
p3.dx = MIN(toPoint.dx + extent.dx - x, from->extent.dx);
p3.dy = MIN(toPoint.dy + extent.dy - y, from->extent.dy);
BitBlt(from, to, p1, p2, p3, rop);
}
}
}
#endif SLOWANDWRONG
void RasterTile (from, to, toPoint, extent, rop)
struct hardware *from, *to;
DevicePoint toPoint, extent;
int rop;
{
Hardware fromhard, tohard;
static GC gc = NULL;
XGCValues values;
int valuemask;
if (to == NULL) return;
if (from == NULL || IsWindowHardware(from))
Punt("Can only RasterTile from Bitmap.");
fromhard = (Hardware) from->hard.addr;
tohard = (Hardware) to->hard.addr;
values.tile = fromhard->w;
values.fill_style = FillTiled;
values.function = rop;
valuemask = GCFunction | GCTile | GCFillStyle;
if (gc == NULL)
gc = XCreateGC(dpy, RootWindow(dpy, SCREEN), valuemask, &values);
else
XChangeGC(dpy, gc, valuemask, &values);
XFillRectangle(dpy, tohard->w, gc, toPoint.dx, toPoint.dy,
extent.dx, extent.dy);
}
/*
* RasterTile () replicates the whole of ``from'' over ``to'', but clipped by
* the rectangle bounded by ``toPoint'' and ``extent''.
*/
/******************* BRIGHTNESS TRANSFER FUNCTION ************************/
#ifdef CANON
int TransferSize ()
{}
#endif CANON
#ifdef CANON
void SetTransfer (vec)
float *vec;
{}
#endif CANON
/*
*
* TransferSize () and SetTransfer () control the mapping function between
* user brightnesses and device brightnesses. The interface is expected to
* perform this mapping of brightnesses to a sufficient resolution.
* SetTransfer takes a table of floating point numbers between 0 and 1. User
* brightnesses are scaled to the size of this table and mapped through it.
* The argument table given to SetTransfer () will be deleted after use.
* TransferSize () simply enquires the required size of the table.
*
* It may be appropriate to half-tone on a grayscale or colour device to
* improve rendering if it is not too expensive. TransferSize () returns the
* size of the pattern table.
*/
/********************** BITMAP CONVERSION ********************************/
char *StringFromHardware (h)
struct hardware *h;
{
XImage *image;
Hardware hard;
unsigned char *result, *ptr, c;
int x, y, i;
if (h == NULL) return NULL;
hard = (Hardware) h->hard.addr;
image = XGetImage(dpy, hard->w, 0, 0, h->extent.dx, h->extent.dy,
AllPlanes, ZPixmap);
result = (unsigned char *) malloc(((h->extent.dx + 7) / 8) * h->extent.dy);
ptr = result;
for (y=0 ; y<h->extent.dy ; y++) {
for (x=0 ; x<h->extent.dx ; x+=8) {
c = 0;
for (i=0 ; i<8 ; i++) {
c = c << 1;
if (x+i < h->extent.dx)
c |= XGetPixel(image, x+i, y);
}
}
*ptr++ = c;
}
free((char *) image);
return (char *) result;
}
struct hardware *HardwareFromString (s, width, height)
char *s;
int width, height;
{
struct hardware *h = NewBitmapHardware(width, height);
Hardware hard = (Hardware) h->hard.addr;
XImage *image;
if (s == NULL) Punt("HardwareFromString called with NULL string!");
image = XCreateImage(dpy, DefaultVisual(dpy, SCREEN),
DefaultDepth(dpy, SCREEN), ZPixmap, 0, s,
width, height, 8, 0);
image->bitmap_bit_order = MSBFirst;
XPutImage(dpy, hard->w, fillgc[GXcopy], image, 0, 0, 0, 0, width, height);
free((char *) image);
return h;
}
/*
*
* StringFromHardware () produces a string from its argument which describes
* the bitmap. The bitmap is returned in row-major order with the leftmost
* bit of each byte in the most significant position. Rows are padded to byte
* boundaries. Only single plane bitmaps are used.
*
* HardwareFromString () performs the inverse mapping, generating a bitmap
* from a set of bits, given a width and height. Only single plane bitmaps are
* used.
*/
/************************* HALF-TONE SCREEN *******************************/
#ifdef CANON
int ScreenSize (freq, rotation)
float freq, rotation;
{}
#endif CANON
#ifdef CANON
void BuildScreen (freq, rotation, x, y)
float freq, rotation, *x, *y;
{}
#endif CANON
#ifdef CANON
void SetScreen (freq, rotation, thresh)
float freq, rotation, *thresh;
{}
#endif CANON
/*
* ScreenSize () allows PostScript to determine how large an array of sample
* points to expect. It should return the length of the side of the sample
* square.
*
* BuildScreen () returns a set of sampling coordinates to PostScript to hand
* to the users spot-function
*
* SetScreen () allows PostScript to set the thresholds for each sample point
* so that half-tone bitmaps can be made.
*/
/************************* CLIPPING ******************************************/
#ifdef CANON
void SetClipHardware (h, clip)
struct hardware *h, *clip;
{}
#endif
/*
*
* SetClipHardware sets hardware which is a clip mask for BitBlt. This mask
* should be ANDed with any output operation. If clip is NULL, masking will
* not be needed.
*/
/************************ UPDATE CONTROLS **********************************/
void HardUpdate ()
{
XFlush(dpy, 0);
}
/*
* HardUpdate is a hook to allow devices which do output buffering to flush
* that buffering when appropriate. This allows an interactive user to see
* completed graphics between prompts (it is called as a side-effect of the
* PostScript flush operator). Typically is is a no-op.
*/
void UpdateControl (h, on)
struct hardware *h;
int on;
{}
/*
* This call can be used to enable batching of output operations.
* UpdateControl (h, FALSE) means ``start of batching'' UpdateControl (h,
* TRUE) means ``end of batching''. It is used to improve performance on
* machines where screen updates have a high locking overhead. It may be a
* no-op. The operation should nest if batching is already in progress: FALSE
* increments a counter, TRUE decrements a counter. Display changes are
* allowed when the counter is non-zero.
*/
/********************************** CANONICAL IMPLEMENTATION LIBRARY ******************************/
/*
* Some parts of the above interface can be supported by a canonical library.
* This library contains:
SetClipHardware
HardUpdate
IsWindowHardware
HardwareExtent
PaintTrapezoid
BitBltTrapezoid
Paint
PaintLine
DeviceMatrix
InitTransfer
TransferSize
SetTransfer
ScreenSize
BuildScreen
SetScreen
*
* As the driver matures, the user may provide his own versions of the
* canonical routines. This leaves the following for implementation by
* the user.
*
InitHardware
NewBitmapHardware
NewWindowHardware
DestroyHardware
HardwareFromString
StringFromHardware
UpdateControl
RasterTile
BitBlt
BitBltLine
BitBltBlob
* There is a pedagogical implementation in null.c
*
* There are a number of interface issues concerning the canonical driver.
* Firstly, a canonical struct hardware is defined, which contains a union of
* a char * and an int handle. The remainder are expected to use this to store
* device specific information.
*
* InitTransfer() should be called during InitHardware with the number of
* pixels per inch on the display as an argument.
*/
\Rogue\Monster\
else
echo "will not over write ./X11.c"
fi
if `test ! -s ./makefile`
then
echo "writing ./makefile"
cat > ./makefile << '\Rogue\Monster\'
OBJECTS=array.o boolean.o config.o control.o dictionary.o file.o\
integer.o main.o math.o misc.o name.o operator.o\
poly.o property.o real.o save.o stack.o string.o unix.o
LIBS=libww.a -lsuntool -lsunwindow -lpixrect -g
GRAPHICS=cache.o colour.o device.o fill.o font.o gsave.o image.o mat.o matrix.o\
pat.o path.o state.o stroke.o
CFLAGS=-g -DX11
XLIB= /usr/src/X11/lib/X/libX11.a
XLIBINCLUDES = -I/usr/src/X11/X11 -I/usr/src/X11
xps: $(OBJECTS) $(GRAPHICS) X11.o canon.a $(XLIB) makefile
rm -f xps
cc -o xps $(OBJECTS) $(GRAPHICS) X11.o canon.a -lm $(XLIB)
OLDXLIB= /usr/src/x11/Xlib/libX11.a
OLDXLIBINCLUDES = -I/usr/src/X11/X11 -I/usr/src/X11
xps.old: $(OBJECTS) $(GRAPHICS) X11.o canon.a $(OLDXLIB) makefile
rm -f xps.old
cc -o xps.old $(OBJECTS) $(GRAPHICS) X11.o canon.a -lm $(OLDXLIB)
X11.o: X11.c
cc -c $(CFLAGS) $(XLIBINCLUDES) X11.c
PS: $(OBJECTS) $(GRAPHICS) hard.o canon.a
cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) hard.o canon.a -lm `libs` -o PS
sunPS: $(OBJECTS) $(GRAPHICS) hard.o canon.a pixrect
cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) hard.o canon.a -lm -lpixrect -o sunPS
CPS: $(OBJECTS) $(GRAPHICS) colour-ww.o trapezoid.o canon.o
cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) colour-ww.o canon.o trapezoid.o -lm `libs` -o CPS
postscript: $(OBJECTS) $(GRAPHICS) adapter.o protocol.o
cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) adapter.o protocol.o -lm -o postscript
XPS: $(OBJECTS) $(GRAPHICS) X.o
cc $(CFLAGS) $(OBJECTS) $(GRAPHICS) X.o -lm libX.a -o XPS
canon.a: canon.o screen.o trapezoid.o paint.o
ar ruv canon.a canon.o screen.o trapezoid.o paint.o
ranlib canon.a
viewer: protocol.o viewer.o hard.o canon.a
cc protocol.o viewer.o hard.o canon.a `libs` -o viewer
all: PS postscript viewer
ww: ww.o wwlib installww
pixrect: pixrect.o
cp pixrect.o hard.o
sun: ww wwsun
orion: orion.o installorion orionlib
X.o:
cc -c X.c
wwlib:
if [ -f libww.a ]; \
then \
echo 'echo libww.a' >lww; \
else \
echo 'echo -lww' >lww; \
fi; \
chmod +x lww
echo "echo `lww`" >libs; chmod +x libs
wwsun:
echo "echo `lww` -lsuntool -lsunwindow -lpixrect" >libs; chmod +x libs
orionlib:
echo 'echo -lG' >libs; chmod +x libs
installww:
cp ww.o hard.o
installorion:
cp orion.o hard.o
\Rogue\Monster\
else
echo "will not over write ./makefile"
fi
echo "Finished archive 1 of 1"
exit
--
+*************************************************************************+
* Dana Chee (201) 829-4488 *
* Bellcore *
* Room 2Q-250 *
* 445 South Street ARPA: dana@bellcore.com *
* Morristown, NJ 07960-1910 UUCP: {gateways}!bellcore!dana *
+*************************************************************************+devon@hcx1.SSD.HARRIS.COM (07/19/88)
Contact: Pipeline Associates, Inc. 239 W. Main St. West Orange, NJ 07052 (201) 731-7860 They advertise PSVIEW, a PostScript previewer for X.