ftp.nice.ch/peanuts/GeneralData/Documents/adobe/DPS.UNIXReview.Aug94.tar.gz#/eps2.c

This is eps2.c in view mode; [Download] [Up]

#include <stdio.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <DPS/dpsXclient.h>
#include <DPS/dpsXcommon.h>
#include <DPS/dpsXshare.h>
#include <ieeefp.h>

int isinf(double d) {return !finite(d);}

/*
 * The following declarations are part of the mechanism that
 * calls the Redisplay procedure whenever the contents need
 * to be updated.
 */

typedef struct {
  float    rotate;
  float    scalex;
  float    scaley;
} ApplicationData, *ApplicationDataPtr;

void Redisplay();
double PixelsPerPoint(Screen *);
int getBoundingBox(FILE *, XRectangle *);
Boolean imageFile(FILE *);
String translations = "<Expose> : Redisplay()";
XtActionsRec actions[] = { {"Redisplay", Redisplay} };

Display *display;       /* Connection to the X server   */
Window window;          /* Window that we'll draw in    */
GC gc;                  /* X graphics context           */
DPSContext ctxt;
FILE *epsf;
Pixmap pixmap;
XRectangle pixelSize, pixmapSize2, pixmapSize2;
XRectangle bbox, pixmapSize, scaled_pixmapSize;
ApplicationData data;


static XtResource resources[] = {
  { "rotate", "Rotate", XtRFloat, sizeof (float),
    XtOffset(ApplicationDataPtr, rotate), XtRString,"0.0" },
  { "scalex", "Scalex", XtRFloat, sizeof (float),
    XtOffset(ApplicationDataPtr, scalex), XtRString,"1.0" },
  { "scaley", "Scaley", XtRFloat, sizeof (float),
    XtOffset(ApplicationDataPtr, scaley), XtRString,"1.0" }
  };

static XrmOptionDescRec options[] = { 
  {"-rotate", "*rotate", XrmoptionSepArg, NULL},
  {"-scalex",   "*scalex",   XrmoptionSepArg, NULL},
  {"-scaley",   "*scaley",   XrmoptionSepArg, NULL}
};

void main(argc, argv)
  int argc;
  char **argv;
{
  Widget appShell, w;
  XtAppContext app;
  int retval;
  Bool doneFlag;
  char *file;
  int depth;
  double pixelsperpoint;
  Pixmap pixmap2;

  /*
   * The call to XtAppInitialize creates a connection to the
   * X server. We extract that connection with the call to
   * XtDisplay()
   */

  appShell = XtAppInitialize(&app, "Demo", options, XtNumber(options),
			    &argc, argv, 
                             NULL, NULL, 0);
  /*
   *  Retrieve the resources.
   */
  XtGetApplicationResources(appShell, &data, resources, 
                            XtNumber(resources), NULL, 0);
  if(argc < 2) {
    fprintf(stderr,"Usage: %s eps-file\n",argv[0]);
    exit(1);
  }
  file = argv[1];

  display = XtDisplay(appShell);
  depth = DefaultDepthOfScreen(XtScreen(appShell));
  pixelsperpoint = PixelsPerPoint(XtScreen(appShell));

  /*
   * XtAppAddActions adds Redisplay as an action procedure that 
   * is called when an Expose event is received by the widget.
   */
  XtAppAddActions(app, actions, XtNumber(actions));

  /*
   * Now we can create the window. First we set up some parameters
   * like width and height. The call to XtVaCreateManagedWidget and
   * XtRealize create and initialize the window. We extract the
   * window identifier with the XtWindow call.
   */

  epsf = fopen(file, "r");
  if(epsf == NULL) {
    perror(file);
    exit(1);
  }
  retval = getBoundingBox(epsf, &bbox);
  switch(retval) {
  case dps_status_success:
    break;
  case dps_status_failure:
    fprintf(stderr,"File is not an EPS file\n");
    exit(1);
  }
  pixmapSize.x      = (short)(bbox.x * pixelsperpoint * data.scalex);
  pixmapSize.y      = (short)(bbox.y * pixelsperpoint * data.scaley);
  pixmapSize.width  = (unsigned short)(bbox.width * pixelsperpoint * data.scalex);
  pixmapSize.height = (unsigned short)(bbox.height * pixelsperpoint * data.scaley);
  w = XtVaCreateManagedWidget("da", coreWidgetClass, appShell,
		  XtNwidth, pixmapSize.width,
		  XtNheight, pixmapSize.height,
                  XtNtranslations, XtParseTranslationTable(translations),
                  NULL);
  XtRealizeWidget(appShell);
  window = XtWindow(w);
  pixmap = XCreatePixmap(display, 
		  window, pixmapSize.width,
		  pixmapSize.height,
		  depth);

  /*
   * The following creates an X graphics context
   */
  gc = XCreateGC(display, window, 0, NULL);

  /*
   * Create a context to which the PostScript language code
   * will be sent
   */
  ctxt = XDPSCreateSimpleContext(display, pixmap, gc, 0, pixmapSize.height, 
                        DPSDefaultTextBackstop, 
                        DPSDefaultErrorProc, (DPSSpace) NULL);
  switch(retval) {
  case dps_status_success:
    break;
  case dps_status_unregistered_context:
    fprintf(stderr,"Context not registered\n");
    exit(1);
  case dps_status_illegal_value:
    printf("XDPSSetContextDrawable: Invalid context drawable height\n");
    exit(1);
  default:
    fprintf(stderr, "Internal error %d\n", retval);
    exit(1);
  }
  /*
   * This is where I am having the problem.  I can't figure out the
   * appropriate parameter to PSWTransformBeforeEPSF() in order to
   * scale x and y and rotate about the center
   */
  PSWTransformBeforeEPSF(ctxt, 
	    (float)bbox.width * data.scalex / 2,	/* Find center */
	    (float)bbox.height * data.scaley / 2,
	    data.scalex,
	    data.scaley,
	    data.rotate,
	    -(float)bbox.x - (float)bbox.width  / 2,
	    -(float)bbox.y - (float)bbox.height / 2);
  PSWDefineExecFunction(ctxt);
  imageFile(epsf);

  XtAppMainLoop(app);
}

