diff options
Diffstat (limited to 'nx-X11/lib/dpstk/XDPSpreview.c')
-rw-r--r-- | nx-X11/lib/dpstk/XDPSpreview.c | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/nx-X11/lib/dpstk/XDPSpreview.c b/nx-X11/lib/dpstk/XDPSpreview.c new file mode 100644 index 000000000..d36331b71 --- /dev/null +++ b/nx-X11/lib/dpstk/XDPSpreview.c @@ -0,0 +1,636 @@ +/* + * XDPSpreview.c + * + * (c) Copyright 1990-1994 Adobe Systems Incorporated. + * All rights reserved. + * + * Permission to use, copy, modify, distribute, and sublicense this software + * and its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notices appear in all copies and that + * both those copyright notices and this permission notice appear in + * supporting documentation and that the name of Adobe Systems Incorporated + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. No trademark license + * to use the Adobe trademarks is hereby granted. If the Adobe trademark + * "Display PostScript"(tm) is used to describe this software, its + * functionality or for any other purpose, such use shall be limited to a + * statement that this software works in conjunction with the Display + * PostScript system. Proper trademark attribution to reflect Adobe's + * ownership of the trademark shall be given whenever any such reference to + * the Display PostScript system is made. + * + * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR + * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE + * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT + * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. + * + * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems + * Incorporated which may be registered in certain jurisdictions + * + * Author: Adobe Systems Incorporated + */ +/* $XFree86$ */ + +#include <X11/Xlib.h> +#include <DPS/dpsXclient.h> +#include <DPS/XDPSlib.h> +#include <DPS/psops.h> +#include <stdio.h> +#include <stdlib.h> + +#ifndef NeXT +#include <unistd.h> +#endif + +#include <DPS/dpsXshare.h> +#include <DPS/dpsXpreview.h> +#include "XDPSpwraps.h" +#include "dpsXcommonI.h" +#include <math.h> +#include <X11/Xos.h> + +#if defined(hpux) || defined(AIXV3) +#define SELECT_TYPE int * +#else +#define SELECT_TYPE fd_set * +#endif + +#define BEGINDOCUMENTLEN 15 /* Length of "%%BeginDocument" */ +#define BEGINBINARYLEN 14 /* Length of "%%BeginBinary:" */ + +static int ParseFileForBBox(FILE *file, XRectangle *bb); +static void FillPixmapWithGray( + Screen *screen, + Drawable dest, + XRectangle *bbox, + int xOffset, int yOffset, + double pixelsPerPoint, + Bool createMask); + +static XDPSRewindFunction rewindFunction = XDPSFileRewindFunc; +static DPSPointer rewindClientData = NULL; +static XDPSGetsFunction getsFunction = XDPSFileGetsFunc; +static DPSPointer getsClientData = NULL; + +int XDPSSetFileFunctions( + XDPSRewindFunction rewindFunc, + DPSPointer rewindData, + XDPSGetsFunction getsFunc, + DPSPointer getsData) +{ + if (rewindFunc != NULL) { + rewindFunction = rewindFunc; + rewindClientData = rewindData; + } + if (getsFunc != NULL) { + getsFunction = getsFunc; + getsClientData = getsData; + } + return 0; +} + +/* ARGSUSED */ + +void XDPSFileRewindFunc(FILE *f, DPSPointer data) +{ + rewind(f); +} + +/* ARGSUSED */ + +char *XDPSFileGetsFunc(char *buf, int n, FILE *f, DPSPointer data) +{ + return fgets(buf, n, f); +} + +void XDPSEmbeddedEPSFRewindFunc(FILE *f, DPSPointer data) +{ + XDPSPosition *p = (XDPSPosition *) data; + + p->nestingLevel = 0; + p->continuedLine = False; + p->binaryCount = 0; + + if (fseek(f, p->startPos, SEEK_SET) != 0) { + (void) fseek(f, 0L, SEEK_END); /* Go to the end */ + } +} + +static Bool imaging = False; + +char *XDPSEmbeddedGetsFunc(char *buf, int n, FILE *f, DPSPointer data) +{ + XDPSPosition *p = (XDPSPosition *) data; + int count; + unsigned len; + + if (fgets(buf, n, f) == NULL) { + if (imaging) p->startPos = -1; + return NULL; + } + + /* If previous call didn't get a whole line, we're somewhere in the + middle, so don't check for comments. Also, if we're in the middle of + binary data, don't look for comments either. */ + + len = strlen(buf); + + if (p->binaryCount != 0) { + if (len > p->binaryCount) p->binaryCount = 0; + else p->binaryCount -= len; + + } else if (!p->continuedLine) { + if (strncmp(buf, "%%BeginDocument", BEGINDOCUMENTLEN) == 0) { + p->nestingLevel++; + + } else if (strncmp(buf, "%%BeginBinary:", BEGINBINARYLEN) == 0) { + count = sscanf(buf, "%%%%BeginBinary: %lu", &p->binaryCount); + if (count != 1) p->binaryCount = 0; /* Malformed comment */ + + } else if (strcmp(buf, "%%EndDocument\n") == 0) { + if (p->nestingLevel == 0) { + if (imaging) p->startPos = ftell(f); + return NULL; + } + else p->nestingLevel--; + } + } + + if ((int)len == n-1 && buf[n-1] != '\n') p->continuedLine = True; + else p->continuedLine = False; + + return buf; +} + +int XDPSCreatePixmapForEPSF( + DPSContext context, + Screen *screen, + FILE *epsf, + int depth, + double pixelsPerPoint, + Pixmap *pixmap, + XRectangle *pixelSize, + XRectangle *bbox) +{ + Pixmap p; + int width, height; + XRectangle bb; + + if (screen == NULL || depth <= 0 || + pixelsPerPoint <= 0) { + return dps_status_illegal_value; + } + + if (context == NULL) { + context = XDPSGetSharedContext(DisplayOfScreen(screen)); + } + + (*rewindFunction)(epsf, rewindClientData); + + if (ParseFileForBBox(epsf, &bb) == dps_status_failure) { + return dps_status_failure; + } + + width = ceil(bb.width * pixelsPerPoint); + height = ceil(bb.height * pixelsPerPoint); + if (width <= 0 || height <= 0) return dps_status_failure; + + p = XCreatePixmap(DisplayOfScreen(screen), RootWindowOfScreen(screen), + width, height, depth); + + if (pixmap != NULL) *pixmap = p; + if (pixelSize != NULL) { + pixelSize->x = pixelSize->y = 0; + pixelSize->width = width; + pixelSize->height = height; + } + if (bbox != NULL) *bbox = bb; + + if (context != NULL) return dps_status_success; + else return dps_status_no_extension; +} + +static int ParseFileForBBox(FILE *file, XRectangle *bb) +{ +#define BBOXLEN 14 /* Length of "%%BoundingBox:" */ +#define BUFLEN 256 +#define ATENDLEN 8 /* Length of "(atend)" plus one byte for \0 */ + char buf[BUFLEN]; + char buf2[ATENDLEN]; + Bool atend = False; /* Found a %%BoundingBox: (atend) */ + float x, y, r, t; + int n; + int nestingLevel = 0; + unsigned long binaryCount = 0; + Bool continuedLine = False; + unsigned len; + + while (1) { + if ((*getsFunction)(buf, BUFLEN, file, getsClientData) == NULL) { + return dps_status_failure; + } + + len = strlen(buf); + + /* If in binary data or continued line, ignore everything */ + + if (binaryCount != 0) { + if (len > binaryCount) binaryCount = 0; + else binaryCount -= len; + + } else if (!continuedLine) { + if (strncmp(buf, "%%BeginBinary:", BEGINBINARYLEN) == 0) { + n = sscanf(buf, "%%%%BeginBinary: %lu", &binaryCount); + if (n != 1) binaryCount = 0; /* Malformed comment */ + + } else if (strncmp(buf, "%%BeginDocument", BEGINDOCUMENTLEN) == 0) { + nestingLevel++; + + } else if (strcmp(buf, "%%EndDocument\n") == 0) { + nestingLevel--; + + /* Only check for bounding box comments at nesting level 0 */ + + } else if (nestingLevel == 0) { + + /* If we haven't already hit an (atend), the end of the + comments is a good place to stop looking for the bbox */ + + if (!atend && (strcmp(buf, "%%EndComments\n") == 0 || + strcmp(buf, "%%EndProlog\n") == 0)) { + return dps_status_failure; + } + + if (strncmp(buf, "%%BoundingBox:", BBOXLEN) == 0) { + n = sscanf(buf, "%%%%BoundingBox: %f %f %f %f", + &x, &y, &r, &t); + + if (n != 4) { + n = sscanf(buf, "%%%%BoundingBox: %7s", buf2); + + if (n == 1 && strcmp(buf2, "(atend)") == 0) { + atend = True; + } else return dps_status_failure; + + } else { + bb->x = (int) x; + bb->y = (int) y; + bb->width = r - bb->x; + if ((float)((int) r) != r) bb->width++; + bb->height = t - bb->y; + if ((float)((int) t) != t) bb->height++; + return dps_status_success; + } + } + } + } + + /* See if this line fills the buffer */ + if (len == BUFLEN-1 && buf[BUFLEN-1] != '\n') continuedLine = True; + } + +#undef ATENDLEN +#undef BUFLEN +#undef BBOXLEN +} + +#define mmPerPoint (25.4/72.0) + +double XDPSPixelsPerPoint(Screen *screen) +{ + return (float) WidthOfScreen(screen) * mmPerPoint / + (float) WidthMMOfScreen(screen); +} + +static int timeStart = 200, maxDoubles = 3; + +void XDPSSetImagingTimeout(int timeout, int max) +{ + timeStart = timeout; + maxDoubles = max; +} + +typedef struct _StatusInfo { + DPSContext ctxt; + DPSPointer cookie; + Bool *doneFlag; + unsigned long startReqNum, endReqNum; + XDPSStatusProc oldProc; + struct _StatusInfo *next, *prev; +} StatusInfo; + +static StatusInfo *StatusList; + +static void SetUpStatusVariables( + DPSContext context, + DPSPointer cookie, + Bool *doneFlag, + unsigned long startReq, + XDPSStatusProc oldProc) +{ + StatusInfo *info = (StatusInfo *) malloc(sizeof(StatusInfo)); + + info->ctxt = context; + info->cookie = cookie; + info->doneFlag = doneFlag; + info->startReqNum = startReq; + info->endReqNum = 0xFFFFFFFF; + info->oldProc = oldProc; + if (StatusList != NULL) StatusList->prev = info; + info->next = StatusList; + info->prev = NULL; + StatusList = info; +} + +static void SetEndReqNum( + DPSContext context, + unsigned long endReq) +{ + StatusInfo *info = StatusList; + + while (info != NULL && info->ctxt != context) info = info->next; + if (info != NULL) info->endReqNum = endReq; +} + +static void HandlePreviewStatus( + DPSContext context, + int status) +{ + unsigned long serial; + Display *dpy; + StatusInfo *info = StatusList; + + while (info != NULL && info->ctxt != context) info = info->next; + if (info == NULL) return; + + (void) XDPSXIDFromContext(&dpy, context); + serial = LastKnownRequestProcessed(dpy); + + /* This event is from before our imaging; send to old status proc. */ + if (serial < info->startReqNum) { + (*info->oldProc) (context, status); + return; + } + + /* This event is from during our imaging; ignore it */ + if (serial < info->endReqNum) return; + + /* This event is juuuuust right. */ + if (status == PSFROZEN) *info->doneFlag = True; +} + +static int FinishUp( + DPSContext context, + DPSPointer cookie) +{ + static char restorebuf[] = + "\n$Adobe$DPS$Lib$Dict /EPSFsave get restore grestore\n"; + StatusInfo *info = StatusList; + int err; + + /* Check the results of the imaging: Get the error status and restore the + context */ + + _DPSPCheckForError(context, &err); + + /* Can't do this is a wrap because of restore semantics */ + DPSWritePostScript(context, restorebuf, strlen(restorebuf)); + + (void) XDPSPopContextParameters(cookie); + + /* See if we have an info record and delete it if so */ + while (info != NULL && info->ctxt != context) info = info->next; + if (info != NULL) { + if (info == StatusList) StatusList = info->next; + else info->prev->next = info->next; + if (info->next != NULL) info->next->prev = info->prev; + XDPSRegisterStatusProc(context, info->oldProc); + free(info); + } + + if (err) return dps_status_postscript_error; + else return dps_status_success; +} + +int XDPSCheckImagingResults( + DPSContext context, + Screen *screen) +{ + StatusInfo *info = StatusList; + int status; + + if (context == NULL) { + context = XDPSGetSharedContext(DisplayOfScreen(screen)); + if (context == NULL) return dps_status_no_extension; + } + + while (info != NULL && info->ctxt != context) info = info->next; + if (info == NULL) return dps_status_illegal_value; + + status = XDPSGetContextStatus(context); + if (status != PSFROZEN) return dps_status_imaging_incomplete; + + XDPSUnfreezeContext(context); + return FinishUp(context, info->cookie); +} + +static void msleep(int ms) +{ + struct timeval incr; + + incr.tv_sec = ms / 1000; + incr.tv_usec = (ms % 1000) * 1000; + (void) select (0, (SELECT_TYPE) NULL, (SELECT_TYPE) NULL, + (SELECT_TYPE) NULL, &incr); +} + +int XDPSImageFileIntoDrawable( + DPSContext context, + Screen *screen, + Drawable dest, + FILE *file, + int drawableHeight, + int drawableDepth, + XRectangle *bbox, + int xOffset, int yOffset, + double pixelsPerPoint, + Bool clear, Bool createMask, + Bool waitForCompletion, + Bool *doneFlag) +{ +#define BUFSIZE 256 +#define EXECLEN 6 + char buf[BUFSIZE]; + static char eobuf[] = "\n$Adobe$DPS$Lib$Dict /execSuccess true put\n\ +stop\n\ +Magic end of data line )))))))))) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2\n"; + XDPSStandardColormap maskMap; + XDPSStandardColormap rgbMap; + unsigned int flags = 0; + int status; + Bool inited; + DPSPointer cookie; + int doublings; + int ms; + XDPSStatusProc oldProc; + unsigned long startReqNum = 0, endReqNum; + + if (screen == NULL || dest == None || + drawableHeight <= 0 || drawableDepth <= 0 || + pixelsPerPoint <= 0) { + return dps_status_illegal_value; + } + + if (context == NULL) { + context = XDPSGetSharedContext(DisplayOfScreen(screen)); + if (context == NULL) { + FillPixmapWithGray(screen, dest, bbox, xOffset, yOffset, + pixelsPerPoint, + createMask); + return dps_status_no_extension; + } + } + + (*rewindFunction)(file, rewindClientData); + + if (!waitForCompletion) { + DPSWaitContext(context); + /* Any status events before this point go to old handler */ + startReqNum = NextRequest(DisplayOfScreen(screen)); + } + + status = _XDPSTestComponentInitialized(context, + dps_init_bit_preview, &inited); + if (status != dps_status_success) return status; + if (!inited) { + (void) _XDPSSetComponentInitialized(context, dps_init_bit_preview); + _DPSPDefineExecFunction(context); + } + + if (createMask) { + if (drawableDepth != 1) return dps_status_illegal_value; + maskMap.colormap = None; + maskMap.red_max = 1; + maskMap.red_mult = -1; + maskMap.base_pixel = 1; + rgbMap.colormap = None; + rgbMap.red_max = rgbMap.green_max = rgbMap.blue_max = + rgbMap.red_mult = rgbMap.green_mult = rgbMap.blue_mult = + rgbMap.base_pixel = 0; + flags = XDPSContextGrayMap | XDPSContextRGBMap; + } + + status = XDPSPushContextParameters(context, screen, drawableDepth, + dest, drawableHeight, + &rgbMap, &maskMap, + flags | XDPSContextScreenDepth | + XDPSContextDrawable, &cookie); + + if (status != dps_status_success) return status; + + _DPSPSetMatrix(context, xOffset, yOffset, pixelsPerPoint); + + if (clear) _DPSPClearArea(context, (int) bbox->x, (int) bbox->y, + (int) bbox->width, (int) bbox->height); + + if (createMask) _DPSPSetMaskTransfer(context); + + /* Prepare to read PostScript code */ + _DPSPSaveBeforeExec(context, !waitForCompletion); + DPSWritePostScript(context, "\nexec\n", EXECLEN); + + imaging = True; + while ((*getsFunction)(buf, BUFSIZE, file, getsClientData) != NULL) { + DPSWritePostScript(context, buf, strlen(buf)); + } + imaging = False; + + /* This marks the end of the data stream */ + DPSWritePostScript(context, eobuf, strlen(eobuf)); + + if (!waitForCompletion) { + *doneFlag = False; + oldProc = XDPSRegisterStatusProc(context, HandlePreviewStatus); + SetUpStatusVariables(context, cookie, doneFlag, startReqNum, oldProc); + XDPSSetStatusMask(context, 0, 0, PSFROZENMASK); + + ms = timeStart; + + /* Check for done until we run out of time */ + doublings = 0; + while (1) { + if (XDPSGetContextStatus(context) == PSFROZEN) { + waitForCompletion = True; + XDPSUnfreezeContext(context); + break; + } + if (doublings >= maxDoubles) break; + + /* Wait a while */ + msleep(ms); + ms *= 2; + doublings++; + } + } + + /* If previous decided imaging is done, it changed waitForCompletion */ + + if (waitForCompletion) return FinishUp(context, cookie); + else { + endReqNum = NextRequest(DisplayOfScreen(screen)) - 1; + SetEndReqNum(context, endReqNum); + return dps_status_imaging_incomplete; + } +#undef EXECLEN +#undef BUFSIZE +} + +static void FillPixmapWithGray( + Screen *screen, + Drawable dest, + XRectangle *bbox, + int xOffset, int yOffset, + double pixelsPerPoint, + Bool createMask) +{ + int width, height, x, y; + GC gc; + XGCValues v; + static char grayBits[] = {0x01, 0x02}; + Pixmap grayStipple; + Display *dpy = DisplayOfScreen(screen); + + width = ceil(bbox->width * pixelsPerPoint); + height = ceil(bbox->height * pixelsPerPoint); + x = (bbox->x + xOffset) * pixelsPerPoint; + y = (bbox->y + yOffset) * pixelsPerPoint; + + if (createMask) { + v.foreground = 1; + v.function = GXcopy; + + gc = XCreateGC(dpy, dest, GCForeground | GCFunction, &v); + XFillRectangle(dpy, dest, gc, x, y, width, height); + XFreeGC(dpy, gc); + return; + } + + grayStipple = XCreateBitmapFromData(dpy, dest, grayBits, 2, 2); + + v.foreground = BlackPixelOfScreen(screen); + v.background = WhitePixelOfScreen(screen); + v.function = GXcopy; + v.stipple = grayStipple; + v.fill_style = FillOpaqueStippled; + gc = XCreateGC(dpy, dest, GCForeground | GCBackground | GCFunction | + GCStipple | GCFillStyle, &v); + XFillRectangle(dpy, dest, gc, x, y, width, height); + XFreeGC(dpy, gc); + XFreePixmap(dpy, grayStipple); +} |