Introduction: ------------ This directory contains implementations of interfaces to various drawing models. The main interface is the DrawContext class, which is an abstract class that basically defines the interface methods (which correspond to DPS function calls). From here one can create a concrete subclass (e.g. XtDrawContext), which maps these DPS calls to a specific drawing model, such as the Xlib library. Basically, the intent is to concentrate all the window/graphic/event specific code in a DrawContext subclass, so that the appkit can be built independent of the drawing model. I think this is a good idea, because: 1 - one can switch contexts on the fly simply by instantiating a different subclass of DrawContext. For instance, one could instantiate a StreamContext to print Postscript to a stream. 2 - Whenever a good DPS implementation comes along, it can simply be dropped into objcX without changing multiple appkit classes - no code changes to either the appkit or any program based on the appkit! 3 - It provides a consistent, simple and fast interface for handling graphics and events for X-Windows until someone wants a more powerful system. 4 - It may allow an easier transition from the current objcX focus on NeXTStep compatability to OpenStep compatability. Getting Started --------------- Using the Display PostScript interface is almost the same as programming in PostScript. If you already know PostScript, use of the psops functions (specified in "psops.h") should be transparent. For instance, drawing a grey, filled rectangle is as simple as: PSsetgray(0.5); PSrectfill(10, 10, 200, 300); or the slower way: PSsetgray(0.5); PSmoveto(10, 10); PSlineto(200, 10); PSlineto(200, 300); PSlineto(10, 300); PSclosepath(); PSfill(); Certain window system specific functions are not defined in Display PostScript, but must be specified by the particular implementation. In this case, the interface used by NeXT is closely followed. These window specific calls are defined in "wraps.h" and "dpsGNU.h", and documented in the NeXTStep Reference Manual. As a minimum, you must first create a Context, create/order a window, and tell the current graphic state which window to draw in: int number; DPSContext context = DPSCreateContext(NULL, NULL, NULL, NULL); PSwindow(10, 10, 200, 300, NX_RETAINED, &number); PSorderwindow(NX_ABOVE, 0, number); PSwindowdeviceround(number); Once you create a context, it automatically becomes the current context. Thus you can use any of the "PS" calls, and they will refer to the most recently created context. Implementation details (XtDrawContext): --------------------------------------- The current XtDrawContext isn't intended to be even close to a complete Postscript implementation. However, it should be enough to base a widget set on and do simple drawing. NOTE: Not all psops/wrap functions are implemented and there is NO indication when you call a method that is not implemented. You need to check if a function is implemented (in XtDrawContext AND XtGState (if applicable)) before you call it, otherwise you will not get good results (e.g. the stack might get messed up). All files starting with xt or Xt are intended to be Xlib specific implmentations of the DrawContext drawing model. The fact that the files have the prefix "Xt" is probable a misnomer. The only Xt library call currently used is "XtWindow" as well as the "Widget" structure, so that it can work with the current Motif implementation of objcX. In the future, XtDrawContext will only use Xlib calls. Drawing with XtDrawContext -------------------------- If you plan on avoiding the psops functions, or you want to implement more of the psops functions, here are some things to know about: - Backing Store: Backing store is probably one of the most fundamental aspects of a windowing system. Unfortunately, the X-Windows backing store protocol leaves something to be desired. This library, however, does implement backing store in a somewhat non-intrusive way. In a style similar to NeXT's DPS, graphics written to buffered or retained windows is first written to a backing pixmap, and then transfered to the window after the drawing is complete. When a window is exposed, the data from the pixmap is automatically transfered to the window to refresh the parts of the window that were previously covered. What do you have to do? If you use psops calls, as with DPS, you need not worry about how backing store or graphics is implemented. If you need to draw directly using Xlib routines (not recommended - think about just implementing the corresponding psops routine if it isn't already), you'll need to know which drawable (from the current gstate) to draw to. You can get the current gstate (XtGState object) using PSgstateobject. - XWContext: The X-Windows/objcX widget set has a sort-of context which holds information about the X application, including the display, the application colormap and the current gstate. Use PSxwcontext(&context) to get the context for the application. The definitions for XWContext are in dpsclient/xwfriends.h. - XtGState: Every view, when lockFocus'ed, has it's own gState, which you can access through context->gstate. The gstate is a XtGstate object which incudes the following information: Coordinate transform matrix: Contains information about the current offset (origin), scale and rotation of the view. It's important that you use this offset when you are drawing, so that buffering will work correctly. xgcntxt: This is a standard X Graphic Context that you can modify and use for your drawing (for example, to change the foreground color, etc). draw: This is the drawable that you should send all drawing too (see backing store). After doing any drawing, you should also call setNeedsDisplay:, so that the data is transfered from the pixmap to the window. This is to avoid unecessary transfering when no drawing was done. - Coordinate system: Note that the X-windows coordinate system places the origin in the upper-left-hand corner, and y increases downward. You should keep track of this (of course, you do not need to worry about this when using psops/wraps calls). TODO list: ---------- 2 - If NSInvocation ever gets working, we could support true procedures and executable/use paths as well as error procedures (as in PostScript). 3 - Should make use of Dictionaries for font info and window devices - this is slower and more work, but it may be more robust. At the least, it follows the same model as PostScript. 4 - Implement arcs. I've already got the code, just need to integrate it.
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.