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). 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. Edit: The current state of the error-handling behavior for a client.Changing the program to introduce an /undefined error produces quite of bit of noise diagnostic output on the stdout that I need to clean up.And then it appears to stall and needs to be killed. So it's buggy, but it should return from xpost_run with an error code. Internal error codes are described here: http://code.google.com/p/xpost/source/browse/src/lib/xpost_error.h Edit: Upon further thought, returning an error code will be much trickier. I've changed xpost_run to return a value, but currently it only distinguishes between a return via showpage and however-else-it-may-have-terminated. It attempts to handle internal errors internally, by looking up the error name in the errordict dictionary as described in the PLRM. The error actions can be modified by executing a prolog which modifies the dictionary. The current (expected) behavior is to print a message and a dump of the stacks and flush the rest of the ps program and quit (ie. return from xpost_run).I've changed xpost_create to return a handle which must be passed to xpost_run and xpost_destroy. And fixed the circle-fill bug.Edit: Changed it to a blue circle and fixed byte-ordering and use a pixel struct type.http://code.google.com/p/xpost/source/browse/src/bin/xpost_client.chttp://code.google.com/p/xpost/source/browse/src/lib/xpost.hhttp://code.google.com/p/xpost/source/browse/src/lib/xpost_memory.hhttp://code.google.com/p/xpost/source/browse/src/lib/xpost_object.hhttp://code.google.com/p/xpost/source/browse/src/lib/xpost_context.hhttp://code.google.com/p/xpost/source/browse/src/lib/xpost_interpreter.hxpost_interpreter.h defines the enums describing the various ways of initializing or specifying a program.enum Xpost_Showpage_Semantics {    XPOST_SHOWPAGE_DEFAULT,    XPOST_SHOWPAGE_NOPAUSE,    XPOST_SHOWPAGE_RETURN};enum Xpost_Output_Type {    XPOST_OUTPUT_DEFAULT,    XPOST_OUTPUT_FILENAME,    XPOST_OUTPUT_BUFFERIN,    XPOST_OUTPUT_BUFFEROUT};enum Xpost_Input_Type {    XPOST_INPUT_STRING,    XPOST_INPUT_FILENAME,    XPOST_INPUT_FILEPTR,    XPOST_INPUT_RESUME};/* 3 simple top-level functions */Xpost_Context *xpost_create(const char *device,                 enum Xpost_Output_Type output_type,                 const void *outputptr,                 enum Xpost_Showpage_Semantics semantics,                 int is_installed);int xpost_run(Xpost_Context *ctx, enum Xpost_Input_Type input_type,               const void *inputptr);void xpost_destroy(Xpost_Context *ctx);xpost_client.c is the example program showing the usage of the API./*   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.hchar *prog =    %%BoundingBox: 200 300 400 500\n    0 0 1 setrgbcolor\n    300 400 100 0 360 arc\n    fill\n    showpage\n;int main() {    Xpost_Context *ctx;    void *buffer_type_object;    int ret;    xpost_init();    if (!(ctx = xpost_create(bgr,            XPOST_OUTPUT_BUFFEROUT,            &buffer_type_object,            XPOST_SHOWPAGE_RETURN,            1)))        fprintf(stderr, unable to create interpreter context), exit(0);    ret = xpost_run(ctx, XPOST_INPUT_STRING, prog);    printf(executed program. xpost_run returned %s\n, ret? yieldtocaller: zero);    {        typedef struct { unsigned char blue, green, red, zero; } pixel;        pixel *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++) {                pixel pix = *buffer++;                fprintf(fp, %d , pix.red);                fprintf(fp, %d , pix.green);                fprintf(fp, %d , pix.blue);                if ((j%20)==0)                    fprintf(fp, \n);            }            fprintf(fp, \n);        }        fclose(fp);    }    xpost_destroy(ctx);    free(buffer_type_object);    xpost_quit();    return 0;}QuestionsOne 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?InstallingIn unixes, Cygwin and mingw, you can hg clone https://luser.droog@code.google.com/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 rendering of a filled circle in xpost_client_out.ppm which loads ok for me in Gimp. 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.
RFC PS Rasterizer Library API
c;image;library;postscript
Based on these two linesxpost_create(bgr,         XPOST_OUTPUT_BUFFEROUT,         &buffer_type_object,         XPOST_SHOWPAGE_RETURN,         1); xpost_run(XPOST_INPUT_STRING, prog);I am puzzled by the interaction between xpost_create() and xpost_run().  Is it possible to create and use multiple xpost contexts at once?  If so, shouldn't xpost_create() return some kind of handle that would be passed as a parameter to xpost_run()?  Or, if not, then why should I need to call xpost_create() and xpost_destroy() at all?I would expect the library to behave more like a printer, in that it would produce an image for every showpage command.  One way to make that work would be to register a callback, which would be called whenever showpage is encountered.  Perhaps it could pass some information about the bounding box as parameters to the callback, since it's unreasonable to have to guess or hard-code that information.It's odd that the color model is called bgr, but the pixel values are arranged in the opposite order (red, green, blue) in the output buffer.  I would also consider treating the buffer as an array oftypedef {    int red;    int green;    int blue;} struct pixel; instead of separate red, green, and blue integers.Your example client doesn't seem to demonstrate any error-handling capability.  What happens, for example, if the PostScript interpreter has a stack underflow?