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.