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.