We're doing lots of stuff with the code base at the moment, but they do fall under a few broad categories.
Source Portability.
I'm routinely checking the program under Mingw, Cygwin, and Ubuntu (Virtualbox), and Vincent has mentioned checking it with OpenIndiana (OpenSolaris), FreeBSD, and Visual Studio. These last few still need some work, I understand; for FreeBSD, there are certain calls (like mremap) which take different arguments than other Unices; for Visual Studio, it needs to be clean C89 (so we're also removing //comments for completeness, first from the library). But the code was ready for a lot of that. I had already removed designated initializers, compound literals, and VLAs. No bitfields. But I was using <stdbool.h> all over the place, even in header files, requiring them all over the place even where not specifically used. Bools are all ints now.
Interoperability.
We are also working to unravel my tangled web of inter-module dependencies, and to migrate most of the program into the library. We haven't hammered out all the details yet, but Vincent is firmly against ghostscript's (argc, argv) initialization. He says (compellingly) that the initialization should be more "library" like. And, put that way, I can't disagree.
A big hurdle for me is removing the setjmp/longjmp mechanism that I've long used for error recovery. It's not appropriate behavior for a library. So I've been slowly replacing return values with pass-by-pointer, and void functions with int functions. Once the last call to error() is removed, then there won't be any more longjmps. But there won't be a backup error handler, either. Which feels weird. But /good/ weird, you know? Instead it has a powerful logging system for tracking internal errors and messages. One that I'm only beginning to put to proper use.
Update: setjmp/longjmp have been removed. This removes the bulk of bin/xpost_error.c, so xpost_error is pretty much ready to migrate to the library, then xpost_save, and then maybe context. With context, then the rest of the data types can come over, dict, array, string, file. Then finally, xpost_interpreter. And the garbage collector still needs a lot of work.
Graphics.
I'm missing a big algorithm in the middle of the chain: shape-reduction. Oh, and operations using the even-odd winding-number rule. I don't know how to do those (yet).
I think my device structure is workable, although still quite primitive. The prototype is based around generating a pgm file, but it can be made to work with any byte-map format by replacing the /Emit procedure.
Here's the description from the
image.ps file which implements the device.
% PGMIMAGE device handles 8bit images.
%
% It uses the full range 0-255 of values and does not calculate
% the actual maximum value in the data before transmitting. MaxVal
% is always 255.
%
% In the list of procedures below, PGMIMAGE is the Class dictionary,
% IMAGE is an instance returned by Create.
%
% procedures:
% width height PGMIMAGE Create -> IMAGE
% val x y IMAGE PutPix -> -
% x y IMAGE GetPix -> val
% val x1 y1 x2 y2 IMAGE DrawLine -> -
% val x y width height IMAGE DrawRect -> -
% val x y width height IMAGE FillRect -> -
% val polygon IMAGE FillPoly -> -
% IMAGE Emit -> -
% eg:
% PS> /dev 40 20 newPGMIMAGEdevice def
% PS> 55 1 1 38 17 dev dup /DrawLine get exec
% PS> 77 9 14 3 3 dev dup /FillRect get exec
% PS> dev dup /Emit get exec
%
So this is the basis upon which I next need (want) to implement an X11 device. I'm planning to write this in C. ... Long ago there was a silly idea to add network client functions and implement the X protocol itself in postscript (Xlib /in/ ps). But ... ick. :P :)
So, the X11 device will inherit the above class dictionary, and overload Create, PutPix, GetPix, and Emit. These will be implemented by operator functions defined in the X11DEVICE dict.
I think it'll work. We'll see. Being able to see the output dynamically is going to make implementing the rest of the graphics algorithms much easier, I think.
PPM images, xcb windows, win32 windows, and much of the graphics and font functionality has been implemented and is being refined and optimized.
Vincent really wants a BGRA device, so that's very high on the list. It would be second for sure, except I've got this nagging desire to do the bitmap device next so I can start playing with caching bitmaps and masks and other mysterious parts of the font machinery. If I've got a color device, then I also have to bring in hsb and cmyk. They have to be there sooner or later. Excuses, excuses. I think the X11 device will show nicely how to get the postscript values /back/ into C.
Bitmaps have been implemented in the `image` operator, but not yet as an output device.
There's also, in DPS and NeWS, a new object type to encapsulate a color value explicitly tied to a color space. If a color value is passed as a single object, then color devices can use the same interface defined above, I think. There's room at the moment for 15 more types before we have to rearrange the flags.
We've put Cairo to one side because of the desire to make Xpost self-contained so that it can be included in LibreOffice and used for EPS rendering. LibreOffice only uses Cairo on Linux, so it's not guaranteed to be present in all the configurations where xpost is wanted. It would also match unfavorably with the current code which uses float for real numbers, whereas cairo uses double. This would require conversions at every function call. There is some (untested) support in the design for using doubles; this would require reworking the dictionary hash function, for starters.