We've got the basic functionality of using my postscript interpreter, xpost
, as a library. I'd like to solicit some feedback from the community on the API setup. This example program, called xpost_client.c
illustrates the API to rasterize a small EPS into a 792x612 BGR buffer, which it then dumps to a file as an ASCII PPM file (so you can check it with a text editor).
/*
This is a simple example of a client calling xpost as a library
with a postscript program, desiring the raster data of the
generated image.
TODO:
define buffer interchange type
*/
#include <stdlib.h>
#include <stdio.h>
#include "xpost.h"
#include "xpost_memory.h"
#include "xpost_object.h"
#include "xpost_context.h"
#include "xpost_interpreter.h"
char *prog =
"%%BoundingBox: 200 300 400 500\n"
"300 400 100 0 360 arc\n"
"fill\n"
"showpage\n";
int main() {
void *buffer_type_object;
xpost_init();
xpost_create("bgr",
XPOST_OUTPUT_BUFFEROUT,
&buffer_type_object,
XPOST_SHOWPAGE_RETURN,
1);
xpost_run(XPOST_INPUT_STRING, prog);
{
unsigned char *buffer = buffer_type_object;
int i,j;
FILE *fp = fopen("xpost_client_out.ppm", "w");
fprintf(fp, "P3\n612 792\n255\n");
for (i=0; i<792; i++) {
for (j=0; j<612; j++) {
unsigned int red, green, blue;
red = *buffer++;
green = *buffer++;
blue = *buffer++;
++buffer;
fprintf(fp, "%d ", red);
fprintf(fp, "%d ", green);
fprintf(fp, "%d ", blue);
if ((j%20)==0)
fprintf(fp, "\n");
}
fprintf(fp, "\n");
}
fclose(fp);
}
xpost_destroy();
free(buffer_type_object);
xpost_quit();
return 0;
}
Currently only the bgr device offers the OUTPUT_BUFFEROUT
option. The C code assumes that the PS program contains a showpage
to trigger the copying of the buffer. No showpage :: your buffer's a trash-pointer, dude.
I do plan to sweep-up the auxiliary headers into a single "xpost.h"
header file. But that's the full list you currently need from the top-level.
One obvious flaw is that there's currently no way to set the geometry or resolution. It's 1-pt per pixel, and that's that. It's also currently hardcoded at letter dimensions, (sorry, rest of the world). Does anybody have ideas about the best way to interface for that at the top level?
Any other options that a library user might want? Does the buffer-type struct
need anything more than height, width and stride? Should stride
count words or bytes?
In unixes, Cygwin and mingw, you can
hg clone https://[email protected]/p/xpost/
then read the INSTALL stuff, but the quick version is
./configure
make
sudo make install
then you can run
xpost_client
to produce a (buggy) rendering of a filled circle in xpost_client_out.ppm which loads ok for me in Gimp.
The program can also be browsed online at:
http://code.google.com/p/xpost/source/browse/src/bin/xpost_client.c
http://code.google.com/p/xpost/source/browse/src/lib/xpost.h
http://code.google.com/p/xpost/source/browse/src/lib/xpost_memory.h
http://code.google.com/p/xpost/source/browse/src/lib/xpost_object.h
http://code.google.com/p/xpost/source/browse/src/lib/xpost_context.h
http://code.google.com/p/xpost/source/browse/src/lib/xpost_interpreter.h
Note: I have also posted this code to comp.lang.postscript for a more discussion-type discussion.
Also note: The interpreter produces temporary files in the current directory named gmemXXXXXX lmemXXXXXX xdumpXXXXXX
(where XXXXXX is a system-generated unique filename sequence) which may needlessly accumulate diskspace. They periodically must be manually removed. And be careful with code that may do an infinite series of pushes to the stack, lmemXXXXXX
may grow very large to hold a huge stack.