[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


4    Advanced Concepts and Tasks

In Chapter 2 and Chapter 3 you learned the basic concepts and tasks you need to write simple applications using XDPS. To write more complex applications, however, you need the additional concepts and tasks described in this chapter.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


4.1    PostScript Language Encoding

In XDPS, PostScript language code can be sent to a context in three encodings: as a binary object sequence, as binary-encoded tokens, or as ASCII text. Each PostScript context has two encoding parameters: DPSProgramEncoding and DPSNameEncoding.

XDPS uses default values for the encoding parameters, so application programmers can usually ignore encoding. Table 4-1 shows the default values for the encoding parameters.

Table 4-1: Default PostScript Language Encodings for XDPS

Context Type Encoding Parameter Default Value
execution DPSProgramEncoding Binary object sequence (dps_binObjSeq)
execution DPSNameEncoding User name index (dps_indexed)
text DPSProgramEncoding ASCII characters (dps_ascii)
text DPSNameEncoding User name string (dps_string)

XDPS lets you change the encoding parameters of a context to any of the three possible encodings. To change the encoding parameters, use the Client Library routine DPSChangeEncoding, described in Chapter 5.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.2    Buffering and the Client Library

In most implementations of the Display PostScript system, the Client Library buffers its communications with the Display PostScript server. But in XDPS, the Client Library communicates with the server by way of Xlib, which buffers its own communication. To avoid duplicate buffering, the XDPS Client Library performs no internal buffering. Instead, all buffering of Client Library communication occurs in Xlib. As a result, the XDPS Client Library routine DPSFlushContext performs the same tasks as the Xlib procedure XFlush.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.3    Accessing Files on the Server

To preserve security on servers, XDPS lets applications access only certain files stored on the server. Specifically, XDPS lets applications access only files stored in two directories referred to here as tempdir and permdir.

The tempdir directory is temporary: its contents are deleted each time the XDPS server is started or reset, such as when the user logs out. In contrast, permdir is a permanent directory: resetting and restarting does not affect its contents. Applications can both read from tempdir and write to it. Applications can only read from permdir; they cannot write to it.

To specify a file stored in tempdir, an application must prefix the filename with %temp%. To specify a file in permdir, an application must use the prefix %perm%. If a filename is preceded by neither %temp% nor %perm%, XDPS searches for the file first in tempdir and then in permdir. XDPS does not let applications access file names that include a slash (/), a bracket ([), or a colon (:).

By default, tempdir is the directory /usr/lib/DPS/tempdir; permdir is /usr/lib/DPS/permdir. You can, however, assign other directory names. To do so, specify those names in the XDPS server startup command.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.4    Converting Coordinates

The X Window System and the PostScript language use different coordinate systems to specify points within the drawing area. As a result, XDPS applications sometimes need to convert user space coordinates (used by the PostScript language) into X coordinates, and vice versa.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.4.1    Preparing to Convert Coordinates

Before converting coordinates, an application should create a context and perform the following steps:

  1. Perform any user space transformations.

  2. Get the current transformational matrix (CTM), its inverse, and the X coordinates of the current user space origin.

  3. Store these values in the VM associated with the context.

The application can then perform coordinate conversions for the context.

To get the CTM, its inverse, and the X coordinates of the current user space origin, an application can call a custom wrap such as PSWGetTransform, whose pswrap source file is shown in Example 4-1.

Example 4-1: Wrap Returning CTM, Its Inverse, and Current User Space Origin

defineps PSWGetTransform(DPSContext ctxt | float ctm[6], invctm[6];
        int *xOffset, *yOffset)
      matrix currentmatrix dup ctm
      matrix invertmatrix invctm
      currentXoffset exch xOffset yOffset
endps

The following C language code calls PSWGetTransform:

DPSContext ctxt;
float ctm[6], invctm[6];
int xOffset, yOffset;
PSWGetTransform(ctxt, ctm, invctm, &xOffset, &yOffset);


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.4.2    X Coordinates to User Space Coordinates

To convert an X coordinate into a user space coordinate, an application can execute the following C language code:

#define A_COEFF 0
#define B_COEFF 1
#define C_COEFF 2
#define D_COEFF 3
#define TX_CONS 4
#define TY_CONS 5
int x,y; /* X coordinate */
float ux, uy; /* user space coordinate */

 
x -= xOffset; y -= yOffset; ux = invctm[A_COEFF] * x + invctm[C_COEFF] * y + invctm[TX_CONS]; uy = invctm[B_COEFF] * x + invctm[D_COEFF] * y + invctm[TY_CONS];


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.4.3    User Space Coordinates to X Coordinates

To convert a user space coordinate into an X coordinate, an application can execute the following C language code:

x = ctm[A_COEFF] * ux + ctm[C_COEFF] * uy + ctm[TX_CONS] + xOffset;
y = ctm[B_COEFF] * ux + ctm[D_COEFF] * uy + ctm[TY_CONS] + yOffset;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.5    Resizing Windows

An application or user can resize the window in which XDPS paints. Resizing can affect two PostScript language settings, the clipping path and the user space origin, as described in the following sections.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.5.1    Window Resizing and the Clipping Path

PostScript language painting occurs only within the area known as the clipping path. When initializing a context, XDPS sets the clipping path equal to the size of the window. If the window is resized, however, XDPS does not reset the clipping path. Instead, each time the window is resized, the application should execute the PostScript language operator initclip, which reinitializes the clipping path to match the window's new size. The application can then reexecute any code that performs further clipping.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.5.2    Window Resizing and the User Space Origin

When an application resizes the window of a context, the user space origin moves according to the bit gravity of the window. Bit gravity is an X window attribute that governs how partial window contents are preserved when a window is resized. (Bit gravity is not to be confused with window gravity, an X attribute that does not affect the user space origin.) In X, specifying the bit gravity of a window is optional: the default value is ForgetGravity. XDPS treats ForgetGravity as NorthWest gravity.

Because a window's user space origin moves according to the window's bit gravity, resizing does not change the distance between the user space origin and any PostScript language images already displayed. Because this distance is unchanged, future PostScript language images align with those already displayed.

Compare Figure 4-1 and Figure 4-2. The left side of Figure 4-1 shows a window displaying the text "NorthWest." As shown, the user space origin is the window's lower left corner, and the bit gravity is NorthWest.

The right side of the figure shows the same window after resizing. Notice that the user space origin (and hence the displayed text) remains a constant distance from the window's upper left corner: its "NorthWest" corner.

Figure 4-1: Resizing a Window with NorthWest Bit Gravity

In Figure 4-2, the size of the window on the left and the position of its text are the same as in Figure 4-1. Also the same is the user space origin: the lower left corner. In Figure 4-2, however, the bit gravity is SouthWest. Therefore, when the window is resized, the user space origin and displayed text remain a constant distance from the window's lower left corner: its "SouthWest" corner.

Figure 4-2: Resizing a Window with SouthWest Bit Gravity

The user space origin is typically the lower left corner of the drawing space. For this reason, typical XDPS applications should explicitly set the bit gravity of windows to SouthWest.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.6    Synchronizing the Display PostScript System and X

X imaging calls complete atomically. Therefore, XDPS applications need not take special precautions when issuing X imaging calls before PostScript language imaging calls. PostScript contexts, however, complete nonatomically and asynchronously within the X server. Thus, when an application issues X imaging calls immediately after issuing PostScript language calls, the X calls can sometimes execute before the PostScript language calls. That is, it is possible for X and the Display PostScript system to become unsynchronized.

Few applications need to synchronize the Display PostScript system and X explicitly. To do so, an application can call the Client Library routine DPSWaitContext before issuing the X imaging calls that follow PostScript language calls. DPSWaitContext forces the PostScript language calls to complete before the X calls. Note that DPSWaitContext causes a round trip to the server. Such trips impair performance, so call DPSWaitContext only when needed.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.7    Synchronizing Client and Context

Applications, or clients, sometimes need to pause the execution of a context. Pausing a context lets an application take control when the PostScript interpreter reaches certain points within a PostScript language procedure.

To pause a context, an application sends the system-specific PostScript language operator clientsync. The clientsync operator causes a context to enter the FROZEN state. The context remains in that state until the application calls the Client Library routine XDPSUnfreezeContext. (For more information on clientsync, see its description in Chapter 6. For a description of XDPSUnfreezeContext, see Chapter 5.)


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.8    Sharing Contexts and Spaces

Although the XDPS Client Library lets applications share contexts and spaces, it does not coordinate the sharing. Instead, the applications themselves must coordinate any sharing of resources.

The sharing applications must avoid race conditions and deadlocks. In addition, if one application obtains the XID of a resource created by another, the application that obtained the XID must create records and handles to access the shared resource through the Client Library.

A context or space cannot be destroyed while shared. If such a resource is shared, the routines DPSDestroyContext and DPSDestroySpace destroy the client data structures created to access the shared resource but do not destroy the resource itself. After a resource is no longer shared, an application can destroy it by calling DPSDestroyContext or DPSDestroySpace.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9    Using Color

In XDPS, the Display PostScript system paints colors and gray shades on an X server. An X server can render only a finite number of exact colors and shades simultaneously; it represents each as a pixel value. In contrast, the PostScript language represents colors and shades not as pixel values but as "pure" colors and "pure" shades, without regard for whether the output device can render them exactly. As a result, to paint on an X display, a PostScript context must first find whether there is a pixel value that matches the pure color or shade specified by the PostScript language.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9.1    Converting Colors and Shades into Pixel Values

To find the pixel value that matches a particular color or shade, a context searches the color cube or gray ramp. The color cube and gray ramp specify pixel values that correspond to a subset of all possible pure colors and shades.

The color cube defines a set of colormap cells whose values form a series of color ramps (progressive changes in color). Each axis of the color cube represents one of three hues: red, green, or blue (r/g/b); all displayed colors are composites of these hues. Values along the axes of the cube represent intensity of hue and increase from 0% to 100% of the displayed color. Note that the color cube is not a cube in the strict sense of the word: the axes need not have the same "length," that is, the same number of values.

The gray ramp defines a set of colormap cells whose values form a single color ramp of gray shades. Values along the gray ramp represent comparative intensities of black and white. Along the ramp, the intensity of white increases from 0% to 100%.

If the color cube or gray ramp contains a pixel value that exactly matches the specified pure color or shade, the context uses the pixel value to paint the pure color or shade. Otherwise, the context approximates the color or shade by dithering, by painting a pattern of colors or gray shades from its color cube or gray ramp.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9.2    Defining a Color Cube and Gray Ramp

When creating a context, an application must allocate and define a color cube and gray ramp. If the application defines no color cube, the context renders colors by dithering from the gray ramp. If the application defines neither a color cube nor a gray ramp, the context cannot paint.

Typically, applications create contexts by calling XDPSCreateSimpleContext. This routine allocates and defines a color cube and gray ramp using the XStandardColormap structures RGB_DEFAULT_MAP and RGB_GRAY_MAP. If these structures do not exist, XDPSCreateSimpleContext allocates them. To allocate and define a different color cube and gray ramp, an application can use either of two methods:

To allocate and define a color cube and gray ramp, an application performs the following steps:

  1. Call XCreateColormap to create a colormap. (This optional step is needed only if the application does not use the default colormap.)

  2. Call XAllocColorCells to allocate the colormap cells needed to store the color cube and gray ramp.

  3. Call XStoreColors to store a color for each pixel value in the color cube and gray ramp.

  4. Call XDPSCreateContext to create a context and pass the XStandardColormap structures describing the color cube and gray ramp.

The following sections describe how XDPS uses the color cube and gray ramp, referring to the following elements of the color cube and gray ramp:
maxred redmult
maxgreen greenmult
maxblue bluemult
maxgrays graymult
firstgray firstcolor
colormapid  

These names are the same as those used for elements of the colorinfo array, which is accessed by the X-specific operators setXgcdrawablecolor and currentXgcdrawablecolor. (For more information, see the description of these operators in Chapter 6.)


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9.2.1    Using the Color Cube

To render an exact color, XDPS searches the colormap for the pixel value matching the r/g/b value specified in the color cube. Conceptually, the color cube is three-dimensional; the colormap, however, is conceptually one-dimensional. Thus, to find the pixel value that matches an r/g/b value, XDPS uses the following formula:

PixelValue = r * redmult + g * greenmult + b * bluemult + firstcolor

In this formula, r, b, and g are integers. The integer r is in the range [0; maxred]; g is in the range [0; maxgreen]; and b is in the range [0; maxblue].

A color cube must start at pixel firstcolor in the X colormap colormapid. Along the red, green and blue axes of the cube, values should increase from zero to the maximum values for each axis. For example, one common color allocation is 3/3/2 (three reds, three greens, and two blues). This allocation results in the following maximum value for each hue:

maxred = 2
maxgreen = 2
maxblue = 1

In the colorinfo array, the elements redmult, greenmult, and bluemult are the scale factors that determine the spacing of the cube in the linear colormap. For the 3/3/2 color cube mentioned earlier, appropriate values might be:

redmult = 32
greenmult = 4
bluemult = 1

Note

In an empty color cube, maxred, maxgreen, and maxblue each equal -1, not zero.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9.2.2    Using the Gray Ramp

The gray ramp must start at pixel firstgray in XStandardColormap colormapid. To find the pixel value that matches a gray value, XDPS uses the following formula, where gray is an integer in the range [0; maxgrays]:

PixelValue = gray * graymult + firstgray

For example, suppose you want to define a 5-cell gray ramp whose values increase from 0% to 100% in steps of 20%. If the corresponding five colormap entries are contiguous, you can describe the map by setting maxgray to 4 and graymult to 1.

A gray ramp must consist of at least two cells: one for black, one for white. If the colormap is associated with the default visual type, you can use the following values to form a 2-cell gray ramp consisting of BlackPixel and WhitePixel:

maxgrays = 1
graymult = WhitePixel- BlackPixel
firstgray = BlackPixel


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


4.9.3    Rendering Colors Not in the Color Cube

By default, XDPS dithers to render any color not in the color cube. To render such an additional color exactly, an application must cause the X server to allocate a colormap cell for the additional color.

To control whether additional colors are rendered exactly or by dithering, an application can set the actual element of the colorinfo array. The actual element specifies the maximum number of additional colormap cells that the server attempts to allocate. Thus, it limits the number of additional colors that the server attempts to render exactly.

If actual is nonzero, the server attempts to allocate a colormap cell for each additional color until it has allocated actual cells. After actual cells have been allocated, the server renders any future additional colors by dithering. If actual equals zero, the server dithers to render all colors not found in the color cube.

To override the maximum set by actual, an application can use the X-specific operator setrgbXactual.

Note

XDPS does not limit the number of colormap cells that one context or one application can allocate.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


4.9.4    The colorinfo Array and XStandardColormaps

The color cube and gray ramp are passed to XDPSCreateContext as XStandardColormap structures. Table 4-2 and Table 4-3 show how the entries in these XStandardColormap structures correspond to elements in the colorinfo array.

Table 4-2: Mapping Between colorinfo Array and XStandardColormap Storing Color Cube

colorinfo Element XStandardColormap Element
maxred red_max
redmult red_mult
maxgreen green_max
greenmult green_mult
maxblue blue_max
bluemult blue_mult
firstcolor base_pixel

Table 4-3: Mapping Between colorinfo Array and XStandardColormap Storing Gray Ramp

colorinfo Element XStandardColormap Element
maxgrays red_max
graymult red_mult
firstgray base_pixel
colormapid colormap