/* The Redisplay procedure is called whenever the       */
/* contents of the window needs to be repainted.        */

void Redisplay(w, event, params, num)
  Widget w;
  XEvent *event;
  String *params;
  Cardinal *num;
{
  XCopyArea(XtDisplay(w),
	    pixmap,
	    window,
	    gc,
	    0, 0,
	    pixmapSize.width,
	    pixmapSize.height,
	    0, 0);


  /*DPSPrintf(ctxt, "[3] 0 setdash (Hello World) false charpath stroke ");*/
}

int getBoundingBox(file, bb)
    FILE *file;
    XRectangle *bb;
{
#define BBOXLEN 14		/* Length of "%%BoundingBox:" */
#define BUFLEN 256
#define ATENDLEN 8		/* Length of "(atend)" plus one byte for \0 */
#define BEGINDOCUMENTLEN 15	/* Length of "%%BeginDocument" */
#define BEGINBINARYLEN 14	/* Length of "%%BeginBinary:" */
    char buf[BUFLEN];
    char buf2[ATENDLEN];
    Bool atend = False;	/* Found a %%BoundingBox: (atend) */
    short r, t;
    int n;
    int nestingLevel = 0;
    unsigned long binaryCount = 0;
    Bool continuedLine = False;
    int len;

    while (1) {
       if (fgets(buf, BUFLEN, file) == 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: %hd %hd %hd %hd",
			       &bb->x, &bb->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->width = r - bb->x;
			bb->height = t - bb->y;
			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
#undef BEGINDOCUMENTLEN
#undef BEGINBINARYLEN
}

Boolean
imageFile(FILE *epsf)
{
#define BUFSIZE 256
#define EXECLEN 6		/* Length of "\nexec\n" */
    char buf[BUFSIZE];
    static char eobuf[] = "/execSuccess true def\n\
stop\n\
Magic end of data line )))))))))) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2\n";
    static char restorebuf[] =
	    "\nEPSFsave restore\n";
    int err;

    /*
    ** Reset to beginning of file
    */
    rewind(epsf);

    /*
    ** Prepare to execute PostScript code
    */
    PSWBeginEPSF(ctxt);
    DPSWritePostScript(ctxt, "\nexec\n", EXECLEN);

    /*
    ** Copy file to context
    */
    while (fgets(buf, BUFSIZE, epsf) != NULL) {
	DPSWritePostScript(ctxt, buf, strlen(buf));
    }

    /*
    ** Mark the end of the data stream
    */
    DPSWritePostScript(ctxt, eobuf, strlen(eobuf));

    /*
    ** Check the results of the imaging:  Get the error status and restore the
    ** context
    */
    PSWEndEPSF(ctxt, &err);

    /*
    ** Can't do this is a wrap because of restore semantics
    */
    DPSWritePostScript(ctxt, restorebuf, strlen(restorebuf));

    return err;
#undef EXECLEN
#undef BUFSIZE
} /* end imageFile() */

double
PixelsPerPoint(Screen *screen)
{
    return (double) ((double)WidthOfScreen(screen) *
		     (double)(25.4 / 72.0) /
		     (double)(WidthMMOfScreen(screen)));
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.