Public interfaces are the only ones that a client (i.e. application program) needs; private interfaces are internal to the implementation of the Interpreter.
Public interfaces
Vector2
Two-dimensional vector type (VEC: TYPE ~ RECORD[x, y: REAL]) and operations on VECs. Vector2 is used by many Imager interfaces.
FunctionCache
A utility module which implements a general caching mechanism. The module provides a facility for writing cached implementations of REF-valued functions. The caches are managed with a move-to-front discipline, and trimmed according to the client supplied limits on the total number of entries or the total number of words consumed.
ImagerTransformation
The Transformation type and operations. This module contains procedures for creating, copying, combining, and modifying transformations. Transformations are two-dimensional affine transformations represented as a 3 by 3 matrix:
[ a d 0 ]
[ b e 0 ]
[ c f 1 ]
As far as the Interpreter is concerned, Transformations are considered to be immutable, as are all Interpress Values. However, the Imager allows clients to treat Transformations as mutable when this is desirable to avoid excessive storage allocations. The representation of Transformations contains some extra information to speed recognition of special cases; the 3 by 3 matrix is always the truth.
ImagerPath
Deals with the representation of outlines and trajectories. The Imager interface uses a callback mechanism as the basic means of communicating these entities between parts of the system, and the relevant procedure types are defined here. A callback mechanism simply means that the client program calls procedures in the Imager which take as a parameter a second client procedure to be "called back" when the Imager is prepared. The Imager sets up the environment in which the callback procedure will be executed. Also provided are some explicit representations, primarily for use by the Interpress interpreter and for other clients where the callback mechanism is not the most natural.
ImagerFont
The definition of the Font type and operations on it. The operations are largely just for accessing the metric information, since the public Show procedures are provided in the Imager interface (see below). A font is object-oriented, so that new kinds of font definitions can be added at will. The mechanism for doing this is not exposed in the public interface. The font implementation record contains tables for the metrics, corresponding to those in ImagerFont, plus one procedure, MaskChar, to apply the mask of a given character to a given Imager context. The simplest kind of Imager device implementation might implement Show just by drawing each character through this mechanism, but in most cases the device implementation is expected to call MaskChar just once per character, and cache the results in a format appropriate to the device, usually a bitmap at device resolution. This is also where any device-specific font tuning may take place; we'll examine this some more later on. Note that the context passed to MaskChar is generally not the same one the client passed to the call to Show, but is a special one designed to capture the image in memory so that it can be cached.
The Font record, like most of the Imager data types, contains a property list. This is so new fields and operations may be added without having to change the interface.
The font interface is designed to use 16-bit character codes. It is desirable to decouple the particular string representation from the rest of the Imager; for example a composition system might have its own internal representation for a string of 16-bit characters, different from the string-body encoding standard, which is, after all, designed for interchange purposes. In all the operations that require a string of characters (StringWidth or StringBoundingBox, for example), a two-level callback mechanism is used; the client calls the package, supplying a StringProc; the package calls the client-supplied StringProc, passing it a charAction procedure, which the client, in turn, calls once for each character. This mechanism is a little confusing at first, but works out to be a very handy way to hook a system together, without having to use a common format or allocate extra memory just for changing representations. The same style is used to pass other complicated entities to the Imager, such as outlines for MaskFill. In all of these cases, convenience procedures are also supplied for what are expected to be the most common representations, so most clients will not need to worry about the general mechanism.
ImagerPixelArrayDefs and ImagerPixelArray
Defines the type corresponding with the Interpress PixelArray type, and procedures for creating and accessing pixel arrays. This, again, is object-oriented, so many different implementations can hide behind this interface. The public interface just provides procedures for creating PixelArrays from a variety of sources, plus the Extract and Join operations. Refer to Sampling and Halftoning, below, for a description of how the Imager uses PixelArrays.
ImagerColorDefs and ImagerColor
Defines the type corresponding to the Interpress Color type. There are two basic kinds of color: constant and sampled. Sampled colors follow the pattern described in the Interpress standard quite literally, consisting of a PixelArray, a Transformation, and a ColorOperator. Constant colors are more complicated than they appear at first thought, the complication arising largely from the desire to support full color, not just shades of gray. Since no real device to date can render the full color gamut, it is important to try to capture the client's intent, not just the ideal color. Just what this specification should look like is still a matter for research.
In addition, there is the desire to be able to specify colors in a somewhat device-dependent way; for example, to generate check-plots for VLSI on a full-color plotter it is handy to be able to use colors that mix where they overlap, just by putting toners down on top of each other. For this type of application it seems sufficient to supply a collection of named colors, e.g. Xerox/.../VLSI/Metal-1, which will make it feasible to provide alternative schemes for other devices, for example stipple patterns on black-and-white printers.
Another type of special constant color is ImagerBackdoor.invert, which is handy for interaction on displays, but which is not supported on all devices.
Imager
This is the main client interface. Aside from the procedures for access to the imager variables, the operations in this interface are all "one-way," that is, the information flow is strictly from the client to the Imager package. This makes it possible to provide a "stateless" implementation, that is, one that does not need to maintain the values of the imager variables. Such an implementation may merely translate the Imager calls into an Interpress master, written as a stream. To make this possible, while still preserving the full power of the imaging model, there are some procedures supplied that will generate some state-accessing Interpress code when used for creating a master. In this category are SetSampledColor and SetSampledBlack, which set a sampled color relative to the current transformation. The other one is DontCorrect, which is useful in contexts where it is necessary to save and restore the correctPass imager variable.
For operations that, in Interpress, take a body, the Imager uses a simple callback mechanism. The procedures that do this are DoSave, DoSaveAll, Correct, and DontCorrect. The callback procedures are parameterless, and, in the case of Correct, may be called more than once. Because they are parameterless, callback procedures will be defined as local to a client's procedure, so they can access the variables of that procedure; in particular, they will need access to the context itself in order to be able to draw anything! This does not restrict the power of the construct, since it is possible for the client to have its own DoSave that uses an action procedure with parameters, written using just the parameterless mechanism provided. In most circumstances, though, using a local callback procedure is most straightforward.
The remainder of the Imager interface simply provides the imaging operations described in chapter 4 of the Interpress standard, as supplemented by the extension strategy. Procedures include translation, rotation, and scaling of imaging contexts, showing characters and strings, all the mask and clipping operations, and setting colors and stroke parameters.
ImagerSample
Defines the notion of a sample buffer and provides procedures for creating, reading, and writing samples. Samples represent a set of values which correpsond to pixel values for a raster device. For example, a sample for a color display would likely consist of a triple of values named red, green, blue.
Also provides the Sampler type, which contains the state needed to sample an array of samples trhough an arbitrary transformation, as well as the sampling primitives GetPointSamples, and GetInterpolatedSamples. GetPointSamples uses undersampling, for use when speed is more important than high image quality, or where the image is not known to contain high spatial-frequency images that might lead to aliasing. GetInterpolatedSamples interpolates a value from neightboring pixels, and is appropriate when the output resolution is higher than the input resolution and the sample values can be combined linearly in a meaningful way.
ImagerColorOperator
Provides operations on ColorOperators and mapping back and forth among samples, pixels, and colors as a function of a ColorOperator. Six color model operators are defined: black, gray linear, gray density, gray visual, RGB linear, and color mapping.
ImagerBackdoor
Low level interface for clients to read and write context state. Not all devices implement Backdoor, and to be strictly device independent clients should not use Backdoor. Also includes MakeStipple, for converting small stipple patterns to Colors.
ImagerTerminal
A low level interface for supplying clients with Imager contexts corresponding to the current black and white or color terminals.
ImagerColorMap and ImagerDitherContext
Two mid-level interfaces for maintaining the color map on the color display device. Its purpose is primarily to provide synchonization between the various clients that modify and use the color map, and to hold extra information about the color map. Provides for setting up standard color maps, client color maps, and gamma correction.
ImagerOps
A miscellaneous low-level interface for manipulating PixelMaps and creating PixelMaps from other kinds of pixel storage such as contexts and frame buffers.
Following is a list and very brief comment on each of the Imager private interfaces. Private interfaces are internal to the implementation of the Imager and should not be needed by clients.
ImagerTypeface and ImagerTypefaceExtras
Defines a private typeface object for use in implementing ImagerFont operations.
ImagerFontPrivate
Private specification of font object representation.
ImagerPixelArrayPrivate
Private specification of pixel array object representation.
ImagerColorPrivate
Private specification of color object representations.
ImagerColorOperatorPrivate
Private specification of color operator object representations.
ImagerPrivate
Private specification of imager state object representation.
ImagerState
Private specification of imager state operators.
ImmutablePropList
Utility interface that implements immutable, sharable property lists.
AISFileFormat
Definitions of record types needed to parse AIS files.
StrikeFontFormat
Definitions of record types needed to parse strike format fonts.
PrePressFontFormat
Definitions of record types and procedures needed to parse PrePress format fonts.
ImagerPixelMap
A PixelMap describes a window into a buffer, and the buffer itself may be positioned anywhere in a global device space. The windowing information is stored in the PixelMap record, so that it may be easily changed to accomplish translation and clipping by rectangles. The translation feature may be used for destination maps to conveniently implement band buffers. This interface provides most of the functionality of BitBlt, without the attendant risks of smashing the world. This is one private interface that could be exported for client use.
ImagerManhattan and ImagerManhattanExtras
A Manhattan polygon which may be described as a collection of non-overlapping rectangles. ImagerManhattan provides objects and procedures for creating and operating on Manhattan polygons, including creation, copy, union, intersection, difference of polygons. This package can be useful in creating complex clipping boundaries for Imager contexts.
ImagerScanConverter and ImagerScanConverterPrivate
The basic module for scan converting from paths to pixels or runs of pixels.
ImagerStroke
Basic routines for producing the outline of a stroke given a path for the stroke centerline.
ImagerDevice
Defines the class and instance types for representing Imager logical devices.
ImagerRaster
Procedures for creating new Imager devices from client definition. Predefines devices for the black and white terminal and color terminal in color map and full color modes.
ImagerRasterPrivate
Private definitions for use in implementing raster devices.
ImagerDither, ImagerDitheredDevice, ImagerDitheredDevicePrivate
Definitions and procedures for implementing a dithering type display device.
ImagerBitmapDevicePrivate
Definition of the object record for a Bitmap Device.
ImagerColor24DevicePrivate
Definition of the object record for a full color Device.
ImagerFastShow
Optimization for displaying a pixel map via an Imager context.
ImagerMask
Procedures to convert masks, bitmaps, and rectangles to run groups
ImagerCache
A simple caching mechanism for caching font bitmaps.
ImagerBox
A utility for dealing with bounding and intersecting boxes
ImagerBrick
Types and procedures for defining halftone "bricks", based on the work of Thomas Holladay [2]. Bricks are used for halftoning by the Imager devices.
Imager device implementations
The Imager interface is object-oriented, and so may have any number of different implementations behind it. For example, the implementation that knows how to write Interpress masters shares very little with other device implementations, and has its own set of procedures in the device class record. This is also the case for other devices that merely record the sequence of calls, for subsequent screen refresh, for example. Most other device implementations will want to share the mechanism for maintaining the imager variables. The raster devices, including the PD file writer, share even more in common. This sharing is accomplished in two ways: one way is to make the common parts into modules that the various devices can call on as appropriate; this collection of modules may be called the implementor's Toolkit, and pieces of this may well be useful for other clients as well. The other way to accomplish the sharing is again to use a classing mechanism. This is done for the raster devices (displays, sampled-image creators, and PD files). This class turns out to need relatively few operations in it. Note that any particular Imager device still has the option of intercepting calls through the Imager class record, making it easy to put in accelerators for frequent cases without doing serious harm to the overall structure.