═══ 1. Correlation ═══ Correlation is the process of determining which primitives, if any, are contained in an area of interest. The process for nonretained graphics is very different from the process for retained graphics. The following topics are related to the information in this chapter:  Presentation spaces  Coordinate spaces and transformations  Editing retained graphics and graphics segments ═══ 1.1. About Correlation ═══ When you want to select an area of interest on the screen, you usually move the pointer to the applicable point and signal (by clicking a mouse, for example) that this is the object you want. This selection process most commonly is used for graphic applications. For example, your application could permit a user to select an object, then change its color. Correlation, however, can also be used in nongraphic applications. For example, your application could model the operation of a calculator and permit a user to select numbers for mathematical operations. The area of interest is defined by the operating system as a small rectangle, centered on the (x,y) coordinate position, that has been sent to the application. The virtual rectangle the application generates is known as the pick aperture. The following figure shows an example of a pick aperture. The Pick Aperture The process of determining what lies in the pick aperture differs between nonretained and retained graphics. For nonretained graphics, the presentation space must be put in a state that supports correlation before the primitives are drawn. Then correlation is performed while the primitives are being drawn. For retained graphics, the segments that contain the graphics can be replayed, permitting correlation after the primitives are drawn. Note: The necessity to correlate graphics can usually be predicted. Therefore you can plan for it when designing applications. However, this does not mean that you have to create retained (rather than nonretained) graphic segments. The decision to retain graphics is dependent on several considerations of which correlation is only one. ═══ 1.1.1. Correlating Nonretained Graphics ═══ For the purposes of correlation, nonretained graphics are those graphics that are being correlated during the drawing process. Nonretained graphics can exist in nonretained graphic segments or completely outside any segment structure. Primitives outside segments are detectable when the applicable draw control is set. Nonretained graphics, inside a segment bracket, can be created in either draw or draw-and-retain modes. If created in draw-and-retain mode, a segment, at first, is considered nonretained while the primitives in the segment are being drawn; then it is considered retained. To be correlated, nonretained segments must have unique, nonzero identifiers, and must be defined as detectable. The primitives within these segments can be tagged just as primitives in retained segments are. However, the tags do not influence the correlation process for nonretained graphics. To get correlation data from the drawing of nonretained graphics, three steps must be performed- after creation of the presentation space but before drawing the primitives: 1. Call GpiSetDrawControl to switch on the correlation flag (DCTL_CORRELATE, DCTL_ON). 2. Call GpiSetPickApertureSize, if necessary, to change the size of the pick aperture. 3. Call GpiSetPickAperturePosition, if necessary, to explicitly position the aperture. As input to this function, you provide the coordinate position on which the pick aperture is to be centered, using presentation page coordinates. Correlation is performed for the following functions:  Individual primitive-drawing requests, for example, GpiBox  GpiPutData  GpiElement  GpiPlayMetaFile Correlation is never performed for GpiErase You detect correlation hits by examining the returned values from the GPI functions. If GpiLine, for example, draws a line that intersects the pick aperture, it returns a value of GPI_HITS to indicate a correlation hit. If the line does not intersect the pick aperture, GpiLine returns a value of GPI_OK, to indicate the successful drawing of a line without a correlation hit. GpiLine returns a value of GPI_ERROR if an error is detected. If the line intersects the pick aperture, a correlation hit is returned even if the line style is LINETYPE_INVISIBLE. For other primitives, if the object is drawn in outline mode, a correlation hit is returned only if the pick aperture intersects the boundary. If the object is in fill mode, a correlation hit is returned if the pick aperture intersects or lies within the boundary. The following figure is an example of primitives intersecting the pick aperture. Correlating Nonretained Graphics Each GPI function whose output intersects the pick aperture returns a hit (GPI_HIT). GpiBox, whose output does not intersect the pick aperture, returns GPI_OK. ═══ 1.1.2. Correlating Retained Graphics ═══ The information in a retained graphic segment can be redrawn; therefore, setting up an environment for correlation is not necessary. Correlation on retained segments is processed through segment IDs and tags throughout the segments. For any retained segment to be a candidate for correlation, the following must be done: 1. Call GpiOpenSegment with a unique, nonzero identifier. 2. Call GpiSetSegmentAttrs with the following settings: a. ATTR_DETECTABLE switched ON b. ATTR_DYNAMIC left OFF (default), unless the segment is unchained and, therefore, drawn non-dynamically c. ATTR_PROP_DETECTABLE left ON (default), in any segment that calls the candidate segment 3. Call GpiSetTag at appropriate locations within the segment. Note: The preceding is the recommended method. However, an application still can receive correlation data about invisible segments. ═══ 1.1.2.1. Tagging Primitives within a Segment ═══ GpiSetTag inserts a long integer value, called a tag, at the current element pointer position. The tag becomes a segment element, which serves as an identifier for the primitives that follow until the next tag is issued. Tags also are called pick tags or pick identifiers. Typically, applications assign tags only to elements that correspond to primitives. You can determine the value of the last tag assigned to an element using GpiQueryTag. Note: Tags are used only in correlation. They are not used in the chaining or calling of segments, nor do they cause or modify output. The long integer value of the tag is 0 by default. However, a 0 value makes the subsequent primitives undetectable. An application can use this effect to make some parts of a segment detectable and other parts of it non-detectable. If you know that this capability is unnecessary, you can change the default tag value using GpiSetDefTag. The tag you specify becomes the current tag, and it applies to all subsequent primitives until you next call GpiSetTag. The tag can be considered one of the attributes of the primitive and therefore affected by the current attribute mode. In AM_PRESERVE mode, it is stored on the LIFO stack and can be recalled with GpiPop. Tags cannot be inserted between a GpiBeginArea and GpiEndArea area bracket. All primitives within an area have the same tag. A tag value greater than 0 enables correlation on the subsequent primitives, but only if the segment ID is greater than 0 as well. The data returned from each correlation consists of a set of segment-tag pairs. The reason for this pairing is that a single segment can draw objects in several locations. By adding identifiers within the segment, an application has a more exact description of what has intersected the pick aperture. For simple chained segments, each unique segment-tag pair within the pick aperture is known as a hit. If two or more primitives in the pick aperture have the same tag, they are considered a single hit. Hits for called segments differ slightly and are described in The lMaxDepth Input Parameter. ═══ 1.1.2.2. Correlation Functions for Retained Graphics ═══ The PM has three different functions that enable you to correlate a uniquely identified retained segment. Function Description GpiCorrelateSegment Permits correlation on a single segment. GpiCorrelateFrom Permits correlation on a range of segments from a segment chain. GpiCorrelateChain Permits correlation on the entire segment chain. For nonretained graphics, the correlation hits are returned by the actual drawing commands. For retained graphics, the correlation hits are returned by the three correlation functions listed above. The size of the pick aperture is set using GpiSetPickApertureSize, just as with nonretained graphics. However, the coordinate position on which the pick aperture is centered usually is obtained from operator input, for example, from a WM_BUTTON1DOWN message, instead of from GpiSetPickAperturePosition. After the graphics orders that create pictures are stored in retained segments, the pictures can be re-created by your application with the various GpiDraw... functions. Then the user can view the pictures, if the output is directed to a screen for example. After the user selects an area of interest, a GpiCorrelate... function redraws the picture internally to determine just what intersects the pick aperture. The user does not see the re-creation. A standard order of functions within your application would be:  GpiDraw...  GpiSetPickApertureSize  GpiCorrelate... ═══ 1.1.2.3. The Correlation Input Parameters ═══ There is only one segment chain per presentation space. Therefore GpiCorrelateChain needs the presentation space handle as input. The segment correlation functions need both the presentation space handle and the segment IDs. All three correlation functions require the following as input:  Correlation attribute type  Maximum number of hits  Number of segment-tag pairs to be returned for a single hit, called the pair depth ═══ 1.1.2.3.1. The lType Input Parameter ═══ The two classifications of segments upon which you can request correlation are the following:  Segments that have been defined as both detectable and visible  All nonzero segments, regardless of their detectability and visibility attributes ═══ 1.1.2.3.2. The lMaxHits Input Parameter ═══ The correlation functions return the number of hits made on the retained segments. The following figure is an example of a line intersecting the pick aperture. Retained Segment Correlation with One Hit The intersection of a unique segment-identified and -tagged primitive with the pick aperture (pa) produces one hit. If the pick aperture size were increased, there still would be only 1 hit. The triangle produces no hit because its tag is 0. The following figure is an example of multiple primitives intersecting the pick aperture. Retained Segment Correlation with Multiple Hits Four separate primitives intersect the pick aperture; however, since two primitives share the same tag, and one primitive has a segment ID of 0, there are only two hits. Your application can set a limit on the number of hits to return from a correlation function. The maximum-number-of-hits parameter influences the size of the array created to handle the segment-tag pair returned for each hit. By comparing the maximum number desired to the actual number of hits, your application can determine whether all hits are accounted for. The following figure shows an example of the alSegTag data structure that contains the segment-tag pairs for the previous figure. alSegTag Data Structure As shown in the previous figure, the The identifier-tag pairs are returned to the application in the reverse order of their occurrence on the segment chain. That is, the highest priority segment is returned first. Therefore, the application can identify the topmost segment, which is the segment most likely to have been picked. ═══ 1.1.2.3.3. The lMaxDepth Input Parameter ═══ When a called segment is picked, correlation data is returned also for all segments above it in the hierarchy, up to and including the root segment. The following figure is an example of a picture drawn from a complex segment chain with called segments. Multiple Hits from a Called Segment Two separate items, called from different portions of the segment chain, intersect the pick aperture. Each has a unique segment identifier and tag, so there are two hits. For called segments, the group of segment-tag pairs constitutes a single hit. You can limit the number of segment and tag pairs returned for each hit using the maximum depth parameter, just as you can limit the total number of hits returned to you using the maximum number of hits parameter. The following figure shows two examples of the alSegTag data structure from the previous figure, for two different lMaxDepth values. ┌─ ┌────────┐ ──┐ ┌─── ┌────────┐ ──┐ │ │id = 300│ 0│ │ │id = 300│ 0│ │ ├────────┤ │ │ ├────────┤ │ │ │tag = 12│ 1│ │ │tag = 12│ 1│ ┌─ ──┤ ├────────┤ │ │ ├────────┤ │ │ │ │id = 100│ 2│ │ │id = 100│ 2│ │ │ ├────────┤ │ │ ├────────┤ │ │ │ │tag = 1 │ 3│ 2 actual │ │tag = 1 │ 3│ │ ╞═ ├────────┤ ├── hits ──┤ ├────────┤ ├─ ─┐ │ │ │id = 222│ 4│ returned │ │ 0 │ 4│ │ │ │ ├────────┤ │ │ ├────────┤ │ │ IMax │ │tag = 6 │ 5│ │ │ 0 │ 5│ │ hits─ ──┤ ├────────┤ │ │ ├────────┤ │ │ = 3 │ │id = 220│ 6│ │ │ 0 │ 6│ │ │ │ ├────────┤ │ │ ├────────┤ │ │ │ │ │tag = 4 │ 7│ │ │ 0 │ 7│ │ │ ╞═ ├────────┤ ══╡ │ ┌─ ├────────┤ ══╡ │ │ │ │ ? │ 8│ │ │ │id = 222│ 8│ │ │ │ ├────────┤ │ │ │ ├────────┤ │ │ │ │ │ ? │ 9│ IMax │ │ │tag = 6 │ 9│ │ └─ ──┤ ├────────┤ ├─ Depth │ │ ├────────┤ │ │ │ │ ? │ 10│ = 2 │ │ │id = 220│ 10│ │ │ ├────────┤ │ │ │ ├────────┤ │ │ │ │ ? │ 11│ IMax │ │ │tag = 4 │ 11│ IMax └─ └────────┘ ──┘ Depth│─┤ ├────────┤ ├─ hits = 4 │ │ │id = 200│ 12│ = 3 │ │ ├────────┤ │ │ │ │ │tag = 2 │ 13│ │ │ │ ├────────┤ │ │ │ │ │id = 100│ 14│ │ │ │ ├────────┤ │ │ │ │ │tag = 1 │ 15│ │ └─└─ ├────────┤ ══╡ │ │ ? │ 16│ │ ├────────┤ │ │ │ ? │ 17│ │ ├────────┤ │ │ │ ? │ 18│ │ ├────────┤ │ │ │ ? │ 19│ │ ├────────┤ ├─ ─┘ │ ? │ 20│ ├────────┤ │ │ ? │ 21│ ├────────┤ │ │ ? │ 22│ ├────────┤ │ │ ? │ 23│ └────────┘ ──┘ alSegTag Data Structure for Different lMaxDepth Values Unused segment-tag pairs for actual hits are set to 0 in the alSegTag array. There are two major reasons for the PM to provide this capacity. The first is the consideration of application storage. If your application is a graphics package, for example, providing extensive design capabilities to an end user, the user's drawing may be very complex with 10 or more levels of segment calling. The data returned from a single hit could require an alSegTag array so large the data overruns the application storage you had reserved. By setting a maximum calling depth, your application can reserve the correct amount of storage. The second consideration is the knowledge that your application's user is interested only in a certain level of calling depth. Many users will be interested only in the topmost called segment, because it usually is the segment containing the functions that performs the actual drawing. ═══ 1.1.3. Pick Aperture ═══ Your application determines the size of the pick aperture using GpiQueryPickApertureSize, and determines the page space coordinates of the center of the aperture with GpiQueryPickAperturePosition. Because your objective is to retrieve a single detectable object for each correlation operation, you have to obtain a balance between the number of detectable objects in a picture and the size of the pick aperture. The more detectable objects you define, the smaller the pick aperture must be to return a manageable amount of information to the application. However, the pick aperture usually is not a 1 pel-by-1 pel rectangle. A larger rectangle makes better sense because the pick aperture can be difficult to hit with a single pel; but a larger sampling area, for example 4 pels-by-4 pels, increases the probability of an intersection between a lighted pel and the pick aperture. The pick aperture can be specified in any of the units available to the presentation space. However, the type of unit must be identical to the type specified for the presentation page. The default size of the pick aperture is square, with sides equal to the default character cell height. ═══ 1.2. Using Correlation ═══ This section explains how to perform correlation on the graphics associated with a segment. The following figure shows how to set the pick aperture size with GpiSetPickAperture and correlate the segment chain with GpiCorrelateChain, passing it the pick-aperture position as the third argument. The functions use the psizlPick and pptlPick arguments to set the aperture size and position the aperture center. The correlation is performed on visible and detectable segments only (PICKSEL_VISIBLE). GpiCorrelateChain copies any segment-tag pairs to the buffer pointed to by alSegTag and returns the count of hits detected. #define INCL_GPICORRELATION #include LONG fncCORL01 (HPS hps, PSIZEL psizlPick, PPOINTL pptlPick, LONG lMaxHits, LONG lMaxDepth, PLONG alSegTag) { LONG cHits; GpiSetPickApertureSize(hps, PICKAP_REC, psizlPick); /* Set the pick aperture. */ cHits = GpiCorrelateChain(hps, PICKSEL_VISIBLE, pptlPick, lMaxHits, lMaxDepth, alSegTag); /* Correlate the hits. */ return (cHits); /* Return count of hits. */ } /* fncCORL01 */ ═══ 2. Coordinate Spaces and Transformations ═══ A transformation is an operation performed on a graphics object that changes the object in one of four ways: translation, rotation, scaling and shearing. Transformations enable an application to control the location, orientation, size, and shape of graphics output on any output device. The transformation of graphics output can be conceptually divided into a series of distinct transformations applied from one logical stopping point to another. Coordinate spaces are used as a method of conceptualizing these logical stopping points. The coordinate spaces are concepts used to explain and manipulate the transformation process. A graphics primitive in an intermediate coordinate space cannot be displayed on an output device and a transformation cannot be interrupted at one of the distinct stages. The entire series of transformation steps is applied all at once. This chapter describes the transformation design process. The following topics are related to the information in this chapter:  Presentation spaces and device contexts  Segments and retained graphics  Clipping ═══ 2.1. About Coordinate Spaces ═══ Most of the GPI functions draw their output in a conceptual area called the world coordinate space. If you picture the presentation space as a blank canvas on which to draw, the world coordinate space is a Cartesian grid that provides a reference of scale for what is being drawn. The components of a picture defined in a world coordinate space are often defined to a scale convenient only to that component. Applications also can define each component, or subpicture, starting at the origin (0,0). This enables applications to define the scale of a subpicture and the location of the subpicture separately. The ability to define all subpictures at the origin means there is not always 1-to-1 correspondence between a presentation space and a world coordinate space. Frequently a separate world coordinate space exists for every subpicture. After subpictures are defined in the world coordinate space, they undergo a process called transformation and then appear on an output device. If an application has not specifically applied a transformation to its subpictures, by default the PM applies the identity transformation, which, in effect, makes no changes to the subpicture. All graphics systems, not just the PM, use at least one coordinate space to generate output. The simplest graphics systems use a single coordinate space, whose points are the pels on the display. These are sometimes called single-space systems. The PM creates multiple coordinate spaces and uses transformations to move subpictures between the coordinate spaces. The PM assembles the application's graphic output in a process that can use up to five coordinate spaces, known collectively as the viewing pipeline. The PM coordinate spaces are:  World coordinate space  Model space  Page space  Device space  Media space. For those who are more familiar with a graphics system that uses a single-coordinate space, the following table lists the differences to expect when using PM's multi-coordinate space. ┌──────────────────────────────┬──────────────────────────────┐ │Single-Coordinate Space │PM Multi-Coordinate System │ │Systems │ │ ├──────────────────────────────┼──────────────────────────────┤ │Distances and locations │Seven units of measurement, │ │specified in pels. │including pels, are available.│ ├──────────────────────────────┼──────────────────────────────┤ │Because the shape, or aspect │The output is device │ │ratio, and size of pels can │independent. │ │vary on different devices, the│ │ │graphic primitives on one │ │ │device might look different on│ │ │another. │ │ ├──────────────────────────────┼──────────────────────────────┤ │Coordinates entered must │Coordinates are made │ │already be device coordinates.│device-compatible through the │ │ │PM. │ └──────────────────────────────┴──────────────────────────────┘ Additionally, a single-space system requires that applications keep track of:  The scaling between the subpictures. Often this is accomplished by forcing the definition of objects to the scale of the picture, instead of to the scale of the subpicture.  The scaling between the creation space and output space. Often this is accomplished by forcing the definition of objects to the scale of the paper or window, instead of to the scale of the subpicture.  All aspects of other transformations. ═══ 2.1.1. World Coordinate Space ═══ The world coordinate space is where most drawing coordinates are specified. Each primitive in a world coordinate space is defined using the coordinate positions in the primitive's definition. For example, if an application draws a line from (8,4) to (20,75), the coordinate values (8,4) and (20,75) are world coordinates. The world coordinate space is specified when the presentation space is created with GpiCreatePS. The PS_FORMAT option supports two sizes of world coordinate spaces: short and long. If the size is short (GPIF_SHORT), the world coordinate space is a rectangular Cartesian space with maximum coordinates of (32767, 32767) and minimum coordinates of (-32768, -32768). If the world coordinate space is short, it is the application's responsibility to ensure that the coordinates defining the subpicture fall within this range. The second size, long (GPIF_LONG), is the default for the world coordinate space. Most GPI functions that direct their output to the world coordinate space, for example GpiLine, accept 32-bit integers as parameters. A 32-bit integer is equivalent to a rectangular Cartesian space with maximum coordinates of (134217727, 134217727) and minimum coordinates of (-134217728, -134217728). World coordinates do not have to be within the range of the presentation page. A graphic image that requires a high degree of detail and precision might use most or all of the available coordinate range. A transformation is used to scale the graphic image down to an appropriate size. The actual presentation page size is unimportant in most cases. It is used with the page viewport to redefine the device transform if GpiSetPageViewport is called. An application can use a clip path clipping area to define the part of the world space to place in the next coordinate space (the model space). A clip path is the only clipping region that can be nonrectangular. Its edges can include arcs, curves, and straight lines. The coordinates that define the dimensions and shape of a clip path are always world coordinates. (Clipping is further described in Clipping and Boundary Determination.) In a world-coordinate space, there can be several graphic primitives. If, however, an application uses the DM_RETAIN drawing mode to store output in graphic segments, the operating system assigns a new world space to each segment. There is also a world space for the drawings outside of segments. ═══ 2.1.2. Model Space ═══ Model space is the conceptual area where the separate components of a picture, defined in world space, are brought together. To assemble one or more primitives from world spaces to model space, the application specifies the transformations to occur. Then the PM applies them to each of the components. Model transformations convert world coordinates to model-space coordinates. For example, an octagon and the word STOP, defined individually in separate world-coordinate spaces, can be assembled into a stop sign in model space. Graphics applications can have more than one model space. If there is more than one model space, the picture components are assembled in page space. If an application has each model space in a different segment, the model transforms are reset for each segment. An application can use a viewing limit clipping area to define the part of a model space to place in the next coordinate space (the page space). A viewing limit is always rectangular, and the coordinates that define its location and dimensions are always model coordinates. ═══ 2.1.3. Page Space ═══ The page space is where a complete picture is assembled for viewing on a display screen, or for printing or plotting on a piece of paper. Page coordinate units can be increments of an inch, a meter, pels, or some arbitrary value. An application uses GpiCreatePS to specify the units used for page coordinates. If the application uses retained-drawing mode, the picture in page space contains parts of models (or pictures) from each of the model spaces that have not been clipped. The picture also contains any additional unclipped graphics-primitive output that the application generated in nonretained-drawing mode. If the application uses nonretained-drawing mode, the picture in page space contains all the graphics-primitive output that has not been clipped. In the page space, an application can use a rectangular clipping area called a graphics field to define the part of the page space to place in the next coordinate space (the device space). The coordinates that define the location and dimensions of the graphics field are always page coordinates. The page space contains the presentation page whose size and units are defined when creating the presentation space with GpiCreatePS. The presentation page is a rectangle in page space. ═══ 2.1.4. Device Space ═══ The device space is the coordinate space in which a picture is drawn before it appears in a display screen window or on the printer or plotter. Device space is defined in device-specific units. Depending on the page unit used, device-coordinate units can be pels, increments of an inch, increments of a meter, or arbitrary. For example, if the page unit is pels, the device-coordinate unit is pels; if the page units are arbitrary, the device-coordinate units are arbitrary. ═══ 2.1.5. Media Space ═══ The media space is used only with windows. When an application draws a primitive at a specified location in a window, it is not actually drawing in the device space, as the device is the entire terminal screen. Drawing in a window involves a shifting transformation which moves a drawing from the given (unitless) position, to position in the specified window. ═══ 2.2. About Transformations ═══ The coordinate spaces are connected by different transformation functions. In reality, the input coordinates of the world coordinate space are transformed directly into device coordinates in a single operation. The intermediate coordinate spaces exist only to provide a useful model to assist in the understanding of how to define the different transformation matrixes. Transformation of graphic primitives occur when a transformation matrix is applied to those primitives. The individual transformations introduced here do not actually transform the primitives, but rather define portions of the transformation matrix. After all portions of the matrix are identified, the actual operation is performed in a single step. The transformation functions manipulate graphics primitives as they move from one coordinate space to the next. Transformation functions usually begin with the letters Gpi. Most of the function names have a transformation type that identifies the entities on which it operates. For example, a model transformation is the transformation type that transforms graphics primitives between a world coordinate space and a model space. There is a 1-to-1 correspondence between these transformation types and the actual functions. The transformation matrix data structure is called MATRIXLF. The following figure lists the sequence of coordinate spaces and the transformation types between the coordinate spaces. Internally, all transformations are combined, and the resulting values are held in the same format as the individual components. By default, there is no viewing window and no graphics field. The application can use the default page viewport. Clipping regions for each coordinate space are also shown. Viewing Pipeline ═══ 2.2.1. Identity Transformation ═══ The identity transformation is the default transformation between all coordinate spaces. The identity transformation, makes no change to the original coordinates of an object. This transformation is also referred to as the unity transformation, because of the mathematical matrix used to make this transformation. The identity matrix looks like this: ┌ ┐ │ 1 0 0 │ │ 0 1 0 │ │ 0 0 1 │ └ ┘ (Transformations are accomplished with matrix multiplication; and 1, not 0, is the multiplication identity.) If a transformation is not explicitly specified, the identity transformation is used to create that portion of the transformation matrix. Most transformations applied to a primitive can be in addition to, or instead of, the current transformation. ═══ 2.2.2. Moving through Coordinate Spaces Using the Identity Transformation ═══ The effects of transformation can be minimized by defaulting to the identity transformation. This means that no deliberate action is requested by the application. Graphic primitives are drawn in their own coordinate scale in world coordinate space. The primitives are then combined in model space. Neither the world coordinate space or the model space have "real world" units associated with them. This means that if an application draws a line on the x-axis from -300000 to +300000, the line exists as a line 600000 Cartesian units long in both world coordinate and model space. Page space is the first of the coordinate spaces to be associated with units such as millimeters or inches. These units are set with the GpiCreatePS option PS_UNITS. If the application specifies the option PS_UNITS with the value PU_ARBITRARY, the page space remains unitless; units are applied when the output is drawn in device space. As an example, assume that the units PU_LOMETRIC, (0.1 mm) have been chosen. Again, assuming the identity transformation between model and page space, the primitive appears in the page space as a line that extends 300000 * 0.1mm to the right of the origin 300000 * 0.1mm to the left of the origin A presentation page, a rectangle in page space, has its size defined when a presentation space is created with GpiCreatePS. The presentation page format is defined with the GpiCreatePS option, PS_FORMAT. The three choices for that option are:  GPIF_DEFAULT-32-bit integers or 2GB  GPIF_LONG-32-bit integers  GPIF_SHORT-16-bit integers or 32KB. PS_FORMAT affects the number of units permitted along the coordinate axes of the presentation page. If the choice was GPIF_LONG or GPIF_DEFAULT, and, for example, PS_UNITS remains PU_LOMETRIC, the presentation page axes could range from 0 to 134217727 0.1mm. If the choice was GPIF_SHORT, the coordinate axes could range only from 0 to 32767 0.1mm. These limits are the maximum number of units, presentation pages are usually much smaller. The presentation page does not affect the primitive in presentation space, it determines what parts of the primitive are visible. With no transformation to scale down the primitive from the model to the page space, the presentation page acts like a sheet of cardboard with a rectangular hole. Only the part of the page space behind the "hole" is visible in page space. The view of everything else is blocked by the "cardboard." Only what is visible in the page space is drawn to the next coordinate space. Continuing with the example of the 600000 units line above, if GPIF_LONG (or GPIF_DEFAULT) is selected, the 600000 unit line could easily be viewed in the presentation page. If GPIF_SHORT is selected, the maximum presentation page size is 65534 * 0.1 mm units long. In the case, much of the 600000 unit line would not be drawn into the next coordinate space. The device space is not affected by the PS_FORMAT option. Whether GPIF_LONG, or GPIF_SHORT, the device space is a rectangle with maximum coordinates of (32767, 32767) and minimum coordinates of (-32768, -32768). Note that not all of this rectangle is visible, since real devices are not that big. The device space relates to the physical device. The transformation between the page and device space is handled automatically by the PM. The presentation page is mapped into a rectangle in the device space called the page viewport. This transformation is based on the parameters and options of GpiCreatePS. Confusion can arise because the effects of the presentation page and the page viewport appear to be a clipping of the primitives in page and device space. While the action taken is identical, the term clipping is reserved for the activity deliberately designated by the application with clipping functions. ═══ 2.2.3. Applying Transformations Other Than the Identity Transformation ═══ To better understand the workings of transformations other than the identity transformation, an example of the picture assembly process is illustrated in the following figure, and a detailed explanation follows. Picture Assembly Process In the world space of the preceding figure four segments are drawn, each containing a different subpicture. The units of the subpictures can be different (for example, the building might be measured in feet, while the window might be measured in inches), because each subpicture is converted to the scale of the completed picture when it is transformed into the completed picture. All of the subpictures in the previous figure are defined at "real world" scales in their own (Cartesian) world coordinate space. The difference between applying and not applying transformations can be seen in the model space in the previous figure. Without transformations, the subpictures would be drawn at exactly the coordinates given in the world space and thus all four subpictures would overlap. With transformations, the subpictures can be scaled and translated to the scale of the final picture. The window subpicture, Segment id=200 has been scaled, rotated, and translated. The model space contains the model of what the application is trying to draw. There can be more than one model space for very complex drawings, but this is not a recommended style of programming. The building also resides in the page space and is prepared in the device space for printing on an 8 and a half by 11 sheet of paper. This is shown in the following figure. Most often the page space to device space transformation (the device transformation) is the identity transformation. Different Spaces The transformation process in the previous figure is acting on segments. To draw the composite picture in model space, create a segment chain that plays all four segments associated with the building. The purpose of the world-to-model-space transformation is to transform the graphic segments into a composite picture. Having built the composite picture, the next step is to map the composite into the page space. Usually, the model-to-page-space transformation is the identity transformation. The different coordinate spaces are shown in the previous figure. The user might want an exploded diagram as well as the composite picture. This is illustrated in the following figure. To create the exploded diagram, the application must draw the segment chain again, with a slight translation down, and scaled up (enlarged) with a very large scaling factor. Again, while it is possible to create several complex images in different model spaces that must be assembled in the page space, the most frequent use of the page space is to prepare a view of the model-from-model space with the first application of "real world" units such as inches or millimeters. As shown in the previous figures, both world and model space share unitless Cartesian coordinates. The usual purpose of the page space is to show multiple views of the image residing in the model space, as shown in the following figure. Different Spaces with an Exploded View The enlarged image on the right side of the page space is drawn after the image on the left. It therefore has a higher priority and therefore would be drawn on top of the left side image. To obtain a multi-viewed page space image, the application defines a clipping region, and applies this region to the second (enlarged image) playback of the segment chain. The clipping region permits the enlarged image to appear only on the right side of the page space. The same building also resides in this model space, but it resides in the page space, along with an exploded view of the uppermost right side window. The view is enlarged to such a magnitude that the details of the window are once again evident. If the images in world coordinate space are not able to be drawn in the amount of detail now supported by the PM, then drawing details, such as an exploded view, would reveal the barrenness of the image. Subpictures can be drawn in world coordinate space without being drawn inside a graphics segment. ═══ 2.2.4. Combining Transformations Between a Coordinate Space Pair ═══ There is more than one transformation between the world coordinate and model spaces, and between the model and page spaces. Depending on the desired output, the transformations can be combined in different ways. Between the world coordinate and model space, there are five ways of combining the three transformations. World Coordinate to Model Space Transformation Combinations ┌──────────────────────────────┬────────────────┬──────────────┐ │Transformation Function │Effect │Transformation│ │ │ │Type Sequence │ ├──────────────────────────────┼────────────────┼──────────────┤ │GpiCallSegmentMatrix │ADD │M I S │ ├──────────────────────────────┼────────────────┼──────────────┤ │ │PREEMPT │I M S │ ├──────────────────────────────┼────────────────┼──────────────┤ │ │REPLACE │ I S │ ├──────────────────────────────┼────────────────┼──────────────┤ │GpiDrawSegment (Call Segment) │Drawing outside │ M S │ │ │of an instance │ │ │ │drawing │ │ │ │primitive but │ │ │ │inside a │ │ │ │segment. │ │ ├──────────────────────────────┼────────────────┼──────────────┤ │No specific function │Drawing outside │ M │ │ │of segments │ │ │ │altogether. │ │ └──────────────────────────────┴────────────────┴──────────────┘ Abbreviations: I - Instance Transformation, M - Model Transformation, S - Segment Transformation Between the model and page space pair are two transformations and they also can be combined in different ways. Model to Page Space Transformation Combinations ┌──────────────────────────────┬────────────────┬──────────────┐ │Transformation Function │Effect │Transformation│ │ │ │Type Sequence │ ├──────────────────────────────┼────────────────┼──────────────┤ │GpiSetPageViewport │Drawing inside │V D │ │ │of and outside │ │ │ │of segments. │ │ ├──────────────────────────────┼────────────────┼──────────────┤ │GpiSetDefaultViewMatrix │Drawing outside │ D │ │ │of segments. │ │ └──────────────────────────────┴────────────────┴──────────────┘ Abbreviations: V - Viewing Transformation, D - Default Viewing Transformation ═══ 2.2.5. Transformation Mathematics ═══ The transformation of a picture can be represented in general terms by two linear equations that define how the (x,y) coordinates of each point in the picture are changed. ┌───────────────────────────────────────────┬─────────────────────────────────────────┐ │ The general form of these equations is: │ where │ │ │ │ │ x' = Ax + Cy + E │ (x,y) defines the original point │ │ │ (x',y') is the transformed point │ │ y' = Bx + Dy + F │ A, B, C, D, E, and F are constants. │ │ │ │ └───────────────────────────────────────────┴─────────────────────────────────────────┘ The transformations that result from these equations depend on the values of the constants, which in turn vary according to the type of transformation being applied. The operating system handles transformations by using matrix mathematics. In the matrix mathematics,  Translation is an addition operation  Scaling, reflecting, rotation, and shear are multiplication operations. If all the transformations were multiplication operations, different types of transformation could be applied with a single transformation operation. Therefore, to facilitate the combining of calls, translation in the IBM OS/2 is performed as a multiplication operation, rather than an addition operation. This requires that the vector representing a point, [ x y ] be extended by a third component, w: [ x y w ] This enables all the transformations to be handled in a uniform manner. This is called a homogeneous coordinate system. The value, w, is a multiplier, so that the point represented is: (wx, wy). Note: The PM does not support a 3-dimensional presentation space. The 3-dimensional matrix is created to effect matrix multiplication. In this notation, the point (x, y) is represented as [ x y 1 ]. To be able to operate on such three-element vectors, and to combine translation with the multiplication operations, the 2-by-2 matrix has to be extended to a 3-by-3 matrix, with the third column being: 0 0 1 ┌────────────────────────────────┬─────────────────────────────────────────┐ │ The linear equations: │ become the matrix equations: │ │ │ ┌ ┐ │ │ x' = Ax + Cy + E │ │ A B 0 │ │ │ │ [ x' y' 1 ] = [ x y 1 ] * │ C D 0 │ │ │ y' = Bx + Dy + F │ │ E F 1 │ │ │ │ └ ┘ │ └────────────────────────────────┴─────────────────────────────────────────┘ In standard matrix notation, you have: ┌ ┐ │ Msub11 Msub12 Msub13 │ [ x' y' 1 ] = [ x y 1 ] * │ Msub21 Msub22 Msub23 │ │ Msub31 Msub32 Msub33 │ └ ┘ ═══ 2.2.6. Model for Building the Transformation Matrix ═══ The transformation matrix shown above can be set equal to an entity as complex as: M*I*S*V*D where * symbolizes matrix multiplication. As mentioned earlier, all the transformation types might not have a distinct value at all times. One, or all, could simply be the identity transformation. These intermediate space and step-wise transformations are not actually how the operating system performs transformations. The reason for this relates to the way the PM stores transformation information. The transformation matrix data structure MATRIXLF, undergoes continuous modification during the drawing process, and it can be influenced by more than one transformation function from the application responding, for example, to what a user wants the drawing to look like. For example, after creating the model of a building from drawing primitives, the user might want to see two identical buildings side-by-side. The application has already applied a series of transformations to the two segments in world coordinate space to create the model of the building. If the application, rather than the PM, had to perform the entire transformation over again from start to finish, it would have to keep track of much more detail. The PM enables applications to process a smaller portion of the MATRIXLF structure, in this example the "V" or "V and D" component, to enable the user to see two buildings side-by-side. ═══ 2.2.7. MATRIXLF, the Transformation Matrix ═══ For all the transformation functions, the 3-by-3 transformation matrix is specified as a one-dimensional array in the following order: (M11, M12, 0, M21, M22, 0, M31, M32, 1) This one-dimensional array corresponds to the data structure, MATRIXLF. The elements in the data structure correspond to the matrix multiplication constants, as shown in the following table. ┌──────────────────────────────┬──────────────────────────────┐ │Transformation Type │Matrix Values │ ├──────────────────────────────┼──────────────────────────────┤ │Scaling, Reflection │M11 and M22 │ ├──────────────────────────────┼──────────────────────────────┤ │Rotation │M11, M12, M21, M22 │ ├──────────────────────────────┼──────────────────────────────┤ │Translation │M31 and M32 │ └──────────────────────────────┴──────────────────────────────┘ All nine elements do not have to be specified for every transformation function. However, those specified are interpreted as the first n of the nine. If the third, sixth, and ninth elements are specified, they must be 0, 0, and 1 respectively. ═══ 2.2.7.1. MATRIXLF Structure ═══ Of the nine fields in MATRIXLF, four are special 32-bit FIXED variables. The remaining five are 32-bit long integer variables. The scaling, reflecting, and rotation constants, M11,M12,M21,M22, are the 32-bit, signed, FIXED variables, with an implied binary point between the second and third bytes. The translation constants, M31 and M32, and the three third-column variables, are 32-bit long integers. A FIXED variable is a binary representation of a floating-point number. A FIXED variable has two parts:  The high-order 16-bits, which contain a signed integer in the range -32768 through 32767.  The low-order 16-bits, which contain the numerator of a fraction in the range 0 through 65535. The denominator for this fraction is 65536. For example, to store the cosine of 60° (0.5) in a FIXED variable, an application would multiply 65536 by 0.5. The result, 32768, would be the value to assign to a field in the MATRIXLF structure. To store a scaling factor of 3 in a FIXED variable, the application would multiply 65536 by 3. Again, the result, 196608, would be the value to assign to a field in the MATRIXLF structure. ═══ 2.2.7.2. MAKEFIXED Macro ═══ The MAKEFIXED macro provides a quick and convenient method for setting the value of FIXED variables. This macro requires two arguments: the first is the integer part of the FIXED value, and the second is the fraction part of the FIXED value. In the following example, MAKEFIXED is used to assign the FIXED value equivalent of 1 1/8 to the matrix component M11. matlf.fxM11 = MAKEFIXED(1, 8192) The first argument, 1, is the integer part of the FIXED value. The second argument, 8192, is the result of multiplying 65536 by 1/8. If it is necessary for an application to scale or rotate an object, the application can avoid most of these mathematics by using the helper functions, GpiRotate and GpiScale. GpiRotate accepts a rotation in degrees and converts this value into the appropriate fields in the MATRIXLF structure. Similarly, GpiScale accepts a scaling factor and fills in the MATRIXLF structure with the appropriate values. ═══ 2.3. About Transformation Operations ═══ The available transformations are listed in the following table. Transformations ┌────────────────┬────────────────────────────────────────────┐ │Operation │Result │ ├────────────────┼────────────────────────────────────────────┤ │Scaling │Shrinks or enlarges the object │ ├────────────────┼────────────────────────────────────────────┤ │Reflection │Creates a mirror image of an object with │ │ │respect to the x- or y- axis │ ├────────────────┼────────────────────────────────────────────┤ │Rotation │Rotates the object │ ├────────────────┼────────────────────────────────────────────┤ │Translation │Shifts the object with respect to the origin│ │ │of the coordinate system │ ├────────────────┼────────────────────────────────────────────┤ │Shear │Rotates either all the vertical or all the │ │ │horizontal lines in an object │ └────────────────┴────────────────────────────────────────────┘ These basic operations can be combined. The PM provides special functions to perform scaling, rotation, and translation and also enables applications to specify the transformation matrix directly. Applications can specify values for more than one type of transformation on a single transformation call. Transformations are used to manipulate graphic objects as they are being moved from one coordinate space to another. These operations are performed by functions called transformation functions. There are also functions that help perform the transformations called helper functions. The scaling, reflection, rotation, translation, and shear transformations are best demonstrated by applying them to a picture. The following figure shows the image of a flag before any transformations have been applied. The flag is defined by five points. Their (x,y) coordinates are (0,0), (0,4), (0,6), (2,6), and (2,4). Flag Before Transformation In the next several sections, where the transformations are described in detail, the effect of the transformation on the flag is illustrated. ═══ 2.3.1. Scaling and Reflection Transformations ═══ Applications can scale an object by using GpiScale or by modifying the MATRIXLF structure directly. A scaling transformation reduces or increases the size of a graphics object. A reflecting transformation creates a mirror image of an object with respect to the x- or y-axis. A scaling factor of:  greater than 1 causes an increase in size  greater than 0 but less than 1 causes a reduction in size  less than 0 causes a reflection about that axis. That is, a negative x scaling factor causes reflection in the x direction. Note: If an application specifies a scaling factor of greater than 1, the graphics presentation space must be defined with the coordinate format GPIF_LONG. This is because 32-bit matrix elements are required to store these values in retained segment and metafile orders. The equations to scale by factors Sx and Sy are obtained from the general equations (with M11 = Sx and M22 = Sy) and can be written: x' = xSx y' = ySy A scaling transformation reduces or increases all the coordinates of an object by the scaling factor. Any object not aligned on the x- and y-axes is therefore moved nearer to the origin by a reduction in size, and away from the origin by an increase in size. For example, if an application applies a scaling factor of 0.5 to a simple box with its corners at (4,4), (10,4), (10,10), and (4,10), the four corners moves to (2,2), (5,2), (5,5), and (2,5). To scale an object about a point without causing it to move, the following sequence of transformations is required: 1. Translate the scaling point of the object to the origin. 2. Scale the object at the origin. 3. Translate the scaling point of the object back to its original position. ═══ 2.3.1.1. Scaling a Graphics Object ═══ An application can scale the flag by 0.5, by applying: x' = 0.5x y' = 0.5y The original five points of the flag are transformed: (0,0) ─ (0,0) (0,4) ─ (0,2) (0,6) ─ (0,3) (2,4) ─ (1,2) (2,6) ─ (1,3) The following figure shows the effect of the scaling. Scaling by 0.5 This scaling preserves the shape and orientation of the object, because the scaling factors in both directions are the same. However, scaling equations permit different scaling factors to be applied to x and y, which can cause distortion of the original shape of the object. ═══ 2.3.1.2. Reflecting a Graphics Object ═══ A negative scaling factor causes a reflection of the object to be drawn. A scaling factor of -1, for example, causes a mirror image of the object to be drawn in the appropriate direction. The following figure shows the flag reflected by applying a negative y scaling factor. Reflection ═══ 2.3.1.3. MATRIXLF Structure for Scaling and Reflecting ═══ When an application scales an object by using the scaling transformation, the matrix element M11 contains the horizontal scaling component (Sx), and the matrix element M22 contains the vertical scaling component (Sy). ┌ ┐ │ Sx 0 0 │ [ x' y' 1 ] = [ x y 1 ] * │ 0 Sy 0 │ │ 0 0 1 │ └ ┘ If the matrix element M11 contains a negative horizontal reflection component (-Sx), it causes reflection about the y-axis. If the matrix element M22 contains a negative vertical reflection component (-Sy) it causes reflection about the x-axis. ═══ 2.3.2. Rotation Transformations ═══ The application can rotate an object either using GpiRotate or by modifying the MATRIXLF structure directly. The operating system applies a transformation to all points in the source coordinate space. This means that unless an object is drawn about the origin of the source coordinate space, translation occurs when the object is rotated or scaled. GpiRotate enables an application to specify a point, relative to the origin, that is the center of rotation. The equations for the rotation of an object about the origin (0,0) through an angle (theta), can be written: x' = x cos (theta) - y sin (theta) y' = x sin (theta) + y cos (theta) A negative (theta) value rotates the object clockwise. For clockwise rotation, the rotation equations are: x' = x cos (theta) + y sin (theta) y' = -x sin (theta) + y cos (theta) To rotate an object about some other point (p,q), the following sequence of transformations is required: 1. Translate the object by (-p,-q) to move the point of rotation to the origin. 2. Rotate the object around the origin. 3. Translate the object by (p,q) to move it back to its original position. Rotation preserves the shape and size of the object. ═══ 2.3.2.1. Rotating a Graphics Object ═══ An application can rotate the flag counterclockwise through 90°, by applying: x' = x cos 90 - y sin 90 y' = x sin 90 + y cos 90 Because cos 90 = 0 and sin 90 = 1, these equations become: x' = - y y' = x The original five points are transformed: (0,0) ─ (0,0) (0,4) ─ (-4,0) (0,6) ─ (-6,0) (2,4) ─ (-4,2) (2,6) ─ (-6,2) The following figure shows the effect of rotating the flag 90°. Rotation Counterclockwise through 90° ═══ 2.3.2.2. MATRIXLF Structure for Rotating ═══ For counterclockwise rotation: ┌ ┐ │ cos (theta) sin (theta) 0 │ [ x' y' 1 ] = [ x y 1 ] * │ -sin (theta) cos (theta) 0 │ │ 0 0 1 │ └ ┘ For clockwise rotation: ┌ ┐ │ cos (theta) -sin (theta) 0 │ [ x' y' 1 ] = [ x y 1 ] * │ sin (theta) cos (theta) 0 │ │ 0 0 1 │ └ ┘ ═══ 2.3.3. Translation Transformations ═══ The application can translate an object either using GpiTranslate or by modifying the MATRIXLF structure directly. To move a graphics object by an absolute number of coordinate units, a translation equation is applied. The equations for translation by Tx and Ty are obtained from the general equations (with E = Tx, and F = Ty) and can be written: x' = x + Tx y' = y + Ty Translation preserves the shape, size, and orientation of the object. A negative Tx value causes movement to the left. A negative Ty value causes movement downward. ═══ 2.3.3.1. Translating a Graphics Object ═══ If Tx is equal to 8 and Ty is equal to 5, then: x' = x + 8 y' = y + 5 The original five points are transformed: (0,0) ─ (8,5) (0,4) ─ (8,9) (0,6) ─ (8,11) (2,4) ─ (10,9) (2,6) ─ (10,11) The following figure shows the effect of translating the flag by (8,5). Translation by (8,5) ═══ 2.3.3.2. MATRIXLF Structure for Translating ═══ When an application translates an object by using the translation transformation, the matrix element M31 contains the horizontal translation component, and the matrix element M32 contains the vertical translation component, as follows: ┌ ┐ │ 1 0 0 │ [ x' y' 1 ] = [ x y 1 ] * │ 0 1 0 │ │ Tx Ty 1 │ └ ┘ ═══ 2.3.4. Shearing Transformations ═══ There are two shear transformations: vertical and horizontal. The vertical shear transformation affects only the y-component of the coordinates of points in an object, and the horizontal shear transformation affects only the x-component. If an application shears an object that contains two orthogonal vectors (two perpendicular lines), the vectors are no longer orthogonal. A shearing transformation alters the shape of an object by translating its x-coordinates relative to its y-coordinates, or its y-coordinates relative to its x-coordinates. The amount by which the coordinates are translated is determined by the angle of the shear. The equation for shearing an object to the left along the x axis by angle (theta) is: x' = x - y tan (theta) y' = y To shear an object along the y-axis, the tangent of the angle of the shear is represented by constant B in the general equation. ═══ 2.3.4.1. Shearing a Graphics Object ═══ The following figure shows the flag sheared to the left along the x-axis. Shearing Along the X-Axis ═══ 2.3.4.2. MATRIXLF Structure for Shearing ═══ For vertical shear transformation, the matrix element M11 contains the horizontal shear component, and the element M21 contains the vertical shear component, as follows: ┌ ┐ │ 1 -tan (theta) 0 │ [ x' y' 1 ] = [ x y 1 ] * │ 0 1 0 │ │ 0 0 1 │ └ ┘ For horizontal shear transformation, the matrix element M21 contains the horizontal shear component, and the matrix element M22 contains the vertical shear component, as follows: ┌ ┐ │ 1 0 0 │ [ x' y' 1 ] = [ x y 1 ] * │ -tan theta 1 0 │ │ 0 0 1 │ └ ┘ ═══ 2.4. About Transformation Functions ═══ Transformation functions manipulate objects between coordinate spaces by applying transformations. Transformation functions require two coordinate spaces: a source coordinate space, and a target coordinate space. Which transformation function an application should use is determined by the two coordinate spaces and by the transformation effect desired. The world-to-model space, model-to-page space, and page-to-device space transformations are all actually performed as a single operation. The different coordinate spaces are conceptual in nature, rather than explicitly defined entities. Describing them separately is meant to help explain the levels of activity during transformations. All transformation functions share certain parameters, although the values and defaults of those parameters might not be identical. ═══ 2.4.1. Current Transformation ═══ Every graphics object, whether in world, model, page, or device space, has a current transformation value, even if that value is simply the identity transformation. The default current model transformation is the concatenation of any instance, segment, and model transformations from the root segment downward. The default current viewing transformation is the one most recently specified. The device transformation, which is set by the page viewport and the presentation page, should not be changed while drawing is in progress. ═══ 2.4.2. Accumulating Transformations ═══ Each time one of the transformation functions is called by an application, the application can set the function's option parameter to control how the function combines the transformation with existing transformations and in what order the transformations are applied. ┌────────────────────────────────────┬────────────────────────┐ │If the application uses this flag...│Then the operating │ │ │system... │ ├────────────────────────────────────┼────────────────────────┤ │TRANSFORM_REPLACE │Replaces any existing │ │ │transformations with the│ │ │new transformation. The │ │ │existing value of the │ │ │matrix is discarded and │ │ │replaced by straight │ │ │substitution. │ ├────────────────────────────────────┼────────────────────────┤ │TRANSFORM_PREEMPT │Applies the new │ │ │transformation before │ │ │applying the existing │ │ │transformation. │ │ │The transformation │ │ │matrix of the new │ │ │transformation is │ │ │pre-multiplied with the │ │ │transformation matrix of│ │ │the current │ │ │transformation. │ ├────────────────────────────────────┼────────────────────────┤ │TRANSFORM_ADD │Applies the new │ │ │transformation after │ │ │applying the existing │ │ │transformation. │ │ │The transformation │ │ │matrix of the new │ │ │transformation is │ │ │post-multiplied with the│ │ │transformation matrix of│ │ │the current │ │ │transformation. │ └────────────────────────────────────┴────────────────────────┘ The order in which transformations are applied affects the appearance of the picture. For example, suppose that a box primitive has been defined, with its lower-left corner at (4,2) and its upper-right corner at (8,8), and that you want both to scale the box by 0.5 and to translate it by (-10,-10). If the box is translated before scaling it, the transformed box is as shown in the following figure. Translating before Scaling The translated box has its lower-left corner at (-6,-8), and its upper-right corner at (-2,-2). Each of its coordinates is then scaled by 0.5, and the transformed box has its corners at (-3,-1), (-1,-1), (-3,-4), and (-1,-4). If the box is scaled before translating it, the transformed box is as shown in the figure after the following figure. Scaling before Translating The scaled box has its lower-left corner at (2,1), and its upper-right corner at (4,4). The box is then translated by (-10,-10), and the transformed box has its corners at (-8,-6), (-6,-6), (-6,-9), and (-8,-9). When an application is drawing a picture in which there are called segments, and in which transformations are applied to the root segments, the root-segment transformations should usually be applied to any segments they call. For example, if a segment that is translated to the left of the picture (by changing its segment transformation) calls a second segment, that leftward transformation should also be applied to the called segment. In this instance, the application would specify TRANSFORM_ADD in the call to GpiCallSegmentMatrix to add the instance transformation to the calling segments' segment transformation. Instance transformations are automatically reset on return to the calling segment. ═══ 2.4.3. Concatenating Transformations ═══ When an application applies more than one transformation, it can concatenate the individual transformations to produce a final result. To concatenate transformations, multiply the individual transformation matrixes. The product of this multiplication is the concatenated transformation. There are four ways the final matrix can be concatenated: 1. Hard code the matrix values into the application, then call the transformation functions. 2. Multiply the individual matrixes, then call the transformation functions. 3. Use the helper functions with the TRANSFORM_ADD option, then call the transformation functions. 4. Alternately apply transformation operations directly to the transformation matrix, then apply a transformation function. Concatenating before calling provides better performance. ═══ 2.4.3.1. Hard Coding Values for a Concatenated Matrix ═══ Pre-calculating the concatenated matrix values, then hard coding the values into the application, gives the fastest performance. However, this is rarely practical as the actual transformations to be performed are often variable. If an application is, for example, performing interactive graphics, and one of the options offered to the user is a menu choice of rotate by 90°, and enlarge by 4, then the rotational and scaling factors would not change, and the matrix values could be hard coded into the application. ═══ 2.4.3.2. Multiplying Matrix Values ═══ Multiplying transformation matrix values directly offers the second fastest performance, yet can still respond to a variety of desired transformations. As many transformation matrixes as needed can be multiplied together. If the application is concatenating the matrixes itself, it is responsible for preventing the accumulated transformation side effects. For example, to rotate an object counterclockwise about the point (p,q) using a single transformation call requires three transformations to be concatenated. When the application is specifying each transformation, step-by-step, the sequence of actions would be: 1. Translate the object by (-p,-q) to move the point of rotation to the origin. 2. Rotate the object about the origin. 3. Translate the object by (p,q) to move it back to its original position. The individual matrixes are: ┌ ┐ ┌ ┐ ┌ ┐ │ 1 0 0 │ │ cos (theta) sin (theta) 0 │ │ 1 0 0 │ │ 0 1 0 │ │ -sin (theta) cos (theta) 0 │ │ 0 1 0 │ │ -Tx -Ty 1 │ │ 0 0 1 │ │ Tx Ty 1 │ └ ┘ └ ┘ └ ┘ The matrix for the concatenated transformation is produced incrementally. That is, two adjacent matrixes are multiplied to produce a single matrix, which is then multiplied with the third matrix. You can begin by multiplying either the first two matrixes or the second two matrixes. If you start by multiplying matrixes 2 and 3 together, the resulting matrix is: ┌ ┐ │ cos (theta) sin (theta) 0 │ │ -sin (theta) cos (theta) 0 │ │ Tx Ty 1 │ └ ┘ This matrix is multiplied with the first matrix to produce the matrix for rotating an object at the point (p,q): ┌ ┐ │ cos (theta) sin (theta) 0 │ │ -sin (theta) cos (theta) 0 │ │ a b 1 │ └ ┘ where: a = (-Txcos (theta) + Tysin (theta) + Tx) and b = (-Txsin (theta) - Tycos (theta) + Ty) If an application were performing the concatenation for a scaling operation, again it would have to specify the transformation step-by-step. The sequence of actions would be: 1. Translate the object's scaling point to the origin. 2. Scale the object at the origin. 3. Translate the object back to its original position. Here are the three matrixes required to obtain this effect: ┌ ┐ ┌ ┐ ┌ ┐ │ 1 0 0 │ │ Sx 0 0 │ │ 1 0 0 │ │ 0 1 0 │ │ 0 Sy 0 │ │ 0 1 0 │ │ -Tx -Ty 1 │ │ 0 0 1 │ │ Tx Ty 1 │ └ ┘ └ ┘ └ ┘ The matrix of the concatenated transformation is: ┌ ┐ │ Sx 0 0 │ │ 1 Sy 0 │ │ (-TxSx+Tx) (-TySy+Ty) 1 │ └ ┘ ═══ 2.4.3.3. Transformation Helper Functions ═══ Three helper functions, are provided to perform the matrix math required to concatenate transformations:  GpiTranslate  GpiRotate  GpiScale Any of these three functions can be used with the TRANSFORM_ADD option to concatenate the new matrix with an existing matrix. This method builds up the matrix in application storage in a sequence of steps before using a single transform function. While this is slower than hard coding the matrix, it is faster than alternating between applying transformation operations directly to the matrix then applying a transformation function. The helper functions merely calculate the appropriate matrix. The transformation is not applied until the array containing the matrix values is passed to the appropriate transformation function. Applications use GpiTranslate to change the position of an object. The application specifies the coordinates of the point to which to move the object and the name of the transform matrix to use as input to GpiTranslate. The transformation matrix must be in the form of a one-dimensional array. The application also can specify whether this transformation is to replace the value for a previous transformation, or whether it is to be added to it. Applications use GpiRotate to rotate an object. The application specifies the angle of rotation, the coordinates of the point around which the object is to rotate, and the transformation matrix. The transformation matrix must be in the form of a one-dimensional array. The application also can specify whether this transformation is to replace the value for a previous transformation, or whether it is to be added to it. To scale an object at a point without also moving the object, applications use GpiScale. When using GpiScale, the application specifies the scaling factor, the coordinates of the center point, and the transformation matrix. The transformation matrix must be in the form of a one-dimensional array. The application also can specify whether this transformation is to replace the value for a previous transformation, or whether it is to be added to it. An application could alternate between applying transformation operations directly to the transformation matrix, then applying a transformation function with the TRANSFORM_ADD option set. This would build up the matrix in the presentation space. This method has the slowest performance of the concatenation methods. ═══ 2.4.4. Round-Off Error ═══ Whenever an application uses transformations, it should handle any round-off error that occurs after multiple scaling, rotation, shear, or reflection transformations. The rounding error increases because a transformation is incrementally updated by the amount of the error with, for example, the TRANSFORM_ADD option. For the rotation to remain accurate, the application should recalculate the transformation, rather than accumulate many small changes. For example, if an application uses a rotation transformation to rotate the hands of a clock, the accuracy of the clock diminishes due to rounding off after the transformation. The rounding error should be periodically removed by using the TRANSFORM_REPLACE option at known points, for example, every 90° or every complete revolution of the clock. ═══ 2.4.5. World-Space to Model-Space Transformations ═══ The model transformation drawing attribute operates between world and model space. This attribute can be updated by one of the three following transformation functions:  GpiSetModelTransformMatrix  GpiSetSegmentTransformMatrix  GpiCallSegmentMatrix If the model transformation drawing attribute has never been updated, the attribute defaults to the identity transformation. If the drawing attribute has been updated, the existing transformation is the concatenation of any instance, segment, or model transformations from the root segment downwards. Each time a new segment is opened (using GpiOpenSegment), the model transformation drawing attribute is reset to its default value. The three transformations that operate between world space and model space are:  Model transformations  Segment transformations  Instance transformations The transformations that occur between world-coordinate and model spaces depend on the drawing mode and the possible segment type of the drawing primitive. The drawing mode can be either nonretain or retain. Nonretain mode is also called draw mode, as the graphics are immediately displayed. In retain mode, the graphics orders are stored in chained and unchained segments. A series of segments are shown in the following figure. Segments A model transformation effects objects in any of these segments. A segment transformation affects the six chained segments, on the left and must be issued before Root Segment 1 is accessed. An instance transformation can be applied only to Segment B or Segment D and must be issued from Segment A or Segment 2 or Segment C. The instance transformation is reset on return to the calling segment. ═══ 2.4.5.1. Model Transformations ═══ Model transformations also can be applied to objects both inside and outside of segments. Model transformations also can be applied to objects created under retained or nonretained drawing mode. This means model transformations affect the output from:  GpiDrawChain  GpiDrawFrom  GpiDrawSegment  Any GPI functions that occur outside of a retained-drawing segment Applications can change the model transformation any number of times in a single segment. Changing the model transformation changes the transformation applied to any drawing primitives used subsequently. An application can determine the values for the current model transformation by calling GpiQueryModelTransformMatrix, model transformation's scaling, rotation, and translation values in a one-dimensional array representing elements in the MATRIXLF structure. GpiSetModelTransformMatrix specifies the model transformation's scaling, rotation, and translation values applied to subsequent primitives in the segment. As this function does not require the name a segment, it also can be used to apply transformations to primitives outside of segments. For example, in the building example earlier in the chapter, if the window is stored in a retained segment, an application could draw several identical windows on the house by setting a new translation component in the model transformation before calling GpiBox. ═══ 2.4.5.2. Segment Transformations ═══ The segment transformation provides a way of defining the model transformation drawing attribute at the start of a retained segment. The attribute can subsequently be updated by the model transform orders within the segment. A segment transformation can be applied only to a retained segment. Segment transformations alter retained-drawing output. Unlike a model transformation, which can be set and reset within a segment bracket, a segment transformation must be set outside of a segment bracket. An application can determine the values for the current segment transformation by calling GpiQuerySegmentTransformMatrix, which returns the model transformation's scaling, rotation, and translation values in a one-dimensional array representing elements in the MATRIXLF structure. To apply a segment transformation, applications use GpiSetSegmentTransformMatrix. GpiSetSegmentTransformMatrix can be used to apply any sort of transformation to a segment. For example, it can be used to translate a dynamic segment from one screen position to another, when movement is requested by the user. The application could perform the following steps, for example, on receipt of a WM_MOUSEMOVE message: 1. Use the new mouse position to calculate the required displacement from the current position. 2. Call GpiRemoveDynamics to remove the dynamic segment from its current position. 3. Call GpiSetSegmentTransformMatrix to translate the segment coordinates by the required amount. 4. Call GpiDrawDynamics to redraw the segment in its new position. ═══ 2.4.5.3. Instance Transformations ═══ Instance transformations provide a way of defining the model transformation drawing attribute for the duration of a called segment. Instance transformations alter the retained-drawing output from special segments referred to as called segments. A called segment usually contains a subpicture duplicated several times in other subpictures. The instance transformation positions, sizes, and rotates the subpicture each time the segment is duplicated, because the transformation is set each time the segment is called. An instance transformation applies only to the called segment, and is reset on return to the calling segment. There is no query function associated with the transformation as it must be explicitly set for each called segment. To apply an instance transformation, applications call GpiCallSegmentMatrix from the calling segment. GpiCallSegmentMatrix calls the segment and also applies the model transformation's scaling, rotation, and translation values in a one-dimensional array representing elements in the MATRIXLF structure and passes a segment identifier. ═══ 2.4.5.4. World Space-to-Model Space Transformation Summary ═══ The following table summarizes the choices available during world-coordinate space to model space transformations. World to Model Space Transformation Summary ┌───────────────┬──────────────────────────────────┬───────────┐ │Transformation │Transformation Function │Applies │ │Type │ │to... │ ├───────────────┼──────────────────────────────────┼───────────┤ │Model │GpiSetModelTransformMatrix │Primitives │ │transformations│ │both inside│ │ │ │and outside│ │ │ │a segment │ ├───────────────┼──────────────────────────────────┼───────────┤ │Segment │GpiSetSegmentTransformMatrix │A retained │ │transformations│ │segment, │ │ │ │issued at │ │ │ │the first │ │ │ │element of │ │ │ │the segment│ ├───────────────┼──────────────────────────────────┼───────────┤ │Instance │GpiCallSegmentMatrix │Only the │ │transformations│ │called │ │ │ │segment │ └───────────────┴──────────────────────────────────┴───────────┘ Note: The effect of GpiSetModelTransformMatrix and GpiCallSegmentMatrix on the model transformation drawing attribute can be duplicated by an equivalent drawing order in a drawn retained segment. ═══ 2.4.6. Model Space-to-Page Space Transformations ═══ There are two transformations that operate between the model space and the page space:  Viewing transformations  Default viewing transformations All three model transformation types and the viewing transformations can be considered a part of the picture. The default viewing transformation is part of the environment, and must not be used for picture construction. Viewing transformations only apply in retained or nonretained segments. The viewing transformation attribute is set to the presentation space viewing transformation matrix value at the start of each drawn root segment and remains constant for that segment. If GpiSetViewingTransformMatrix is called, the new value is not used until the next segment is opened. The matrix drawing attribute is reset to identity at the end of the segment. Each change in a viewing transformation is equivalent to defining a new model space. The default viewing transformation is a presentation space attribute and should not normally be modified in the middle of a picture. This attribute can be updated by GpiSetDefaultViewMatrix. A picture is normally constructed in the presentation page with an identity default viewing transformation. The default viewing transformation can then be used to scale and scroll the entire picture in the presentation page. ═══ 2.4.6.1. Viewing Transformations ═══ More than one copy of an entire model space can be drawn in page coordinate space, and each copy can be transformed as required. Parts of the model space also can be transformed to the presentation page. For example, an enlarged view of the tail of an aircraft can be shown with a reduced view of the complete aircraft in one corner. This is shown in the following figure. Presentation-Page Space The entire model space (the aircraft) and a part of the model space (the tail of the aircraft) are drawn to a single page coordinate space. In each instance, scaling and translation transformations have been applied. Alternatively, the displayed picture can be made up of several subpictures with no common graphical elements. For example, the aircraft can be drawn in one part of the display, and a map of an airport in another part of the display. In this instance, the final picture would be derived from different model spaces. Whether multiple views are derived from a single model space or from different model spaces, there are two items to address for each instance of a model space incorporated into the presentation page: 1. The part of the model space to be displayed must be identified by defining a viewing window for the model space. 2. To position and size the contents of the model space in page coordinate space, a viewing transformation must be specified. To get views of one or more model spaces on the screen simultaneously, each model space is drawn the required number of times. Before each drawing request, the viewing window is defined and a viewing transformation is specified. ═══ 2.4.6.2. Defining the Viewing Window ═══ The viewing window is a conceptual boundary around a part of the model space. To produce the picture in the previous figure, the aircraft is drawn twice. The first time, the viewing window is on only the tail of the aircraft, and the second time, the viewing window is on the entire aircraft. Only those parts of the model space within the viewing window are visible in the picture assembled in presentation-page space. GpiSetViewingLimits is used to define the viewing window. ═══ 2.4.6.3. Graphics Field ═══ Applications also can specify a type of viewing window for the presentation page smaller than the page. This window is known as the graphics field. To define a graphics field, use GpiSetGraphicsField. By default, no graphics field is specified. If a graphics field is defined, the picture assembled within it is the picture that is visible on the output device. An application can determine the current values for the viewing transformation by calling GpiQueryViewingTransformMatrix, which returns the transformation values in a one-dimensional array representing elements in the MATRIXLF structure. The application can set the values by calling GpiSetViewingTransformMatrix, and passing the transformation values in a one-dimensional array representing elements in MATRIXLF structure. ═══ 2.4.6.4. Default Viewing Transformations ═══ The default viewing window is the same size as the model space. Therefore, to display one or more entire model spaces, draw the picture the required number of times and let the viewing window default each time. Default viewing transformations scroll or zoom pictures in a window on a display screen. An application can determine the current values for the default viewing transformation by calling GpiQueryDefaultViewMatrix, which returns the default-viewing-transformation values in a one-dimensional array representing elements in MATRIXLF structure. The application can set these values by calling GpiSetDefaultViewMatrix and passing the transformation values in a one-dimensional array representing elements in MATRIXLF structure. A default viewing transformation is applied when the screen contents are zoomed or scrolled by user interaction. A picture is zoomed when the user wants to increase or decrease the size of an area of interest. A picture is usually scrolled when there is more in the presentation page than can be displayed in a single page of output. Anything lying off the screen, but within the range of the presentation page, can be scrolled into view. The default viewing transformation applies to the entire page coordinate space, and can be added to, or can replace, the current default viewing transformation. The PM applies it after any viewing transformations. When a presentation page is created, the default viewing transformation is set to identity. For example, if the presentation-page contents are scrolled:  Erase the screen contents.  Call GpiSetDefaultViewMatrix to translate the presentation-page picture by the required amount.  Draw the picture again. The following figure shows the airplane presentation-page contents scrolled to the left. Scrolling the Presentation Page Every presentation-page coordinate is translated to the left by the same amount. Zooming is implemented in the same way, except that the default viewing transformation is used to scale the picture up or down as required. If you want to display only one view of a single picture, and if you do not want scrolling and zooming capabilities, you can let the viewing and default viewing transformations default. When both transformations are permitted to default, page coordinate space is effectively the same as model space. ═══ 2.4.7. Page-Space to Device-Space Transformations ═══ There is only one transformation between the page coordinate space and the device space, the device transformation. The device transformation enables applications to work in any presentation-page units regardless of the target device. Unlike the transformations previously described, the device transformation only scales and translates objects, and it is defined by two rectangles. The first rectangle is called the presentation page. Its location is the bottom left origin and its dimensions are fixed. The second is called the page viewport. Its location is the bottom left origin and its dimensions can be varied. The device transformation, which maps the picture in presentation-page space to device space, happens automatically. The device transformation is established when the presentation space is created, and ensures that graphics are displayed in the correct size and, where possible, that their aspect ratio is preserved. To modify the device transformation, applications use GpiSetPageViewport. Input for this function is the device coordinates of the lower-left and upper-right corners of the page viewport. Applications should modify the default device transformation only when it is necessary to use nonstandard page units. ═══ 2.4.7.1. Presentation Pages ═══ A presentation page is a rectangle in a page space. Its lower-left corner is always positioned at the origin of the page space. An application can determine the dimensions of the presentation page by calling GpiQueryPS. It returns a pointer to a SIZEL structure that contains the page dimensions. If an application specifies arbitrary page units when creating a presentation space with GpiCreatePS, the page viewport is constructed such that the origin of the page rectangle maps to the origin of the default device rectangle and either the right or top edge maps to the corresponding edge. Thus, the aspect ratio of the graphic is preserved. If either the height or width of the presentation page is set to 0 (using GpiCreatePS), the application must set GPIA_ASSOC to set the default presentation page size to the default device rectangle size. ═══ 2.4.7.2. Page Viewports ═══ A page viewport is a rectangle in device space, whose origin and size can be varied. The operating system uses the presentation-page rectangle and the page-viewport rectangle to define the device transformation. An application can determine the current dimensions of the page viewport by calling GpiQueryPageViewport, which returns a pointer to a RECTL structure that contains the coordinates of the viewport. The application can set the location and dimensions of the page viewport by calling GpiSetPageViewport and passing it a pointer to a RECTL structure that contains the new values. The ratio of the page width to the page-viewport width defines a horizontal scaling factor. The ratio of the page height to the viewport height defines a vertical scaling factor. Applications can use DevQueryCaps to obtain the horizontal and vertical resolution of a device in pels per meter. The dimensions of a pel can vary from one device to another, but they usually fall in the range of 0.25 to 0.50 mm. The page viewport can be shifted in the device space by a translation transformation. ═══ 2.4.7.3. Mapping the Presentation Page to the Device ═══ When an application associates a presentation space with a device context, a default device transformation is set. A page viewport is defined according to the rules in the following table: ┌──────────────────┬────────────────────┬──────────────────────┐ │Presentation-page │Page viewport size │Usage. │ │specification │ │ │ ├──────────────────┼────────────────────┼──────────────────────┤ │Pels │The same size as the│The lower-left corner │ │ │presentation page. │of the presentation │ │ │ │page maps to the │ │ │ │lower-left corner of │ │ │ │the device space. For │ │ │ │example, if an │ │ │ │application defines a │ │ │ │presentation page of │ │ │ │300 coordinates │ │ │ │(x-axis)-by-200 │ │ │ │coordinates (y-axis), │ │ │ │then the picture is │ │ │ │transformed to a │ │ │ │screen area of the │ │ │ │same size. │ ├──────────────────┼────────────────────┼──────────────────────┤ │Metric units │The coordinates that│The lower-left corner │ │ │produce the correct │of the presentation │ │ │matrix for the │page maps to the │ │ │physical spacing of │lower-left corner of │ │ │the pels. │the device space. │ ├──────────────────┼────────────────────┼──────────────────────┤ │Arbitrary units │The default size for│The page viewport is │ │ │the device is used. │constructed such that │ │ │For a plotter or │the presentation-page │ │ │printer, this is the│coordinates give equal│ │ │maximum accessible │x- and y-spacing. The │ │ │area of the paper, │lower-left corner of │ │ │and for a screen, it│the presentation page │ │ │is the maximized │maps to the lower-left│ │ │window size. │corner of the device │ │ │ │space, and either the │ │ │ │right or the top edges│ │ │ │map, such that the │ │ │ │picture is contained │ │ │ │within the device │ │ │ │rectangle and its │ │ │ │aspect ratio is │ │ │ │preserved. │ └──────────────────┴────────────────────┴──────────────────────┘ The following figure shows mapping from the presentation page to the device. The device transformation can be explicitly specified using GpiSetPageViewport. Mapping a Picture from the Presentation Page to the Device In this example, a map of the world has been drawn in a presentation page, defined in arbitrary units, that is much larger than the device space. The device transformation scales the picture to fit the maximized window size and preserves its aspect ratio. ═══ 2.4.7.4. Coding the Device Transformation ═══ The PM automatically transforms the presentation-page contents to the area of the device space within the page viewport. The drawing is not clipped to the page viewport because this is a scaling transformation only. The entire picture is displayed, regardless of the size of the page viewport specified. The following figure shows the airplane presentation-page contents scaled to fit the page viewport. Device Space A page viewport smaller than the presentation page has been defined. The picture assembled in the presentation page is therefore scaled to fit the page viewport. After transformation to device space, graphics coordinates must be in the range -32768 through +32767, even if the presentation page is defined in GPIF_LONG format. An attempt to address a coordinate outside this range results in a coordinate-overflow error. To determine if a graphics object will give an error, applications can do the following:  If the application is not rotating or shearing a graphics object, it calls GpiConvert to convert the device-space limits to world-coordinate-space limits, then uses these limits when creating the graphics object.  If the application is rotating or shearing a graphics object, it uses GpiConvert to convert the device-space limits back to model space, and ensures that the picture boundary is inside these limits. Note that this method only applies if all rotational and shearing is performed using 1 of the model transformation types. Remember that world-coordinate space has its own own limits:  -32768 through +32767 for a GPIF_SHORT-format presentation page  -134217728 through +134217727 for a GPIF_LONG-format presentation page. Although applications can specify a page viewport of any size, the presentation page can be mapped only to an area equal to, or less than, the available device space. If an application specifies a viewport larger than the available device space, part of the presentation page contents are displayed outside the visible device output area. To find out the dimensions of the page viewport for the currently associated device, use GpiQueryPageViewport. Applications can store the dimensions of the current page viewport before changing them, and restore them later. ═══ 2.4.7.5. Device-Transformation Matrix ═══ To directly manipulate the device-transformation matrix it is necessary for applications to know the following values: X1 the x-coordinate of the lower-left corner of the page viewport Y1 the y-coordinate of the lower-left corner of the page viewport X2 the x-coordinate of the upper-right corner of the page viewport Y2 the y-coordinate of the upper-right corner of the page viewport XPS the presentation-space width -1 YPS the presentation-space height -1. The device-transformation matrix is defined as: ┌────────────────────────────────────┬──────────────────────────────┐ │ The device-transformation matrix: │ where: │ │ ┌ ┐ │ │ │ │ Msub11 0 0 │ │ a = (Xsub2-Xsub1)/(Xps+1) │ │ │ 0 Msub22 0 │ │ │ │ │ Msub31 Msub32 1 │ │ b = (Ysub2-Ysub1)/(Yps+1) │ │ └ ┘ │ │ │ │ c = Xsub1+(a-1)/2 │ │ │ │ │ │ d = Ysub1+(b-1)/2 │ │ │ │ └────────────────────────────────────┴──────────────────────────────┘ ═══ 2.4.8. Windowing-System Transformation ═══ There is one transformation, the windowing-system transformation, performed automatically by the PM. The windowing-system transformation, which is a translation transformation only, maps the coordinates of the picture in device space to the coordinates of the screen window or printer page. This happens when a picture is first drawn and whenever the display window in which the picture has been drawn is moved. ═══ 2.4.9. Transforming Bit-Map Data ═══ In general, graphics defined in device coordinates (bit maps and image primitives) cannot be transformed. For example, the size of an image primitive is specified in device coordinates, and cannot be altered. The size, therefore, remains unaltered down the viewing pipeline. The position of an image primitive, however, is specified in world coordinates. The image is therefore subject to translation transformations. Note, however, that GpiWCBitBlt permits the target rectangle to be specified in world coordinates, which are transformed. Because the position of the image primitive is specified in world coordinates and its width is specified in device coordinates, positioning two images together on the screen causes special difficulties. The second image cannot be positioned without knowing the width, in world coordinates, of the first image. To get the width of the first image: 1. Identify two coordinate positions, one on the image's left edge, and one on its right edge. For example, the two positions could be (10,80) and (150,80). These positions are in device coordinates. 2. Convert these device coordinates to world coordinates using GpiConvert. GpiConvert converts an array of (x,y) coordinates that apply in one coordinate space to their corresponding values in another coordinate space. 3. Subtract the lower x-coordinate from the higher x-coordinate. In the above example, the width of the image is the difference between the world-coordinate equivalents of 150 and 10. When you have the width of the first image in world coordinates, you can calculate the start position of the second image. Paths, although defined in world coordinates, are device-dependent and are bound in device coordinates when they are defined. Subsequent transformations (other than the windowing-system transformation) have no effect on paths. However, if a path is used to create a wide line, the width of the line is scaled as required. ═══ 2.5. Using Coordinate Spaces and Transformations ═══ This section explains how to:  Set an application's drawing units to convenient units  Translate, rotate, and scale a picture  Shear a picture ═══ 2.5.1. Setting Drawing Units ═══ Applications can use GpiCreatePS to set the device transformation so that it uses page units that might be more convenient than pels; for example, centimeters. If the output device is a screen, the application first opens a device context by calling WinOpenWindowDC. If the output device is a printer or plotter, the application opens a printer or plotter device context by calling DevOpenDC. The application then creates a presentation space by calling GpiCreatePS, specifying low-metric page units and associating the device context with the presentation space. The following figure is an example of how to set drawing units. HWND hwnd; /* Client-window handle */ HAB hab; /* Anchor-block handle */ HPS hps; /* Presentation-space handle */ HDC hdc; /* Device-context handle */ SIZEL sizlPage; /* Presentation-page rectangle */ hdc = WinOpenWindowDC(hwnd); sizlPage.cx = 0; sizlPage.cy = 0; hps = GpiCreatePS(hab, /* Anchor-block handle */ hdc, /* Device-context handle */ &sizlPage, /* Address of SIZEL structure */ PU_LOMETRIC /* Centimeters as page units */ | GPIA_ASSOC); /* Associates window DC with PS */ ═══ 2.5.2. Translating, Rotating, and Scaling a Picture ═══ GpiTranslate, GpiRotate, and GpiScale provide a convenient method for transforming objects in a picture. The following figure shows how to use these functions to translate, rotate, and scale a triangle. MATRIXLF matlfTransform; POINTL ptlStart, ptlTrans, ptlRotate, ptlScale; FIXED fxAngle, afxScale[2]; POINTL aptlTriangle[] = { 575, 300, 575, 500, 500, 300 }; ptlStart.x = 500; /* Starting point x direction */ ptlStart.y = 300; /* Starting point y direction */ GpiMove(hps, &ptlStart); GpiPolyLine(hps, sizeof(aptlTriangle) / sizeof(POINTL), aptlTriangle); ptlTrans.x = 75; /* x coordinate for translation */ ptlTrans.y = 75; /* y coordinate for translation */ GpiTranslate(hps, /* Presentation-space handle */ &matlfTransform, /* Address of matrix */ TRANSFORM_REPLACE, /* Replace old matrix with new */ &ptlTrans); /* Coordinates for translation */ GpiSetModelTransformMatrix(hps, /* Presentation-space handle */ 9, /* Number of points in matrix */ &matlfTransform, /* Address of matrix */ TRANSFORM_REPLACE); /* Replace old matrix with new */ GpiMove(hps, &ptlStart); /* Move to starting point */ GpiPolyLine(hps, sizeof(aptlTriangle) / sizeof(POINTL), aptlTriangle); fxAngle = MAKEFIXED(-45, 0); /* Rotate 45 degrees clockwise */ ptlRotate.x = 550; /* x coordinate rotation origin */ ptlRotate.y = 350; /* y coordinate rotation origin */ GpiRotate(hps, /* Presentation-space handle */ &matlfTransform, /* Address of matrix */ TRANSFORM_REPLACE, /* Replace old matrix with new */ fxAngle, /* Rotation angle */ &ptlRotate); /* Origin of rotation */ GpiSetModelTransformMatrix(hps, 9, &matlfTransform, TRANSFORM_REPLACE); GpiMove(hps, &ptlStart); /* Move to starting point */ GpiPolyLine(hps, sizeof(aptlTriangle) / sizeof(POINTL), aptlTriangle); ptlScale.x = 550; /* x coordinate scale origin */ ptlScale.y = 350; /* y coordinate scale origin */ afxScale[0] = MAKEFIXED(2, 0); /* Scaling factor on x axis */ afxScale[1] = MAKEFIXED(2, 0); /* Scaling factor on y axis */ GpiScale(hps, /* Presentation-space handle */ &matlfTransform, /* Address of matrix */ TRANSFORM_REPLACE, /* Replace old matrix with new */ &afxScale[0], /* Scaling factor */ &ptlScale); /* Origin of scaling operation */ GpiSetModelTransformMatrix(hps, 9, &matlfTransform, TRANSFORM_REPLACE); GpiMove(hps, &ptlStart); /* Move to starting point */ GpiPolyLine(hps, sizeof(aptlTriangle) / sizeof(POINTL), aptlTriangle); ═══ 2.5.3. Shearing a Picture ═══ The following figure is an example of shearing a picture by modifying the transformation matrix directly. MATRIXLF matlfTransform; POINTL ptlStart, ptlEnd; ptlStart.x = 500; /* x coordinate, lower-left corner of box */ ptlStart.y = 300; /* y coordinate, lower-left corner of box */ GpiMove(hps, &ptlStart); ptlEnd.x = 700; ; /* x coordinate, upper-right corner of box */ ptlEnd.y = 500; ; /* y coordinate, upper-right corner of box */ GpiBox(hps, DRO_OUTLINE, &ptlEnd, 0, 0); /* Draw first box */ matlfTransform.fxM11 = MAKEFIXED(1, 0); matlfTransform.fxM12 = MAKEFIXED(0, 0); matlfTransform.lM13 = 0; matlfTransform.fxM21 = MAKEFIXED(0, 65536 / 2); /* Shear factor .5 */ matlfTransform.fxM22 = MAKEFIXED(1, 0); matlfTransform.lM23 = 0; matlfTransform.lM31 = 200; /* Translate 200 units right */ matlfTransform.lM32 = 0; matlfTransform.lM33 = 1; GpiSetDefaultViewMatrix(hps, 9, &matlfTransform, TRANSFORM_REPLACE); GpiMove(hps, &ptlStart); GpiBox(hps, DRO_OUTLINE, &ptlEnd, 0, 0); /* Draw sheared box */ ═══ 2.5.4. Using World to Model Space Transformations ═══ The following is an example of a sequence of calls in which segment, model, and instance transformations are applied to graphics objects. GpiSetDrawingMode (DM_RETAIN) /* Sets the current drawing mode */ /* to DM_RETAIN */ GpiOpenSegment (segment 1) /* Creates a chained segment */ GpiCloseSegment GpiSetSegmentAttrs /* Make segment 1 an unchained segment */ GpiOpenSegment (segment 2) /* Creates a retained, chained segment */ GpiSetModelTransformMatrix (TRANSFORM_ADD) /* Specifies a transformation to */ /* apply to subsequent primitives. */ /* This is in addition to the current */ /* model transformation. */ GpiCallSegmentMatrix (1, TRANSFORM_ADD) /* Calls segment 1 and applies a */ /* transformation to it. */ /* This transformation is in addition */ /* to the current model transformation, */ /* and applies only to the called */ /* segment. */ . . GpiSetCurrentArcParams GpiPointArc /* The 3-point arc is not subject */ /* to the transformation specified */ /* on the call to GpiCallSegmentMatrix. */ /* The transformation that was */ /* current before segment 1 was called */ /* is applied to the remainder of */ /* segment 2. */ GpiCloseSegment GpiSetSegmentTransformMatrix (segment 2) /* Specifies a segment transformation */ /* for segment 2 */ GpiDrawSegment /* Draws segment 2 */ ═══ 2.5.5. Viewing Transformation ═══ Each time an application draws the model space, it specifies a different viewing transformation to transfer a view of the picture-to-page coordinate space. GpiSetViewingTransformMatrix is used to apply a viewing transformation. There is one viewing transformation for each part or whole model space to be incorporated in page-coordinate space. GpiSetViewingTransformMatrix cannot be called while there is an open segment, and it has no effect on primitives outside segments. When it has been specified, the viewing transformation applies to all subsequently created segments until it is next changed. The viewing transformation that is current when a segment is created is a fixed part of the segment. Once specified, the viewing transformation cannot be queried, nor can it be altered, unless you re-create the segment. This is inconvenient when several versions of the same picture are being drawn. The problem can be solved by:  Defining the picture in one or more unchained segments.  Creating a segment chain and calling the unchained segments from each root segment.  Setting the viewing transformation before each root segment. Each time the segment chain is drawn, multiple views of the same picture are produced. This sequence is illustrated in the following example, where the segment chain comprises three root segments, each of which calls a single unchained segment. GpiSetInitialSegmentAttrs /* Switches off the chained attribute */ GpiOpenSegment /* Creates an unchained segment */ /* containing the picture definition */ GpiCloseSegment GpiSetInitialSegmentAttrs /* Switches on the chained attribute */ GpiSetViewingTransformMatrix /* Sets the viewing transformation */ /* for segment 1 */ GpiOpenSegment (segment 1) GpiCallSegmentMatrix /* Calls the unchained segment */ GpiCloseSegment GpiSetViewingTransformMatrix /* Sets the viewing transformation */ /* for segment 2 */ GpiOpenSegment (segment 2) GpiSetViewingLimits /* Specifies the area of interest */ /* in the model space. */ GpiCallSegmentMatrix /* Calls the unchained segment */ GpiCloseSegment GpiSetViewingTransformMatrix /* Sets the viewing transformation */ /* for segment 3 */ GpiOpenSegment (segment 3) GpiCallSegmentMatrix /* Calls the unchained segment */ GpiCloseSegment When a segment chain has been created using this method, an application cannot change the viewing transformation unless it re-creates the segment chain. The viewing transformation of a segment is permanently recorded and cannot be edited. The application would not, however, have to re-create the picture definition in the unchained segment. If the picture definition comprises a number of unchained segments, an application must create an intermediate segment to contain the GpiCallSegmentMatrix calls for those segments. Each root segment would then call the intermediate segment. The viewing transformation applies to the entire root segment and cannot be overridden from within the segment. It is particularly useful for positioning and scaling one or more segments of a subpicture within the presentation page when a segment transformation cannot be used. A segment transformation can be overridden by any model or instance transformations within the segment. A typical example of its use is when importing a subpicture using GpiPutData or GpiPlayMetaFile. Note: The viewing transformation must be set to its default value before an application defines an unchained segment to be called from another segment. ═══ 3. Editing Retained Graphics and Graphics Segments ═══ This chapter describes editing retained graphics and graphics segments. The following topics are related to the information in this chapter:  Presentation spaces and device contexts  Coordinate spaces and transformations  Creating and drawing retained graphics ═══ 3.1. About Editing Retained Graphics and Graphics Segments ═══ In the OS/2 operating system, applications store retained graphics in segments. One of the advantages of using graphics segments is that segments can be edited, which allows the retained image to be modified without having to re-create the unmodified portion with multiple GPI functions. Creating and Drawing Retained Graphics described how to create a segment, and store GPI functions within the segment bracket (the GPI functions bracketed by GpiOpenSegment and GpiCloseSegment). To understand how to edit a segment, the underlying structure of a segment is described here in greater detail. The GPI functions are not inserted directly into a segment bracket. Instead, the operating system converts the GPI functions into graphics orders. A graphics order, also known as a drawing order, is the smallest complete portion of a segment. Once the GPI functions are converted into graphics orders, these orders are stored in the GpiOpenSegment-GpiCloseSegment bracket. Generally, each of the GPI functions within the segment bracket generates one element of the segment. An element is the smallest portion of a segment that can be edited and is made up of one or more orders. The following figure illustrates the levels of graphic segment construction. GpiOpenSegment (...); Graphic Segment ┌───────────────────────┐ element GpiLine (...); │ line order │ element 0  pointer │ │ GpiBeginElement (...); │ begin element order │ element 1 │ │ GpiBox (...); │ box order │ GpiPolyline (...); │ polyline order │ │ │ GpiEndElement (...); │ end element order │ │ │ GpiLabel (...); │ label order │ element 2 │ │ GpiSetColor (...); │ set-color order │ element 3 └───────────────────────┘ GpiCloseSegment (...); Structure of a Graphics Segment Elements 0, 2, and 3 are each composed of a single order. Element 1 is composed of two orders bracketed by GpiBeginElement and GpiEndElement. ═══ 3.1.1. Graphics Orders ═══ A graphics order is a low-level graphics command that corresponds to a primitive function or attribute. In addition to code and data requirements, each graphics order uses approximately 11 bytes of storage. An application that uses 2000 graphics drawing orders will use around 22KB of memory to store them. The following table describes the four sizes of graphics orders. Graphics Orders ┌────────────────────────┬────────────────────────────────────┐ │Graphics Order Size │Content │ ├────────────────────────┼────────────────────────────────────┤ │1 byte │A hexadecimal identifier │ │ │corresponding to a drawing function │ │ │or attribute function. This │ │ │identifier is also known as the │ │ │order code. │ ├────────────────────────┼────────────────────────────────────┤ │2 byte │The order code is in the first byte,│ │ │and data is in the second byte. │ ├────────────────────────┼────────────────────────────────────┤ │Long │The order code is in the first byte.│ │ │ │ │ │The length value of the actual data,│ │ │in bytes, is in the second byte. │ │ │ │ │ │The actual data (up to 255 bytes). │ ├────────────────────────┼────────────────────────────────────┤ │Very long │A hexadecimal identifier │ │(maximum length of 64KB)│specifically for extended orders, is│ │ │in the first byte. │ │ │ │ │ │The order code is in the second │ │ │byte. │ │ │ │ │ │A length value that specifies how │ │ │many bytes are used by the │ │ │graphics-order arguments, (high │ │ │order) is in the third byte. │ │ │ │ │ │A length value that specifies how │ │ │many bytes are used by the │ │ │graphics-order arguments, (low │ │ │order) is in the fourth byte. │ │ │ │ │ │The actual data. │ └────────────────────────┴────────────────────────────────────┘ The following example shows a long graphics order that corresponds to GpiLine: 81 8 100 0 0 0 100 0 0 0 The first number, 81, is the hexadecimal identifier that corresponds to GpiLine. The second number, 8, is the length value that specifies how many bytes are used by the graphics-order arguments. The next eight bytes contain the arguments for GpiLine. In this case, the arguments specify the line's end point at (100,100). Graphics Segment │ ┌──────────────────────┐ ┌── 0x21 ┼────────── order # ──┐ │ │ │ 0x08 ┼────────── length │ │ ptl.x = 100L; │ │ 0x00 │ ────┐ │ │ ptl.y = 100L; │ │ 0x00 │ ├── x │ │ GpiMove (hps, &ptl); ┼──┘ 0x10 │ │ ├── element │ ptl.x = 200L; │ 0x00 │ ────┘ │ │ ptl.y = 400L; │ 0x00 │ ────┐ │ │ GpiMove (hps, &ptl); ┼──┐ 0x00 │ ├── y │ │ │ │ 0x20 │ │ │ └──────────────────────┘ │ 0x00 │ ────┘ ──┘ └── 0x81 ┼────────── order # ──┐ 0x08 ┼────────── length │ 0x00 │ ────┐ │ 0x00 │ ├── x │ 0x30 │ │ ├── element 0x00 │ ────┘ │ 0x00 │ ────┐ │ 0x00 │ ├── y │ 0x40 │ │ │ 0x00 │ ────┘ ──┘ │ Graphics Orders The encoding that appears in the Graphics Segments column is a hexadecimal version of the order, length, and parameter information. In most cases, graphics orders in a segment correspond to a subpicture, which is part of a complete, more complex picture. Your application would combine the individual segments to form the complete picture. Three drawing modes affect how the operating system stores graphics orders in segments. These modes are described in the following table. The default drawing mode is draw (DM_DRAW). To specify another as the current drawing mode, use GpiSetDrawingMode. The actual drawing mode is a combination of the drawing mode as set using GpiSetDrawingMode, and the segment status-chained, unchained, or outside of the segment. The actual drawing mode does not affect the storing of orders in segments. Segment Graphics Drawing Modes ┌──────────────────┬──────────────────┬────────────────────────┐ │Drawing Mode │GpiSetDrawingMode │When this mode is set...│ │ │Value │ │ ├──────────────────┼──────────────────┼────────────────────────┤ │Draw │DM_DRAW │it is not possible to │ │ │ │store graphics orders in│ │ │ │a chained segment. │ ├──────────────────┼──────────────────┼────────────────────────┤ │Retain │DM_RETAIN │your application can │ │ │ │store graphics orders in│ │ │ │chained and unchained │ │ │ │segments. │ ├──────────────────┼──────────────────┼────────────────────────┤ │Draw-and-retain │DM_DRAWANDRETAIN │your application can │ │ │ │store graphics orders in│ │ │ │chained and unchained │ │ │ │segments. In this mode,│ │ │ │output intended for a │ │ │ │chained segment is both │ │ │ │drawn on the device and │ │ │ │stored in a segment. │ └──────────────────┴──────────────────┴────────────────────────┘ ═══ 3.1.2. Graphics Elements ═══ Graphics elements are composed of either a single graphics order, or a series of graphic orders that are bracketed by an opening and closing element function. The purpose of this element bracket is to allow the addition of a single element, that comprises more than one graphics order, to a segment. This is most useful when you know that you will want to retrieve those orders at a later time, and manipulate them as a group rather than as individual functions. Note: There is no reason for enclosing a single GPI function within a GpiBeginElement-GpiEndElement bracket, although it is a valid construction. Element brackets also are valid when drawing graphics directly to the output device, but again, they serve no purpose unless converted to a retained segment at a later time. Elements cannot be nested, so two elements cannot begin in succession without an intervening GpiEndElement request. Certain GPI functions cannot be called between GpiBeginElement and GpiEndElement. For example, GpiLabel cannot be used between GpiBeginElement and GpiEndElement. Element construction is valid only within segments. ═══ 3.1.2.1. Adding Elements to a New Segment ═══ There are four ways of adding elements to a newly created segment:  Call one or more GPI functions. Each function generates one element of the segment. This is the simplest way of supplying graphics data to a segment.  Call GpiBeginElement, and follow it with one or more GPI functions. Close the element using GpiEndElement. All the GPI functions enclosed within the bracket and GpiBeginElement and GpiEndElement generate a single element of the segment, and therefore occupy a single-element-pointer position. Subsequently, the graphics orders cannot be accessed individually with the element pointer, although the orders can be accessed directly, for example, using GpiGetData.  Call GpiElement. As input, you supply the graphics orders themselves, rather than the GPI functions that generate them. No matter how much data you supply on this request, it is considered a single element of the segment. Multiple orders added to a segment in this way cannot be accessed individually using the element pointer, but they can be accessed directly, for example, using GpiGetData. GpiElement cannot be included within a GpiBeginElement-GpiEndElement bracket. The data passed by GpiElement must not include GpiBeginElement and GpiEndElement.  Call GpiPutData. As with GpiElement, supply graphics orders as input. You can even include GpiBeginElement and GpiEndElement orders in this data, and thus add more than one element to the segment. GpiPutData is useful when there is a large amount of data to add to a segment. GpiPutData cannot be used if the segment editing mode is set to SEGEM_REPLACE. When the segment editing mode is SEGEM_INSERT, the element pointer must point to the last element in the current segment. The segment editing mode can be set by using GpiSetEditMode.. GpiPutData is most often used in conjunction with GpiGetData, which copies data as a list of drawing orders from a segment to application storage. ═══ 3.1.2.2. Element Types ═══ Each element that results from a single GPI function has an associated element type. The element type is generally the graphics-order code associated with the graphics order generated by the GPI function, and is supplied by the system. For example, GpiLine has the element type, OCODE_GCLINE, which identifies it as a line-drawing request. Your application can determine the current classification of an element using GpiQueryElementType. When using GpiElement or GpiBeginElement, you can simultaneously add several graphics orders to a segment. Those orders become one element of the segment. You can supply your own classification for these compound elements by supplying a value for the type parameter of GpiElement or GpiBeginElement in the range of 0x81000000 through 0XFFFFFFFF. For example, the orders passed by a single GpiElement function could change the line type to dotted, set the current color to blue, and draw a line. You could classify this element with a type value that identifies it as a blue dotted line. Note: Element types are used only for classification. They are not used as location markers or correlation tags. ═══ 3.1.2.3. Element Pointer ═══ Use the element pointer to change the contents of an existing segment. When calling GpiOpenSegment, the element pointer is set to 0. The first element that you add to a newly created segment causes the pointer to be set to 1, and each subsequent element causes the pointer to be incremented by 1. When a segment is closed, the element pointer is always reset to 0. Your application can move the element pointer to a specified value using GpiSetElementPointer. For example, to address the sixth element in a segment, set the element pointer to 6. Your application also can move the element pointer by a specific number, rather than to a specific number, using GpiOffsetElementPointer. For example, if the element pointer currently addresses element 3, to move it to element 8, code an offset of 5 in GpiOffsetElementPointer. The pointer moves backward rather than forward through the segment. The offset value can be a positive or negative number. If the sum of the offset and the current pointer position is less than 0, the operating system sets the pointer so that it points to position 0. Position 0 precedes the first element in the segment. If the sum of the offset and the current pointer position is greater than the number of elements in the segment, the operating system sets the pointer so that it points to the last element in the segment. You can determine the current location of the element pointer using GpiQueryElementPointer. To request the contents of a part of or all of the elements at the current pointer position, use GpiQueryElement. ═══ 3.1.2.4. Labels ═══ You can include labels in a segment to make locating particular elements of the segment easier. If you label an element that is likely to be edited, you can access that element when necessary, regardless of whether the actual position of the label-element pair within the segment has changed. Warning: When editing segments, do not inadvertently insert elements between a label and the element that follows. Your application will no longer be able to use certain GPIs correctly because their default locations and offsets will be invalid. A label is only a place-holder or reference point, and is itself an element of the segment. Labels are long integer values. To include a label in a segment, use GpiLabel. The following example includes the label 5 in the current segment, whose segment id is 4. GpiOpenSegment(hps, 4L); GpiLabel(hps, 5L); . . . Your application can set the element pointer to the label position using GpiSetElementPointerAtLabel, then increment the pointer position to the element itself using GpiOffsetElementPointer with an offset of 1. Note: This example of GPI cannot work properly if your application has allowed the insertion of elements between a label and the element that follows it. Labels do not have to be unique. If you do not use unique labels, GpiSetElementPointerAtLabel positions the element pointer at the first occurrence of the label, starting from the current pointer position. If the label is not found between the current pointer position and the end of the segment, an error condition is raised. Using labels as a navigation aid might be quicker than scanning the segment for a particular element. If you do not use labels, you must locate an element before you can change it. To locate a specific element in a segment, you must repeatedly move the element pointer using GpiSetElementPointer then read the contents of the element using GpiQueryElement. This can be quite a lengthy procedure depending upon the number of elements in the segment. ═══ 3.1.3. Graphics Segments ═══ Segments are made up of elements, which are in turn made up of one or more graphic orders. The previous sections have discussed the properties and functions for orders and elements. The following sections discuss the attributes and functions that apply to segments as a whole. The segment attributes are encoded in a segment prior to the graphics orders that correspond to GPIs and attributes. ═══ 3.1.3.1. Segment Attributes ═══ Each segment has a number of characteristics, called attributes that you can set in accordance with your application's requirements. The attributes of a segment are quite different from those of a graphics primitive, in that segment attributes have ON and OFF settings. There are seven segment attributes, each described in the following table. Graphic Segment Attributes and Initial Settings ┌──────────────────┬────────────────────┬──────────────┬────────┐ │Attribute │Value │If set... │Default │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Chained │ATTR_CHAINED │the operating │ON │ │ │ │system adds │ │ │ │ │each new │ │ │ │ │segment in │ │ │ │ │your │ │ │ │ │application's │ │ │ │ │presentation │ │ │ │ │space to the │ │ │ │ │segment chain.│ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Fast chain │ATTR_FASTCHAIN │the operating │ON │ │ │ │system │ │ │ │ │prevents the │ │ │ │ │resetting of │ │ │ │ │primitive │ │ │ │ │attributes to │ │ │ │ │their default │ │ │ │ │values before │ │ │ │ │drawing the │ │ │ │ │segment chain.│ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Dynamic │ATTR_DYNAMIC │the operating │OFF │ │ │ │system draws │ │ │ │ │segment output│ │ │ │ │by using the │ │ │ │ │XOR raster │ │ │ │ │operation. │ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Detectable │ATTR_DETECTABLE │your │OFF │ │ │ │application │ │ │ │ │can perform │ │ │ │ │correlation │ │ │ │ │operations on │ │ │ │ │segments │ │ │ │ │created in │ │ │ │ │this │ │ │ │ │presentation │ │ │ │ │space. │ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Propagate │ATTR_PROP_DETECTABLE│the detectable│ON │ │detectable │ │attribute will│ │ │ │ │be set in each│ │ │ │ │segment called│ │ │ │ │by a chained │ │ │ │ │segment. │ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Visible │ATTR_VISIBLE │GpiDrawChain, │ON │ │ │ │GpiDrawFrom, │ │ │ │ │and │ │ │ │ │GpiDrawSegment│ │ │ │ │will generate │ │ │ │ │output on a │ │ │ │ │device. │ │ ├──────────────────┼────────────────────┼──────────────┼────────┤ │Propagate visible │ATTR_PROP_VISIBLE │The visible │ON │ │ │ │attribute will│ │ │ │ │be set in each│ │ │ │ │segment called│ │ │ │ │by a chained │ │ │ │ │segment. │ │ └──────────────────┴────────────────────┴──────────────┴────────┘ When an application creates a segment in a presentation space, the operating system assigns initial attributes to it. By default, five of the attributes will be set ON and two will be set OFF. Your application can override the defaults for all subsequently created segments within the presentation space using GpiSetInitialSegmentAttrs. Use GpiQueryInitialSegmentAttrs, to retrieve the values of the current initial attributes. ═══ 3.1.3.1.1. The Dynamic Attribute ═══ Dynamic segments are graphics segments that can be moved from where they were drawn on the screen to a different coordinate position, or altered in some other way, without affecting the remaining part of the picture. The new position of a dynamic segment can be provided with an input device, such as a mouse, or it can be application-generated. The dynamic attribute is set to OFF by default. The setting is always inherited by called segments from the setting of their callers. If a calling segment is nondynamic, any segments called by it are also nondynamic, regardless of how they have been defined. If the calling segment is dynamic, all segments called by it are also dynamic. Any segment explicitly defined as dynamic must have a unique name, and it cannot be created when the current drawing-mode parameter is DM_DRAW or DM_DRAWANDRETAIN. Although no error condition is raised if you define an unchained segment as dynamic, it is not treated as dynamic unless the segment is called from a dynamic root segment. Graphics objects to be moved without disturbing the remaining contents of the display are drawn in exclusive-OR mode. Segments that you define as dynamic always are drawn in exclusive-OR mode, regardless of the current mix attribute settings and any GpiSetMix functions the segment itself might contain. For performance reasons, dynamic segments are to be grouped at the start of the picture chain. There are GPI functions that handle dynamic segments as a group, so it is more efficient if the entire segment chain does not have to be scanned to locate them. When the entire picture chain is drawn, however, dynamic segments are to be drawn after all other segments in the chain to ensure that the effects of drawing in exclusive-OR mode are not adversely affected by drawings in other mix modes. Also, you must ensure that no nondynamic drawing overlays the dynamic segments after they have been drawn. The PM ensures that dynamic segments are always drawn on top of other graphics. ═══ 3.1.3.1.2. The Detectability Attribute ═══ The detectability attribute of a segment determines if that segment can be selected with an input device, such as a mouse. A segment with this attribute is said to be selectable. Selectable segments can be selected for correlation operations. The detectability attribute is set OFF by default. All detectable segments must have unique names. If you define a zero segment as detectable, it is created as nondetectable. ═══ 3.1.3.1.3. The Propagate-Detectability Attribute ═══ This attribute controls whether the detectability attribute of a calling segment is inherited by any segments called from it. The propagate-detectability attribute is set ON by default. This value overrides the detectability setting of the called segment. For example, if you set the detectability attribute of a calling segment to OFF, all segments called from it are nondetectable, regardless of how they have been defined. ═══ 3.1.3.1.4. The Visibility Attribute ═══ The visibility attribute controls whether a segment is to be visible on an output device. The contents of a segment that is not defined with the visibility attribute set ON are still executed whenever the segment is drawn. This can cause changes to the current position and to current attribute values, even though the primitives themselves are not visible on the output device. The visibility attribute is set ON by default. ═══ 3.1.3.1.5. The Propagate-Visibility Attribute ═══ This attribute controls whether the visibility attribute of a calling segment is inherited by any segments called from it. The propagate-visibility attribute is set ON by default. This value overrides the visibility setting of the called segment. For example, if the visibility attribute of a calling segment is set to OFF, all segments called from it are invisible, regardless of how they have been defined. ═══ 3.1.4. Changing the Attributes of a Segment ═══ After you create a segment, you might need to alter its attributes. For example, if you created a segment using the default attributes and you want to perform a correlation operation on the subpicture in that segment, you will need to set the detectable attribute using GpiSetSegmentAttrs. You can retrieve the values of the attributes for any segment using GpiQuerySegmentAttrs. You can change the default segment-attribute settings globally for a single presentation space using GpiSetInitialSegmentAttrs. The attribute setting that you specify in this function applies to all segments created subsequently in that presentation space, except that a nonretained segment can never have the dynamic attribute. For example, if you want all segments to be detectable, you can call this function to change the setting for all of them before you create them. GpiSetInitialSegmentAttrs cannot be used to change the attributes of existing segments. You also can change the attributes of any single retained segment, but not those created subsequently, using GpiSetSegmentAttrs. This is useful if, for example, you want most of the segments in a picture chain to be detectable. You can change the attribute setting to detectable for the entire chain, before creating it, using GpiSetInitialSegmentAttrs; then, change the attribute to nondetectable for each of the segment exceptions using GpiSetSegmentAttrs. You can also use GpiSetSegmentAttrs, for example, to make a visible segment invisible when an erase request is received from the operator, or to take a segment out of the chain by redefining it as unchained. If you change an unchained segment to chained, it is added to the end of the segment chain. If you want the newly chained segment to be positioned elsewhere in the chain, use GpiSetSegmentPriority rather than GpiSetSegmentAttrs. Some of these segment attributes apply equally to primitives that are outside of segments, although their default settings cannot be changed. Primitives outside of segments are always detectable and visible. They cannot be dynamic, because the dynamic attribute applies only to retained graphics. The chained and fast-chaining attributes do not apply to primitives outside of segments. ═══ 3.1.5. Editing a Segment ═══ The operating system provides segment editing functions for writing applications that allow users to edit segments or elements in a segment. For example, after performing a correlation operation using your application, a user might need to alter the elements that intersected the pick aperture. Correlation and the pick aperture are explained in in Correlation. You can edit the contents of any retained segment that has a unique name. You also can edit the contents of a retained zero segment that has not yet been closed. Zero segments cannot be edited after they have been closed, because you cannot refer to a zero segment when it is no longer the current open segment. Before you can begin editing, you must set the current drawing-mode parameter to DM_RETAIN. You cannot edit a segment if the current drawing-mode parameter is DM_DRAWANDRETAIN or DM_DRAW. To begin editing, call GpiOpenSegment and specify the name of the segment you want to edit. When you are finished editing a segment, close it using GpiCloseSegment. The operating system has two edit modes: insert mode and replace mode. You can set the edit modes using GpiSetEditMode. You can determine which mode is currently set using GpiQueryEditMode. The current edit mode applies to all segments in the presentation space until you change it. The edit mode is not an attribute of a particular segment and can be changed at any time. The default edit mode, which is set when you create a presentation space, is insert mode. When you create a graphics segment, you are actually editing it in insert mode. If the edit mode is set to insert (SEGEM_INSERT) you can insert an element at the current location of the element pointer. The operating system shifts the element that was previously at that location into the next slot, and so on, until the last element is shifted into a new, final slot. The following figure shows a segment before and after a new element is inserted at position 0, the beginning of the segment. Original Segment New Segment Element Pointer ┌─────────────┐ │ │ ┌─────────────┐ Position 0 │ │────┘ └─────│ │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 1 │ Element 1 │─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐ │ New element │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 2 │ Element 2 │─ ─ ─ ─ ─ ─ ─ ─ ─┐ └─ ─ ─│ Element 1 │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 3 │ Element 3 │─ ─ ─ ─ ─ ─ ─ ─┐ └─ ─ ─ ─│ Element 2 │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 4 │ Element 4 │─ ─ ─ ─ ─ ─ ─┐ └─ ─ ─ ─ ─│ Element 3 │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 5 │ Element 5 │─ ─ ─ ─ ─ ─┐ └─ ─ ─ ─ ─ ─│ Element 4 │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 6 │ Element 6 │─ ─ ─ ─ ─┐ └─ ─ ─ ─ ─ ─ ─│ Element 5 │ │ │ │ │ │ ├─────────────┤ │ ├─────────────┤ Position 7 │ Element 7 │─ ─ ─ ─┐ └─ ─ ─ ─ ─ ─ ─ ─│ Element 6 │ │ │ │ │ │ └─────────────┘ │ ├─────────────┤ └─ ─ ─ ─ ─ ─ ─ ─ ─│ Element 7 │ │ │ └─────────────┘ Inserting a New Element in a Segment The new element is inserted after the current element; then, the element pointer is set to the new element. If replace mode is set (SEGEM_REPLACE) you can replace the element at the current pointer location with a new element. The following figure shows a segment before and after the third element was replaced. Original Segment New Segment ┌─────────────┐ ┌─────────────┐ Position 0 │ │ │ │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 1 │ Element 1 │ │ Element 1 │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 2 │ Element 2 │ │ Element 2 │ │ │ Element pointer │ │ ├─────────────┤ │ │ ├─────────────┤ Position 3 │ Element 3 │────┘ └─────│ Element 3 │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 4 │ Element 4 │ │ Element 4 │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 5 │ Element 5 │ │ Element 5 │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 6 │ Element 6 │ │ Element 6 │ │ │ │ │ ├─────────────┤ ├─────────────┤ Position 7 │ Element 7 │ │ Element 7 │ │ │ │ │ └─────────────┘ └─────────────┘ Replacing an Element with a New Element The new element overwrites the previous element; the element pointer does not change. Replacing elements is the recommended technique for redrawing identical primitives with different attributes-for example, color. You can insert or replace data in an existing segment using any of the functions described in Adding Elements to a New Segment. As mentioned previously, GpiPutData is valid only in insert mode and only when the element pointer is addressing the final element in the segment. That is, when you are editing, you can use GpiPutData only to add data to the end of a segment. A replace request is not valid when the element pointer is set to 0. If you call GpiOpenSegment to create a new segment without first ensuring that the current edit mode is insert, your first attempt to add an element to the segment might cause an error condition to be raised. ═══ 3.1.5.1. Deleting a Graphics Element ═══ The PM has three different functions that allow you to delete elements within the currently opened segment. Function Description GpiDeleteElement Deletes a single element at the current element pointer location. GpiDeleteElementRange Deletes a range of elements in a segment. GpiDeleteElementsBetweenLabels Deletes a series of elements between two labels. When you remove an element from a segment, the element pointer addresses the element immediately before the one you deleted. As with other editing functions, the current drawing mode parameter must be DM_RETAIN when you are deleting elements. The current editing mode (insert or replace) has no effect on the delete functions. ═══ 3.1.5.2. Deleting Graphics Segments ═══ When you have finished drawing the subpicture associated with a segment, you should delete the segment. The PM has two different functions that allow you to delete segments. Function Description GpiDeleteSegment Deletes a retained segment GpiDeleteSegments Deletes a range of retained segments. Your application can only delete segments that have unique names because you use the segment identifiers to identify the segment or range of segments for deletion. Retained zero segments cannot be deleted. They disappear only when their associated presentation space is deleted or reset. The presentation space can be reset either by GpiResetPS with the GRES_SEGMENTS flag or the GRES_ALL flag set, or by GpiSetPS. Resetting the presentation space is described in Reusing the Presentation Space. If GpiDeleteSegment occurs within a segment bracket and the segment identified is the currently open segment, the operating system deletes the segment and ignores the remainder of the functions up to, and including, GpiCloseSegment. If GpiDeleteSegment occurs within a segment bracket and the identifier for a segment other than the currently open segment, the operating system deletes the segment, then continues processing the remaining functions in the segment bracket. If GpiDeleteSegment occurs outside of a segment and references a segment in the segment chain, the operating system removes the segment from the chain and links the two adjacent segments, if such segments exist. If the range of segments deleted by GpiDeleteSegments were in the segment chain, the operating system "repairs" the chain by linking the segments immediately preceding and following the deleted segments, if such segments exist. ═══ 3.1.5.3. Copying a Single Graphics Element ═══ Your application can copy the graphics orders from a single element using the GpiQueryElement and GpiElement functions. GpiQueryElement copies the graphics orders (or part of the orders, depending on allocated size) from an element into an array of bytes. GpiQueryElement is not valid within an element bracket, nor if the drawing mode is other than DM_RETAIN. GpiElement copies the data from the array back into the current segment. The data may not contain any begin or end element orders. GpiElement is not valid within an element bracket. The element is retained if the drawing mode is DM_RETAIN and drawn if the mode is either DM_DRAW, or DM_DRAWANDRETAIN. ═══ 3.1.5.4. Copying Multiple Graphics Elements ═══ Your application can use GpiGetData and GpiPutData to:  Copy elements from one segment to another  Copy elements from one position in a segment to another position in the same segment. GpiGetData copies a buffer of graphics orders from a named segment, into an area of application storage, whose byte size you specify on input. Only the named segment must not be open when you call this function. The named segment is also known as the source segment. The first time GpiGetData is called, data retrieval has to start at the beginning of the segment. This is done by declaring an element offset of 0. Output from GpiGetData depends on whether the area of application storage is large enough to hold the entire buffer of graphics orders. If so, the buffer is returned along with a count of the number of bytes of data returned to you from the segment. If not, the application storage is filled, and the count is set to the size of the application storage. The offset of the element where GpiGetData stopped copying, and the count are returned. Your application can then determine if a subsequent GpiGetData needs to be called, by checking that the count is less than the size (length) of the application storage. On subsequent GpiGetData functions, the element offset can be 0, or it can be the offset value that was returned from the previous function. In this manner, if your application calls GpiGetData more than once to copy an entire segment, it can "pick up where it left off", rather than recopying the segment from the beginning each time. You can copy the data from the application storage to a new location in a segment using GpiPutData. This receiving segment is also known as the destination segment. The segment into which you are copying the data can be open when you call GpiPutData. If GpiGetData does not retrieve a complete segment, the data it does retrieve can be written out to the second segment using GpiPutData, even if the last order copied is incomplete. The current drawing mode determines whether the graphics orders are executed, stored in the segment, or both. When you call GpiPutData, the current edit mode must be SEGEM_INSERT and, if there is already data in the destination segment, the element pointer must address the last element of the segment. Because the PM does not support explicit renaming of segments, GpiGetData-GpiPutData is the method you use to rename a segment. That is, create a second segment with the desired name, copy the contents of the first segment to it, then delete the original segment. ═══ 3.1.6. Drawing Retained Graphics ═══ Nonretained graphics segments and primitives outside of graphics segment are always drawn immediately to the current output device. Segments that have been retained in segment store, however, can be drawn any number of times to any number of device contexts. The PM has three different functions that allow you to draw segments: Function Description GpiDrawSegment Draws a single segment in the chain GpiDrawFrom Draws a group of segments in the chain GpiDrawChain Draws the entire chain GpiDrawSegment draws a single, named segment, which can be chained or unchained. You supply the segment name as input to this function. GpiDrawSegment can draw a dynamic segment in some circumstances. These are described in Drawing Dynamic Segments. GpiDrawFrom draws one or more root segments from the segment chain. You supply the names of two root segments as input. The drawing process starts at the first named segment and draws all chained and called segments, excluding dynamic segments, up to and including the second named segment. The order in which you specify the segment names is to reflect their relative positions in the segment chain. If the second-named segment appears in the segment chain before the first-named segment, no error is raised, but drawing starts from the first named segment and continues to the end of the chain. This also happens if the second segment is an unchained segment rather than a root segment. If the drawing control, DCTL_DYNAMIC is set, any dynamic segments already drawn on the display are removed before GpiDrawFrom begins to draw nondynamic segments. Then they are redrawn after GpiDrawFrom ends. GpiDrawChain draws all nondynamic chained segments in a named presentation space, as well as any unchained segments called by those chained segments. It does not draw dynamic segments. You supply only the presentation space handle as input to this function. If the drawing control, DCTL_DYNAMIC is set, any dynamic segments already drawn on the display are removed before GpiDrawFrom begins to draw nondynamic segments. Then they are redrawn after GpiDrawFrom completes. You can call any of these functions while a segment is open. The open segment is not modified by these functions, although any of them can result in the current attribute values and current position being modified. For more information about the attribute-resetting process, see Graphics Attributes. The current drawing mode determines whether the segments identified in the drawing functions are executed, stored in the segment, or both. The current drawing mode does not affect which segments are drawn, or the priority in which they are drawn for any of these three GPI drawing functions. If an error occurs during the drawing process, you can determine where the error occurred using GpiErrorSegmentData. This function returns information about the last error that occurred during a segment-drawing operation. It returns a pointer to the segment identifier and a pointer to one of three constants that indicate when the error occurred. Constant Error occurred... GPIE_SEGMENT While drawing the segment GPIE_ELEMENT While calling GpiElement GPIE_DATA While calling GpiPutData ═══ 3.1.7. Drawing Dynamic Segments ═══ A dynamic segment is a chained segment that possesses special properties. Dynamic segments are those that can be moved or changed in some other way without disturbing the remaining parts of the picture. To draw dynamic segments on the display screen for the first time, use GpiDrawDynamics. GpiDrawDynamics draws every dynamic segment in the segment chain. When they have been drawn on the display, dynamic segments can be updated. For example, to move one or more dynamic segments to another part of the display screen, remove them from their current position using GpiRemoveDynamics. You can restrict the scope of this function by supplying the names of a start segment and a finish segment. The start segment and finish segment can be the same. Dynamic segments outside of this range are not removed from the display screen. If you intend to re-associate the presentation space, call GpiRemoveDynamics first; otherwise, GpiRemoveDynamics cannot remove the dynamic segments after the presentation space has been re-associated. The dynamic segments effectively cease to be dynamic. After removing the appropriate dynamic segments from the display screen, you can redraw them elsewhere, again using GpiDrawDynamics. If you specify a range of dynamic segments in GpiRemoveDynamics, the redrawing is restricted to that range. Note that, when dynamic segments have been drawn on the display screen, you must not edit their definitions in segment store. Dynamic segments are treated like nondynamic segments when you are directing output to a hardcopy device. GpiRemoveDynamics and GpiDrawDynamics raise an error condition if the current output device is not a display window. ═══ 3.1.8. The Drawing Controls ═══ GpiErase clears the output display of the currently associated device to CLR_BACKGROUND, which is the normal background color for the device. If you are using the default color table, this value clears the window background to white. This is a once-only request and must be issued each time you want the display screen cleared before drawing a new picture. You can use this function for either a micro presentation space or a normal presentation space. To get this effect for more than one drawing request, you can use GpiSetDrawControl. This function establishes current values for five drawing controls, which remain in effect until they are reset. The following table describes the five drawing controls. Drawing Controls ┌────────────────────────┬────────────────┬────────────────────┐ │Control │Value │If set, the │ │ │ │operating system... │ ├────────────────────────┼────────────────┼────────────────────┤ │Boundary data │DCTL_BOUNDARY │computes the │ │accumulation │ │dimensions of the │ │ │ │smallest rectangle │ │ │ │that would │ │ │ │completely surround │ │ │ │the retained-drawing│ │ │ │output. │ │ │ │This control is │ │ │ │described in │ │ │ │Clipping and │ │ │ │Boundary │ │ │ │Determination. │ ├────────────────────────┼────────────────┼────────────────────┤ │Correlation │DCTL_CORRELATE │performs correlation│ │ │ │operations on any │ │ │ │primitives or any │ │ │ │output associated │ │ │ │with GpiPutData or │ │ │ │GpiElement. │ │ │ │This control is │ │ │ │described in │ │ │ │Correlation. │ ├────────────────────────┼────────────────┼────────────────────┤ │Display control │DCTL_DISPLAY │draws retained │ │ │ │output on the device│ │ │ │identified by the │ │ │ │current device │ │ │ │context. If this │ │ │ │control is not set, │ │ │ │no retained output │ │ │ │will appear on the │ │ │ │device. │ ├────────────────────────┼────────────────┼────────────────────┤ │Draw-dynamic-segments │DCTL_DYNAMIC │calls │ │ │ │GpiRemoveDynamics │ │ │ │before drawing any │ │ │ │retained output and │ │ │ │then, after drawing │ │ │ │the retained output,│ │ │ │it calls │ │ │ │GpiDrawDynamics to │ │ │ │draw output stored │ │ │ │in dynamic segments.│ │ │ │This automatically │ │ │ │removes all dynamic │ │ │ │segments from the │ │ │ │display screen │ │ │ │before a GpiDraw... │ │ │ │request is issued, │ │ │ │then later redraws │ │ │ │the segments. This │ │ │ │ensures that dynamic│ │ │ │segments are always │ │ │ │drawn on top of │ │ │ │nondynamic segments │ │ │ │and primitives. │ ├────────────────────────┼────────────────┼────────────────────┤ │Erase-before-draw │DCTL_ERASE │calls GpiErase │ │ │ │before drawing any │ │ │ │retained output. │ └────────────────────────┴────────────────┴────────────────────┘ GpiSetDrawControl can be called in either a micro or a normal presentation space, although not all of the controls are valid in a micro presentation space. GpiDrawSegment can be used to draw a dynamic segment in some circumstances. Its effects are as follows:  If the named segment is both chained and dynamic, and the DCTL_DYNAMIC drawing control is set, all dynamic segments in the chain, including the named segment, are drawn as dynamic.  If the named segment is both chained and dynamic, and the DCTL_DYNAMIC control is not set, the named segment is not drawn.  If the named segment is unchained and dynamic, it is drawn as a nondynamic segment, regardless of the setting of the DCTL_DYNAMIC control. If you called GpiRemoveDynamics prior to calling GpiDrawDynamics and you specified a range of dynamic segments, the operating system draws only that range. If you set the DCTL_DYNAMIC control using GpiSetDrawControl, the operating system calls GpiRemoveDynamics before drawing the subpictures from the dynamic segments. The DCTL_DISPLAY control is the only control set to DCTL_ON by default. All other controls are set to DCTL_OFF when you create a presentation space. ═══ 3.2. Using Segment Editing Functions ═══ You can use editing functions to:  Create a chained-dynamic segment  Delete a segment  Edit the contents of a segment The following figure shows an example of how to edit the contents of a segment. In the example, three elements are inserted. The steps required for this task are as follows: 1. Set the segment edit mode to insert or replace using GpiSetEditMode. 2. Set the drawing mode to retain. 3. Open the segment using GpiOpenSegment, passing it the segment identifier from a previous correlation operation. 4. Set the element pointer so that it points to the position at which you will replace or insert an element using GpiSetElementPointer, GpiSetElementPointerAtLabel or GpiOffsetElementPointer. 5. Insert the new primitives using any of the Gpi primitive functions. 6. Delete any unnecessary primitives using GpiDeleteElement or GpiDeleteElementRange. 7. Close the segment using GpiCloseSegment. #define INCL_GPISEGEDITING #define INCL_GPICONTROL #include void fncESEG01(void){ HPS hps; LONG idNonChained; POINTL ptl; GpiSetEditMode(hps, SEGEM_INSERT); GpiSetDrawingMode(hps, DM_RETAIN); GpiOpenSegment(hps, idNonChained); GpiSetElementPointer(hps, 0L); GpiSetColor(hps, CLR_YELLOW); ptl.x = 100; ptl.y = 100; GpiMove(hps, &ptl); ptl.x = 150; ptl.y = 150; GpiBox(hps, DRO_OUTLINE, &ptl, 40L, 40L); ptl.x = 30; ptl.y = 30; GpiMove(hps, &ptl); GpiSetElementPointer(hps, 5L); GpiDeleteElement(hps); GpiCloseSegment(hps); } /* fncESEG01 */ The first element inserted contains the graphics order that sets the color to yellow; the second element moves the current position; and the third element draws an outlined box with rounded corners. After the three elements are inserted, the code deletes the element at position 5 in the segment (this element was previously at positions 1 and 2). ═══ 4. Fonts ═══ In typography, a font is a collection of characters that share a common height, line weight, and appearance. In Presentation Manager, fonts are an lcid-identified resource, like bit maps, and are used in conjunction with the character string primitive data structures to define the appearance of displayed and printed text. The primary role of the PM with regard to fonts is to evaluate whether a particular font is appropriate for a given situation. The following topics are related to information in this chapter:  Presentation spaces and device contexts  Character string primitives  Coordinate spaces and transformations  Color and mix attributes ═══ 4.1. About Fonts ═══ Font height is specified in printer's points, referred to in this book as just points. A point equals approximately 1/72 of an inch. The line weight and appearance of a font are specified by the categories listed in the following table. Examples of Line Weight and Font Appearance Categories ┌────────────┬────────────┬────────────────────────────────────┐ │Attribute │Category │Description │ ├────────────┼────────────┼────────────────────────────────────┤ │Line Weight │Normal │Characters drawn with a normal line │ │ │ │weight │ ├────────────┼────────────┼────────────────────────────────────┤ │ │Bold │Characters drawn with a heavier line│ │ │ │weight │ ├────────────┼────────────┼────────────────────────────────────┤ │Appearance │Condensed │Characters drawn with half the │ │ │ │average character width │ ├────────────┼────────────┼────────────────────────────────────┤ │ │Expanded │Characters drawn with twice the │ │ │ │average character width │ ├────────────┼────────────┼────────────────────────────────────┤ │ │Italic │Characters drawn with a normal line │ │ │ │weight and sloped to the right │ └────────────┴────────────┴────────────────────────────────────┘ A font family is a collection of fonts that share common design characteristics such as stroke width and serif. Stroke width refers to the width of lines used to draw the characters and symbols of a font. A serif is a short cross-line drawn at the ends of the main strokes forming a character or symbol. Text output is drawn with the characters and symbols of a font. The operating system stores fonts either in memory or on devices. Applications can access fonts through a device context associated with the current presentation space. When an application creates a presentation space, using GpiCreatePS or WinGetPS, the operating system assigns the presentation space a default font from one of the available fonts. An application can retrieve information about the default font using GpiQueryFontMetrics. ═══ 4.1.1. Image Font and Outline Font Implementation ═══ The operating system can define and implement the characters of a font as either images or outlines. Each of the characters in an image font (sometimes called a raster font) is created by alternating the ON and OFF settings of pels to produce the image. The image characters are stored as a bit map. Sometimes image fonts are even referred to as bit-map fonts. The characters in an image font must be drawn in a fixed size-you cannot rotate or scale them, for example-but usually they are of good quality. They are displayed faster than outline characters, and frequently they look better at low resolutions. The characters in an outline font, on the other hand, are drawn using a sequence of lines and arcs. Then the characters are filled if so requested. The outline characters are stored as a collection of line, fillet, and spline functions. Outline fonts are transformable because the outline characters can be scaled, rotated, and sheared. Outline fonts can be implemented as vectors, drawn by a series of small, straight lines. If that is the case, they can be referred to correctly as vector fonts. Vector fonts can be drawn much faster than fonts requiring the inclusion of actual curves and arcs. A major advantage of outline fonts is their device independence. Unlike image fonts, whose appearance depends on the device's pel definition. The following figure is an example of a character in both an image font and an outline font. Image and Outline Characters The image character is produced by manipulating pels. The outline character is produced by drawing a sequence of lines and arcs. (The resultant shape of an outline character can be filled if desired.) Most of the functions and data structures described in this chapter relate only to outline fonts. ═══ 4.1.2. PM-Supplied Fonts ═══ The PM provides a number of both image and outline typographic-quality character fonts. On some devices, image fonts in small font sizes have a better appearance than their outline-font equivalents. Type size is measured in points. There are approximately 72 points to an inch, so each character in a 24-point font, for example, is 1/3-inch high. Each incremental unit of a presentation page in PU_TWIPS format is 1/20 of a printer's point (1/1440 inch). The following image fonts are available on all OS/2-supported display adapters: ┌─────────────────────────┬───────────────────────────────────┐ │Font Family Name │Point Sizes Available │ ├─────────────────────────┼───────────────────────────────────┤ │Tms Rmn │8, 10, 12, 14, 18, 24 │ ├─────────────────────────┼───────────────────────────────────┤ │Helv │8, 10, 12, 14, 18, 24 │ ├─────────────────────────┼───────────────────────────────────┤ │Courier (monospace) │8, 10, 12 │ ├─────────────────────────┼───────────────────────────────────┤ │System Monospace │10 │ └─────────────────────────┴───────────────────────────────────┘ In addition, a default system font is used in window components such as title bars and menus. It is a proportionally spaced Swiss font. The outline fonts provided by the PM are Adobe** Type 1. The appearance and performance characteristics of these fonts are more flexible than for image fonts. The following table lists the outline fonts available with the operating system and their equivalent fonts from earlier versions of the OS/2 operating system. Available Outline Fonts ┌──────────────────┬────────────────────────────┬──────────────┐ │Outline Font │OS/2 Fonts Available │Equivalent │ │Family Name │ │Name │ ├──────────────────┼────────────────────────────┼──────────────┤ │Times New Roman** │Times New Roman │Tms Rmn │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Times New Roman Bold │Tms Rmn Bold │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Times New Roman Bold Italic │Tms Rmn Bold │ │ │ │Italic │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Times New Roman Italic │Tms Rmn Italic│ ├──────────────────┼────────────────────────────┼──────────────┤ │Helvetica** │Helvetica │Helv │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Helvetica Bold │Helv Bold │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Helvetica Bold Italic │Helv Bold │ │ │ │Italic │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Helvetica Italic. │Helv Italic │ ├──────────────────┼────────────────────────────┼──────────────┤ │Courier │Courier │Courier │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Courier Bold │Courier Bold │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Courier Bold Italic │Courier Bold │ │ │ │Italic │ ├──────────────────┼────────────────────────────┼──────────────┤ │ │Courier Italic │Courier Italic│ ├──────────────────┼────────────────────────────┼──────────────┤ │Symbol │Symbol │None │ └──────────────────┴────────────────────────────┴──────────────┘ ┌──────────────────────────────────────────────────────────────┐ │The outline font names provided with earlier versions of the │ │OS/2 operating system are still supported, but the │ │corresponding new fonts are obtained when the previous font │ │names are selected. │ └──────────────────────────────────────────────────────────────┘ ═══ 4.1.3. Availability of Additional Fonts ═══ Over 600 Adobe Type 1 fonts are available from font vendors, and user systems could have a large number of these installed. Applications must be capable of functioning properly with whatever font the user selects. An application can examine the font metrics to see what a font looks like or display different font characters from which the user can choose. When dealing with an interactive or user-driven application, the recommended method of choosing a font is to call WinFontDlg, which displays an example of the font in a dialog box. Additional Adobe Type 1 fonts can be used just like other outline fonts. Notice, however, that some of those fonts are more stylized; that is, the fonts have a greater variation in the widths of different characters within the same font, which is provided by kerning. Adobe Type 1 fonts, provided with and for a particular application, can be loaded with GpiLoadFonts, provided that the following rules are observed:  The .AFM file of the font must be specified as the font file.  The .PFB file must be in the same directory as the .AFM file. ═══ 4.1.4. Font Data Structures and Attributes ═══ The attributes of fonts are contained in the FONTMETRICS data structure. The appearance of the actual text is influenced also by the attributes of the individual characters, which can be found in the CHARBUNDLE data structure. An application can determine whether to use a particular font by examining its font metrics, which are the measurements that define the features of that font. The measurements are decided on by a font designer, whose most important criteria might be ensuring that the font is pleasing to the eye. Unlike the attributes of a character string primitive, the individual font metrics attributes cannot be changed using specific GPI functions. Your application can determine the values of the current logical font attributes by calling GpiQueryFontMetrics, which accepts as input the amount of data to be returned as well as a pointer to the data area. Unlike other GPI calls, GpiQueryFontMetrics does not return the size necessary for all font metrics data. Querying with a sizeof operator, instead of calling the query twice, returns the size data. The following table and text defines and explains the uses of the various font metric attributes. ┌──────────────────────────────┬──────────────────────────────┐ │Attribute │Description │ ├──────────────────────────────┼──────────────────────────────┤ │Face name │The full typeface name of a │ │ │font, such as Courier Bold │ │ │Italic. │ ├──────────────────────────────┼──────────────────────────────┤ │Family name │A broader equivalent of the │ │ │face name (e.g.Courier). │ ├──────────────────────────────┼──────────────────────────────┤ │Code page │The mapping between a set of │ │ │codepoints and a set of │ │ │graphic characters. │ ├──────────────────────────────┼──────────────────────────────┤ │Character cell │Controls the height and width │ │ │of outline font characters. │ ├──────────────────────────────┼──────────────────────────────┤ │Character cell ascent │Distance between the baseline │ │ │to the top of the character │ │ │cell. │ ├──────────────────────────────┼──────────────────────────────┤ │Character cell descent │Distance between the baseline │ │ │and the bottom of the │ │ │character cell. │ ├──────────────────────────────┼──────────────────────────────┤ │Maximum baseline extent │Maximum vertical extent of │ │ │font characters in world │ │ │coordinates. │ ├──────────────────────────────┼──────────────────────────────┤ │Maximum ascender │Maximum distance a font │ │ │character ascends above the │ │ │baseline. │ ├──────────────────────────────┼──────────────────────────────┤ │Maximum descender │Maximum distance a font │ │ │charter descends below the │ │ │baseline. │ ├──────────────────────────────┼──────────────────────────────┤ │Internal leading │Vertical distance equal to the│ │ │difference between the maximum│ │ │baseline extent and the em │ │ │height. │ ├──────────────────────────────┼──────────────────────────────┤ │Em height │Equivalent to the character │ │ │cell height. │ ├──────────────────────────────┼──────────────────────────────┤ │Em width │Equivalent to the character │ │ │cell width. │ ├──────────────────────────────┼──────────────────────────────┤ │X height │Height above the baseline of │ │ │any lowercase character. │ ├──────────────────────────────┼──────────────────────────────┤ │Lowercase ascent │Maximum distance of a │ │ │lowercase character above the │ │ │baseline. │ ├──────────────────────────────┼──────────────────────────────┤ │Lowercase descent │Maximum distance of a │ │ │lowercase character below the │ │ │baseline. │ ├──────────────────────────────┼──────────────────────────────┤ │External leading │Maximum vertical font spacing │ │ │that can be added without │ │ │adversely affecting the │ │ │appearance of the text. │ ├──────────────────────────────┼──────────────────────────────┤ │Average character width │Average width of font │ │ │characters in world │ │ │coordinates │ ├──────────────────────────────┼──────────────────────────────┤ │Character slope │Initial slope of a character │ │ │with respect to a vertical │ │ │line. │ ├──────────────────────────────┼──────────────────────────────┤ │Inline direction │Character angle measured with │ │ │respect to a horizontal line. │ ├──────────────────────────────┼──────────────────────────────┤ │Weight class │Specifies the thickness of │ │ │each stroke of a font │ │ │character. │ ├──────────────────────────────┼──────────────────────────────┤ │First, last, default, and │See the topic Glyphs, Code │ │break characters │Pages and Code Points. │ └──────────────────────────────┴──────────────────────────────┘ The face name attribute is the typeface name by which a particular font design is known. Two examples are Times New Roman Bold and Times New Roman Italic. Roman is the family name of these fonts. You always should provide a face name because most outline fonts are known by it. The code page to be associated with the font is identified by this metric. Some fonts are specific to a particular code page and should be used with only that code page. Other fonts are universal and can be used with any supported code page. Every character in a font is drawn within a rectangular region called a character cell. The character-cell height is the distance from the bottom of the character cell to its top. The width of the character cell is the distance from one side to the other. An imaginary horizontal line, called a baseline, is drawn through the lower portion of the character cell. The operating system uses the baseline to position characters. All uppercase and most lowercase letters in a given font rest approximately on the baseline. Some lowercase letters, such as g and y, descend below the baseline. The distance from the baseline to the top of the character cell is the character-cell ascent. Similarly, the character-cell descent is the distance from the baseline to the bottom of the character cell. The following figure illustrates characters drawn along a baseline inside their character cells. Various font metrics also are illustrated. Some Font Metrics The maximum baseline extent is the sum of the maximum ascender and the maximum descender values. The internal leading is the space allowed for diacritics above capital letters. When an application draws a string of text, the operating system positions the leftmost point of the baseline over a predetermined point for each character in the string. A font's Em height is a measure of its visual height. This measurement was given its name because, historically, the height of an uppercase letter M usually was equal to the average height of all uppercase characters in the font. However, this is no longer the case. The value of Em height represents the font point size in world coordinates and is the same as the character cell height. For an outline font, this can be set by the character cell height attribute. The value of Em Width is the equivalent horizontal dimension and is the same as the character cell width. For an outline font this also can be set by the character cell width attribute. These are, in fact, the dimensions of the em square (a typographic term) and, like point size, cannot be defined in terms of any measurable characteristic of a visible character of the font. The average distance from the baseline to the top of any lowercase character is called a font's x height. This measurement was given its name because the height of a lowercase x usually is equal to the average height of all lowercase characters in the font. The maximum ascender is the height of the tallest character in a font. The maximum descender is the depth (below the baseline) of the lowest character in a font. The lowercase ascent is the height of the tallest lowercase character in a font. The lowercase descent is the depth (below the baseline) of the lowest lowercase character in a font. Many fonts reserve part of the space in the top of each character cell for accent marks. This reserved space is called internal leading. Some fonts require a certain amount of space to be left between rows of text. This space, called external leading, is not included in the character-cell height or ascent measurements. The external leading is the recommended space to leave between rows of text to preserve its pleasing appearance. The average character width is stored in the lAveCharWidth field in the FONTMETRICS structure. The average character width is a measure of character width based on the normal frequency of lowercase letter usage in the English language. You can use this value to approximate the average width of a character in string length calculations. The maximum baseline extent for a font is the sum of the maximum ascender and the maximum descender. Maximum baseline extent is not equal to cell height for outline fonts, but is for image fonts. The character slope is an angle measured clockwise with respect to a typical vertical line. The slope of a normal font is 0; the slope of an italic font is other than 0. The character slope in the FONTMETRICS data structure can be thought of as the initial slope, since the slope can be changed in the CHARBUNDLE data structure. The inline direction is an angle measured clockwise with respect to a horizontal line. The inline direction for a Swiss, Helvetica, or Roman font is normally 0-exactly horizontal. The inline direction for a Hebrew font is normally 180, because Hebrew text is oriented right to left. The character-rotation angle is an angle measured counterclockwise with respect to a horizontal line. The baselines of characters are aligned with the vector drawn at the angle of rotation. The weight class specifies the thickness of each stroke that forms part of each character in a font. The first, last, default, and break character all are associated with glyphs for UGL fonts and code pages. A superscript is a character drawn immediately above and to the right of a normal character in a string of text. Superscripts are identified by a width and height and by vertical and horizontal offsets. A subscript is a character drawn immediately below and to the right of a normal character in a string of text. Subscripts are identified by a width and height and by vertical and horizontal offsets. ═══ 4.1.5. Glyphs, Code Pages, and Code Points ═══ The image or picture that you associate with each character or symbol in a font is called a glyph. The mapping between a set of glyphs and their code points is called a code page. For a single byte character set (SBCS), each code page contains up to 256 code points. Normally these are 8-bit integers in the range 0 through 255, with one code point identifying one glyph in that code page. The code pages can be either ASCII or EBCDIC. Because a code point repeats on a new code page, you need both the code page and code point to uniquely identify a glyph. There usually is one code page per font. However, double byte character sets (DBCS) are sometimes used for Asian languages with large character sets. Fonts are a set of glyph definitions and a default code page mapping. The same set of font glyph definitions is remapped for different code pages. Each font contains four special glyph points:  First glyph  Last glyph  Default glyph  Break glyph First and last glyph points are of more interest to the font designers than application programmers because they apply to the set of font glyph definitions rather than a particular code page. The last character is the maximum code point of the font that has a glyph associated with it and may be bigger than 256. The default glyph appears in text when an application specifies a glyph point that does not exist in the font. The break glyph usually is the space character and often has the same code point as the default character. Actually a font can have more or less than 256 definitions, but any particular code page may have less than 256 but no more. There may be a translation between the code point in the code page and the code point (between the first and last glyphs) that references the glyph in the font. The operating system assigns unique identifiers to each of its code pages. Common code pages are 437-the United States code page, and 850-the multilingual code page. The default code page is 850. An application can determine the current code page by calling GpiQueryCp. or it can assign a new code page using GpiSetCp. If you default the code page in the FATTRS structure when calling GpiCreateLogFont, you get the current code page as specified by GpiSetCp (or returned by GpiQueryCp). You can specify any one of the code page identifiers returned to you from WinQueryCpList. When using a font other than the system font, you specify the required code page in the FATTRS structure of GpiCreateLogFont. You can determine the code page for that font (if it is the current logical font) by using GpiQueryFontMetrics. ═══ 4.1.6. Proportional and Monospace Fonts ═══ When text is drawn, the operating system aligns each character by positioning its character cell next to that of the previous character. A monospace font provides the same amount of space for each character, whatever its shape. These fonts also are called fixed fonts. Courier and System Monospaced are monospace fonts. Monospace fonts, in fact, are essential for some purposes- for example program listings, where vertical alignment is important. A proportionally-spaced font is one in which some characters are allotted less space than others, so that each character occupies the proportion of space that is correct for its shape. For example, a lowercase letter l does not need the same space as a lowercase letter m. Many graphics fonts supplied by the PM, including the system font, support proportional spacing. The font metrics value maxcharinc specifies the width of the widest character in the font, and the value avecharwidth specifies an average width of the characters in the font. You can retrieve information about the widths of the characters in the current font by calling GpiQueryWidthTable. You provide the code point of the first character you are interested in and the number of characters for which you want width-table information. ═══ 4.1.7. Kerning ═══ Kerning, like proportional spacing, is a type of letter spacing. In a kerned font, some characters are allowed to overhang others and, therefore, occupy an area that is less than each character's increment for that font. Usually this feature is restricted to pairs of characters whose appearance might benefit from greater proximity. The five character pairs that most commonly benefit from kerning are Yo, We, To Tr, and Ta. Kerning is not available in the system-provided image fonts. The Helvetica and Times New Roman outline fonts provided with the system do include kerning information. You can specify kerning as a requirement on the GpiCreateLogFont. Selecting a kerned font lets kerning take place whenever it is defined. The a-space is the area of the character cell before the character; the b-space is the area of the character cell occupied by the character; the c-space is the area of the character cell after the character. The a-space and c-space are shown in the following figure. a-Space, b-Space, and c-Space The best way to implement kerning is to use a kerning-pair table. The kerning table will exist only for certain pairs of characters for which adjustments are desirable. Each of the entries in a kerning-pair table contains the code points of a pair of kerned characters and an adjustment that should be applied to the character width of the first character of the pair. A negative value means that the space is decreased, and a positive value means it is increased, whenever the two characters in a kerning pair are produced together. A kerning-pair table might be provided with a purchased font. If so, it will be recorded in the font header. If kerning is specified on a character-pair basis (that is, if the font has a kerning-pair table), the font has a specific number of kerned pairs. GpiQueryKerningPairs returns kerning-pair information from the current logical font. For each pair of kerned characters, you are given the characters themselves and an adjustment in world coordinates that must be applied to the character width of the first character of the pair. When you specify negative a- and c-space values, the values affect any character paired with the kerned character. Because this form of kerning cannot be applied selectively, you have to choose the kerned characters carefully. For example, an italic letter f ( Я ) is a good candidate for this sort of kerning, because it can overhang most of the characters that precede and follow it. An application can adjust the amount of space between all characters in a font with GpiSetCharExtra. Any extra space is added to font kerning values. An application also can adjust the width of a font's break character (space) with GpiSetCharBreakExtra. Kerning is not available on all devices. On devices that support kerning, kerning is enabled by default. When kerning is not supported on a device, kerning support is switched off by default. When kerning support is switched off, the kerning information supplied with a font is ignored. To determine whether a device supports kerning, use DevQueryCaps. The kerning information can be implemented by your application when a character string primitive is written to an output device. This is called rendering the text. GpiCharStringPos and GpiCharStringPosAt, permit specification of the starting position for each character. The entire character string can be searched for character pairs that also are kerning pairs for the kerning information to be applied. ═══ 4.1.8. FATTRS Data Structure ═══ The FATTRS structure is used to identify the characteristics of a requested font. Certain attributes of a font that govern many individual character string primitives are contained in FATTRS, as follows:  Record length  Selection indicators  Match value  Face name  Registry identifier  Code page  Maximum baseline extent  Average character width  Type indicator  Font use indicator ═══ 4.1.8.1. Record Length ═══ Record length determines the length of the FATTRS structure. An application normally specifies this with the sizeof operator. ═══ 4.1.8.2. Selection Indicators ═══ There are five selection indicators: Indicator If set ON, selects... FATTR_SEL_ITALIC A font with an italic appearance. This is intended for use with an image font and results in a simulation of an italic font. FATTR_SEL_BOLD A boldface version of the font. This is intended for use with an image font and results in a simulation of a boldface font. FATTR_SEL_OUTLINE Hollow characters when using an outline font. This only can be used with outline fonts. This indicator is less important than the others because improved performance is now available (from Adobe Type Manager) on filled outline fonts than was originally available when this option (FATTR_SEL_OUTLINE) was introduced. FATTR_SEL_STRIKEOUT A font in which the characters are struck through. This option also might be selected on the character string primitive. FATTR_SEL_UNDERSCORE A font in which the characters are underscored. This option also might be selected on the character string primitive. Any combination of these indicators can be set. When set, they cause a simulation of the selected feature. For example, if you require a bold, italicized version of a PM image font, PM simulates that feature because bold, italic image fonts are not supplied. ═══ 4.1.8.3. Match Value ═══ The match value is a number that identifies a physical font. It is allocated to the font when the font is loaded. If the match value is less than 0, the font is a device font; and, if the match value is greater than 0, the font is a generic font. A device font is exclusive to the device with which it is associated, and its match number is guaranteed to be unique only within the device driver. If an application prints on a different printer, the application cannot guarantee that the font will be identical just by specifying the match value. A generic font is available on more than one device. The PM-supplied fonts, for example, are generic fonts. Printer fonts always are device fonts, but you also can and should use generic fonts with printers. You can choose whether or not to use the match value to specify the font when calling GpiCreateLogFont. Specifying the match value is easier but less flexible than the alternative, which is to specify the font name and outline characteristics. For an image font, the alternative is to specify the maximum baseline extent and average character width of the required font. ═══ 4.1.8.4. Face Name ═══ The face name value in the FATTRS data structure is identical to the face name of the FONTMETRICS data structure when describing a specific font. ═══ 4.1.8.5. Registry Identifier ═══ The registry identifier is a unique number by which the font is registered with IBM. The registry identifier of a particular font can be retrieved by calling GpiQueryFonts. If you do not have a registry number, set this value to 0. ═══ 4.1.8.6. Code Page ═══ The code page is the identifier of the code page to be associated with the font. You can default the code page in GpiCreateLogFont by specifying 0. Like the face name, the code page in the FATTRS data structure is identical to the code page in the FONTMETRICS data structure when describing a specific font. ═══ 4.1.8.7. Maximum Baseline Extent ═══ The maximum baseline extent is the vertical space occupied by characters in the font. If you are setting the font-use indicator FATTR_FONTUSE_OUTLINE, you should set the maximum baseline extent to 0. Outline fonts take an equivalent value from the character cell attribute that is current when text is written to an output device. The maximum baseline extent value is required to select an image font and must be specified in world coordinates. For image fonts, this is the vertical height in world coordinates of character images in the font. This field must be specified when requesting an image font with GpiCreateLogFont. The maximum baseline extent measurement is shown in a previous figure. The maximum baseline extent in the FATTRS data structure is used for programming, unlike the maximum baseline extent in the FONTMETRICS data structure, which is only measurement as recommended by the font's designer. ═══ 4.1.8.8. Average Character Width ═══ The average character width of a font is the average character increment in world coordinates. The character increment is the sum of the a-space, b-space, and c-space of a character. If you are setting the font-use indicator FATTR_FONTUSE_OUTLINE, you can set the average character width to 0 because the outline fonts take an equivalent value from the character cell attribute that is current when text is written to an output device. This field should be specified when requesting an image font using GpiCreateLogFont. It must be specified in world coordinates. ═══ 4.1.8.9. Type Indicator ═══ PM provides a type indicator to allow the further specification of font most appropriate to your application. The type indicators found in the FATTR data structure are not interchangeable with the type indicators in the FONTMETRICS data structure. The most commonly used type indicator, FATTR_TYPE_KERNING, causes kerning to take effect for those fonts that contain kerning-pair information. FATTR_TYPE_KERNING is supported only for PostScript** devices. There are three other type indicators provided: Indicator When... FATTR_TYPE_ANTIALIASED An anti-aliased font is required FATTR_TYPE_MBCS A mixed single- or double-byte code page is required FATTR_TYPE_DBCS A double-byte code page is required. ═══ 4.1.8.10. Font-Use Indicators ═══ The font-use indicators tell the PM what you intend to do with the font, and determine whether you get an image font or an outline font. There are three font-use indicators: Indicator If set ON... FATTR_FONTUSE_OUTLINE Forces selection of an outline font. This value must be set if you intend to use graphics characters in a path definition. FATTR_FONTUSE_TRANSFORMABLE Allows the scaling, rotating, or shearing of font characters. Set this value ON if the current character mode is CM_MODE3. FATTR_FONTUSE_NOMIX Allows the PM to ignore current mix-mode values. Set this value ON if the graphics text is not going to be written over or underneath other graphics, because it improves the performance of text drawing. FATTR_FONTUSE_TRANSFORMABLE and FATTR_FONTUSE_OUTLINE normally are both specified to select an outline font. Specify neither if you want to select an image font. ═══ 4.1.9. Public and Private Fonts ═══ The fonts supplied by PM are loaded automatically when the system is started and are available to any application at any time. They are said to be public fonts. Any font that you define locally has to be loaded before you can use it. If you load a locally defined font using the Install option of the Workplace Font Palette, that font is available to any application in the system, and, therefore is a public font. Some devices provide their own fonts. All device fonts are public fonts. Any font loaded using GpiLoadFonts from within an application is a private font. A private font is available only to the application that loads it. The file in which you store a locally created font definition can contain more than one font definition. GpiLoadFonts loads a named font file and, therefore, loads all fonts defined in that file. GpiQueryFontFileDescriptions provides the family name and the face name of each font in a locally defined font file. Use this function to determine if a particular file contains the font you want to use before you load it. To unload a previously loaded private font file, call GpiUnloadFonts. You cannot unload public fonts with this function. You cannot use private fonts in a document that you want to print using the spooler. If you want to print the document from a printer server, using the PM_Q_STD format, all the fonts used in the document must be installed as public fonts on the server. You can use either public or private fonts if you specify the data format PM_Q_RAW or if you want to print without the spooler. ═══ 4.1.10. Drawing a Character String Primitive ═══ To draw a string of one or more graphics characters from the current font, call GpiCharString. The string starts at the current position and, when it has been drawn, the new current position is the point at which the next character would be, had there been one. To draw the string starting at a position other than the current position, call GpiCharStringAt. This is equivalent to calling GpiSetCurrentPosition or GpiMove, followed by GpiCharString. You supply the text of the character string as a parameter to the appropriate GPI function. Note: You also can call WinDrawText, which draws text to the screen a line at a time. WinDrawText differs from the GpiCharString... functions in that WinDrawText ignores the DM_RETAIN drawing mode and can only be used to draw to a window device context. The following figure shows some examples of a character string primitive. The Character String Primitive This example shows the string Presentation Manager drawn from different logical fonts. ═══ 4.1.11. Font Files and Dynamic-Link Libraries ═══ You can use the Font Editor to alter and customize image-font files. Files created with the Font Editor have a .FNT extension. After you create a custom font, put it into a dynamic-link library (DLL) that the application can load. Once the application loads this library, it can use any of the custom fonts the library contains. DLLs that contain fonts are unique; they contain data segments and empty (or useless) code segments. They are unique because they contain no executable code, unlike normal DLLs. Also you are able to install the font file as a public font if desired; GpiLoadFonts will make it available only as a private font. The operating system naming convention for a DLL that contains font information end with a .FON extension. To create a DLL, you must use an assembler, a linker, and the operating system Resource Compiler. For this example, assume that your custom font file is named NEWFONT.FNT. After creating your custom font file, you need to create a special assembler language file with your editor. Call this file MYFONT.ASM, for example. The following figure shows an example of the source code for this file. code segment word ;Makes dummy code segment aligned on word boundary db "empty_segment" ;Initializes a string in dummy segment code ends ;Dummy segment ends here end ;Terminates source file After you have created MYFONT.ASM, assemble it by using the following command: masm myfont After assembling the MYFONT.ASM file, create a module-definition file. Call this file MYFONT.DEF, for example. It should contain the statements in the following figure. LIBRARY myfont SEGMENTS CODE MOVEABLE The first statement tells the linker that you are creating a library with the module name, MYFONT. The second statement tells the linker that the segments in this library are movable code segments. After creating MYFONT.DEF, start the linker with the command in the following figure. link myfont,,,,myfont.def This command creates an empty executable file called MYFONT.EXE. After creating the empty executable file, which is the template for a DLL, create a resource file and call it MYFONT.RC. For example, if your font file is called NEWFONT.FNT, you would place the statement in the following figure in MYFONT.RC. FONT 200 NEWFONT.FNT This statement assigns the identifier, 200, to the font resource NEWFONT.FNT. Finally, use the Resource Compiler to add the font file (NEWFONT.FNT) to the empty DLL as in the following figure. rc myfont.rc The executable file, MYFONT.EXE, now contains your custom fonts. After you have renamed this file, MYFONT.FON, you can load the fonts into your application using GpiLoadFonts and pass it a pointer to the path and library name as the second argument-for example, c:\os2\dll\myfont.fon. ═══ 4.2. Using Fonts ═══ You can use the font functions to:  Determine the characteristics of available fonts  Select a font for text output  Delete or unload a font when finished  Create a font  Create marker sets and pattern sets  Use a bit map as a fill pattern  Use a clip path as a fill pattern ═══ 4.2.1. Selecting a Font ═══ Every presentation space has a current font, and graphics characters must be drawn in that font. By default, the current font is the system font. Before an application can use any font other than the system font, it has to identify the other font as the new current font. There are two distinct ways to identify the other font:  Call GpiQueryFonts to request information about the available physical fonts, and then explicitly select one of those fonts by supplying its identifier as input to GpiCreateLogFont. This process has 11 steps and is covered in the topic "Explicit Font Selection." This method of selecting a font is most useful for selecting image fonts. If you must have an image font, you are urged to use this "explicit selection"method, because you need to specify a maximum baseline extent and an average character width in the FATTRS structure. These values can be determined only by calling GpiQueryFonts. If you specify values that are not valid, you are likely to be given an outline font.  Use GpiCreateLogFont to specify the features you require in a font, and permit the PM programming interface to make an appropriate font available to you. This process has two steps and is covered in the topic "Closest Matching Font Selection." ═══ 4.2.1.1. Explicit Font Selection ═══ An application can select either a public or a private font with GpiCreateLogFont. A public font is available to all applications. A private font is loaded by an application for its exclusive use. Use the Presentation Manager Control Panel to load a public font. Four DLLs contain the Times Roman, Helvetica, Courier, and System Monospaced image fonts. The names of these libraries are:  TIMES.FON  HELV.FON  COURIER.FON  SYSMONO.FON Unlike most DLLs, font libraries typically use the file name extension .FON. If the user loads all four libraries, a total of 76 public fonts are available. An application can use both outline and image formats of these fonts. Characters in the image format are available in sizes ranging from 8 to 24 points. Characters in the outline format can be any size. Call GpiLoadFonts to load a private font. Pass the function the path and name of the DLL that contains the font. After the application loads the DLL of fonts, it can determine the characteristics of the fonts in that library by calling GpiQueryFonts. To select a public font from all of the available public fonts, do the following: 1. Call GpiQueryFonts. passing the QF_PUBLIC flag, a NULL pointer to the font's face name, and a count of 0 to determine the number of available public fonts, as shown in the following figure. #define INCL_GPILCIDS #include void fncFONT06(void){ FONTMETRICS fm, afm[80]; LONG cFonts = 0, cPublicFonts; HPS hps; cPublicFonts = GpiQueryFonts(hps, /* Queries all public fonts */ QF_PUBLIC, (PSZ) NULL, &cFonts, sizeof(fm), (PFONTMETRICS) NULL); } /* fncFONT06 */ Note: To load and use a private font, follow the same procedure, but specify QF_PRIVATE, instead of QF_PUBLIC, in the calls to GpiQueryFonts. 2. Copy the value returned by GpiQueryFonts into a LONG integer variable. 3. Allocate memory for the FONTMETRICS data structures. 4. Call GpiQueryFonts again, passing the QF_PUBLIC flag, a NULL pointer to the font's face name, the count returned by the previous call, and the address of an array of FONTMETRICS structures. GpiQueryFonts the font metrics of every font available the array of FONTMETRICS structures. The font metrics define in detail the physical characteristics of a font. Because the font metrics are so detailed, the amount of information returned to you from GpiQueryFonts can be extensive. You can restrict the amount of information returned by this function by:  Specifying an absolute number of fonts about which you require information.  Asking for information about fonts of a specific face name only.  Limiting the length of the font-metrics buffer. If you request information for more fonts than are available on the system, GpiQueryFonts returns all the information about the available fonts and a value indicating how many fonts it has returned. If you request information for fewer fonts than are available on the system (that match the specified face name, and so forth), GpiQueryFonts returns a value indicating the number of fonts that it was unable to return. The following figure is an example of this technique of selecting a font. #define INCL_GPILCIDS #include PFONTMETRICS fncFONT07 (HPS hps, PLONG pcPublicFonts) { PFONTMETRICS afm = NULL; LONG fonts = 1000; *pcPublicFonts = GpiQueryFonts(hps, QF_PUBLIC, (PSZ) NULL, &fonts, sizeof(*afm), (PFONTMETRICS) NULL); if (!DosAllocMem(&afm, sizeof(*afm)*(*pcPublicFonts), PAG_COMMIT | PAGWRITE )) { GpiQueryFonts(hps, QF_PUBLIC, (PSZ) NULL, pcPublicFonts, sizeof(*afm), afm); } /* endif */ return afm; } 5. Examine the array of FONTMETRICS structures. a. For an outline font, examine the face name and other attributes of the font your application requires. b. For an image font, examine the device resolution fields. These fields are the ones that determine if a particular font and its metrics match the device with which you wish to use it. Note: If your application is interactive, organize the face names and other information relevant to those fonts (such as point sizes) in a menu. When the operator has selected a font, supply the relevant information from the font metrics of that font in the FATTRS structure of GpiCreateLogFont. 6. After determining which font to use, your application must fill in the fields of the FATTRS structure. Some of the data for these fields will be copied (explicitly) from the FONTMETRICS structure. Then call GpiCreateLogFont. If you do not supply a face name, the default font is used. If you supply a face name, and the presentation driver cannot find a matching font, a default font is selected. The FATTRS structure describes a logical font. An application can have up to 254 logical fonts defined at any one time in a single presentation space. A logical font is a list of font attributes, whereas a physical font is the bit-map or vector information that the system uses to draw characters. 7. The fonts supplied by the PM programming interface, the fonts you load using the Control Panel, and any fonts you load with GpiLoadFonts are all physical fonts. Copying the entries in the FATTRS structure ensures that, if a particular font is unavailable, an attempt is made to find the most suitable substitute. Without the FATTRS information, PM is less likely to locate a suitable font. 8. Initialize a local identifier (lcid) for the new font. 9. Call GpiCreateLogFont and pass as input parameters:  The lcid for the font  The address of an 8-character array containing the name you want to give to the logical font, (or, if you do not want to specify a name, the value NULL)  The address of the FATTRS structure 10. Examine the return value from GpiCreateLogFont. The value will be 2 if the function is successful; 1, if the default font was used. 11. Pass the lcid to GpiSetCharSet, assigning the font to your application's presentation space. Then the application can use it for text output. (This step identifies a logical font as the current font.) The following figure shows how to select an image font at least 14 device coordinate units high. #define INCL_GPILCIDS #include LONG fncFONT08(HPS hps, LONG lcid, LONG xres, LONG yres) { FATTRS fat; PFONTMETRICS afm; LONG cFonts; LONG i; LONG rc = 0; afm = fncFONT07(hps, &cfonts); if (amf) { for (i=0; 1= 14) { fat.usRecordLength = sizeof(fat); fat.fsSelection = 0; fat.lMatch = 0; strcpy(fat.szFacename, afm[i].szFacename); fat.idRegistry = afm[i].idRegistry; fat.usCodePage = 0; fat.lMaxBaselineExt = afm[i].lMaxBaselineExt; fat.lAveCharWidth = afm[i].lAveCharWidth; fat.fsType = 0; fat.fsFontUse = 0; rc = GpiCreateLogFont(hps, (PSTR8) NULL, lcid, &fat); if (rc) { GpiSetCharSet(hps, lcid); } /* endif */ } /* endfor */ } /* endif */ return rc; } GpiQueryFonts returns device coordinates for image fonts. For outline fonts, it returns notional coordinates. Notional coordinates are the coordinate in which the font was defined. Usually outline fonts are defined over a 1000-by-1000 matrix, with the unit of the matrix a 1/1000 of the em height. ═══ 4.2.1.2. Reassociating the Presentation Space ═══ The match value of any device font is guaranteed to be unique only for the current device. If you associate the presentation space with a different device context, any logical fonts that also are device fonts are no longer available. On the new device, the match number could identify a different device font (which may not be suitable) or no font at all. Therefore, you should redefine a logical font and select it as the current font if you reassociate the presentation space when the current font is a device font. Otherwise, the default font is used. If you do not intend to use the font on the new device, however, you need not redefine it. You will be able to continue using the font if you reassociate the presentation space with the original device context. Any generic fonts can continue to be used after the presentation space is reassociated if they are suitable for the new device. An image font, for example, can be used only on devices that are all-points addressable. ═══ 4.2.1.3. Font Resolution ═══ Device fonts, particularly printer fonts, usually are designed for a specific resolution, namely the resolution of the device on which they are to be used. By contrast, generic outline fonts are not device-specific. Generic image fonts are designed for a particular resolution value and, therefore, are really applicable only to devices with a matching resolution value. The horizontal and vertical font resolution values for the device are returned by DevQueryCaps. The desired horizontal and vertical device resolution values in the font metrics of the font concerned are returned by GpiQueryFonts. Compare these the device and the desired resolution values only for an image font. If they are identical then this image font is designed for use with this device (for example, the point size in the font metrics will be accurate for this device). To select a font, do the following: 1. Query the available fonts using GpiQueryFonts. 2. If you want an outline font, search the metrics of fonts returned by GpiQueryFonts for a font that is an outline font and that has the required face name. 3. If you want an image font, search the metrics of the fonts returned by GpiQueryFonts for a font that is an image font and that has the following:  Required face name  Required point size  Horizontal device resolution font metric that matches the horizontal resolution for the device  Vertical device resolution font metric that matches the vertical resolution for the device. 4. As an alternative to the above for an image font, search the metrics of the fonts returned by GpiQueryFonts for a font that is an image font and that has the following:  Required face name  Required em height in world coordinates. Before you define a logical font, determine the resolution of the current device by using DevQueryCaps with the CAPS_VERTICAL_FONT_RES and CAPS_HORIZONTAL_FONT_RES parameters. Compare the values returned from this function with the xDeviceRes and yDeviceRes values in the font metrics of the available fonts. These two values contain the resolution of the device for which the font was designed. All measurements are in pels per inch. By comparing the font resolution with the device resolution, you can identify the image font best suited to the current device. ═══ 4.2.1.4. Closest-Matching Font Selection ═══ The alternative to selecting a specific font is to set the match value to 0. To have the Presentation Manager programming interface select the closest-matching font available, do the following: 1. Define a logical font with GpiCreateLogFont. This function establishes a link between the calling application and an appropriate physical font. GpiCreateLogFont accepts a number of options as input, including the font attributes, which describe the physical features and capabilities of the font. 2. Complete the FATTRS structure of GpiCreateLogFont. The FATTRS structure describes a logical font, which the system uses to find the closest matching physical font. Depending on whether you are selecting a font using a match number, fill in the FATTRS structure, observing the rules listed in the following table. Filling in the FATTRS Structure ┌──────────────────────────────┬──────────────────────────────┐ │If using a match number │If not using a match number │ ├──────────────────────────────┼──────────────────────────────┤ │Set the match number to the │Set the match number to zero. │ │required FONTMETRICS value. │ │ │The FONTMETRICS value is the │If your font is an image font:│ │value in the FONTMETRICS │ │ │structure for the required │Set the maximum baseline │ │font returned by GpiQueryFonts│extent to the required │ │. │FONTMETRICS value. │ │ │ │ │Set the maximum baseline │Set the average character │ │extent to zero. │width to the required │ │ │FONTMETRICS value. │ │Set the average character │ │ │width to zero. │ │ │ │ │ │Note: A negative lMatch is │ │ │only unique for a device. A │ │ │positive lMatch is only unique│ │ │on a particular system at a │ │ │particular time. │ │ └──────────────────────────────┴──────────────────────────────┘ Also observe the rules concerning the font-use indicator that are listed in the following table. Font-Use Indicator Considerations ┌──────────────────────────────┬──────────────────────────────┐ │If you have not set the │If you have set the │ │FATTR_FONTUSE_OUTLINE │FATTR_FONTUSE_OUTLINE │ │indicator: │indicator: │ ├──────────────────────────────┼──────────────────────────────┤ │PM looks for an image font │PM looks for a suitable │ │that has the required │outline font whose selection │ │selection indicators and whose│indicators match those you │ │maximum baseline extent and │have specified. │ │average character width match │ │ │those you have specified. │If no suitable outline font is│ │ │found, the default font is │ │If no suitable image font is │used. No attempt is made to │ │found, PM looks for an outline│substitute an image font. │ │font with the required face │ │ │name and selection indicators.│ │ │ │ │ │If no suitable outline font is│ │ │found, the default font is │ │ │made available to you. │ │ └──────────────────────────────┴──────────────────────────────┘ Outline fonts are affected by the current character attributes (for example, character box, shear, and angle). Because an outline font might be made available to you, even when you requested an image font, call GpiQueryFontMetrics to determine whether the font is an image font or an outline font. GpiQueryFontMetrics returns the metrics of the current logical font in world coordinates. The setting of the definition indicators in the FONTMETRICS structure tell you whether the font is either an image or outline font, or a device or generic font. If the font is an outline font, specify values for the character attributes before using the font. Outline fonts are unaffected by the maximum baseline extent and average character width values specified in GpiCreateLogFont. If the default font provided is an image font, and you also have specified FATTR_FONTUSE_TRANSFORMABLE, any attempt to draw graphics characters in CM_MODE3 raises an error condition. This is an exception to the general rule that a FATTR_FONTUSE_TRANSFORMABLE font must be used in CM_MODE3 only. ═══ 4.2.2. Selecting the New Current Font ═══ In addition to completing the FATTRS structure, you must supply as input to GpiCreateLogFont a unique lcid for the font. The identifier is a number in the range of 1 through 254. Because you can have more than one logical font definition in a presentation space, you must select the current font by supplying the font's lcid as input to GpiSetCharSet. You do not have to call GpiSetCharSet to use the default font. When you want to reset the current font to its default value, however, call GpiSetCharSet with the value LCID_DEFAULT. The current font, like other modal attributes, reverts automatically to its default value when specific GPI functions are called. ═══ 4.2.3. Deleting Logical Fonts and Unloading Physical Fonts ═══ A logical font can be used only by the application that defines it. The logical font definition is stored in the presentation space and is saved on the LIFO stack with its lcid when GpiSavePS is called. Unlike a physical font definition, a logical font definition is temporary and is lost when the presentation space is deleted. To specifically delete a logical font, call GpiDeleteSetId, which deletes the logical font, and makes its lcid available for reuse. Sometimes this is necessary because there are only 255 lcids available. The logical font must not be the current font when you call GpiDeleteSetId. Logical fonts are deleted to release the lcid and free memory. Unload private fonts using GpiUnloadFonts to free memory and to make them no longer available. Uninstall public fonts using the Control Panel to free memory and to make them no longer available. You must end the association between physical and logical fonts before calling GpiUnloadFonts. If you call GpiUnloadFonts to unload a private font file, you must end the association between the physical fonts in that file and the logical fonts defined by the application. Do the following:  Call GpiSetCharSet to select a current font (such as the default font) that is not linked to the physical fonts you are unloading  Call GpiDeleteSetId to delete each logical font that refers to any of the physical fonts in the font resource file. If you fail to do this, an error is returned to your application from GpiUnloadFonts. *GpiUnloadFonts. ═══ 4.2.4. Creating Fonts ═══ You cannot edit the definitions of any of the PM-provided fonts, although you can create and edit image-font files using the Font Editor. A font file contains a header, that describes the font in general terms and a section containing bit maps of the characters themselves. The font definition is stored in a resource file. ═══ 4.2.5. Creating Marker Sets and Pattern Sets ═══ Like character sets, marker sets and pattern sets are defined in fonts. For both marker sets and pattern sets, there are system-provided defaults. You also can create your own image markers or patterns, but not outline markers or patterns, using the Font Editor. The font definition containing the image or pattern can be loaded either as a public font (using the Install selection from the Control Panel) or as a private font (using GpiLoadFonts). The current character mode has no effect on marker sets and pattern sets. Any character from a font can be used as a marker or as an area-fill pattern. Before you can use a locally defined marker set or pattern set, you must call GpiCreateLogFont to define a logical font and to give it an lcid, just as you would for a character font. Most of the values you can specify with GpiCreateLogFont are not applicable to marker sets and pattern sets. Furthermore, in the instance of marker sets and pattern sets, you usually know that you want to use a particular font. To select a locally defined marker set or pattern set: 1. Call GpiQueryFonts to obtain a match value for the font. 2. Call GpiCreateLogFont, specifying the face name, match value, and lcid for the font. 3. Select the logical font as the current marker set or pattern set by calling GpiSetMarkerSet or GpiSetPatternSet, as appropriate. To revert to using the default pattern or marker sets, call GpiSetPatternSet or GpiSetMarkerSet with the value LCID_DEFAULT. ═══ 4.2.6. Using Bit Maps as Area-Fill Patterns ═══ An alternative to using the Font Editor to create your own pattern sets is to use a bit map as an area-fill pattern. You must call GpiSetBitmapId to give the bit map an lcid, and then call GpiSetPatternSet, specifying the lcid of the bit map. The bit map becomes a pattern set containing one pattern, and the current pattern-symbol attribute is ignored. GpiQueryBitmapHandle returns the handle of the bit map currently known by the lcid that you supply as input. PM cannot distinguish among the lcids associated with a particular presentation space. Any lcid can identify a character set, marker set, pattern set, or bit map (that is being used as an area-fill pattern). For example, if you call GpiQueryNumberSetIds to determine how many lcids are currently assigned in the presentation space, the number returned to you includes all logical fonts defined for this presentation space. You also can use GpiDeleteSetId to remove lcids associated with the non-font entities. If you call this function to delete a bit map that is being used as an area-fill pattern, the bit map itself is not deleted. However, it is disassociated from its lcid, and the lcid can be reused. ═══ 4.2.7. Using Paths with Fill Patterns ═══ Using paths lets you fill a character string with a complicated or nonrepeating pattern. The following sequence is recommended:  Select the required outline font, and set the required character attributes.  Create a path by calling GpiBeginPath, GpiCharString, and GpiEndPath.  Set the required pattern symbol and other AREABUNDLE pattern attributes.  Fill the path using GpiFillPath. The following figure provides an example of using paths with fill patterns to create characters. Using Clip Paths to Create Characters ═══ 4.3. Font-File Format ═══ The OS/2 font-file format consists of two sections. The first section contains the general attributes of the font, and describes features such as its typeface, style, and nominal size. The second section contains the actual definitions of the characters belonging to the font. The font resource is a set of self-defining records of the form: typedef struct _RECORD { ULONG ulIdentity; /* structure identity code */ ULONG ulSize; /* structure size in bytes */ . /* data */ . . } RECORD; A font starts with a special font-signature structure and ends with an ending structure. The font signature has the form: typedef struct _FONTSIGNATURE { ULONG ulIdentity; ULONG ulSize; CHAR achSignature [12] } FONTSIGNATURE; Where: ulIdentity 0xFFFFFFFE ulSize 20 achSignature "OS/2 FONT" for an OS/2 1.x format font, or "OS/2 FONT 2" for an OS/2 2.x format font. A 2.x format font includes additional font description information in the PANOSE structure. This structure will be added to the end of the .FNT file (prior to the ENDFONT record). The font end structure has the form: typedef struct _ENDFONT{ ULONG ulIdentity; ULONG ulSize; }ENDFONT Where: ulIdentity 0xFFFFFFFF ulSize 8 All records should be in the order of their identity fields. There are three or four records in a font resource between the font signature and the font end:  The font metrics  The font character definitions  The pair kerning table.  The PANOSE description (for "OS/2 FONT 2" fonts). Following compilation, the records in the resource are in the order defined above. ═══ 4.3.1. Metric Information Contained in Fonts ═══ This section gives an explanation of how to set the fields of the FOCAMETRICS structure when developing:  A bit map or outline font for general use by PM graphics applications  A description of a bit map or outline device font that is built in to a device or can be downloaded to a device. The following structure contains the physical font metrics used when creating fonts. It is defined in the file \INCLUDE\PMFONT.H. typedef struct _FOCAMETRICS { ULONG ulIdentity; ULONG ulSize; CHAR szFamilyname[32]; CHAR szFacename[32]; SHORT usRegistryId; SHORT usCodePage; SHORT yEmHeight; SHORT yXHeight; SHORT yMaxAscender; SHORT yMaxDescender; SHORT yLowerCaseAscent; SHORT yLowerCaseDescent; SHORT yInternalLeading; SHORT yExternalLeading; SHORT xAveCharWidth; SHORT xMaxCharInc; SHORT xEmInc; SHORT yMaxBaselineExt; SHORT sCharSlope; SHORT sInlineDir; SHORT sCharRot; USHORT usWeightClass; USHORT usWidthClass; SHORT xDeviceRes; SHORT yDeviceRes; SHORT usFirstChar; SHORT usLastChar; SHORT usDefaultChar; SHORT usBreakChar; SHORT usNominalPointSize; SHORT usMinimumPointSize; SHORT usMaximumPointSize; SHORT fsTypeFlags; SHORT fsDefn; SHORT fsSelectionFlags; SHORT fsCapabilities; SHORT ySubscriptXSize; SHORT ySubscriptYSize; SHORT ySubscriptXOffset; SHORT ySubscriptYOffset; SHORT ySuperscriptXSize; SHORT ySuperscriptYSize; SHORT ySuperscriptXOffset; SHORT ySuperscriptYOffset; SHORT yUnderscoreSize; SHORT yUnderscorePosition; SHORT yStrikeoutSize; SHORT yStrikeoutPosition; SHORT usKerningPairs; SHORT sFamilyClass; PSZ pszDeviceNameOffset; } FOCAMETRICS; Note: FOCAMETRICS is a parallel structure with FONTMETRICS as returned to applications in the GpiQueryFonts and GpiQueryFontMetrics function calls. The FONTMETRICS fields are derived from FOCAMETRICS by the Presentation Manager graphics engine. Most values are passed though unchanged. The exceptions are:  The Identity field. This must be 1. This field is not a part of the FONTMETRICS structure.  The Size field. This must be set to the size of the FOCAMETRICS structure. This field is not a part of the FONTMETRICS structure.  The Codepage field. Ignore the description in FONTMETRICS, and use the following: Place 850 in this field if the font is intended to support any PM supported code page. Place 65400 in this field if the font has special glyphs, for example if it is a Symbol font. Place other valid code pages in this field if the font is specific to this code page. Do not place other values in this field.  FONTMETRICS fields which contain values in world coordinates. The corresponding field in FOCAMETRICS should contain pel values for bit-map fonts, and notional units for outline fonts. See FONTMETRICS for a detailed explanation of the fields. ═══ 4.3.2. Font Character Definitions ═══ Two formats of font character definition are supported. These are: Image format The character glyphs are represented as pel images. Outline format The character glyphs are represented by vector data that traces the outline of the character. Note: Intelligent Font Technology fonts (such as ATM Type-1 fonts) may be stored in a technology specific format, and thus will not conform to this definition for outline fonts. The definition consists of a header portion and a portion carrying the characters themselves. The header portion contains information about the format of the character definitions and data about each character including width data and the offset into the definition section at which the character definition begins. (See Definitions of Terms Used When Describing Fonts.) 1. Proportional characters (a+b+c = character increment) for each character: a,b,c >= 0 2. Characters where a, b, and c are definitions for all characters: b >= 0 a, c any integer Raster fonts contain a "null character". The character definition record for this occurs after the one for the last character. Thus the format has usLastChar+2 characters, although the null character is not counted in the range returned. The null character is composed of zeros and is always eight pels wide. ═══ 4.3.2.1. Font Definition Header ═══ This structure defines the format or the character definition records that follow it: typedef struct_FONTDEFINITIONHEADER { ULONG ulIdentity; ULONG ulSize; SHORT fsFontdef; SHORT fsChardef; SHORT usCellSize; SHORT xCellWidth; SHORT yCellHeight; SHORT xCellIncrement; SHORT xCellA; SHORT xCellB; SHORT xCellC; SHORT pCellBaseOffset; } FONTDEFINITIONHEADER; typedef FONTDEFINITIONHEADER FAR *PFONTDEFINITIONHEADER; Where: ulIdentity 4 bytes. Must be equal to 2. ulSize 4 bytes. Size of this structure in bytes. fsFontdef 2 bytes of flags. Indicates which fields are present in the font definition data in the header. Type 1 Bit 0 1 = width defined in header Bit 1 1 = height defined in header Bit 2 1 = char increment same as width, so that it is defined for the whole font Bit 3 0 = a-space not defined Bit 4 0 = b-space not defined Bit 5 0 = c-space not defined Bit 6 1 = base offset same for all characters. Type 2 Bit 0 0 = width for each character unique Bit 1 1 = height defined in header Bit 2 0 = char increment same as width, so that it is unique for each character Bit 3 0 = a-space not defined Bit 4 0 = b-space not defined Bit 5 0 = c-space not defined Bit 6 1 = base offset same for all characters. Type 3 Bit 0 0 = width for each character unique Bit 1 1 = height defined in header Bit 2 0 = char increment same as width, so that it is unique Bit 3 0 = a-space not defined Bit 4 0 = b-space not defined Bit 5 0 = c-space not defined Bit 6 1 = base offset same for all characters. FsChardef 2 bytes of flags. Indicates which fields are present on a per character basis. Type 1 Bit 0 1 = width defined for each character (performance op) Bit 1 0 = height is in header Bit 2 0 = char increment is in header Bit 3 0 = a-space not defined Bit 4 0 = b-space not defined Bit 5 0 = c-space not defined Bit 6 0 = base offset defined in header Bit 7 1 = offset to glyph defined. Type 2 Bit 0 1 = width defined for each character Bit 1 0 = height is in header Bit 2 0 = char increment same as width Bit 3 0 = a-space not defined Bit 4 0 = b-space not defined Bit 5 0 = c-space not defined Bit 6 0 = base offset defined in header Bit 7 1 = offset to glyph defined. Type 3 Bit 0 1 = width not defined, use a, b, c Bit 1 0 = height is in header Bit 2 0 = char increment same as width Bit 3 1 = a-space defined Bit 4 1 = b-space defined Bit 5 1 = c-space defined Bit 6 0 = base offset defined in header Bit 7 1 = offset to glyph defined. usCellSize 2-byte integer. Indicates the length in bytes of each character definition record (the per character data). Type 1 6 bytes Type 2 6 bytes Type 3 10 bytes. xCellWidth 2-byte integer The width of the characters, in pels for image fonts, and relative units for outline fonts. Type 1 Width of the characters Type 2 Zero Type 3 Zero. yCellHeight 2-byte integer. The height of the characters, in pels for image fonts, and relative units for outline fonts. Type 1 Height of the characters Type 2 Height of the characters Type 3 Height of the characters. xCellIncrement 2-byte integer. The distance along the character baseline required to step from one character to the next (when forming a character string). Type 1 Width of the characters Type 2 Zero Type 3 Zero. xCellA 2-byte signed integer. The width of the space before a character in the inline direction (the a-space). Type 1 Zero Type 2 Zero Type 3 a-space for all characters. xCellB 2-byte integer. The width of a character (inline direction). The b-space. Type 1 Zero Type 2 Zero Type 3 b-space for all characters. xCellC 2-byte signed integer. The width of the space after a character in the inline direction (the c-space). Type 1 Zero Type 2 Zero Type 3 c-space for all characters. pCellBaseOffset 2-byte signed integer. The position of the top of a character definition relative to the baseline in the direction perpendicular to the baseline. Type 1 Baseline offset for all characters Type 2 Baseline offset for all characters Type 3 Baseline offset for all characters. Character Definition Record xCellSize bytes per record. The following fields may or may not be present, according to the font character definition fields flags. If a field is present, it is present for each character and the value applies to that character only. There are usLastChar+2 such records for raster fonts. The final one is for the null character.  Character Definition Offset: 4-byte integer. The offset into the Font File at which the character definition begins. Data for a single character raster or vector should not span two segments; that is, if a character is too big to fit into a segment it should be put in the next segment. This field should be set to zero if the character being defined is a blank character.  Character Cell Width: 2-byte integer. The width of the character definition in pels.  Character Cell Height: 2-byte integer. The height of the character definition in pels.  Character Increment: 2-byte integer. The length along the character baseline required to step from this character to the next (when forming a character string).  Character a-space: 2-byte signed integer. The width of the space before the character in the inline direction.  Character b-space: 2-byte integer. The width of the character shape (inline direction).  Character c-space: 2-byte signed integer. The width of the space after the character in the inline direction.  Character Baseline Offset: 2-byte signed integer. The position of the top of a character definition relative to the baseline in the direction perpendicular to the baseline. Note: Type 1 fonts have offset/width pairs (like type 2); however, the usCellSize and xCellIncrement are nonzero. In the fsType field of the font metrics, the proportional-space flag, bit 0, is set. ═══ 4.3.2.2. Image Data Format ═══ The bits for each character are stored separately, and start on a byte boundary. Sequential bytes represent vertical pieces of the character image. For example, a 15-bit-wide H is stored as follows: Byte Byte ┌──────────┬──────────┐ 1 │ 00000000 │ 0000000- │ 13 Bytes 1 through 12 are composed of 2 │ 01100000 │ 0000110- │ 14 whole bytes of data stored row by row. 3 │ 01100000 │ 0000110- │ 15 4 │ 01100000 │ 0000110- │ 16 Bytes 13 through 24 are composed of 5 │ 01100000 │ 0000110- │ 17 bytes stored row by row, where each byte 6 │ 01111111 │ 1111110- │ 18 contains 7 bits of information and the 7 │ 01111111 │ 1111110- │ 19 last bit is unused. 8 │ 01100000 │ 0000110- │ 20 9 │ 01100000 │ 0000110- │ 21 Thus the character is laid down in 10 │ 01100000 │ 0000110- │ 22 byte-wide columns. 11 │ 01100000 │ 0000110- │ 23 12 │ 00000000 │ 0000000- │ 24 └──────────┴──────────┘ Notes: 1. There is always an additional (null) character defined in an Image Font (defined at character position LastChar+2) which is 8 bits wide, the height of the font character, and set to all zeros. 2. The maximum size of each individual Image Font must not exceed 64KB. ═══ 4.3.3. The Kerning Pair Table ═══ The kerning pair table record is not present if the _KerningPairs record in the metrics is zero. If it is present, the code points are words, not bytes. This table should be sorted by kpChar1 and kpChar2 order to allow binary searches. typedef struct _KERNPAIRTABLE { ULONG ulIdentity; ULONG ulSize; CHAR cFirstpair; }KERNPAIRTABLE; typedef struct _KERNPAIRS { SHORT sFirstChar; SHORT sSecondChar; SHORT sKerningAmount; }KERNINGPAIRS; Where: ulIdentity 3 ulSize 10 sFirstChar First character of the kerning pair. sSecondChar Second character of the kerning pair. sKerningAmount Kerning value. Positive values increase the inter-character spacing while negative values bring the characters closer together. Outline Data Format Fonts defined by outlines (vectors) may contain any of these graphics orders:  Line at given position (GLINE)  Line at current position (GCLINE)  Relative line at given position (GRLINE)  Relative line at current position (GCRLINE)  Fillet at given position (GFLT)  Fillet at current position (GCFLT)  Sharp fillet at given position (GSFLT)  Sharp fillet at current position (GCSFLT)  Bezier curve at given position (GBEZ)  Bezier curve at current position (GCBEZ)  No operation (GNOP1)  Comment (GCOMT)  End of symbol definition (GESD). The maximum length of the data in these orders is 255 bytes. The drawing order code and the length fields are not included in the length count. The size of each outline font definition must not be longer than 64KB. ═══ 4.3.4. Additional Metrics ═══ The additional metrics structure extends the metrics describing the font to include the PANOSE fields. The fields allow for quantitative descriptions of the visual properties of font faces. The format of the ADDITIONALMETRICS structure is: typedef struct { ULONG ulIdentity; ULONG ulSize; PANOSE panose; } ADDITIONALMETRICS; Where: ulIdentity 4 ulSize 20 panose The ten digit PANOSE number with two bytes of padding. The PANOSE definition consists of ten digits, each of which describes one of up to sixteen variations. The current digits are: 1. Family Kind (6 variations) 0 = Any 1 = No Fit 2 = Text and Display 3 = Script 4 = Decorative 5 = Pictorial 2. Serif Style (16 variations) 0 = Any 1 = No Fit 2 = Cove 3 = Obtuse Cove 4 = Square Cove 5 = Obtuse Square Cove 6 = Square 7 = Thin 8 = Bone 9 = Exaggerated 10 = Triangle 11 = Normal Sans 12 = Obtuse Sans 13 = Perp Sans 14 = Flared 15 = Rounded 3. Weight (12 variations) 0 = Any 1 = No Fit 2 = Very Light 3 = Light 4 = Thin 5 = Book 6 = Medium 7 = Demi 8 = Bold 9 = Heavy 10 = Black 11 = Nord 4. Proportion (10 variations) 0 = Any 1 = No Fit 2 = Old Style 3 = Modern 4 = Even Width 5 = Expanded 6 = Condensed 7 = Very Expanded 8 = Very Condensed 9 = Monospaced 5. Contrast (10 variations) 0 = Any 1 = No Fit 2 = None 3 = Very Low 4 = Low 5 = Medium Low 6 = Medium 7 = Medium High 8 = High 9 = Very High 6. Stroke Variation (9 variations) 0 = Any 1 = No Fit 2 = Gradual/Diagonal 3 = Gradual/Transitional 4 = Gradual/Vertical 5 = Gradual/Horizontal 6 = Rapid/Vertical 7 = Rapid/Horizontal 8 = Instant/Vertical 7. Arm Style (12 variations) 0 = Any 1 = No Fit 2 = Straight Arms/Horizontal 3 = Straight Arms/Wedge 4 = Straight Arms/Vertical 5 = Straight Arms/Single Serif 6 = Straight Arms/Double Serif 7 = Non-Straight Arms/Horizontal 8 = Non-Straight Arms/Wedge 9 = Non-Straight Arms/Vertical 10 = Non-Straight Arms/Single Serif 11 = Non-Straight Arms/Double Serif 8. Letterform (16 variations) 0 = Any 1 = No Fit 2 = Normal/Contact 3 = Normal/Weighted 4 = Normal/Boxed 5 = Normal/Flattened 6 = Normal/Rounded 7 = Normal/Off Center 8 = Normal/Square 9 = Oblique/Contact 10 = Oblique/Weighted 11 = Oblique/Boxed 12 = Oblique/Flattened 13 = Oblique/Rounded 14 = Oblique/Off Center 15 = Oblique/Square 9. Midline (14 variations) 0 = Any 1 = No Fit 2 = Standard/Trimmed 3 = Standard/Pointed 4 = Standard/Serifed 5 = High/Trimmed 6 = High/Pointed 7 = High/Serifed 8 = Constant/Trimmed 9 = Constant/Pointed 10 = Constant/Serifed 11 = Low/Trimmed 12 = Low/Pointed 13 = Low/Serifed 10. X-height (8 variations) 0 = Any 1 = No Fit 2 = Constant/Small 3 = Constant/Standard 4 = Constant/Large 5 = Ducking/Small 6 = Ducking/Standard 7 = Ducking/Large When using the PANOSE number to match fonts, the ordering of the PANOSE digit is the key to finding the closest match. The most significant digit is the first digit, and the least significant digit is number ten. To find matches, the digits need to be compared, in the order given. A font mapper may want to change the precedence of the digits, to give higher weightings to other font features. ═══ 4.3.5. Font Directory ═══ This section describes the directory section of a font resource. A font resource contains a directory consisting of a set of structures each containing the metrics of a font and a pointer to the font itself. This font directory is generated by the resource compiler. The format of the font directory is: typedef struct { USHORT usHeaderSize; USHORT usnFonts; USHORT usiMETRICS; FONTENTRY fntEntry[1]; } FONTDIRECTORY; typedef struct { USHORT usIndex; FONTFILEMETRICS metrics; } FONTENTRY; Where: usHeaderSize The size of the header, in bytes. usnFonts The number of fonts in the resource. usiMetrics The size of the FOCAMETRICS structures that follow the header. Note that the set of metrics for all the fonts in the resource follow the header. usIndex The index of a particular font; an identifier assigned to the font when the resource was created (defined in the .RC file). metrics The font metrics structure for the font. This is identical to a FOCAMETRICS structure with the addition of the PANOSE fields to the end. ═══ 4.3.6. Definitions of Terms Used When Describing Fonts ═══ a-space, b-space, c-space - The a-space is the distance from the left of the character frame to the left edge of the character. The b-space is the width of the character. The c-space is the distance from the right edge of the character to the right of the character frame. Negative values of a and c allow adjacent character frames to overlap. See also character increment, and space default values. average char width - The average horizontal distance from the left edge of one character to the left edge of the next. Contrast with max char increment. baseline - The line on which the bottom of a character rests, and below which a descender extends. beak char code point - The code point of the space or break character. Contrast with default char code point, first char code point, and last char code point. character increment - A set of three values (a-space, b-space, and c-space) that define the proportions of a character. The sum of the three values (a+b+c) specifies only one value for the entire character increment. See also font width and space default values. character rotation - The angle by which each character is rotated around its own center, increasing clockwise from vertical. Contrast with character slope and inline direction. character slope - The angle by which a character is slanted, increasing clockwise from vertical. Contrast with character rotation and inline direction. default char code point - The code point of the character to be used if a code point outside the range of a font is passed to an application using that font. Contrast with break char code point, first char code point, and last char code point. em height - The maximum distance above the baseline reached by an uppercase symbol. Contrast with x height. external leading - The vertical distance from the bottom of one character to the top of the character below it. Contrast with internal leading and max baseline extent. first char code point - The code point of the first character. All numbers between the first char code point and the last char code point must represent a character in the font. Contrast with break char code point, default char code point, and last char code point. fixed spacing - The same amount of space separates each character. Contrast with proportional spacing. font weight - The line-thickness of a character relative to its size. Contrast with font width. font width - The relative width of a character to its height; condensed fonts are very narrow while expanded fonts are very wide. See also character increment. Contrast with font weight. inline direction - The angle of a line of type, increasing clockwise from horizontal. Contrast with character rotation and character slope. internal leading - The vertical distance from the top or bottom of a character to any accent marks that may appear with it. Contrast with external leading. last char code point - The code point of the last character. All numbers between the first char code point and the last char code point must represent a character in the font. Contrast with break char code point, default char code point, and first char code point. lowercase ascent - The maximum distance above the baseline reached by any part of any lowercase character. Contrast with maximum ascender and x height. lowercase descent - The maximum distance below the baseline reached by any part of any lowercase character. Contrast with maximum descender. max baseline extent - The maximum space occupied by the font (typically, the sum of the maximum ascender and maximum descender). Contrast with external leading and max char increment. max char increment - The maximum horizontal distance from the left edge of one character to the left edge of the next character to the right. Contrast with average char width and max baseline extent. maximum ascender - The maximum distance that any part of any character may extend above the x height of a font. Contrast with lowercase ascent and maximum descender. maximum descender - The maximum distance that any part of any character may extend below the x height of a font. Contrast with lowercase descent and maximum ascender. maximum vert point size - The maximum vertical dimensions to which a font can be resized. Contrast with minimum vert point size and nominal vert point size. minimum vert point size - The minimum vertical dimensions to which a font can be resized. Contrast with maximum vert point size and nominal vert point size. nominal vert point size - The normal display size of a font. Contrast with maximum vert point size and minimum vert point size. pel - The smallest element of a display surface that can be independently assigned color and density. point - Printer's unit of measurement. There are 72 points to an inch (approximately 3.5 points to a millimeter). proportional spacing - The space that each character occupies is in proportion to its width. See also font width. Contrast with fixed spacing. Registry ID - A code number that Presentation Manager uses to register a font file as a resource. space default values - Values that specify the space to be left between characters. Once defined, they are used for the entire font, and do not have to be specified for each character. However, they can be changed for characters that require more or less spacing than the defaults provide, by giving values for the a Space and the c Space. See also character increment. strikeout position - The distance of the strikeout character above the baseline (in pels). See also strikeout size and underscore position. strikeout size - The size of the strikeout character (in points). See also strikeout position and underscore size. subscript position - The distance of a subscript character of a font below the baseline (in pels). See also subscript size and superscript position. subscript size - The size of a subscript character (in points). See also subscript position and superscript size. superscript position - The distance of a superscript character above the baseline (in pels). See also subscript position and superscript size. superscript size - The size of a superscript character (in points). See also subscript size and superscript position. target dev resolution X - The number of pels per inch in the horizontal axis of a display device on which a font is to be displayed. Contrast with target dev resolution Y. target dev resolution Y - The number of pels per inch in the vertical axis of a display device on which a font is to be displayed. Contrast with target dev resolution X. underscore position - The distance in pels of the first underscore stroke from the baseline of a font. Successive strokes below this create a heavier underscore. See also strikeout position and underscore size. underscore size - The size of the underscore character measured in single strikeout strokes. See also strikeout size and underscore position. x height - The maximum distance above the baseline reached by a lowercase character. Contrast with em height and lowercase ascent. ═══ 5. Graphics Attributes ═══ Every graphics presentation space has a set of graphics attributes. A normal presentation space has a larger set of graphics attributes than a micro or cached micro presentation space. (Segment-related attributes, for example, do not apply in micro presentation spaces.) These attributes all have default values, which means that they always have an effect on graphics, even if you have not explicitly specified their values. The attributes can be broken into two general groups. The first group comprises those attributes that form a part of the picture and that can vary as the picture is drawn. These are:  All primitive attributes  The segment attributes  The primitive tag  The current position  The viewing window  The clipping path  The model and segment transformations  The viewing transformation. With the exception of the segment attributes and the viewing transformation, these attributes are reset to their default values at the start of a root segment, unless the fast-chaining attribute is set. If the fast-chaining attribute is set, their values cannot be guaranteed. You should, therefore, explicitly set any attribute values required in the segment. Similarly, the values of these attributes cannot be guaranteed following a call to: Any GpiDraw... function Any GpiCorrelate... function GpiCallSegmentMatrix GpiCloseSegment Therefore, if any of these functions is followed by primitives outside a segment, you should explicitly set required attribute values. When GpiCloseSegment is followed by GpiOpenSegment (and also between any two segments in the chain), the fast-chaining attribute determines what happens to the current values of these attributes. The viewing transformation and the segment attributes are unaffected by fast-chaining. These attributes take effect when graphics are sent to an output device, not when graphics are defined. For this reason, the calls to GpiQuery... that retrieve the current values of these attributes are invalid in retain mode. The majority of the group-one attribute-setting functions cause graphics orders to be added to the current segment. The second group of attributes defines the environment in which the picture is drawn. These attributes do not normally vary as the picture is drawn, but have an overall effect on the result of any drawing or correlation operation. This group includes:  The default viewing transformation  The page viewport  The graphics field  The clipping region  The pick-aperture size  The drawing controls. The functions to GpiQuery... that retrieve the current values of these attribute are valid in all drawing modes. None of the group-two attribute-setting functions causes graphics orders to be added to the current segment. The following table lists the graphics attributes, identifies the GPI function or functions that you use to change current settings, and lists the default value of each one. Note that these default values are the initial settings. The table also indicates whether the attribute is a group-one or a group-two attribute. ┌──────────────┬──────────────────────────────┬─────────────────────────────┬─────┬─────┐ │Graphics │GPI Function │Default Value │Group│Group│ │Attribute │ │ │One │Two │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Arc parameters│GpiSetArcParams │(1,1,0,0) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Foreground │GpiSetColor(1) │CLR_DEFAULT │Yes │ │ │color │ │(device-dependent) │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Foreground mix│GpiSetMix(1) │FM_DEFAULT (overpaint) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Background │GpiSetBackColor(1) │CLR_DEFAULT │Yes │ │ │color │ │(device-dependent) │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Background mix│GpiSetBackMix(1) │BM_DEFAULT (leave-alone) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character │GpiSetCharAngle(1) │(1,0) │Yes │ │ │angle │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character box │GpiSetCharBox(1) │Device-dependent │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character │GpiSetCharDirection(1) │CHDIRN_DEFAULT (left to │Yes │ │ │Direction │ │right) │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character mode│GpiSetCharMode(1) │CM_DEFAULT (mode 1) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character set │GpiSetCharSet(1) │LCID_DEFAULT (system font) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Character │GpiSetCharShear(1) │(0,1) │Yes │ │ │shear │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Line end │GpiSetLineEnd(1) │LINEEND_DEFAULT (flat) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Line join │GpiSetLineJoin(1) │LINEJOIN_DEFAULT (beveled) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Line type │GpiSetLineType(1) │LINETYPE_DEFAULT (solid) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Line width │GpiSetLineWidth(1) │LINEWIDTH_DEFAULT (1.0) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Geometric line│GpiSetLineWidthGeom(1) │1 │Yes │ │ │width │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Marker │GpiSetMarker(1) │MARKSYM_DEFAULT (cross) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Marker box │GpiSetMarkerBox(1) │Device-dependent │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Marker set │GpiSetMarkerSet(1) │LCID_DEFAULT (system marker │Yes │ │ │ │ │set) │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Pattern │GpiSetPattern(1) │PATSYM_DEFAULT (solid) │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Pattern │GpiSetPatternRefPoint(1) │(0,0) │Yes │ │ │reference │ │ │ │ │ │point │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Pattern set │GpiSetPatternSet(1) │LCID_DEFAULT (system pattern │Yes │ │ │ │ │set) │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Model │GpiSetModelTransformMatrix │Identity │Yes │ │ │transformation│ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Instance │GpiCallSegmentMatrix │Identity │Yes │ │ │transformation│ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Segment │GpiSetSegmentTransformMatrix │Identity │Yes │ │ │transformation│ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Viewing │GpiSetViewingTransformMatrix │Identity │Yes │ │ │transformation│ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Default │GpiSetDefaultViewMatrix │Identity │ │Yes │ │viewing │ │ │ │ │ │transformation│ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Page viewport │GpiSetPageViewport │Device-dependent │ │Yes │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Clipping path │GpiSetClipPath │No clipping │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Viewing window│GpiSetViewingLimits │No clipping │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Graphics field│GpiSetGraphicsField │No clipping │ │Yes │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Clipping │GpiSetClipRegion │No clipping │ │Yes │ │region │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Tag │GpiSetTag │0 │Yes │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Segment │GpiSetInitialSegmentAttrs │ATTR_DETECTABLE - OFF │Yes │ │ │attributes │GpiSetSegmentAttrs │ATTR_VISIBLE - ON │ │ │ │ │ │ATTR_CHAINED - ON │ │ │ │ │ │ATTR_DYNAMIC - OFF │ │ │ │ │ │ATTR_FASTCHAIN - ON │ │ │ │ │ │ATTR_PROP_DETECTABLE - ON │ │ │ │ │ │ATTR_PROP_VISIBLE - ON │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Pick-aperture │GpiSetPickAperturePosition │Device-dependent │ │Yes │ │size │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Current │GpiSetCurrentPosition GpiMove¤│(0,0) │Yes │ │ │position │ │ │ │ │ ├──────────────┼──────────────────────────────┼─────────────────────────────┼─────┼─────┤ │Drawing │GpiSetDrawControl │DCTL_ERASE - OFF │ │Yes │ │controls │ │DCTL_DISPLAY - ON │ │ │ │ │ │DCTL_BOUNDARY - OFF │ │ │ │ │ │DCTL_DYNAMIC - OFF │ │ │ │ │ │DCTL_CORRELATE - OFF │ │ │ └──────────────┴──────────────────────────────┴─────────────────────────────┴─────┴─────┘ Notes: (1). Can also be set using GpiSetAttrs. (2). Is also updated indirectly by most primitive-drawing functions. Each of the following functions causes all group-one and group-two graphics attributes to be set to their default values:  GpiCreatePS  GpiSetPS  GpiResetPS, if GRES_ALL or GRES_SEGMENTS is specified  WinGetPS  WinGetScreenPS  WinBeginPaint, with a NULL presentation space handle. In specific circumstances, some of the GPI functions modify the group-one attributes and thus make their values unpredictable. Therefore, when you call any of these functions, you should respecify attribute values that have a particular importance to your application. For example, if the current foreground color is CLR_RED before you call GpiDrawChain you cannot always rely on the current color remaining CLR_RED when GpiDrawChain completes. If you want to continue working in red, respecify the color when GpiDrawChain completes. In general, the functions that affect group-one-attribute values are those related to the drawing and correlation of retained graphics, and to the creation, closing, and deletion of graphics segments. With the exception of the viewing transformation and the segment attributes, the default values of these attributes apply to all primitive-drawing that occurs outside a segment bracket.  The following function sets the group-one attributes to their default values, and in addition sets the current clipping region and page viewport to their default values. - GpiAssociate.  Each of the following functions makes the group-one-attribute values unpredictable: - GpiCloseSegment - GpiCorrelateChain - GpiCorrelateFrom - GpiCorrelateSegment - GpiErase - GpiCallSegmentMatrix - GpiDrawDynamics - GpiRemoveDynamics. Note: In the last two functions here, the foreground-mix value is always set to FM_XOR, and the background-mix value is always set to BM_LEAVEALONE.  Each of the following functions makes group-one-attribute values unpredictable if a segment to be deleted is open when the function is called: - GpiDeleteSegments - GpiDeleteSegment  Each of the following functions makes group-one-attribute values unpredictable if there is no open segment when the function is called: - GpiDrawChain - GpiDrawFrom - GpiDrawSegment. If there is an open segment when any of these functions is called, and that segment was the last one drawn, then group-one-attribute values are unaffected. If, however, dynamic segments were caused to be redrawn by the same function, group-one-attribute values are made unpredictable. This occurs because dynamic segments are always drawn after nondynamic segments. ═══ 6. Line and Arc Primitives ═══ Line and arc primitives are graphics building blocks for creating pictures that consist of objects such as polygons, circles, fillets, ellipses, and other geometric figures. The following topics are related to information in this chapter:  Presentation spaces and device contexts  Color and mix attributes  Area primitives ═══ 6.1. About Line and Arc Primitives ═══ Simple drawing applications use line and arc primitives as drawing tools. They are useful, for example, in spreadsheet applications for constructing pie charts, bar charts, and graphs. Sample Pie Chart Created with Line and Arc Primitives Following are more illustrations that were drawn using line and arc primitives. Sample Bar Graph Created with Line and Arc Primitives Computer-aided-design (CAD) applications combine line and arc primitives to draw such complex pictures as schematic diagrams for electrical wiring, blueprints for building sites, and cross-sectional views of machinery. Sample Blueprint Created with Line and Arc Primitives Line and arc primitives are actually two families of primitives that contain many variations of straight lines and curved lines, respectively. They are presented together in this chapter because all the variations are governed by the attributes found in the data structure LINEBUNDLE. An application draws the line and arc primitives by first calling GpiMove or GpiSetCurrentPosition, either of which sets the current position to a specified starting point. GpiMove ignores the AM_PRESERVE mode, whereas GpiSetCurrentPosition saves the current position if the AM_PRESERVE mode is set. The more sophisticated function, GpiPolyLineDisjoint, contains its own starting point and does not need to be preceded by GpiMove, or GpiSetCurrentPosition. Prior to calling a line or arc function, the current position can be determined with GpiQueryCurrentPosition. ═══ 6.1.1. Attributes of Line and Arc Primitives ═══ The attributes of the line and arc primitives contained in LINEBUNDLE are:  Line width  Geometric width  Line type  Line end  Line join  Line color  Line mix The line end and line join attributes apply only to lines drawn in a primitive called a path. When an application creates a presentation space, the line and arc attributes are set to the default values shown in the following table. Line Attribute Default Values ┌───────────────┬──────────────┬───────────────────────────────┐ │Attribute │Default Value │Function that Redefines │ │ │ │Attribute │ ├───────────────┼──────────────┼───────────────────────────────┤ │Width │1.0 │GpiSetLineWidth │ ├───────────────┼──────────────┼───────────────────────────────┤ │Geometric width│None │GpiSetLineWidthGeom │ ├───────────────┼──────────────┼───────────────────────────────┤ │Type │LINETYPE_SOLID│GpiSetLineType │ ├───────────────┼──────────────┼───────────────────────────────┤ │Color │CLR_NEUTRAL │GpiSetAttrs (LBB_COLOR) │ ├───────────────┼──────────────┼───────────────────────────────┤ │Mix attribute │FM_OVERPAINT │GpiSetAttrs (LBB_MIX_MODE) │ └───────────────┴──────────────┴───────────────────────────────┘ ═══ 6.1.2. Line Width and Geometric Width ═══ The operating system defines two types of lines: cosmetic and geometric, representing two separate concepts. Cosmetic lines represent the mathematical ideal of a line being an entity with only one dimension-length. When cosmetic lines are drawn, they usually are only one pel wide. The line width attribute provides a visual method of distinguishing different types of lines. For example, on a map, roads might be drawn thicker than railroad tracks. The line width attribute defines a multiplier to be applied to the normal (or default) line width. Your application can determine the cosmetic line width by calling GpiQueryLineWidth. There are certain devices that do not define the thickness of cosmetic lines in terms of a number of pels. The PM interface interprets the specified width for these devices as shown in the following table: ┌────────────────────┬────────────────────────────────────────┐ │Identifer │Description │ ├────────────────────┼────────────────────────────────────────┤ │LINEWIDTH_DEFAULT │The default width for the device. │ ├────────────────────┼────────────────────────────────────────┤ │LINEWIDTH_NORMAL │The line width equivalent to a │ │ │multiplier of 1. Identical to │ │ │LINEWIDTH_DEFAULT unless changed with │ │ │GpiSetDefAttrs. │ ├────────────────────┼────────────────────────────────────────┤ │LINEWIDTH_THICK │The line width equivalent to a │ │ │multiplier greater than 1. │ └────────────────────┴────────────────────────────────────────┘ Your application can set the cosmetic line width with either a multiplier or an identifier value using GpiSetLineWidth. Since the line represents a widthless ideal, the actual drawn width is a fixed value. The line width remains unchanged when you increase the size of, or zoom in on, a graphics object. The cosmetic line width is not subject to transformations. In contrast, geometric lines represent an area whose thickness is equal to the specified line width. Geometric lines are subject to changes in scale through transformations, in the same manner as geometric figures. The width of a geometric line does not have a default value. Width is treated as a line attribute for programming convenience, but it actually is a geometric property. A line width is set with GpiSetLineWidthGeom. If a width is already specified, that width can be determined with GpiQueryLineWidthGeom. To use geometric line width, the lines are assembled into a path. When you use a path to define wide lines, you can specify the following:  Geometric width for the lines, using the geometric line width attribute  Style of the line ends, using the line end attribute  Style of the junctions of the lines, using the line join attribute These three attributes apply only to geometric lines drawn using paths. ═══ 6.1.3. Line Types ═══ Line type, also called line style, defines the way a line or arc is drawn: as a solid line, a series of dashes, a series of dots, or a combination of dashes and dots. The line type for all subsequent line primitives is selected using GpiSetLineType. If you want to change the line type to LINETYPE_DOT, for example, any line or arc primitive subsequently drawn is drawn as a dotted line. The following table illustrates the nine standard line types provided by PM. You cannot define other line types for PM applications. Standard Line Types ┌────────────────────────┬────────────────────────┬────────────┐ │Type │Identifer │Long Value │ ├────────────────────────┼────────────────────────┼────────────┤ │Dotted line │LINETYPE_DOT │1L │ ├────────────────────────┼────────────────────────┼────────────┤ │Short-dashed line │LINETYPE_SHORTDASH │2L │ ├────────────────────────┼────────────────────────┼────────────┤ │Dash-dot line │LINETYPE_DASHDOT │3L │ ├────────────────────────┼────────────────────────┼────────────┤ │Double-dotted line │LINETYPE_DOUBLEDOT │4L │ ├────────────────────────┼────────────────────────┼────────────┤ │Long-dashed line │LINETYPE_LONGDASH │5L │ ├────────────────────────┼────────────────────────┼────────────┤ │Dash-double-dot line │LINETYPE_DASHDOUBLEDOT │6L │ ├────────────────────────┼────────────────────────┼────────────┤ │Solid line │LINETYPE_SOLID │7L │ ├────────────────────────┼────────────────────────┼────────────┤ │Invisible line │LINETYPE_INVISIBLE │8L │ ├────────────────────────┼────────────────────────┼────────────┤ │Alternate pels on │LINETYPE_ALTERNATE │9L │ └────────────────────────┴────────────────────────┴────────────┘ The default line type (LINETYPE_DEFAULT) is identical to the LINETYPE_SOLID type, and has a long value of 0L. The error line type (LINETYPE_ERROR) has a long value of -1L. The following figure illustrates the nine line types. Your application can determine the current line type using GpiQueryLineType. The Nine Line Types ═══ 6.1.4. Line Color and Mix Attributes ═══ The color attribute defines the color used to draw a primitive or an object. The mix attribute determines how the color of a primitive or an object is combined with the color of the drawing surface, or any other objects on the surface. The line color defines the color used to draw the output from any of the operating system's line functions. When a presentation space is created, the line color initial default is black. Unlike certain other primitives, the line and arc primitives do not have a background color. The current color of the drawing surface automatically plays a greater role in the appearance of line and arc primitives than in those primitives that do have a background color. Specifically, when an application draws a dotted or dashed line, the color that appears between the dots or dashes is the current drawing-surface color, as shown in the following figure. Line and arc primitives have only a color attribute for the actual line. The mix attribute controls the combination of line color with drawing surface color. Line and Arc Primitives When a presentation space is created, the line mix attribute initial default is FM_OVERPAINT. The overpaint mix attribute specifies that the line color is not modified by the color of the drawing surface. If the line mix attribute is changed, the line color is mixed with colors that are already on the drawing surface. To specify a new color or mix attribute use GpiSetAttrs. This function accepts as input the type of primitive, for example PRIM_LINE, a list of attributes that are to be changed, a list of attributes that are to be set to their default values, and the values for the attributes that are to be changed. GpiSetAttrs is useful for specifying colors and mix attributes just for a specific data structure (for example, the LINEBUNDLE structure). GpiSetAttrs also provides some protection against invalid colors. To determine the current line color and mix attribute, use GpiQueryAttrs. This function accepts as input the primitive type and the attributes in question. It returns as output an array of values for the specifically queried attributes. To reset the default line color and mix attribute, just as with any other attribute specified in the LINEBUNDLE data structure, use GpiSetDefAttrs. This function accepts as input the type of primitive, for example PRIM_LINE, the attributes to be changed, and the values that will become the new default values. The changing of default values is important when working with segments. Changing the default values during a series of drawing functions is not recommended. The line color and mix attribute also can be specified with GpiSetColor and GpiSetMix, respectively. However, those two functions have the disadvantage of specifying the color and mix attribute for all primitive BUNDLE data structures that have a component for foreground color and foreground mix attribute. The queries, GpiQueryColor and GpiQueryMix, determine the color and mix attribute as specified by GpiSetColor and GpiSetMix. If the line color or mix attribute is specified individually, the aforementioned queries can return a value inconsistent with the current line color or mix attribute. ═══ 6.1.5. Line Primitive Family ═══ The following table describes the three variants of the basic line primitive and the functions that draw them. Functions that Draw Straight Lines ┌────────────┬────────────────────────┬──────────────────────────────────┐ │Variants │Function │Description │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │Lines │GpiLine │Draws a single line from the │ │ │ │current position to a specified │ │ │ │point. │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │Polylines │GpiPolyLine │Draws a series of connected lines,│ │ │ │from the current position through │ │ │ │successive points. │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │(series of │GpiPolyLineDisjoint │Draws a series of unconnected │ │lines) │ │lines. │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │Boxes │GpiBox │Draws a rectangular box with one │ │ │ │corner at the current position. │ └────────────┴────────────────────────┴──────────────────────────────────┘ When the operating system draws a line, it includes the pels at the starting and ending points of the line. The algorithm used to draw the rest of the line depends on the device driver. For example, a driver for a raster device might use a modified Bresenham algorithm to draw a line, but a driver for a vector device, such as a plotter, simply would connect the starting and ending points of the line. In all cases, the result is a line primitive that looks the same from device to device. ═══ 6.1.5.1. Lines ═══ GpiLine draws a line from the current position to a specified end point, as shown in the following figure. After drawing the line, the current position is at the end point specified by GpiLine. GpiLine The current position is (4,3), and the specified end point of GpiLine is (9,7). When the line has been drawn, (9,7) becomes the current position. To draw a single point, you can use GpiLine with an end point identical to the current position, as shown in the following figure. The current position can be determined using GpiQueryCurrentPosition. GpiLine Used to Draw a Single Point ═══ 6.1.5.2. Polylines ═══ GpiPolyLine draws a sequence of connected lines, starting at the current position and passing through a series of specified coordinate positions, as shown in the following figure. After drawing the series of lines, the current position is at the end point of the last line specified by GpiPolyLine. If you are drawing a graph that has five connected lines, you can use GpiPolyLine once rather than GpiLine five times. GpiPolyLine accepts as input a number of points and an array of point coordinates. GpiPolyLine The starting position is (2,2), and the polyline is drawn through (4,4), (6,4), (8,6), and (10,3). The new current position is (10,3). GpiPolyLineDisjoint is a new function that eliminates having to use a series of GpiMove and GpiLine functions to draw multiple lines that are not connected. GpiPolyLineDisjoint accepts as input an even number, the number of points, and an array of point coordinates. The first point in a point-pair is the starting point; the second, the end point of that line segment. Upon completion, the end point of the final line becomes the current position. The following figure shows the results of a GpiPolyLineDisjoint call. GpiPolyLineDisjoint A graph with discontinuities. ═══ 6.1.5.3. Boxes ═══ At its simplest, GpiBox draws a rectangular box with one corner at the current position and the diagonally-opposite corner at a position that you specify. The sides of the box are parallel to the x- and y-axes. Like GpiPolyLine, GpiBox lets you draw a number of connected lines using a single function rather than four separate GpiLine, functions. The current position is unchanged by GpiBox. Note: The start and end position of any closed shape are always the same. Therefore the current position is unchanged after drawing a closed figure. The GpiBox primitive is shown in the following figure. The Box The current position is (3,2) and the corner position is at (8,6). When the box has been drawn, the current position remains at (3,2). In addition to the corner position, GpiBox accepts as input an option for rounded corners and for filled interior. The PM programming interface rounds the corners of a box by drawing an elliptical section in place of the square corner. Two GpiBox parameters, IHRound and IVRound, represent the horizontal and vertical length of the full axis of the ellipse used to round each corner. If the two values are equal, a quarter-circle is used for the rounding. If the two values are 0, no rounding is performed. The following figure shows an example of rounding corners using a quarter-circle. Quarter-Circle Box-Corner Rounding The current position is (20,20). GpiBox is called with a corner position of (65,60) and an identical vertical and horizontal rounding value of 26. The following figure shows the complete result. The intermediate steps are not visible to the user of your application. Box with Rounded Corners All four corners are rounded with identical values. Since GpiBox can be used to define a closed figure, it also accepts as input a long value signifying a filled interior. The long value lControl can be any of the following: Value Description DRO_OUTLINE Draw the box only. DRO_FILL Fill the box interior only. DRO_OUTLINEFILL Draw the box and fill its interior. The pattern that fills the interior and other drawing options are controlled by the data structure AREABUNDLE. GpiFullArc is the only other line and arc primitive that can be used to define a closed figure. ═══ 6.1.6. Attributes of Arc Primitives ═══ The arc primitive shares width, type, and color and mix attributes with line primitives. For example, if you use GpiSetLineType to change the line type to LINETYPE_DASHDOT, all subsequent arcs are drawn with a dash-dot line. In addition to the line attributes defined in the LINEBUNDLE data structure, arc primitives in the simple-arc family are influenced by the values in the ARCPARAMS data structure. Arc primitives in the multiple-arc family have a different method of construction and are not influenced by ARCPARAMS. In terms of geometrical pictures, the simple arcs contain full or partial: Circles Closed curves whose center is equidistant from every point on the curve. Ellipses Closed curves defined by two fixed points such that the sum of the distances from any point on the curve to the two fixed points is constant. Multiple arcs contain: Fillets Curves that are tangential to the two lines defined by three control points. Splines Curves that, given four control points, are tangent to the first and last of three intersecting lines. There are three simple arc operations that begin with a unit circle that lies at the origin of world coordinate space. This unit circle defines the current arc on which subsequent full, partial, and 3-point arcs are based. Your application can define the following attributes of the current arc with GpiSetArcParams:  Shape  Orientation  Size  Drawing direction GpiSetArcParams accepts as input an ARCPARAMS data structure that has four parameters (p, q, r, and s). Of the four:  p scales in the x-direction  q scales in the y-direction  r and s are shear components The mathematical origins of the parameters are illustrated in the following figure. The ARCPARAMS Values in World Coordinates The values were derived from the major and minor axis of an ellipse. An application can determine the current arc parameters with GpiSetDefArcParams which copies the current arc parameters to their corresponding fields in the supplied ARCPARAMS structure. The application can set the arc parameters with GpiSetArcParams. This function accepts as input a copy of the ARCPARAMS structure that contains the new arc parameters. The default values of p, q, r, and s, unless changed by GpiSetArcParams, define a unit circle:  p and q are 1  r and s are 0. The arc parameters define a transformation that is applied to each point on the perimeter of the unit circle. For any point (x,y) on the perimeter of the unit circle, there exists a new point (x',y'), as determined by the following two linear equations: x' = p x x + r x y y' = s x x + q x y These parameters form a 2-by-2 matrix, ┌ ┐ │ p r │ │ s q │ └ ┘ that scales and shears simple arcs. This transformation matrix is not related to the general transformation functions that move objects through coordinate spaces. It is a special purpose matrix that transforms the shape and size of the imaginary unit circle. The transformed unit circle, also called the current arc, is then used to define the shape and size of the simple arc functions in world coordinates. After an arc has been described in world coordinates, it can be transformed with the transformation functions, just as any other primitive can. A transformation is orthogonal when: (p x r) + (s x q) = 0 If orthogonal, the line from the origin (0,0) to the point (p,s) is either:  The radius of a circle  Half the major or minor axis of an ellipse; and, the line from the origin to the point (r,q) is either:  The radius of a circle  Half the minor or major axis of an ellipse. An orthogonal transformation does not guarantee that the shape of an object as defined by an application will be the same as the shape of the object on the output device. For example, if the page units in the application are PU_PELS, and the pels on the device are rectangular (but not square), calling GpiFullArc produces an ellipse-not a circle- even when the arc parameters are set to their default values. The product of the 2-by-2 matrix multiplication influences the direction of any arc based on the current arc, except a 3-point arc. The following table illustrates this directional influence. ┌──────────────────────────────┬──────────────────────────────┐ │If... │GpiFullArc and GpiPartialArc │ │ │... │ ├──────────────────────────────┼──────────────────────────────┤ │(p x q) is greater than (r x │Draw the ellipse │ │s) │counterclockwise. │ ├──────────────────────────────┼──────────────────────────────┤ │(p x q) is less than (r x s) │Draw the ellipse clockwise. │ ├──────────────────────────────┼──────────────────────────────┤ │(p x q) equals (r x s) │Draw a straight line rather │ │ │than an ellipse. │ └──────────────────────────────┴──────────────────────────────┘ ═══ 6.1.7. Simple-Arc Primitive Family ═══ The following table describes the three variants of a simple-arc primitive and the functions that draw them. All are defined, to some extent, by the current arc parameters. As with line primitives, an application draws simple-arcs by first using GpiMove or GpiSetCurrentPosition to set the current position. Functions that Draw Simple Arcs ┌────────────┬──────────────┬──────────────────────────────────┐ │Variants │Function │Description │ ├────────────┼──────────────┼──────────────────────────────────┤ │Full arcs │GpiFullArc │Draws a circle or an ellipse. │ ├────────────┼──────────────┼──────────────────────────────────┤ │Partial arcs│GpiPartialArc │Draws a straight line followed by │ │ │ │a section of a circle or ellipse. │ ├────────────┼──────────────┼──────────────────────────────────┤ │3-point arcs│GpiPointArc │Draws an arc through three points.│ └────────────┴──────────────┴──────────────────────────────────┘ ═══ 6.1.7.1. Full Arcs ═══ GpiFullArc draws a complete circle or ellipse with its center at the current position. The current position remains unchanged. Whether GpiFullArc draws a circle or an ellipse depends on the current arc parameters. When the current arc is a circle, GpiFullArc draws a circle; when it is an ellipse, GpiFullArc draws an ellipse. ═══ 6.1.7.1.1. Defining an Ellipse ═══ To define an ellipse as the current arc, use GpiSetArcParams where the values (p,s) and (r,q) are the world coordinates of the end points of the major and minor axes of the ellipse. For example, current arc parameters of (18,0) and (0,10) define an ellipse with a major axis of 36 coordinate units and a minor axis of 20 coordinate units. The resultant ellipse is shown in the following figure. The Ellipse For maximum accuracy, create the axes of an ellipse so that they are at right-angles to each other. You can check this by ensuring that the following equation is always true: p x r + s x q = 0 So, to check the above example: 0 x 18 + 10 x 0 = 0 You also can define a tilted ellipse as the current arc. None of the current arc parameters for a tilted ellipse will be 0, though you should still ensure that the axes of the ellipse are at right-angles to each other. The following figure shows a tilted ellipse defined with current arc parameters of (8,6) and (-3,4). Tilted Ellipse ═══ 6.1.7.1.2. Defining a Circle ═══ To define a circle as the current arc, (r,q) and (p,s) can be any such value that they lie on a circle. For example, if (r,q) and (p,s) are set to (-4, 3) (3,4), the current arc is a circle with a radius of 5 coordinate units. For simplicity, a circle can be defined by specifying current arc parameters where p is the radius of the circle, and p = q, r = 0, and s = 0. For example, to define a circle centered on the origin and with a radius of 10 world-coordinate units, use GpiSetArcParams with the values (0,10) (10,0). The default values of the current arc parameters are (0,1) (1,0), which define a circle with a radius of one world-coordinate unit (a unit circle). GpiFullArc Input Parameters GpiFullArc accepts as input a multiplier value, so that the size of the full arc is increased or decreased in relation to the current arc. For example, if the current arc parameters define an ellipse whose major axis is 20 coordinate units and whose minor axis is 8 coordinate units, a multiplier of 2 in GpiFullArc creates an ellipse whose major axis is 40 coordinate units and whose minor axis is 16 coordinate units. Because the arc parameters are integers when a fraction is required, for example when rotating an ellipse, greater precision can be obtained by scaling up the required arc parameter values as much as possible, then using a multiplier smaller than 1 to scale the ellipse back down to the required size. With the default arc parameters defining a circle of 1 world coordinate unit, you can draw a circle of any size by allowing the arc parameters to default, then specifying the radius of the circle with the GpiFullArc multiplier. For example, to draw a circle with a radius of 12 coordinate units, call GpiFullArc with a multiplier of 12 and allow the GpiSetArcParams to default. Since GpiFullArc, like GpiBox, can be used to define a closed figure, it also accepts as input a long value signifying a filled interior. The long value, IControl, can be: Value Description DRO_OUTLINE Draw the arc only. DRO_FILL Fill the arc interior only. DRO_OUTLINEFILL Draw the arc and fill its interior. The pattern that fills the interior and other drawing options are controlled by the data structure AREABUNDLE. See Area and Polygon Primitives for detailed information on using areas. The Full Arc (a) is a tilted ellipse that is defined by the current arc parameters. (b) is drawn using GpiFullArc with:  A multiplier value that reduces the size of the arc relative to the current arc  An IControl value filling the interior with the current area-fill pattern, but not drawing the arc's outline. ═══ 6.1.7.2. Partial Arcs ═══ A partial arc is a section of a full arc defined by the current arc parameters. To draw a partial arc, use GpiPartialArc, which draws two separate figures. The first figure is a straight line from the current position to the starting point of a partial arc, and the second figure is the partial arc itself. When the arc has been drawn, the new current position is at the end point of the partial arc. GpiPartialArc accepts as input the center of the current full arc, of which the partial arc is a part, specified in world coordinates. You also can specify a multiplier value to increase or decrease the size of the partial arc in relation to the current full arc. You also must specify two positive fixed values: a start angle and a sweep angle. If the current full arc is a circle, the start angle is measured counterclockwise from the x-axis of the circle. The intersection of the start angle with the full arc, adjusted by the multiplier value, defines the starting point of the partial arc. The sweep angle continues the counterclockwise measurement, beginning where the start angle left off. The intersection of the sweep angle with the full arc, adjusted by the multiplier value, defines the partial arc. If the current arc is not a circle, the start and sweep angle are skewed to the same degree that the ellipse is a skewed circle. The following figure shows how the partial arc is constructed. The Partial Arc A is the start angle; B, the sweep angle. C is the center point; D, the current position. Arc.EF is the partial arc. F is the new current position. The inner circle in the previous figure is the arc defined by the current arc parameters. A multiplier has been specified with GpiPartialArc, so the partial arc is based on the full arc described by the outer circle. Point C is the center point specified on GpiPartialArc. Angle A is the start angle, and angle B is the sweep angle. GpiPartialArc therefore, draws a line from the current position (point D) to the start of the partial arc (point E). It also draws arc EF. Point F is the new current position. The arc is drawn counterclockwise because the current arc parameters define a counterclockwise circle. You can join points F and D with GpiLine. This line is drawn automatically if you define the partial arc within a GpiBeginArea and GpiEndArea bracket. ═══ 6.1.7.3. 3-Point Arcs ═══ GpiPointArc draws an arc from the current position through an intermediate point to an end point. When the arc is drawn, the current position is at the end point of the arc. You specify both the intermediate point and the end point, and these values determine both the size of the arc and the direction in which it is drawn. The shape and the orientation of a 3-point arc are determined by the current arc parameters. The following figure shows how a 3-point arc is constructed. The 3-Point Arc If the current arc parameters define an ellipse, that ellipse is scaled up or down to fit the three points of the arc. When you want the three points of the arc to be points on a circle, allow the current arc parameters to default so they define a unit circle. You do not need to use the values p and q to specify the radius of the circle, because the radius is determined by the relative positions of the three points of the arc. ═══ 6.1.8. Multiple-Arc Primitive Family ═══ The following table describes the three variants of the simple-arc primitive and the functions that draw them. As with line primitives, an application draws simple arcs by first using GpiMove or GpiSetCurrentPosition to set the current position. The multiple arcs are the most sophisticated of the arc primitives and their construction does not depend on the current arc parameters. Functions that Draw Multiple Arcs ┌────────────┬────────────────────────┬──────────────────────────────────┐ │Variants │Function │Description │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │Fillets │GpiPolyFillet │Draws one or more fillets. │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │ │GpiPolyFilletSharp │Draws one or more fillets with │ │ │ │varying degrees of sharpness. │ ├────────────┼────────────────────────┼──────────────────────────────────┤ │Splines │GpiPolySpline │Draws one or more splines. │ └────────────┴────────────────────────┴──────────────────────────────────┘ ═══ 6.1.8.1. Fillets ═══ GpiPolyFillet constructs a fillet (a curved line) made up of one or more arcs, each of which touches a different straight line. You specify the end points of these straight lines with GpiPolyFillet. The lines are not drawn but are used to construct the curve. The fillet starts at the current position and finishes at the end point of the last line. On the way from the start point to the end point, the fillet is tangential to all intermediate lines at their midpoints. When the fillet is drawn, the current position is at the end point of the last construction line. The following figure is an example of how a fillet is constructed. The Fillet The fillet starts at (2,6) and ends at (5,1). The fillet is tangential to the midpoints of the lines from (2,8) to (6,9), from (6,9) to (9,5), and from (9,5) to (5,3). When you supply only two points, the construction lines of the fillet are drawn from the current position to the first point, and from the first point to the second point. The fillet is drawn from the current position to the second point, and is tangential to the construction lines at those same points. GpiPolyFilletSharp creates a fillet on a series of connected construction lines. The first fillet in the series is built using two construction lines: one drawn from the current position to point 1 (the control point), and one drawn from point 1 to point 2 (the end point). The fillet is drawn from the current position to the end point, and is tangential to the two construction lines at those points. GpiPolyFilletSharp also accepts as input a sharpness value. Sharpness is a measure of the distance between the fillet and the control point. It is calculated as shown in the following figure. Fillet with Sharpness Specified Point A is the current position, point B is the control point, and point C is the end point. W is the midpoint of the notional line AC. D is the point at which the fillet crosses the notional line WB. The sharpness of the fillet is the value WD / DB. The line WD is 10 coordinate units, and the line DB is 5 coordinate units; therefore the sharpness value is 2. The sharpness value defines the type of arc. This is shown in the following table. ┌──────────────────────────────┬──────────────────────────────┐ │A sharpness value of... │Defines... │ ├──────────────────────────────┼──────────────────────────────┤ │Greater than 1.0 │A hyperbola │ ├──────────────────────────────┼──────────────────────────────┤ │Equal to 1.0 │A parabola │ ├──────────────────────────────┼──────────────────────────────┤ │Less than 1.0 │An ellipse │ └──────────────────────────────┴──────────────────────────────┘ Subsequent fillets start from the end point of the previous fillet, and are constructed using the next two lines in the sequence in exactly the same way. For each fillet you define one control point, one end point, and one sharpness value. Upon completion, the current position is at the end point of the final construction line in the sequence. There might be discontinuity of gradient between multiple fillets drawn with GpiPolyFilletSharp. To avoid this, ensure that points B and C of one fillet are on the same construction line as points A and B of the next fillet in the sequence. This concept is illustrated in connection with the spline primitive in the figure that follows the next figure. Discontinuity of gradient between fillets does not occur when the fillets are drawn with GpiPolyFillet. ═══ 6.1.8.2. Splines ═══ GpiPolySpline creates a succession of one or more Bezier splines. The spline also is a curve, but its construction method is different from that of the fillet. As input to this function, you supply three construction points for each spline. The first spline starts from the current position and ends at the third specified point. The two intermediate points are control points for the curve. Subsequent splines start at the end point of the previous spline, have two intermediary control points, and end at the third control point. The following figure shows the construction method for the spline. The Spline Points (1) and (2) are the control points of the spline, and point (3) is the end point. To avoid discontinuity of gradient between the end of one spline and the start of the next, ensure that the last two construction points of the first spline and the first two construction points of the second spline are positioned along a single construction line. This concept is shown in the following figure. Spline with No Discontinuity of Gradient The last two points of the first spline (points 2 and 3) are positioned along the same construction line as the first two points (current position and point 1) of the second spline. ═══ 6.2. Using Line and Arc Primitives ═══ This section explains how to:  Draw a straight line  Create a "rubber-banding" effect with straight lines or arcs  Draw a circle, ellipse, fillet, or spline ═══ 6.2.1. Drawing a Straight Line ═══ To draw a straight line, set the current position with GpiMove or GpiSetCurrentPosition. Set the end point of the line by filling in a POINTL structure, then draw the line with GpiLine. The following figure shows how to draw a straight line in a PM application. #include BOOL DrawLine(HPS hps, LONG xStart, LONG yStart, LONG xEnd, LONG yEnd){ POINTL ptl; /* Point structure */ ptl.x = xStart; /* Loads starting x-coordinate */ ptl.y = yStart; /* Loads starting y-coordinate */ GpiMove(hps, &ptl); /* Sets current position */ ptl.x = xEnd; /* Loads ending x-coordinate */ ptl.y = yEnd; /* Loads ending y-coordinate */ if (GpiLine(hps, &ptl) == GPI_OK){ return TRUE; /* Draw Line. */ } /* if */ else return FALSE; } /* DrawLine */ The second argument of GpiMove is the address of a POINTL structure that contains coordinates of the line's starting point. The second argument of GpiLine is the address of another POINTL structure that contains the coordinates of the last point on the line. ═══ 6.2.2. Creating a Rubber-Banding Effect with a Straight Line ═══ When lines are drawn with a rubber-banding effect, two things happen: the original line (if one exists) is erased, and a new line is drawn in its place. This process typically takes place each time the mouse is dragged and continues until the mouse button is released. The quickest way to erase the original line (having ensured that it was drawn using mix attribute FM_XOR) is to redraw it using mix attribute FM_XOR. The following figure shows how to create this effect. #define INCL_WININPUT #define INCL_GPITRANSFORMS #define INCL_GPIPRIMITIVES #include HPS hps; /* Presentation-space handle */ LONG curr_color; MRESULT EXPENTRY wpGeneric(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ static POINTL ptlStart; /* Starting point of line */ static POINTL ptlNew; /* Ending point of line */ static POINTL ptlPrev; /* Previous end point of line */ static BOOL fDraw; /* Line-drawing flag */ switch (msg) { case WM_BUTTON1DOWN: /* User begins drawing */ GpiSetColor(hps, CLR_GREEN); ptlStart.x = (LONG) (LOUSHORT(mp1)); ptlStart.y = (LONG) (HIUSHORT(mp1)); GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 1L, &ptlStart); ptlPrev.x = ptlStart.x; ptlPrev.y = ptlStart.y; GpiMove(hps, &ptlStart); fDraw = TRUE; return ((MRESULT) TRUE); case WM_MOUSEMOVE: /* User draws line */ if (fDraw) { ptlNew.x = (LONG) (LOUSHORT(mp1)); ptlNew.y = (LONG) (HIUSHORT(mp1)); GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 1L, &ptlNew); curr_color = GpiQueryColor(hps); GpiSetMix(hps, FM_XOR); if ((ptlStart.x != ptlPrev.x) || (ptlStart.y != ptlPrev.y)) { GpiMove(hps, &ptlStart); GpiLine(hps, &ptlPrev); } /* if */ if ((ptlStart.x != ptlNew.x) || (ptlStart.y != ptlNew.y)) { GpiMove(hps, &ptlStart); GpiLine(hps, &ptlNew); ptlPrev.x = ptlNew.x; ptlPrev.y = ptlNew.y; } /* if */ GpiSetMix(hps, FM_OVERPAINT); } /* if */ return ((MRESULT) TRUE); case WM_BUTTON1UP: /* User stops drawing */ fDraw = FALSE; return ((MRESULT) TRUE); } /* switch */ } /* wpGeneric */ ═══ 6.2.3. Drawing a Circle ═══ When drawing a circle, all the transformations between the world, model, page, and device spaces must maintain square units. This means that your application should select metric, English, or arbitrary page units instead of pels. On most devices, pels are rectangular, but not necessarily square. This also means that the Sx and Sy scaling factors should be equal. If the transformations maintain square units and the arc parameters are set to their default values, GpiFullArc produces a circle. In the example shown in the following figure, if the page units are PU_LOENGLISH and the default transformations are set, a circle with a radius of 1/2 inch is drawn. #define INCL_GPIPRIMITIVES #include HPS hps; /* Presentation-space handle */ MRESULT EXPENTRY wpClient (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ ARCPARAMS arcp; /* Structure for arc parameters */ POINTL ptlPos; /* Structure for current position */ FIXED fxMult; /* Multiplier for circle */ arcp.lP = 1; arcp.lQ = 1; arcp.lR = 0; arcp.lS = 0; GpiSetArcParams(hps, &arcp); /* Sets parameters to default */ ptlPos.x = 100; /* Loads x-coordinate */ ptlPos.y = 100; /* Loads y-coordinate */ GpiMove(hps, &ptlPos); /* Sets current position */ fxMult = MAKEFIXED(50, 0); /* Sets multiplier */ GpiFullArc(hps, DRO_OUTLINE, fxMult); /* Draws circle */ } /* wpClient */ The second argument to GpiFullArc DRO_OUTLINE, specifies that the operating system should draw only the outline of the circle-rather than filling the interior with the current fill pattern. The third argument, fxMult, specifies that the operating system should multiply the size of the circle by 50 units. Because the page units are PU_LOENGLISH and the default transformations are set, 50 units is equivalent to 1/2 inch. ═══ 6.2.4. Drawing an Ellipse ═══ If you set the world, model, page, and device transformations so that they maintain square units, you can use the arc parameters to transform the shape of the unit circle to an ellipse, and draw this with GpiFullArc. The example in the following figure alters the arc parameter, p, by doubling its value, making the ellipse twice as wide horizontally as it is vertically. In the example shown in the following figure, if the page units are PU_LOENGLISH and the default transformations are set, an ellipse with a 2-inch major axis (parallel to the x-axis) and a 1-inch minor axis (parallel to the y-axis) is drawn. #define INCL_GPIPRIMITIVES #include HPS hps; /* Presentation-space handle */ MRESULT EXPENTRY wpClient (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ POINTL ptlPos; /* Structure for current position */ FIXED fxMult; /* Multiplier for ellipse */ ARCPARAMS arcp; /* Structure for arc parameters */ arcp.lP = 2; arcp.lQ = 1; arcp.lR = 0; arcp.lS = 0; GpiSetArcParams(hps, &arcp); /* Sets parameters to default */ ptlPos.x = 200; /* Loads x-coordinate */ ptlPos.y = 100; /* Loads y-coordinate */ GpiMove(hps, &ptlPos); /* Sets current position */ fxMult = MAKEFIXED(50, 0); /* Sets multiplier */ GpiFullArc(hps, DRO_OUTLINE, fxMult); /* Draws circle */ } /* wpClient */ Because the arc-parameter fields, lP and lQ, are set to 2 and 1, the operating system creates an ellipse with a major axis that is twice as long as the minor axis. ═══ 6.2.5. Drawing a Pie Slice ═══ The following steps describe how to use GpiPartialArc to draw a closed shape bounded by a chord and an arc: 1. Set the current line type to LINETYPE_INVISIBLE with GpiSetLineType. 2. Call GpiPartialArc with the start angle equal to angle B, and the sweep angle equal to 0. This effectively moves the current position to a point on the current arc, and thereby defines one end of the chord. 3. Select a visible line type with GpiSetLineType 4. Call GpiPartialArc with the start angle equal to angle A, and the sweep angle equal to angle B - angle A. Angle B must be greater than angle A. The center point is the same on both GpiPartialArc calls. To fill this partial arc with the current area-fill pattern, you can bracket the GpiPartialArc call of step 4 with GpiBeginArea and GpiEndArea. You should not call GpiBeginArea before step 2. The effect of this sequence is shown in the following figure. Closed Figure Bounded by Chord and Arc The circle in the preceding figure is defined by the current arc parameters. Point F is the current position, and point C is the center of the arc as specified with the first GpiPartialArc call. The first GpiPartialArc call-with the line type set to LINETYPE_INVISIBLE-moves the current position to point D. The second GpiPartialArc call-with the line type set to LINETYPE_SOLID- draws the chord from the current position (point D) to the start point of the arc (point E), and draws arc ED. The partial arc has been defined within an area and has been filled with the current area-fill pattern. The following figure shows how to draw a "pie slice". like the one drawn in the previous figure. #define INCL_GPIPRIMITIVES #include void Figure_516(){ HPS hps; POINTL ptlCenter = {2L, 2L}; /* Coordinates of the center point */ FIXED fxAngleA = 20L; /* Angle A in degrees */ FIXED fxAngleB = 130L; /* Angle B in degrees */ GpiSetLineType(hps, LINETYPE_INVISIBLE); /* Set position to start drawing the arc at angle B. */ GpiPartialArc(hps, &ptlCenter, MAKEFIXED(1, 0), fxAngleB, 0L); GpiSetLineType(hps, LINETYPE_ID); GpiBeginArea(hps, BA_BOUNDARY | BA_ALTERNATE); /* Fill the area */ GpiPartialArc(hps, &ptlCenter, MAKEFIXED(1, 0), fxAngleA, fxAngleB-fxAngleA); GpiEndArea(hps); /* Cancel area-fill */ } ═══ 6.2.6. Drawing a Fillet ═══ A fillet is tangential to two lines. The curve of the fillet is always tangential to a line drawn between its start and control points and a line drawn between its end and control points. The following figure shows an example of how to draw a single curve, using the current position and two control points. #include HPS hps; /* Presentation-space handle */ MRESULT EXPENTRY wpClient(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ POINTL aptl[2]; /* Structure for control points */ aptl[0].x = 50; /* Loads x-coord. of first control point */ aptl[0].y = 50; /* Loads y-coord. of first control point */ GpiMove(hps, aptl); /* Sets current position */ aptl[0].x = 75; /* Loads x-coord. of second control point */ aptl[0].y = 75; /* Loads y-coord. of second control point */ aptl[1].x = 100; /* Loads x-coord. of third control point */ aptl[1].y = 50; /* Loads y-coord. of third control point */ GpiPolyFillet(hps, 2, aptl); /* Draws fillet */ } /* wpClient */ When you draw a sharp fillet, the sharpness value controls the shape of the curve, as shown in a previous table. The following figure shows an example of using a sharpness value of 3, which creates a hyperbolic curve. #include HPS hps; /* Presentation-space handle */ MRESULT EXPENTRY wpClient(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ POINTL aptl[2]; /* Structure for control points */ FIXED fxSharpness; /* Sharpness value */ aptl[0].x = 50; /* Loads x-coord. of first control point */ aptl[0].y = 50; /* Loads y-coord. of first control point */ GpiMove(hps, aptl); /* Sets current position */ aptl[0].x = 75; /* Loads x-coord. of second control point */ aptl[0].y = 75; /* Loads y-coord. of second control point */ aptl[1].x = 100; /* Loads x-coord. of third control point */ aptl[1].y = 50; /* Loads y-coord. of third control point */ fxSharpness = MAKEFIXED(3, 0); /* Sets sharpness value */ GpiPolyFilletSharp(hps, /* Draws fillet */ 2L, aptl, &fxSharpness); } /* wpClient */ ═══ 6.2.7. Drawing a Spline ═══ When you use GpiPolySpline to draw a spline, each curve is tangential to the first and last of three connected lines. The following figure shows how to draw a spline. #include HPS hps; /* Presentation-space handle */ MRESULT EXPENTRY wpClient(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ POINTL aptl[3]; /* Structure for control points */ aptl[0].x = 50; /* Loads x-coord. of first control point */ aptl[0].y = 100; /* Loads y-coord. of first control point */ GpiMove(hps, aptl); /* Sets current position */ aptl[0].x = 75; /* Loads x-coord. of second control point */ aptl[0].y = 200; /* Loads y-coord. of second control point */ aptl[1].x = 100; /* Loads x-coord. of third control point */ aptl[1].y = 0; /* Loads y-coord. of third control point */ aptl[2].x = 125; /* Loads x-coord. of fourth control point */ aptl[2].y = 100; /* Loads y-coord. of fourth control point */ GpiPolySpline(hps, 3L, aptl); /* Draws spline */ } /* wpClient */ ═══ 7. Marker Primitives ═══ Marker primitives are graphics objects-such as stars, dots, or crosses-that are used, for example, to indicate the plotted points on a line graph. The following topics are related to the information in this chapter:  Presentation spaces  Line and arc primitives  Color and mix attributes  Fonts ═══ 7.1. About Marker Primitives ═══ Marker primitives always are drawn centered over a point. In a designated presentation space, GpiMarker draws a single marker primitive of the current marker symbol, with its center at a specified position. This position becomes the new current position when the marker is drawn. Another marker function, GpiPolyMarker, draws multiple marker primitives in the designated presentation space. Each marker primitive is centered over a position specified in an input array to GpiPolyMarker. All marker primitives drawn by a single call to GpiPolyMarker use the same (current) marker symbol. When a series of marker primitives is drawn, the current position is the center point of the last marker in the series. The following figure shows the use of marker primitives in a line graph. Marker Primitives This example shows a sequence of diamond-shaped marker primitives drawn on a line graph at (1,2), (3,4), (4,3), (7,5), (8,4), (9,8), (10,6), and (11,6). The new current position is at (11,6). The marker portion of this example could have been drawn with a single call to GpiPolyMarker or with eight separate GpiMarker calls. ═══ 7.1.1. Attributes of Marker Primitives ═══ Marker primitive attributes are contained in a data structure called MARKERBUNDLE. Following is a list of these attributes:  Marker symbol  Marker box  Marker set  Foreground color  Background color  Foreground mix attribute  Background mix attribute When an application creates a presentation space, the marker attributes are set to the default values shown in the following table. Marker Attribute Default Values ┌────────────────┬──────────────────┬──────────────────────────┐ │Attribute │Default Value │Function that Redefines │ │ │ │Attribute │ ├────────────────┼──────────────────┼──────────────────────────┤ │Marker symbol │Cross │GpiSetMarker │ ├────────────────┼──────────────────┼──────────────────────────┤ │Marker box │Device dependent; │GpiSetMarkerBox │ │ │equal to the size │ │ │ │of one character │ │ ├────────────────┼──────────────────┼──────────────────────────┤ │Marker set │LCID_DEFAULT │GpiSetMarkerSet │ │ │ │Note: If this default is │ │ │ │changed, the base marker │ │ │ │set cannot be reselected │ │ │ │with GpiSetMarkerSet. │ ├────────────────┼──────────────────┼──────────────────────────┤ │Foreground color│Black │GpiSetAttrs (MBB_COLOR) │ ├────────────────┼──────────────────┼──────────────────────────┤ │Background color│Clear │GpiSetAttrs │ │ │ │(MBB_BACK_COLOR) │ ├────────────────┼──────────────────┼──────────────────────────┤ │Foreground mix │Overpaint │GpiSetAttrs (MBB_MIX_MODE)│ ├────────────────┼──────────────────┼──────────────────────────┤ │Background mix │Leave alone │GpiSetAttrs │ │ │ │(MBB_BACK_MIX_MODE) │ └────────────────┴──────────────────┴──────────────────────────┘ ═══ 7.1.2. Marker Symbols ═══ The current marker symbol is selected from the current marker set using GpiSetMarker. The marker symbol selected for the specified presentation space is used for all subsequent GpiMarker and GpiPolyMarker calls until a new symbol is selected. The following table describes the marker symbols provided by the PM in a base marker set. These symbols are not necessarily available from other marker sets. The Base Marker Set ┌──────────────────┬────────────────────────────────┬──────────┐ │Symbol │Identifier │Long Value│ ├──────────────────┼────────────────────────────────┼──────────┤ │Cross │MARKSYM_CROSS │1L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Plus sign │MARKSYM_PLUS │2L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Diamond │MARKSYM_DIAMOND │3L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Square │MARKSYM_SQUARE │4L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Six-point star │MARKSYM_SIXPOINTSTAR │5L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Eight-point star │MARKSYM_EIGHTPOINTSTAR │6L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Solid diamond │MARKSYM_SOLIDDIAMOND │7L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Solid square │MARKSYM_SOLIDSQUARE │8L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Dot │MARKSYM_DOT │9L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Small circle │MARKSYM_SMALLCIRCLE │10L │ ├──────────────────┼────────────────────────────────┼──────────┤ │Blank, (Often │MARKSYM_BLANK │64L │ │called the │ │ │ │invisible marker) │ │ │ └──────────────────┴────────────────────────────────┴──────────┘ The default marker symbol (MARKSYM_DEFAULT) is identical to the MARKSYM_CROSS symbol and has a long value of 0L. The error marker symbol (MARKSYM_ERROR) has a long value of -1L. The following figure shows the visible marker symbols from the base marker set. Your application can determine the marker set with GpiQueryMarkerSet. The Base Marker Set ═══ 7.1.3. Marker Box ═══ The marker box is a rectangular boundary that defines the horizontal and vertical space occupied by the marker symbol. The marker box is used to center the current marker symbol. If the current marker set contains vector marker primitives (characters outlined by using line and arc functions), changing the size of the marker box changes the size of the marker primitives also. When you change the size of the marker box, a vector marker symbol is scaled up or down automatically to fit the box. Image marker primitives, however, cannot be scaled. If the current marker set contains image characters, the marker box dimensions are fixed, because you cannot alter the size of image markers. You can use GpiSetMarkerBox to change the size of the marker box for a particular presentation space. Set the value of the appropriate SIZEF structure to the required size. The new size is expressed in world coordinates and should not contain any fractional values. The default size of the marker box can be determined using DevQueryCaps. The values, CAPS_MARKER_WIDTH and CAPS_MARKER_HEIGHT, depend on the currently associated device and the presentation page. Marker box values set with GpiSetMarkerBox can be determined using GpiQueryMarkerBox. GpiSetAttrs also can be used to change the size of the marker box. GpiSetDefAttrs can be used to change the default size of the marker box. ═══ 7.1.4. Marker Set ═══ When you create a presentation space, the current marker set, along with other marker attributes, are set to default. The current marker symbol (the cross described earlier) is specified from the supplied marker set. The supplied set of marker primitives contains only image, or raster, marker primitives. The marker primitives in the default marker set are drawn by setting the color of the pels in the marker box. Within the marker box, the color of the set pels defines the foreground color. The default foreground color is neutral- black on the display screen and on printers. The color of the pels that are not set defines the background color. The default background color is the background color on the device-white on the display screen, and the loaded paper color on printers. The default background mix is LEAVE_ALONE, or transparent, which means the background color is irrelevant. If the default set is changed using GpiSetDefAttrs, its markers are not accessible. The markers from the default set can be recovered by calling GpiSetDefAttrs and specifying the value LCID_DEFAULT, (0). ═══ 7.1.4.1. Customizing Marker Sets ═══ If the current marker set does not contain a symbol that suits your application, you can load a new marker set and select a marker symbol from that set. The only way to see the current marker set is to display it on the screen or view a hardcopy of the symbols. You load a new marker set for a specified presentation space by creating a logical font. Then you select the font as a marker set by specifying the logical font identifer (lcid) as an input parameter to GpiSetMarkerSet. After selecting the marker set, call GpiSetMarker to select a marker from the set. You can set both values simultaneously, with GpiSetAttrs. You can use any font's character set as a marker set and any character within that marker set as a marker. To determine the value that identifies the current marker set, call GpiQueryMarkerSet. To determine the value that identifies the current marker character, call GpiQueryMarker. You can retrieve both values simultaneously with GpiQueryAttrs. You also can create image marker symbols using the Font Editor. ═══ 7.1.5. Marker Color and Mix Attributes ═══ The color attribute defines the color used to draw a primitive or an object. The mix attribute determines how the color of a primitive or an object is combined with the color of the drawing surface, or any other objects on the surface. The marker color defines the color used to draw the output from any of the IBM OS/2 marker functions. When a presentation space is created, the marker color initial default is black. Markers are one of the primitives that have a foreground and background color, as shown in the following figure. For image markers, the colors are determined by the setting of pels. For vector markers, the foreground consists of the arcs and lines that define the marker. The background color appears between the foreground lines. The marker can be solid, or filled, in which case the background color does not appear between the foreground lines. Marker Primitives Marker primitives have both a color and background color attribute. The mix attribute controls the combination of marker color with drawing-surface color, while the background mix attribute controls the combination of the marker box color with the drawing-surface color. When a presentation space is created, the marker mix attribute initial default is FM_OVERPAINT. The overpaint mix attribute specifies that the marker color is not to be modified by the color of the drawing surface. If the marker mix attribute is changed, the marker color is mixed with colors that are already on the drawing surface. The marker background color initial default is CLR_BACKGROUND. Usually this is defined by the application to the same color as the drawing surface. The marker background mix attribute initial default is BM_LEAVEALONE. The leave-alone mix background attribute specifies that the marker background color is not drawn. The box that effectively surrounds the marker appears only if the marker background mix attribute is changed. To specify a new color or mix attribute call GpiSetAttrs. This function accepts as input the type of primitive, for example PRIM_MARKER, a list of attributes that are to be changed, a list of attributes that are to be set to their default values, and the values for the attributes that are to be changed. GpiSetAttrs is useful to specify colors and mix attributes just for a specific data structure- MARKERBUNDLE, for example. GpiSetAttrs also provides some protection against invalid colors. To determine the current marker color and mix attribute call GpiQueryAttrs. This function accepts as input the primitive type and the attributes in question. It returns as output an array of values for the specifically queried attributes. To reset the default marker color and mix attribute, just as with any other attribute specified in the MARKERBUNDLE data structure, call GpiSetDefAttrs. This function accepts as input the type of primitive, for example PRIM_MARKER, the attributes to be changed, and the values that will become the new default values. The changing of default values is important when working with segments. Changing the default values during a series of drawing functions is not recommended. The marker color and mix attribute also can be specified with:  GpiSetColor  GpiSetMix  GpiSetBackColor  GpiSetBackMix However, these functions have the disadvantage of specifying the foreground and background color or mix attribute for all primitive BUNDLE data structures that have the respective component. There are four query functions that determine the color and mix attribute as specified by GpiSet... functions:  GpiQueryColor  GpiQueryMix  GpiQueryBackColor  GpiQueryBackMix If the marker color, marker background color, mix attribute, or background mix attribute were specified individually, the queries can return a value inconsistent with the current marker attribute. ═══ 7.2. Using Marker Primitives ═══ You can use marker functions to:  Draw a single marker or a series of markers  Set or determine (query) any combination of the marker bundle attributes including: - Determining the lcid for the current marker set - Selecting a character set as the new marker set - Determining the value that identifies the current marker - Selecting a character as the new marker - Setting or changing the size of the marker box - Setting or changing the color of a marker ═══ 7.2.1. Drawing Marker Primitives ═══ You can draw either a single marker or a series of markers using the current marker symbol. To draw a single marker, set the fields in a POINTL structure to correspond to the desired position in world coordinates. Then call GpiMarker passing it the address of the POINTL structure as the second argument. To draw a series of markers, set the fields in an array of POINTL structures to correspond to the desired positions in world coordinates. Then call GpiPolyMarker, passing it the number of points in the array as the second argument and the name of the array as the third argument. The following figure shows how to draw a graph with GpiPolyLine and GpiPolyMarker. #include void fncMARK01(void){ HPS hps; /* Presentation-space handle */ POINTL aptl[6]; /* Array of points */ aptl[0].x = 10; aptl[0].y = 15; /* Assigns points */ aptl[1].x = 150; aptl[1].y = 30; aptl[2].x = 200; aptl[2].y = 32; aptl[3].x = 250; aptl[3].y = 70; aptl[4].x = 360; aptl[4].y = 120; aptl[5].x = 380; aptl[5].y = 98; GpiPolyMarker(hps, sizeof(aptl) / sizeof(POINTL),aptl); /* Plots points */ GpiMove(hps, aptl); /* Sets current position */ GpiPolyLine(hps, sizeof(aptl) / sizeof(POINTL),aptl); /* Draws lines */ } /* fncMARK01 */ ═══ 7.2.2. Selecting a New Marker ═══ The following figure shows how to check whether the default marker primitive from the default marker set is being used currently, and if so, how to replace the cross with the six-pointed star. #define INCL_GPIPRIMITIVES #include void fncMARK02(void){ HPS hps; if ((GpiQueryMarker(hps) == MARKSYM_DEFAULT) && (GpiQueryMarkerSet(hps) == LCID_DEFAULT)) GpiSetMarker(hps, MARKSYM_SIXPOINTSTAR); ═══ 7.2.3. Selecting a New Marker Set ═══ The following figure is an example of how to load a Helvetica** vector font, select it as the new marker set, and select the uppercase A as the new marker primitive. #define INCL_GPILCIDS #define INCL_GPIPRIMITIVES #include void fncMARK03(void){ LONG cHelvFonts, cFonts, lcid, i, j; HPS hps; FATTRS fattrs; FONTMETRICS afm[80]; MARKERBUNDLE mbnd; cHelvFonts = GpiQueryFonts(hps, QF_PUBLIC, "Helv", &cFonts, sizeof(FONTMETRICS), (PFONTMETRICS) NULL); /* Queries the number of Helvetica fonts. */ GpiQueryFonts(hps, QF_PUBLIC, "Helv", &cHelvFonts, sizeof(FONTMETRICS), afm); /* Loads the array of FONTMETRICS structures. */ for (i = 0; !(afm[i].fsDefn & FM_DEFN_OUTLINE) && i < cHelvFonts; i++); /* Finds outline font */ fattrs.usRecordLength = sizeof(FATTRS); fattrs.fsSelection = 0; fattrs.lMatch = afm[i].lMatch; /* Uses Helvetica outline font */ for (j = 0; j <= sizeof(afm[i].szFacename); j++) fattrs.szFacename[j] = afm[i].szFacename[j]; fattrs.idRegistry = 0; fattrs.usCodePage = 850; /* Uses international code page */ fattrs.lMaxBaselineExt = 0; fattrs.lAveCharWidth = 0; fattrs.fsType = 0; fattrs.fsFontUse = FATTR_FONTUSE_TRANSFORMABLE; GpiCreateLogFont(hps, (PSTR8) NULL, lcid, &fattrs); mbnd.usSet = lcid; /* Uses font as marker set */ mbnd.usSymbol = 'A'; /* Uses capital A as primitive */ GpiSetAttrs(hps, PRIM_MARKER, MBB_SYMBOL | MBB_SET, 0, &mbnd); } /* fncMARK03 */ ═══ 7.2.4. Changing the Marker Color ═══ The following figure shows how to set the marker foreground color to green. #define INCL_GPIPRIMITIVES #include void fncMARK04(void){ HPS hps; MARKERBUNDLE mbnd; mbnd.lColor = CLR_GREEN; GpiSetAttrs(hps, PRIM_MARKER, MBB_COLOR, 0L, &mbnd); } /* fncMARK04 */ ═══ 8. Matrix Multiplication ═══ To show how matrix multiplication is implemented, here are two matrixes: ┌ ┐ ┌ ┐ │ a b c │ │ j k l │ │ d e f │ * │ m n o │ │ g h i │ │ p q r │ └ ┘ └ ┘ The multiplication of these two matrixes produces a value for each of the nine elements of the resulting matrix: ┌ ┐ │ element1 element2 element3 │ │ element4 element5 element6 │ │ element7 element8 element9 │ └ ┘ To produce element 1 of the matrix, element a is multiplied by element j, element b is multiplied by element m, and element c is multiplied by element p. That is: element1 = (a x j) + (b x m) + (c x p) To produce element 2 of the matrix, element a is multiplied by element k, element b is multiplied by element n, and element c is multiplied by element q. To produce element 3 of the matrix, elements a, b, and c are multiplied by their corresponding elements (l, o, and r) in the third vertical line of the second matrix. To produce element 4 of the matrix, you move down a row in the first matrix. That is, element d is multiplied by element j, element e is multiplied by element m, and element f is multiplied by element p. You continue the multiplication in this way until each of the nine elements has a value. The complete workings for this example are as follows: element1 = (a x j) + (b x m) + (c x p) element2 = (a x k) + (b x n) + (c x q) element3 = (a x l) + (b x o) + (c x r) element4 = (d x j) + (e x m) + (f x p) element5 = (d x k) + (e x n) + (f x q) element6 = (d x l) + (e x o) + (f x r) element7 = (g x j) + (h x m) + (i x p) element8 = (g x k) + (h x n) + (i x q) element9 = (g x l) + (h x o) + (i x r) Note that if the order of the two matrixes is reversed, the results of the multiplication are different. Here is a simple example in which an object is scaled by a factor of 3, and then translated by (5,4): ┌ ┐ ┌ ┐ ┌ ┐ │ 3 0 0 │ │ 1 0 0 │ │ 3 0 0 │ │ 0 3 0 │ * │ 0 1 0 │ = │ 0 3 0 │ │ 0 0 1 │ │ 5 4 1 │ │ 5 4 1 │ └ ┘ └ ┘ └ ┘ You can multiply together as many transformation matrixes as you require. ═══ 9. Metafiles ═══ A metafile is a graphics object that, like a segment, contains the GPI instructions that contribute to the final version of a picture. Unlike a segment, a metafile also contains a header, with state information, and all resources necessary to identically create the picture. Because pictures that are displayed when a graphics application is executed are lost when the application finishes, metafiles provide a method of retaining pictures beyond a single execution of an application. The following topics are related to the information in this chapter:  Presentation spaces and device contexts  Line primitives  Marker primitives  Area primitives  Character string primitives  Color and mix attributes  Paths  Regions  Fonts  Bit maps  Coordinate spaces and transformations  Print job submission and manipulation ═══ 9.1. About Metafiles ═══ Metafiles can exist in three distinct forms. A metafile that has just been created is called a memory metafile because it exists in memory managed by the Presentation Manager on behalf of the application that created it. A metafile that is transferred to disk storage as a file with the default extension of .MET is called a disk metafile. A metafile that is loaded into an application's memory is editable by the application. Metafiles save resources in the following ways:  Metafiles can be created and used in draw mode by a single application. Therefore, an application that is not retaining segments in a segment store can retain graphics in a metafile.  Metafiles remain available while the owning application is running, regardless of the number of presentation spaces the application obtains or defines.  Given the same starting conditions in each presentation space, you can produce an identical picture each time the metafile contents are executed.  Different threads or processes within an application can display a picture stored as a metafile without each having to own the metafile.  If your organization has common graphical resources, such as a company logo, those resources can be stored in a metafile. This avoids the overhead of re-creating the resources each time they are needed.  Because the metafile is a device-independent format, it is useful for transferring pictures that are to be printed when the printer-type is unknown.  PM applications can exchange graphical information by using metafiles, either by using the clipboard or by transferring them over a network.  Your application can also exchange graphics data with non-PM applications that support the Mixed Object Document Content Architecture (MO:DCA) interchange standard. Unlike bit-maps, metafiles offer some device-independence. Bit maps store picture information on a pel-by-pel basis. Metafiles store picture information in the form of low-level graphics commands that the operating system uses to construct the pictures. Note: Metafiles can contain bit maps or other graphics information that is in device-dependent format. The graphics commands, called "graphics orders", represent graphics functions that create a picture. These include drawing instructions, as well as attribute-setting instructions (for example, color tables and logical fonts) and anything that describes the structure of the picture. The contents of a metafile, therefore, are similar to those of the graphics presentation space in which the picture is drawn. The Presentation Manager automatically records the environmental detail of the presentation space in which a picture is drawn in the metafile. Note: A metafile can contain data generated from GPI functions only. Any non-graphical data included in a metafile is ignored. An application can re-create a picture from a metafile and display it in a window on the screen or print it by "playing" the metafile. When an application displays the contents of a metafile, it can use the color table, font, fill pattern, and transformations that are stored in the metafile, or it can use the logical color table, logical font, fill pattern, and transformations that are set for the current presentation space. The appearance of the picture stored in the metafile can, therefore, be changed by editing the current presentation space before playing the metafile. An application can save metafiles to a disk to be loaded later by any application that chooses to access the metafile. Disk metafiles loaded into application memory can also be edited in the same manner as elements in graphics segments are edited. They contain both primitives and attributes. ═══ 9.1.1. Contents of a Metafile ═══ Every graphic function can be represented by one or more graphics orders. The operating system defines graphics orders for:  Areas  Bit maps (for fill patterns) and pattern-reference points  Character output and attribute  Colors and mix modes (foreground and background)  Lines and arcs and line and arc attributes (including GpiBox)  Paths (including clip paths)  Position (for example, GpiMove)  Saving and resetting attributes (including GpiPop)  Transformations (in model space)  Viewing Limits Editing Retained Graphics and Graphics Segments also describes orders and how to edit them. When a picture is drawn in a presentation space associated with a metafile device context, the operating system converts the primitive attributes and drawing functions into graphics orders and stores them in the metafile. The operating system stores the effects of region and other operations that are not permitted as escape orders in the metafile. When an application finishes playing a metafile, the system restores any regions that were defined for the presentation space prior to calling GpiPlayMetaFile. An application can use any of the query functions while creating a metafile, but the system will not store those query functions in the metafile. Similarly, an application can set a value by using a mathematical operator, but the system will store only the result of the operation in the metafile. For example, if an application determines the end point of a line by subtracting 100 from the x- and y-coordinates of the upper-right corner of a window, the system records the end point, not the relative distance, in the metafile. Because the output of bit map functions is dependent upon the capabilities of the output device, Gpi bit map functions might produce unexpected results when they are used in a metafile. If the pel dimensions of the output device are different from the pel dimensions of the device on which the metafile was created, the bit map will be distorted. If the output device is a plotter, the bit map functions will not work at all. Most of the escape functions used by the DevEscape function can be used in metafiles. The escape functions that the system does not save in metafiles are DEVESC_QUERYESCSUPPORT and DEVESC_GETSCALINGFACTOR. ═══ 9.1.1.1. Metafile Content Restrictions ═══ Like areas and paths, not all functions and attributes can be represented in a metafile. Metafile content is mainly dependent upon the drawing mode in which the metafile is to be played. If the metafile is to be played when the current drawing-mode parameter is DM_DRAW (and in no other drawing mode), the metafile content is restricted as shown in Draw-Mode Restrictions. If the metafile is to be played when the current drawing-mode parameter is DM_RETAIN or DM_DRAWANDRETAIN, or if the file is to conform to SAA* guidelines, the metafile content is restricted as shown in Creating Metafiles for Interchange. ═══ 9.1.1.1.1. Draw-Mode Restrictions ═══ The following restrictions apply if the metafile is to be played when the current drawing mode parameter is DM_DRAW:  If the DCTL_DISPLAY flag of GpiSetDrawControl is OFF when you are sending graphics to a metafile, the graphics will not be visible when the metafile is played. Their effects on the current position and on current attribute settings are recorded.  Region functions are not recorded in a metafile. The effects of the following functions, however, are recorded: - GpiSetClipRegion - GpiIntersectClipRectangle - GpiExcludeClipRectangle - GpiOffsetClipRegion - GpiPaintRegion When the metafile is played into a presentation space, temporary regions are created. Upon completion of GpiPlayMetaFile, these temporary regions are automatically deleted, and the clipping region that was current before the metafile was played is restored.  In general, escape functions identified by reserved escape codes (that is, escape codes in the range of 0 through 32767) are recorded in a metafile. However, the DevEscape functions DEVESC_QUERYESCSUPPORT (escape code 0) and DEVESC_GETSCALINGFACTOR (escape code 1) are not stored in the metafile.  The effect of GpiErase, including close-segment processing, is recorded in a metafile.  The following functions can produce unexpected effects if the metafile contents are displayed on a different device from the one they were created for: - GpiBitBlt - GpiSetPel - GpiSetClipRegion - GpiOffsetClipRegion - GpiPaintRegion - GpiIntersectClipRectangle - GpiExcludeClipRectangle The reason for the unexpected effects is because the pel resolutions of the devices might differ. Raster operations (for example, GpiBitBlt) do not work on plotters.  You can associate the metafile device context with a different presentation space while creating the metafile, but the new presentation space must have the same format as the original. ═══ 9.1.1.1.2. Creating Metafiles for Interchange ═══ The following restrictions apply if the metafile is to be played when the current drawing-mode parameter is DM_DRAWANDRETAIN or DM_RETAIN, or if the metafile is to conform to SAA guidelines:  Before you issue the first drawing instruction to a graphics presentation space that has been associated with a metafile device context, you must establish (or default) the following: - The graphics field (use GpiSetGraphicsField) - The color table (use GpiCreateLogColorTable) - The code page for the default character set (use GpiSetCp) - The default viewing transformation (use GpiSetDefaultViewMatrix) - The settings of the drawing controls (use GpiSetDrawControl; DCTL_DISPLAY must be set on) - The default values of attributes (use GpiSetDefAttrs) - The default viewing limits (use GpiSetDefViewingLimits) - The primitive tag (use GpiSetDefTag) - The default arc parameters (use GpiSetDefArcParams) You must not specify a graphics field if the metafile is to conform to SAA guidelines. If a graphics field is specified, you can play the metafile in DM_RETAIN or DM_DRAWANDRETAIN mode, but the graphics field must be specified before the first drawing instruction is issued to the metafile. The effect of the graphics field in the target presentation space when playing the metafile is controlled by the PMF_LOADTYPE option of GpiPlayMetaFile.  You can define logical fonts and identify bit maps to be used as area-fill patterns at any time. You must not, however, issue GpiDeleteSetId against these resources after they have been established. Once assigned, therefore, lcids cannot be reused.  The size of the logical-color-table data must not exceed 31KB.  You must not use clipping regions. Therefore, none of the following functions are supported: - GpiSetClipRegion - GpiExcludeClipRectangle - GpiIntersectClipRectangle - GpiOffsetClipRegion  You must not reassociate the metafile device context.  When you use a bit map as the source of a GpiWCBitBlt operation or as an area-fill pattern, it must not be modified.  Only the following foreground mixes can be used: - FM_DEFAULT - FM_OR - FM_OVERPAINT - FM_LEAVEALONE  Only the following background mixes can be used: - BM_DEFAULT - BM_OVERPAINT - BM_LEAVEALONE  The following functions are not supported: - GpiBitBlt - GpiSetPel - GpiSetPS - GpiResetPS - GpiErase - GpiPaintRegion - DevEscape ═══ 9.1.1.1.3. Micro Presentation Space Restrictions ═══ When you create a metafile from a micro presentation space, or play the metafile through a micro presentation space, the contents of the metafile are restricted to those GPI functions that are valid in a micro presentation space. In this case, the application must use GpiDestroyPS instead of GpiAssociate before issuing DevCloseDC. GpiAssociate is not permitted in a micro presentation space. ═══ 9.1.1.1.4. Query Restrictions ═══ Query functions can be issued, with the usual restrictions, unless the metafile device context was created using the no query option, OD_METAFILE_NOQUERY. ═══ 9.1.1.1.5. Segment Restrictions ═══ Chained and unchained segments invoked by any GpiDraw... command are written to the metafile. Primitives outside segments are recorded automatically as zero segments. If the metafile is subsequently played in DM_RETAIN mode, all graphics are directed to the segment store. Chained dynamic segments cannot be recorded in a metafile. GpiRemoveDynamics and GpiDrawDynamics cause an error condition to be raised when the presentation space is associated with a metafile device context. Unchained dynamic segments are recorded as zero segments. To draw an unchained dynamic segment, use GpiDrawSegment. ═══ 9.1.1.1.6. Asynchronous Drawing Thread Restrictions ═══ If the metafile is being created on an asynchronous drawing thread and the thread is suspended by GpiSetStopDraw, an unusable metafile results. ═══ 9.1.2. Metafile Functions ═══ The OS/2 operating system provides a set of functions that allow you to:  Create a metafile  Store pictures in a metafile  Play a metafile  Save a metafile  Load a metafile  Edit a metafile  Copy a metafile  Delete a metafile How these functions are used to create and manipulate metafiles in relationship to applications and components of the operating system is illustrated in the following figure. Metafile Functions ═══ 9.1.2.1. Creating a Metafile ═══ Pictures are drawn in presentation spaces associated with device contexts. PM considers a metafile to be an output device or destination, in the same manner as a window or printer. This means that to record a picture in a metafile, a metafile device context must be created and associated with a presentation space. A metafile device context is created by calling DevOpenDC and specifying the type of device context as:  OD_METAFILE  OD_METAFILE_NOQUERY. OD_METAFILE is generally used to specify a metafile device context, although OD_METAFILE_NOQUERY provides better recording performance. OD_METAFILE_NOQUERY does not support attribute queries, for example, GpiQueryCurrentPosition, or GpiQueryColor. The device driver for the device that the metafile device context is associated with is specified in the DEVOPENSTRUC data structure required for DevOpenDC. DEVOPENSTRUC is described in Print Job Submission and Manipulation. A metafile device context can be associated with a newly-created presentation space by calling GpiCreatePS and specifying the handle to the metafile device context returned from the call to DevOpenDC. A metafile device context can also be associated with an existing, normal presentation space by calling GpiAssociate and specifying the handle to the metafile device context returned from the call to DevOpenDC. ═══ 9.1.2.2. Storing Pictures in a Metafile ═══ When a metafile device context is associated with a presentation space, presentation space resources (such as the current logical color table) and environmental settings (such as the presentation-page format) are copied automatically into the metafile. These items must be established before the presentation space is associated with the metafile device context. Loading of additional resources (such as fonts) and adjustments to the environment (such as modifying the default viewing transform) should be made before you begin drawing. Attribute settings, segment-creation requests, and primitive-drawing requests that contribute to the picture are directed to the metafile after its device context has been associated with a presentation space. If an application calls GpiSetDrawControl, specifying DCTL_DISPLAY and DCTL_OFF, before drawing graphics into a metafile, the graphics are not visible when the metafile is played. However, the metafile records any changes made to the current position or presentation-space attributes. When the metafile device context has been associated with a graphics presentation space, the metafile is ready to receive graphical data. Just as with any other output destination, whether the picture is sent directly to the metafile is controlled by the current drawing mode, as shown in the following table. Drawing Mode Dependencies When Recording Metafiles ┌──────────────────────┬──────────────────────────────────────┐ │Drawing Mode │Effect │ ├──────────────────────┼──────────────────────────────────────┤ │Draw mode │Graphics go directly to the metafile. │ ├──────────────────────┼──────────────────────────────────────┤ │Retain mode │Graphics go to the segment store of │ │ │the presentation space. They are not │ │ │directed to the metafile until the │ │ │application issues an appropriate │ │ │GpiDraw... request (GpiDrawChain, │ │ │GpiDrawFrom, GpiDrawSegment). │ ├──────────────────────┼──────────────────────────────────────┤ │Draw-and-retain mode │Graphics go directly to the metafile, │ │ │and also to the segment store of the │ │ │presentation space. │ └──────────────────────┴──────────────────────────────────────┘ The drawing mode can be changed at any time while the metafile device context remains open by calling GpiSetDrawingMode. As long as the metafile device context remains open, you can continue drawing. A metafile can only contain data generated from GPI functions. Any nongraphical data included in a metafile is ignored. The following list describes items found in a metafile:  Picture  Logical color table  Logical font  Fill pattern  Viewing transformation  Page units  Page dimensions When an application finishes drawing in a metafile, it must disassociate the metafile device context from the presentation space by calling GpiAssociate. If the metafile is associated with or through a micro presentation space, call GpiDestroyPS to perform an implicit disassociation. When you have finished drawing in the metafile, and the presentation space has been disassociated, the application can close the metafile device context and obtain a handle to the metafile by calling DevCloseDC. A closed metafile cannot be reopened; therefore, additional drawing in the metafile is not possible. A closed metafile can be referenced by the metafile handle. The metafile handle is used to reference the metafile for subsequent operations on the metafile. Use the metafile handle to:  Transfer a metafile to application memory  Transfer a metafile from application memory  Save a metafile on disk  Play a metafile into presentation space  Edit a metafile  Copy a metafile  Delete a metafile Because each metafile can be distinctly identified, your application can work with more than one metafile at a time. However, because metafiles can be very large files, you must make maximum use of the metafile handles to avoid duplicating the actual metafiles in memory. ═══ 9.1.2.3. Playing a Metafile ═══ An application can redraw a picture stored in a metafile by executing the contents of metafile. This is known as playing a metafile into a graphics presentation space. How a picture is redrawn (that is, how the metafile is replayed) depends on the current drawing-mode of the target presentation space. The following table describes these dependencies. Drawing Mode Dependencies When Playing Metafiles ┌──────────────────┬─────────────────────┬─────────────────────┐ │Drawing Mode │Result │If the metafile │ │ │ │contains a segment │ │ │ │chain... │ ├──────────────────┼─────────────────────┼─────────────────────┤ │DM_DRAW │The metafile contents│The contents of the │ │ │are executed, and the│segments in the chain│ │ │picture is directed │represent the picture│ │ │to the current output│output that is │ │ │device. │directed at the │ │ │ │target output device.│ ├──────────────────┼─────────────────────┼─────────────────────┤ │DM_RETAIN │The metafile contents│The chain is added to│ │ │are retained in the │the end of any chain │ │ │application's segment│that may already be │ │ │store. The picture │in the segment store.│ │ │defined in the │If any segment in the│ │ │metafile is not │metafile has the same│ │ │directed to an output│nonzero name as a │ │ │device until the │segment already in │ │ │application issues an│the segment store of │ │ │appropriate │the presentation │ │ │GpiDraw... function. │space, an error │ │ │ │condition is raised. │ ├──────────────────┼─────────────────────┼─────────────────────┤ │DM_DRAWANDRETAIN │The metafile contents│See above. │ │ │are both stored and │ │ │ │executed. │ │ └──────────────────┴─────────────────────┴─────────────────────┘ Note: Unchained segments in the metafile are always retained, regardless of the current drawing-mode parameter. When the contents of a metafile are retained in the segment store of the target presentation space, they can be manipulated by the application as if the application had created them. For example, the segments can be edited, drawn, correlated, and deleted. A metafile is "played" by calling GpiPlayMetaFile. A metafile cannot, however, be "played" within a segment bracket. GpiPlayMetaFile requires a metafile handle, an option count, an options array, a byte count of a descriptive record, and the descriptive record. The GpiPlayMetaFile descriptive record is a natural-language description of the picture contents. For example, its value might be A House. This description is provided on input to the DevOpenDC function that defines the metafile device context. It can be used, for example, in a list box from which a user can select a picture. The GpiPlayMetaFile options array specifies how the operating system alters your application's presentation space before playing the metafile. The options array determines the display attributes of the metafile. The array fields and their respective attributes, as numbered consecutively in the array, are shown in the following table. ┌──────────────────────────────┬──────────────────────────────┐ │Option │Attribute │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_SEGBASE │Reserved, must be 0. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_LOADTYPE │Viewing transform, graphics. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_RESOLVE │Reserved, must be 0. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_LCIDS │Font and local bit map local │ │ │identifiers. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_RESET │Drawing attributes. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_SUPPRESS │Actual playing of the │ │ │metafile. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_COLORTABLES │Color tables, color palettes. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_COLORREALIZABLE │Realization of metafile color │ │ │table. │ ├──────────────────────────────┼──────────────────────────────┤ │PMF_DEFAULTS │Drawing defaults values. │ └──────────────────────────────┴──────────────────────────────┘ ═══ 9.1.2.3.1. PMF_RESET Option ═══ The PMF_RESET option, more so than the other array options, controls the effects of other array options. This option allows a total reset of the presentation space and provides further control of the following presentation space environmental attributes:  Page units (device transform)  Page dimensions  Default viewing transform Warning: If the metafile page units, page dimensions and page coordinate format do not match those in the presentation space, playing the metafile will cause an error. The PMF_RESET option can have one of the values shown in the following table. PMF_RESET Options for GpiPlayMetaFile ┌────────────────┬────────────────────────────────────────────┐ │Value │Description │ ├────────────────┼────────────────────────────────────────────┤ │RES_RESET │Allows the presentation space to be │ │ │completely reset, just as if it were newly │ │ │created, and the values of the │ │ │aforementioned environmental attributes to │ │ │be specified from the metafile into the │ │ │presentation space. │ │ │ │ │ │This option is equivalent to specifying │ │ │GRES_ALL on GpiResetPS. If this option is │ │ │used, the target presentation page is │ │ │redefined so that it is the same size, and │ │ │defined in the same units, as the metafile. │ │ │It also ensures that the physical size of │ │ │the metafile picture is preserved if the │ │ │presentation page is defined in units other │ │ │than pels, or arbitrary units. │ ├────────────────┼────────────────────────────────────────────┤ │RES_NORESET │Prevents resetting of the presentation │ │RES_DEFAULT │space. The existing presentation space │ │ │values of the environmental attributes will │ │ │be preserved, and their values in the │ │ │metafile will be discarded. │ │ │ │ │ │If this option is used, ensure that the │ │ │presentation-page units of the target │ │ │presentation space are the same as those │ │ │with which the metafile was generated, │ │ │before you play a metafile into the │ │ │presentation space. For example, if the │ │ │original presentation page is defined in │ │ │increments of 0.1 mm, the target │ │ │presentation page must be defined in the │ │ │same way. │ │ │ │ │ │To change the format of the target │ │ │presentation page, if the presentation-page │ │ │formats do not match, issue GpiSetPS, but │ │ │only if you know the metafile │ │ │presentation-page units. │ └────────────────┴────────────────────────────────────────────┘ If you are certain that the settings of the current presentation space are appropriate for the metafile, then you can play the metafile with the NO_RESET option. To reset some or all of the current values in the target presentation space, without redefining the presentation page, call: 1. GpiResetPS, with the GRES_ATTRS or GRES_SEGMENTS option 2. GpiPlayMetaFile, with the NO_RESET option. The PMF_LCID option may be used to append or replace fonts from the metafile to the fonts in the presentation space. The PMF_COLORTABLES option may be used to append or replace color table entries in the presentation space from the metafile. Other options (PMF_LOADTYPE, PMF_DEFAULTS, and so on) can be used to selectively replace settings in the presentation space from the metafile. Like the PMF_RESET option, other options, except for PMF_SUPPRESS, either:  Allow the values in the presentation space to be preserved and those in the metafile to be discarded, or  Allow the presentation space to be loaded using the values in the metafile. If the first choice is used with RES_RESET, then the items controlled by the PMF_options will be left set to their default reset state, otherwise it will occur as described in the first choice above. If the second choice is used with RES_RESET, then the items controlled by the PMF_options are as described above. If it is used with RES_NORESET, then the fonts and color tables in the metafile can append to the existing color tables and fonts in the presentation space. Existing presentation space color table entries and fonts, such as viewing transform will be replaced if respecified in the metafile. Note: If your application uses the attributes from the metafile, the attributes that were specified in the presentation space before the metafile was played are overwritten. ═══ 9.1.2.3.2. PMF_SUPPRESS Option ═══ The PMF_SUPPRESS option allows you to control the playing of the metafile. The PMF_SUPPRESS option can have one of the values shown in the following table. PMF_SUPPRESS Options for GpiPlayMetaFile ┌────────────────┬────────────────────────────────────────────┐ │Value │Description │ ├────────────────┼────────────────────────────────────────────┤ │SUP_SUPPRESS │The operating system does not draw the │ │ │metafile on the device associated with the │ │ │presentation space. This option is useful if│ │ │you need to alter the presentation space │ │ │before drawing it on an output device. │ ├────────────────┼────────────────────────────────────────────┤ │SUP_NOSUPPRESS │The operating system draws the metafile on │ │SUP_DEFAULT │the device associated with the presentation │ │ │space. │ └────────────────┴────────────────────────────────────────────┘ You can use the RES_RESET option to reinitialize the presentation space and modify certain resources or presentation space environmental attributes from the application before playing the remainder of the metafile by: 1. Saving the current state of the presentation space by calling GpiSavePS. Use this function only if you wish to restore the previous state of the presentation space after playing the metafile. 2. Calling GpiPlayMetaFile and specifying:  The PMF_RESET option with the value RES_RESET  The PMF_SUPPRESS option with the value SUP_SUPPRESS This causes GpiPlayMetaFile to set the presentation space to the specifications recorded in the metafile but not to play the picture in the metafile. 3. Making any required changes to the presentation space. 4. Calling GpiPlayMetaFile and specifying:  The PMF_RESET option with the value RES_NORESET  The PMF_SUPPRESS option with the value SUP_NOSUPPRESS This causes the picture to play. 5. Restoring the state of the presentation space after playing the metafile by calling GpiRestorePS. ═══ 9.1.2.3.3. PMF_LOADTYPE Option ═══ The PMF_LOADTYPE option of GpiPlayMetaFile determines which viewing transformations and graphics fields affect the metafile picture. The PMF_LOADTYPE option can have one of the values shown in the following table. PMF_LOADTYPE Options for GpiPlayMetaFile ┌────────────────┬────────────────────────────────────────────┐ │Value │Description │ ├────────────────┼────────────────────────────────────────────┤ │LT_ORIGINALVIEW │Viewing transformations recorded in the │ │ │metafile are used in the target presentation│ │ │space. │ │ │ │ │ │If changes to the graphics field are │ │ │recorded in the metafile, the graphics field│ │ │in the target presentation space is updated,│ │ │and the picture is clipped to that graphics │ │ │field. │ │ │ │ │ │Changes to the default viewing │ │ │transformation recorded in the metafile are │ │ │used to update the default viewing │ │ │transformation in the target presentation │ │ │space. │ ├────────────────┼────────────────────────────────────────────┤ │LT_NOMODIFY │Any viewing transformations recorded in the │ │LT_DEFAULT │metafile are ignored. The metafile contents │ │ │are drawn in accordance with the current │ │ │viewing transformation in the target │ │ │presentation space. (Note that, if you also │ │ │specify RES_RESET, the current viewing │ │ │transformation is reset to its default │ │ │value.) │ │ │ │ │ │The picture is clipped to any graphics field│ │ │defined in the target presentation space, │ │ │and any graphics field recorded in the │ │ │metafile is ignored. │ └────────────────┴────────────────────────────────────────────┘ The PMF_RESET option RES_RESET changes values in the target presentation space. Therefore, the effect of the PMF_LOADTYPE option should always be considered in conjunction with the PMF_RESET option. For example, if you specify both RES_RESET and LT_NOMODIFY, the default viewing transformation in the target presentation space is updated with that from the metafile, even though LT_NOMODIFY means that such values should be ignored. ═══ 9.1.2.3.4. PMF_LCIDS Option ═══ The PMF_LCIDS option of GpiPlayMetaFile controls whether logical resources referenced by a local identifier (lcid) are loaded from the metafile. Logical resources include logical fonts and bit maps used as area-fill patterns. The PMF_LCIDS option can have one of the values shown in the following table. PMF_LCIDS Options for GpiPlayMetaFile ┌────────────────┬────────────────────────────────────────────┐ │Value │Description │ ├────────────────┼────────────────────────────────────────────┤ │LC_LOADDISC │Loads lcid-referenced resources from the │ │ │metafile. │ │ │ │ │ │If the lcids of those resources are already │ │ │in use in the target presentation space, the│ │ │resources currently identified by those lcid│ │ │s are deleted and their lcids are freed │ │ │before the metafile contents are loaded. The│ │ │new fonts and bit maps replace the existing │ │ │ones in the presentation space. (If the │ │ │operating system uses a local identifier │ │ │that the application has already defined, │ │ │GpiPlayMetaFile deletes the existing │ │ │identifier before using it for the metafile │ │ │resource.) │ ├────────────────┼────────────────────────────────────────────┤ │LC_NOLOAD │The operating system uses the presentation │ │LC_DEFAULTS │space's logical font and custom fill │ │ │pattern; it will ignore any logical font or │ │ │custom fill pattern in the metafile. │ │ │ │ │ │An application can use GpiSavePS and │ │ │GpiRestorePS to maintain the local │ │ │identifiers it has already defined. │ └────────────────┴────────────────────────────────────────────┘ ═══ 9.1.2.3.5. PMF_COLORTABLE Option ═══ The PMF_COLORTABLES option may be used to append or replace color table entries in the presentation space from the metafile. The PMF_COLORTABLES option can have one of the values shown in the following table. PMF_COLORTABLES Options for GpiPlayMetaFile ┌────────────────────┬────────────────────────────────────────┐ │Value │Description │ ├────────────────────┼────────────────────────────────────────┤ │CTAB_REPLACE │Replaces the logical color table in the │ │ │presentation space with the color table │ │ │in the metafile. │ ├────────────────────┼────────────────────────────────────────┤ │CTAB_REPLACEPALETTE │Replaces the current palette, if it │ │ │exists, in the presentation space with │ │ │the palette in the metafile. │ ├────────────────────┼────────────────────────────────────────┤ │CTAB_NOMODIFY │Maintains the logical color table in the│ │CTAB_DEFAULT │presentation space. │ └────────────────────┴────────────────────────────────────────┘ ═══ 9.1.2.3.6. PMF_COLORREALIZABLE Option ═══ The PMF_COLORREALIZABLE option may be used to select whether color table from the metafile is realized upon loading. The PMF_COLORREALIZEABLE option can have one of the values shown in the following table. PMF_COLORREALIZABLE Options for GpiPlayMetaFile ┌────────────────────┬────────────────────────────────────────┐ │Value │Description │ ├────────────────────┼────────────────────────────────────────┤ │CREA_DOREALIZE │Sets the realizable option when loading │ │ │the color table. │ ├────────────────────┼────────────────────────────────────────┤ │CREA_NOREALIZE │Does not set the realizable option when │ │CREA_DEFAULT │loading the color table. │ └────────────────────┴────────────────────────────────────────┘ ═══ 9.1.2.3.7. PMF_DEFAULTS Option ═══ The PMF_DEFAULTS option can have one of the values shown in the following table. PMF_DEFAULTS Options for GpiPlayMetaFile ┌────────────────────┬────────────────────────────────────────┐ │Value │Description │ ├────────────────────┼────────────────────────────────────────┤ │DDEF_LOADDISC │Replaces the default attributes, default│ │ │viewing limits, and default arc │ │ │parameters in the presentation space │ │ │with the values specified in the │ │ │metafile. │ ├────────────────────┼────────────────────────────────────────┤ │DDEF_IGNORE │Maintains the default attributes, │ │DDEF_DEFAULTS │default viewing limits, and default arc │ │ │parameters in the presentation space. │ └────────────────────┴────────────────────────────────────────┘ ═══ 9.1.2.4. Saving a Metafile ═══ A metafile is not a permanent object and, unless it is explicitly saved, disappears when the application that creates it ends. Metafiles are saved in disk files by calling GpiSaveMetaFile. This function accepts as input the metafile handle and the name of the disk file in which the metafile is to be saved. As the disk file is created by this function, an error condition is raised if a file with this name already exists. When you call GpiSaveMetaFile, the memory version of the metafile is deleted. Its handle is no longer valid, until the file is reloaded from disk. ═══ 9.1.2.5. Loading a Metafile ═══ A metafile saved on disk has to be reloaded before it can be used. Any application with access to the disk file can transfer the file from disk storage to application storage by calling GpiLoadMetaFile. GpiLoadMetaFile returns a metafile handle, which identifies the metafile after it has been loaded. ═══ 9.1.2.6. Editing a Metafile ═══ Metafiles can be edited in a manner similar to editing graphics segments. To edit graphics orders in a metafile, an application transfers them into application storage (an array of bytes) by calling GpiQueryMetaFileBits. The number of graphics orders copied depends on the size of the array that the application supplies. The application can determine the size of the metafile (in bytes) by calling GpiQueryMetaFileLength. When the application has finished editing the graphics orders, it can copy them back into the metafile by calling GpiSetMetaFileBits. Edited versions of metafiles can be saved by calling GpiSaveMetaFile. The disk file that contains the edited version of the metafile cannot have the same name as the file from which the metafile was originally loaded. GpiSaveMetaFile raises an error condition if the disk file already exists. ═══ 9.1.2.7. Copying a Metafile ═══ A copy of a memory metafile can be made by calling GpiCopyMetaFile. PM makes a copy of the metafile and returns a new handle to the new metafile. ═══ 9.1.2.8. Deleting a Metafile ═══ A memory metafile is deleted by calling GpiDeleteMetaFile. After the operation is complete, the handle to the metafile no longer points to a usable object. A disk file containing the metafile remains untouched by this operation. A disk metafile is deleted by using operating system commands that delete any other type of file. ═══ 9.1.3. Metafiles and the System Clipboard ═══ A metafile that you have created or loaded can be made available to other applications at the same workstation by placing the handle to the metafile in the system clipboard. When a resource is passed to the clipboard, it becomes the property of the system, and is not deleted when the owning application ends. Any application that can access the clipboard can retrieve the handle to the metafile. Using the handle to the metafile, the application should copy the metafile by calling GpiCopyMetaFile before closing the clipboard. The application can then perform any metafile operation on the metafile. ═══ 9.2. Using Metafiles ═══ Use metafile functions to:  Create a metafile  Draw into a metafile  Load a metafile to disk  Load a metafile from disk into an application  Play a metafile  Edit a metafile  Copy a metafile  Transfer metafile contents to application memory  Transfer metafile contents from application memory ═══ 9.2.1. Creating and Drawing into a Metafile ═══ To create a metafile, you must: 1. Create a metafile device context with DevOpenDC. 2. Create a presentation space with GpiCreatePS, and associate the presentation space with the metafile device context. 3. Draw into the metafile with various Gpi drawing functions. 4. Disassociate the metafile device context from the presentation space with GpiAssociate. 5. Close the metafile device context with DevCloseDC. The following figure shows how to create a simple metafile that draws text within the borders of a three-color box. #include void fncMETA01(void){ DEVOPENSTRUC dop; HDC hdcMeta; HPS hpsMeta; HMF hmf; HAB hab; SIZEL sizlPage; POINTL ptl; dop.pszLogAddress = (PSZ) NULL; dop.pszDriverName = "DISPLAY"; hdcMeta = DevOpenDC(hab, OD_METAFILE, /* Metafile device context */ "*", /* Ignores OS2.INI */ 2L, /* Uses first two fields */ (PDEVOPENDATA) &dop, /* Device information */ (HDC) NULLHANDLE); /* Compatible device context */ hpsMeta = GpiCreatePS(hab, hdcMeta, /* Metafile device context */ &sizlPage, /* Page viewport */ PU_PELS | GPIA_ASSOC); /* Device units and associated context */ /* Draw a box in a metafile. */ GpiSetColor(hpsMeta, CLR_CYAN); ptl.x = 150; ptl.y = 200; GpiMove(hpsMeta, &ptl); ptl.x = 300; ptl.y = 275; GpiBox(hpsMeta, DRO_FILL, &ptl, 0L, 0L); GpiSetColor(hpsMeta, CLR_GREEN); ptl.x = 300; ptl.y = 200; GpiMove(hpsMeta, &ptl); ptl.x = 390; ptl.y = 275; GpiBox(hpsMeta, DRO_FILL, &ptl, 0L, 0L); GpiSetColor(hpsMeta, CLR_YELLOW); ptl.x = 390; ptl.y = 200; GpiMove(hpsMeta, &ptl); ptl.x = 530; ptl.y = 275; GpiBox(hpsMeta, DRO_FILL, &ptl, 0L, 0L); ptl.x = 175; ptl.y = 230; GpiMove(hpsMeta, &ptl); GpiSetColor(hpsMeta, CLR_PINK); GpiCharString(hpsMeta, 41, "METAFILE COPY METAFILE COPY METAFILE COPY"); GpiAssociate(hpsMeta, (HDC) NULLHANDLE); hmf = DevCloseDC(hdcMeta); } /* fncMETA01 */ Creating a Metafile ═══ 9.2.2. Drawing into a Metafile in Retain Mode ═══ To draw into a metafile, set the drawing mode to the appropriate value for your application and then perform the drawing operations. The following figure shows an example of how to copy the contents of a segment into a metafile. #define INCL_GPIMETAFILES #define INCL_GPICONTROL #include void fncMETA02(void){ HDC hdcMeta, hdc; POINTL ptl; HMF hmf; LONG alOpt[10]; HPS hps; /* * Open a segment, assign it an identifier of 10, * and draw some text into it. */ GpiSetDrawingMode(hps, DM_RETAIN); GpiOpenSegment(hps, 10L); ptl.x = 175; ptl.y = 230; GpiMove(hps, &ptl); GpiSetColor(hps, CLR_PINK); GpiCharString(hps, 41, "METAFILE COPY METAFILE COPY METAFILE COPY"); GpiCloseSegment(hps); GpiAssociate(hps, NULLHANDLE); /* Disassociates PS and screen DC */ GpiAssociate(hps, hdcMeta); /* Associates PS and meta DC */ GpiDrawSegment(hps, 10L); /* Draws segment into metafile */ GpiAssociate(hps, NULLHANDLE); /* Disassociates PS and meta DC */ hmf = DevCloseDC(hdcMeta); /* Closes metafile */ GpiAssociate(hps, hdc); /* Associates PS and screen DC */ GpiSetDrawingMode(hps, DM_DRAW); /* Sets drawing mode to DM_DRAW */ /* * Load the array of options for GpiPlayMetaFile * with default values. */ alOpt[PMF_SEGBASE] = 0; /* Reserved */ alOpt[PMF_LOADTYPE] = LT_DEFAULT; /* Default transformations */ alOpt[PMF_RESOLVE] = 0; /* Reserved */ alOpt[PMF_LCIDS] = LC_DEFAULT; /* Uses default lcids */ alOpt[PMF_RESET] = RES_DEFAULT; /* Uses default */ alOpt[PMF_SUPPRESS] = SUP_DEFAULT; /* Uses default */ alOpt[PMF_COLORTABLES] = CTAB_DEFAULT; /* Uses default */ alOpt[PMF_COLORREALIZABLE] = CREA_DEFAULT; /* Uses default */ GpiPlayMetaFile(hps, /* Plays metafile onto screen */ hmf, 8L, alOpt, (PLONG) NULL, 0L, (PSZ) NULL); } /* fncMETA02 */ Copying a Graphic Segment to a Metafile If you want to create a simple drawing in a metafile for repeated display, you can set the drawing mode to DM_DRAW and draw directly into the metafile. The code in the first code fragment shows an example of how to do this. You can store named segments in the metafile that you are recording in DM_DRAW mode by bracketing your output primitive functions between GpiOpenSegment and GpiCloseSegment. ═══ 9.2.3. Copying a Metafile to Disk ═══ You can copy a metafile to disk using GpiSaveMetaFile, and you can load the file back into your application using GpiLoadMetaFile. The following figure shows an example of how to copy a metafile to a file named META.MET, then load the same file back into the application and play it. #define INCL_GPIMETAFILES #include void fncMETA03(void){ HMF hmf; HAB hab; HPS hps; LONG alOpt[10]; GpiSaveMetaFile(hmf, "meta.met"); /* Saves metafile on disk */ hmf = GpiLoadMetaFile(hab, "meta.met"); /* Loads metafile */ alOpt[PMF_SEGBASE] = 0; /* Reserved */ alOpt[PMF_LOADTYPE] = LT_DEFAULT; /* Default transformations */ alOpt[PMF_RESOLVE] = 0; /* Reserved */ alOpt[PMF_LCIDS] = LC_DEFAULT; /* Uses default lcids */ alOpt[PMF_RESET] = RES_DEFAULT; /* Uses default */ alOpt[PMF_SUPPRESS] = SUP_DEFAULT; /* Uses default */ alOpt[PMF_COLORTABLES] = CTAB_DEFAULT; /* Uses default */ alOpt[PMF_COLORREALIZABLE] = CREA_DEFAULT; /* Uses default */ GpiPlayMetaFile(hps, hmf, 8, alOpt, (PLONG) NULL, 0L, (PSZ) NULL); } /* fncMETA03 */ ═══ 9.2.4. Playing a Metafile ═══ The following figure shows an example of how to play the metafile using the font, color table, and fill-pattern descriptions in your application's presentation space. #define INCL_GPIMETAFILES #include void fncMETA04(void){ HPS hps; HMF hmf; LONG alOpt[10]; alOpt[PMF_SEGBASE] = 0; /* Reserved */ alOpt[PMF_LOADTYPE] = LT_DEFAULT; /* Viewing transformation in PS */ alOpt[PMF_RESOLVE] = RS_DEFAULT; /* Reserved */ alOpt[PMF_LCIDS] = LC_DEFAULT; /* Font and fill pattern in PS */ alOpt[PMF_RESET] = RES_DEFAULT; /* Page units and dimensions in PS */ alOpt[PMF_SUPPRESS] = SUP_DEFAULT; /* Draws metafile into PS */ alOpt[PMF_COLORTABLES] = CTAB_DEFAULT; /* Color table in PS */ alOpt[PMF_COLORREALIZABLE] = CREA_DEFAULT; /* Sets realizable option */ GpiPlayMetaFile(hps, hmf, 8, alOpt, (PLONG) NULL, 0L, (PSZ) NULL); } /* fncMETA04 */ The following figure shows an example of how to play a metafile using the font, color table, and fill-pattern descriptions in the metafile. #define INCL_GPIMETAFILES #include void fncMETA05(void){ HPS hps; HMF hmf; LONG alOpt[10]; alOpt[PMF_SEGBASE] = 0; /* Reserved */ alOpt[PMF_LOADTYPE] = LT_DEFAULT; /* Viewing transformation in PS */ alOpt[PMF_RESOLVE] = RS_DEFAULT; /* Reserved */ alOpt[PMF_LCIDS] = LC_LOADDISC; /* Font and fill pattern in metafile */ alOpt[PMF_RESET] = RES_DEFAULT; /* Page units and dimensions in PS */ alOpt[PMF_SUPPRESS] = SUP_DEFAULT; /* Draws metafile into PS */ alOpt[PMF_COLORTABLES] = CTAB_REPLACE; /* Color table in metafile */ alOpt[PMF_COLORREALIZABLE] = CREA_DEFAULT; /* Sets realizable option */ GpiPlayMetaFile(hps, hmf, 8, alOpt, (PLONG) NULL, 0L, (PSZ) NULL); } /* fncMETA05 */ The following figure shows an example of how to play a metafile using the viewing transformation, page units, and presentation-page dimensions specified in the metafile. #define INCL_GPIMETAFILES #include void fncMETA06(void){ HPS hps; HMF hmf; LONG alOpt[10]; alOpt[PMF_SEGBASE] = 0; /* Reserved */ alOpt[PMF_LOADTYPE] = LT_ORIGINALVIEW; /* Viewing transformation */ alOpt[PMF_RESOLVE] = RS_DEFAULT; /* Reserved */ alOpt[PMF_LCIDS] = LC_DEFAULT; /* Font and fill pattern in PS */ alOpt[PMF_RESET] = RES_RESET; /* Page units/dimensions */ alOpt[PMF_SUPPRESS] = SUP_DEFAULT; /* Draws metafile into PS */ alOpt[PMF_COLORTABLES] = CTAB_DEFAULT; /* Uses color table in PS */ alOpt[PMF_COLORREALIZABLE] = CREA_DEFAULT; /* Sets realizable option */ GpiPlayMetaFile(hps, hmf, 8, alOpt, (PLONG) NULL, 0L, (PSZ) NULL); } /* fncMETA06 */ ═══ 10. Print Job Submission and Manipulation ═══ The print subsystem of the OS/2 operating system provides a flexible, high-level interface between your application and an output device. Because most of the internal workings of the subsystem are shielded from both user and programmer, this chapter concentrates on the programming process required to produce hard copy output. Querying of printer resources, working under a specific user's environment, designing for application-specific requirements, and manipulation of print jobs also are described. ═══ 10.1. About the Print Subsystem ═══ This section describes:  The print subsystem components  The print subsystem configuration  Printing data flow ═══ 10.1.1. Print Subsystem Components ═══ The print subsystem comprises the following software components of the operating system:  Spooler  Print subsystem user interface  Queue drivers (queue processors)  Printer drivers  File system  Kernel device drivers ═══ 10.1.1.1. Spooler ═══ The spooler is the central coordinating process for the print subsystem. It gives the user flexibility in organizing and optimizing the use of the system's printers. The spooler has a global view of the system's printing resources, particularly in a server environment and therefore is able to make the best use of those resources.  The spooler ensures that print output from two separately executing applications cannot be intermixed on the printer. As an optional optimization, the spooler can start a printing job before it is completely queued. Any successive jobs are queued normally.  The spooler can print a job in the background while the user continues to use the application. Other single-tasking operating systems, such as DOS, require the user to wait until the print output is sent completely to the printer.  The spooler can send jobs from PM applications across a network to a remote server, without the application's knowledge. Note: The file system handles print jobs from non-PM applications.  Queues within the spooler can be used for various purposes. For example, one queue could be used for large print jobs that are printed at times when print demand is low. Another queue could be configured to print jobs using a special size paper. Print jobs on this queue would be held until the correct paper is loaded into the printer.  The spooler can support a number of printers simultaneously. It can be configured so that jobs on a single queue can be shared among all the printers. This load balancing, which is particularly important in server environments, can be achieved without the application's knowledge.  Jobs can be prioritized while in the queue. For example, an urgent job can be given a higher priority than ordinary jobs. The spooler consists of one or more print queues, one for each printer object defined by the user. Jobs are created by applications and placed in a queue, waiting to print. When the previous job is completed, the next job in the queue is sent to the printer. ═══ 10.1.1.1.1. Print Job Formats ═══ The print jobs held in a spooler queue are known as spool files. Spool files contain the following:  Parameters submitted with the print job  Print job data Print job data is in one of two formats:  PM_Q_STD Standard output data, PM_Q_STD is spooled as a PM metafile; that is, as a series of graphics orders stored in a packed binary format. PM_Q_STD print jobs are created through the GPI. An advantage of the PM_Q_STD format is that the files are smaller than PM_Q_RAW format files. The smaller size saves disk space for jobs in the spooler queue and reduces network traffic when transmitting the data to a network server. The content of PM_Q_STD jobs can be viewed using the PICVIEW application. This is achieved using the job-content menu on a print job in the printer object. The multi-page spool file can be shown in a device-independent manner so that the content of the job can be recognized easily. After a job is spooled and ready to print, the spooler sends the PM_Q_STD job to the queue driver. The queue driver replays the metafile, through the GPI, to the appropriate printer driver. The driver, in turn, converts the data to printer-specific commands, that is, a printer-specific format. There are some restrictions on the content of PM_Q_STD jobs that are related to the restrictions for PM metafiles. PM applications that cannot deal with these restrictions should enqueue print jobs using PM_Q_RAW, but there is an increase in required disk space and, possibly, network traffic. Print jobs sent to network servers that do not support PM are converted automatically to the PM_Q_RAW format by the system. The application still can continue specifying PM_Q_STD. Note: The effect of converting all PM_Q_STD print jobs to PM_Q_RAW can be turned on by the user's selecting Printer-specific format in a printer object settings page.  PM_Q_RAW Raw data, PM_Q_RAW, is the actual printer command to print the job. For example, raw data created for an HP** LaserJet** printer contains Printer Command Language (PCL) commands; and raw data created for a PostScript** printer contains PostScript commands. The content of PM_Q_RAW jobs can be viewed with the system editor. This is achieved using the job content menu on a print job in the printer object. However, it is not always easy to recognize the content of a job. For example, PostScript is very hard to understand and get a visual idea of the actual output. Print jobs are created by the file system as a result of printing directly to the physical port using either INT 17 or INT 21 under DOS or the OS/2 DosOpen API. These print jobs always are queued using PM_Q_RAW. The actual queue chosen depends on the port used and the configuration of the print subsystem. PM applications also can use the PM_Q_RAW format, but the overall print-job creation process normally is slower because the printer driver has to perform more work to create the printer-specific format. If the Print while spooling printer object setting is turned on, the user can perceive a faster response. In particular for a multi-page document, the first page starts printing as soon as the printer driver has completely finished converting the GPI to the printer-specific format. Note: PM applications always should specify the PM_Q_STD format. The difference in disk space used can be from a factor of 2 to a factor of 50. The Printer-specific format and Print while spooling printer object settings can be used to configure optimal performance for the environment. Although the base operating system supports the two print job formats described above, other formats can be supported by providing an appropriate queue driver. ═══ 10.1.1.2. Disabling the Spooler ═══ The workplace user interface to control the spooler can be found in the System Setup folder. For special circumstances or applications, the spooler object can be used to disable the spooler. Generally, this is not recommended because the output from two applications can intermix, or one application can be paused until the first application has finished sending data to the printer. ═══ 10.1.1.3. Print Subsystem User Interface ═══ The print subsystem user interface is composed of printer objects. The spooler implements each printer object by using a queue to hold the jobs. The queue is connected to a logical device that specifies configuration data about the actual physical device, for example, the port and printer drivers. The print subsystem user interface performs the following basic functions:  Print job status Opening a printer object folder displays an icon or detail view of the print jobs waiting in the spooler queue. Opening the settings on an individual job displays the parameters that were used when the job was queued. Some settings, such as the number of copies, can be changed while the print job is waiting in the queue.  Print job manipulation Individual print jobs can be held in or released from the queue. Holding a print job means that it is not printed. Individual or all the print jobs in a queue can be deleted.  Queue manipulation Queues also can be held, released, deleted, copied, or created using the printer object context menu.  Printer object configuration Opening a printer object settings notebook enables a user to browse and modify the configuration of a printer object. For example, the printer driver can be changed if the user just obtained new printer. ═══ 10.1.1.4. Queue Driver ═══ The queue driver is also called a queue processor. It is used to take print jobs from a queue and print the data using the printer driver. The print job data (either PM_Q_STD or PM_Q_RAW format) is passed through the GPI. For PM_Q_STD jobs, GpiPlayMetaFile is used; and for PM_Q_RAW jobs, the DevEscape DEVESC_RAWDATA is used. ═══ 10.1.1.5. Printer Driver ═══ Printer drivers know all details of the printer they support; therefore, printer drivers are unique for each model of printer supported by the operating system. The printer driver is responsible for:  Displaying a dialog that enables the user to inform the system how the physical printer is configured; for example, which paper sizes are installed.  Displaying a dialog that enables the user to configure an individual print job; for example, which orientation (portrait or landscape) to use.  Responding to application queries for available printer capabilities such as color, resolution and forms.  Converting the GPI commands in a print job to the printer-specific language commands that will produce the expected output. The printer-specific commands are passed to the file system. ═══ 10.1.1.6. Port Drivers ═══ Port drivers are dynamic link libraries (DLLs) that contain a set of 32-bit functions, which provide helper functions for the spooler and Workplace Shell. For each port driver DLL, there should be a physical port driver (SYS file) installed in the CONFIG.SYS file. The file type of a port driver is .PDR. The operating system, by default, provides two port drivers; SERIAL.PDR supports COM1 - 4, and PARALLEL.PDR supports LPT1 - 3. For any other port, the supplier of the physical port software is responsible for providing a Presentation Manager port driver if it is necessary. The functions exported from a port driver are:  SplPdEnumPort  SplPdGetPortIcon  SplPdInitPort  SplPdInstallPort  SplPdQueryPort  SplPdRemovePort  SplPdSetPort  SplPdTermPort ═══ 10.1.1.7. File System ═══ The file system is involved in both the spooling process and the printing process. When non-PM applications create print data, the file system intercepts the data and places it on a spooler queue. After a printer driver has processed a print job, the file system sends the data to the appropriate file or device using a kernel device driver. ═══ 10.1.1.8. Kernel Device Driver ═══ The system provides device drivers for physical devices. The two most commonly used by the print subsystem are the parallel device driver and the serial device driver. ═══ 10.1.2. Print Subsystem Configuration ═══ From a user's viewpoint, a printer object represents a printer. The user can specify the printer object settings for configuration; for example, which printer driver and port to use. From a programmer's viewpoint, print configuration is more complicated. Each printer object actually consists of a queue connected to a logical device. The following figure shows some example configurations. The top-left and top-right pictures show one printer object; the bottom-left picture shows two printer objects; the bottom-right picture shows three printer objects. Example Configurations of Queues, Devices, and Printer Objects Multiple queues connected to a single device is termed printer sharing. The advantage of printer sharing is that two queues can have different configurations or be used for different purposes. For example:  One queue could be used for small jobs that are needed quickly, and the other could be used for large jobs printed during times of low demand, such as overnight.  One queue could be used for a normal form such as a letter, and the other could be for a special form and so, would be held. When the special form was loaded into the printer, that queue could be released and the normal form queue could be held. A single queue connected to multiple devices is termed printer pooling. This allows print jobs to be shared among printers for load balancing. The spooler does this by printing a job on the next available printer. For example, one printer usually reserved exclusively for special forms could be connected to a normal form queue during peak loads. The special form queue would be held temporarily. Note: Configuration of a device without a queue is not allowed by the OS/2 operating system. The logical device has the following configuration parameters that are relevant to application programmers:  Name and description  Logical port (for example, LPT1)  List of printer drivers For example, a logical device representing an HP LaserJet printer with an installed PostScript option could have both the HP LaserJet printer driver and the PostScript printer driver in its configuration. Each printer driver in the list also could have printer properties associated with it. Printer properties describe the physical configuration of the printer, such as what size paper is installed. The queue has the following configuration parameters that are relevant to application programmers:  Name and description It is the queue description not the queue name that is used for the printer object title- that is, the text displayed beneath a printer object icon.  Printer driver  Default job properties Job properties describe the parameters that must be used for printing a specific job. An example of a job property is the orientation. The queue's job property defaults are used if none are supplied by the application.  Queue driver  Flags for Printer-specific format and Print while spooling settings  Separator page  Start and stop times The configuration data for printer objects is stored in the OS2SYS.INI file. The spooler provides a set of functions that can be used to query and set this data. Note: Older PM applications might still use the Profile functions (for example, PrfQueryProfileString). If so, these applications must be recoded with the new functions to avoid any dependencies on where and how the system stores configuration data. ═══ 10.1.3. Printing Data Flow ═══ The data flow between your application, the printer driver, the spooler, and the kernel device driver is shown in the following figure. In addition to the data flow for the printer data stream, the data flow for screen output is shown. From an application's point of view, creating output for a printer is conceptually the same as creating screen output. Overview of the Application Interface and Data Flow There are three routes that the application's printer data can follow:  Base Printing Base printing is provided primarily for non-PM programs writing complete printer data streams, including all printer control codes, directly to a printer port. It also provides compatibility for applications that run under DOS or Microsoft** Windows**.  Queued PM Printing Queued printing is recommended for all PM programs. It provides the most flexibility, both for the application and the user. Print jobs created by PM applications are queued on a spooler queue. The spool files are processed and finally sent to the printer asynchronously from the application. Note: If the spooler is disabled, queued print jobs perform as though they were submitted for PM direct printing.  Direct PM Printing Conceptually, direct printing is the same as queued printing for the application interface, but the spooler is bypassed. Therefore, the data is sent directly to the printer, and the application has to wait until the printing is finished. Following are some of the reasons for PM applications to avoid direct printing: - The print job can interfere with other users whose jobs are destined for this printer. Print output could be mixed with the other print jobs - The spooler allows only one job at a time to print to a particular port to avoid mixing of print job output. If your application tries to print directly to the same port while another job is printing, your user must wait for the current job to complete before the user's job can begin. - The printing application loses some of its multitasking advantages because one job must complete before a second job is submitted. - The printer device driver does not protect a print job from job property and printer property mismatches. - Pictures printed directly can be different from those printed through a spooler. The default setting for direct printing is to print pictures their actual size, whereas the default for queue printing is scaled to fit for the output area. Direct printing is recommended only for specialized applications that use dedicated hard copy devices. Print jobs that have a certain degree of security associated with them, such as a corporate payroll or confidential documents, might best be handled with direct printing because files in the spooler can be copied. Jobs that are very large, that is, over 10MB, that you do not want copied in the spool file, also might best be printed directly. ═══ 10.2. Using the Print Subsystem ═══ This section covers the following aspects of using the print subsystem:  Submitting a non-Presentation Manager (base) print job  Submitting a queued Presentation Manager print job  Submitting a direct Presentation Manager print job  Submitting a print job directly to the spooler  Spooler management and configuration ═══ 10.2.1. Submitting a Non-Presentation Manager (Base) Print Job ═══ A program can create a complete printer data stream including all printer control codes (called a raw data stream) by using DosOpen, DosWrite, and DosClose. This is called base printing and it is used by:  OS/2 and DOS Print command (for example, PRINT CONFIG.SYS /D:LPT2)  OS/2 and DOS Copy command (for example COPY CONFIG.SYS LPT1:)  OS/2 and DOS Redirected Output (for example DIR > LPT1: or TYPE C:\CONFIG.SYS > LPT1:) (full screen hard copy)  All DOS applications  All family applications (applications running under DOS and OS/2)  All Microsoft Windows applications. Non-PM applications developed under OS/2 2.0 that must generate graphical data must be able to generate all the necessary Escape Codes, or printer-specific control sequences. Such applications will be coded differently, depending on the printer family-for example, Epson**, HP** LaserJet**, LaserPrinter*, Proprinter*, or PostScript**. Non-PM applications that successfully drove the printer in the environment for which they were designed-DOS for example-will continue to do so successfully under this operating system. DOS applications that directly access output hardware registers could have difficulty printing under the operating system. If this is so, these applications might need to be rewritten. ═══ 10.2.2. Submitting a Queued Presentation Manager Print Job ═══ There are several stages involved in using the PM programming interface to print your application data. From a user interface point of view, the following four dialogs must be provided. The exact order in which these dialogs are used will govern the order of program execution.  Page setup dialog The page setup dialog enables the user to specify the form name or size required. Options on this dialog can include margins on the page, header and footer strings, and whether duplex formatting is required. The actual contents of the dialog depend on the type of application. The important factor is that this page specify formatting options that also are used to display to a screen.  Printer setup dialog The printer setup dialog displays a list of queues available to the user. A Job properties push button on this dialog enables the user to query and modify the job properties for this job.  Font dialog Most PM applications must enable the user to specify the font (or fonts) required. Once the user has chosen a printer, an option on the fonts dialog enables the user to choose from device fonts as well as system fonts.  Print dialog The application should have a Print menu item on the File menu to invoke an application-specific print dialog. It is recommended that Shift+Print Screen be used as an accelerator for printing the client area. The Print-Screen key, unshifted, is used to capture and print a window or the whole screen. ═══ 10.2.2.1. Page Setup Dialog ═══ The page setup dialog is concerned with formatting options for the document. The user must be able to specify the form name, margins, and other application-specific formatting options such as page duplexing; that is, different formats for left and right pages in a multi-page document. Note: The application is responsible for storing the user-defined margins for the form. The application must not allow the user to specify margins smaller than those returned by the printer driver. Application Page Setup Dialog ═══ 10.2.2.1.1. Forms Selection ═══ If the user has not chosen a specific printer, the application can supply a list of standard form sizes- for example, Letter, Legal, Ledger, A4, and A3. The application also must consider, at a minimum, a 0.4 inch (10mm) margin on the form to be within the hardware clip limits of most printers. See the following table for the common form sizes. ┌────────────────────┬────────────────────┬────────────────────┐ │Form Name │Size in inches │Size in mm │ ├────────────────────┼────────────────────┼────────────────────┤ │Letter │8.5 x 11 │216 x 279 │ ├────────────────────┼────────────────────┼────────────────────┤ │Legal │8.5 x 14 │216 x 356 │ ├────────────────────┼────────────────────┼────────────────────┤ │Ledger │11 x 17 │279 x 432 │ ├────────────────────┼────────────────────┼────────────────────┤ │A4 │8.3 x 11.7 │210 x 297 │ ├────────────────────┼────────────────────┼────────────────────┤ │A3 │11.7 x 16.5 │297 x 420 │ └────────────────────┴────────────────────┴────────────────────┘ When a printer is chosen, it must be queried, using DevQueryHardcopyCaps for the forms it supports and the hardware clip margins. First, however, a device context must be created. It is recommended that a OD_INFO context be used, because OD_QUEUED can result in the creation of a print job. See the following figure for a sample code fragment. PPRDINFO3 pprd3Device; /* From SplQueryDevice */ PPRQINFO3 pprq3Queue; /* From SplQueryQueue */ PSZ pszTmp; /* Temporary pointer */ HDC hdc; /* Device context handle */ DEVOPENSTRUC dopData; /* DEVOPEN structure */ LONG clForms; /* Number of forms */ /* The device */ PHCINFO pchinfo; /* Forms information */ /* structure */ ULONG ulrc=DEV_OK; /* Return code */ /* Fill in data for devopendata for OD_INFO */ dopData.pszLogAddress = pprd3Device->pszLogAddr; pszTmp = strchr(pprq3Queue->pszDriverName,'.'); if (pszTmp) *pszTmp = '\0'; dopData.pszDriverName = pprq3Queue->pszDriverName; dopData.pdriv = pprq3Queue->pDriverData; /* Open the information device context */ hdc = DevOpenDC ( (HAB)0, OD_INFO, /* Type */ "*", /* Default token */ 3L, /* Count */ &dopData, /* Pointer to data */ (HDC)0); /* Comp dc */ /* Query number of forms available on the device */ clForms = DevQueryHardcopyCaps(hdc, 0L /* Start at beginning of list */ 0L, /* Get number of forms */ NULL); /* Allocate memory block for forms */ if (DosAllocMem((PPVOID(&pchinfo), clForms*sizeof(HCINFO), fALLOC)) { DevCloseDC(hdc); return(DEV_ERROR); } /* Query forms data */ ulrc = DevQueryHardcopyCaps(hdc, 0L, /* Start with first form */ clForms, /* Query all forms */ pchinfo); /* Structure to hold returned */ /* data */ /* Close the information device context */ DevCloseDC (hdc); /* Close the information */ /* device context */ /* Now use forms information in pchinfo */ DevQueryHardcopyCaps returns one HCINFO structure for each form. The contents of the structure are:  ASCIIZ name of the form (for example, Letter)  Width and height (in millimeters) of the paper  Clipping limits (in millimeters) of the paper  Number of pels between clipping limits  Whether this form is the one installed currently on the device, or whether it is selectable from another paper bin Then the list of forms can be displayed to the user. The form preselected in the list should be one of the forms marked with the HCINFO structure flag HCAPS_CURRENT. It is recommended that an application indicate to the user which forms are currently installed in the printer. This is done by including the HCINFO structure flag HCAPS_SELECTABLE. Then users can decide whether they want a quick print on a form available from the printer or to install a different paper tray in the printer. ═══ 10.2.2.2. Printer Setup Dialog ═══ In a printer setup dialog, an application should offer a list of printer objects that are available to the user and enable the user to select one. (The list of printer objects actually is a list of queues.) If none are available, an appropriate message must be displayed. An application must query the list of available printer objects each time the printer setup dialog is displayed because the user might have created or modified the printer configuration while the application was executing. The following figure is an example of a printer setup dialog. Application Printer Setup Dialog Note: If the document was formatted for a particular device and the user selects a different printer, the application must ask the user's permission before reformatting the document for the new printer. Use SplEnumQueue to query the list of printers (printer objects); printer objects essentially are spool queues. SplEnumQueue returns both a list of queues and information about each queue on the local workstation in an array of PRQINFO3 structures. It also returns information about local workstation queues that reference network print queues. Because the number of queues might vary for each use of your application, it is essential to allocate sufficient storage to hold the data returned by SplEnumQueue. Usually the application issues the query twice: the first time, the application determines the necessary size of the information buffer; after allocating a memory block, the second query actually retrieves the information. The SplEnumQueue parameter pcTotal contains the number of queues available on the local system. The application should display an appropriate message box if the value is 0. The queue description (returned in the structure PRQINFO3 field name pszComment) is the printer object title. This is much more familiar to the user than the queue name, which is displayed only on the view settings page of a printer object. Therefore, the printer setup dialog should show the queue descriptions instead of the queue names. SplEnumQueue returns information about the queue that might influence the user's or application's decision to print to this queue; for example, the queue priority, or the number of jobs already in the queue. SplEnumQueue also returns the default job properties for the queue. This data can be used by the application for the Job properties push button on the printer setup dialog. Less sophisticated applications might decide to dispense with the printer setup dialog and just print to the default queue. The default queue can be queried using PrfQueryProfileString, with an application name of PM_SPOOLER and a keyname of QUEUE. The spooler function SplQueryQueue then can be called to retrieve the default job properties. ═══ 10.2.2.3. Job Properties Considerations ═══ Job properties are options on a per-job basis- for example, orientation, resolution, and form selection. The job properties dialog is displayed by the printer driver. Each driver has a different dialog, depending on the capabilities of the printer. The job properties are held in a printer driver-specific format in the abGeneralData field of the DRIVDATA structure. Note: Job properties from one printer driver should not be given to another printer driver; the job properties probably will not be understood, and the printer driver will either return an error or substitute some default job properties. Then the user will see a change in job properties stored previously. The user should be given the opportunity to change the job properties before the job is printed. This can be achieved by supplying a Job properties push button on the printer setup dialog. Changing job properties requires two steps:  Retrieving job properties  Displaying the job properties dialog ═══ 10.2.2.3.1. Retrieving Job Properties ═══ The application can retrieve job properties from the following:  Previously saved job properties with the document  Current application session job properties  Default job properties from the queue (from pDriverData in the PRQINFO3 data structure)  Printer driver device defaults (from DevPostDeviceModes using the DPDM_QUERYJOBPROP flag). If no job properties were saved with the document, then there may be job properties that are being used by another document that also is to be printed to the same queue. If job properties still cannot be found, then the default job properties stored with the queue can be used. It may be that the user has not set up any default job properties for the queue. Last, query the printer driver for its device defaults using DevPostDeviceModes with the DPDM_QUERYJOBPROP flag. ═══ 10.2.2.3.2. Displaying Job Properties Dialog ═══ The sample code in the following figure shows how to display the job properties dialog. All the parameters required are available from the PRQINFO3 structure returned by SplEnumQueue or SplQueryQueue. In the case of printer pooling, the pszPrinters field of the PRQINFO3 structure contains a list of device names, separated by commas. It is sufficient to choose the first printer in the list because the printer object ensures that the configuration of each spooled printer is the same. Note: It is possible that the printer driver now uses a larger buffer for the job properties than the application is expecting. This occurs when a new version of a printer driver that supports some additional features is installed. In this case, the application must discard the existing document job properties, after a confirmation from the user, and query the printer driver for its device defaults, using the DPDM_QUERYJOBPROPS parameter to DevPostDeviceModes. #define INCL_DEV #define INCL_DOS #include #include { ULONG ulrc=FALSE; HAB hab; PPRQINFO3 pprq3Queue; /* From SplEnumQueue or SplQueryQueue */ PSZ pszDriverName,pszDeviceName,pszTmp; HDC hdc=NULL; LONG cbBuf; /* Use the first device name in the PRQINFO3 structure */ pszTmp = strchr(pprq3Queue->pszPrinters, ','); if (pszTmp) *pszTmp = '\0'; /* Use just the driver name from the driver.device string */ pszDeviceName = strchr(pprq3Queue->pszDriverName, '.'); if (pszDeviceName) { *pszDeviceName = '\0'; pszDeviceName++; } /* Check size of buffer required for job properties */ cbBuf = DevPostDeviceModes( hab, (PDRIVDATA)NULL, pprq3Queue->pszDriverName, pszDeviceName, pprq3Queue->pszPrinters, DPDM_POSTJOBPROP ); /* Return error to caller */ if (cbBuf<=0) return(cbBuf); /* Return BUFFER TOO SMALL error to caller */ if (cbBuf > pprq3Queue->pDriverData->cb) return(DPDM_ERROR); /* Display job properties dialog & get updated job properties from driver */ ulrc = DevPostDeviceModes( hab, pprq3Queue->pDriverData, pprq3Queue->pszDriverName, pszDeviceName, pprq3Queue->pszPrinters, DPDM_POSTJOBPROP ); return(ulrc); } ═══ 10.2.2.4. Font Dialog and Device Font Considerations ═══ There are two types of fonts:  System fonts, which can be used for both displays and printers, and therefore, are generally more flexible.  Device fonts, which are specific to a particular device. Device fonts for printers can be built-in or be installed with font cartridges by a user. Device fonts also can be available on diskette (also termed soft fonts) and can be downloaded to the printer as required by the printer driver. The advantage of device fonts is that, usually, they are printed in the highest resolution of the device and are faster than system fonts. Note: Some printer drivers, in particular, the HP LaserJet (LASERJET) and the LaserPrinter (IBM4019) printer drivers provide an intermediate solution. An option on the job properties dialog enables system fonts to be downloaded to the printer as soft fonts. As stated earlier, an application must provide the user with the ability to choose fonts and, in particular, to choose a device font over a system font to achieve better performance. A standard font dialog box should be used (see WinFontDlg). When an application uses device fonts, and the output mixes text and graphics pictures, the device fonts are clipped per character. System fonts give more precise clipping to the pel. The following figure illustrates the results from clipping two lines of text: one generated in a system font; the other, in a device font. Character Clipping Results for Device and System Fonts The available device fonts can be queried, using GpiQueryFonts, in either an OD_INFO or an OD_QUEUED device context. Device fonts are returned with negative lMatch numbers. Then the appropriate logical font can be used after calling GpiCreateLogFont. If, during the printing process, a logical font is not created, the printer driver uses its default font for the printer, which usually is 12-point Courier. There are two design choices for device fonts:  Use system fonts for the display. When printing, query the printer driver and attempt to choose a device font that closely matches the system font. If no match is found, then print using the system font. A device's font metrics and character spacing might not match exactly, so the printed output might not be exactly the same as the display.  Use a printer font if the user selects one. Determine the metrics and find a system font that shares the same characteristics (for example, a style such as Courier or Serifed). The character string to be displayed is sent to the printer driver and the inter-character spacing is returned, using GpiQueryCharStringPos. The individual character positions are used when the string is sent to the display, using GpiCharStringPos with the flOptions parameter of CHS_VECTOR. While the display output can take longer to display to the screen, true WYSIWYG (What You See Is What You Get) is achievable. ═══ 10.2.2.5. Print Dialog and Print Processing ═══ The print menu must display a dialog to enable the user to specify the number of copies, start page, end page, or any other application-specific print options. A confirm push button (for example, Print) initiates the print. The following figure is an example of a print dialog. Application Printer Setup Dialog The Printer entry field is the read-only name of the printer object (queue) that the user chose from the Printer Setup dialog. The Preview checkbox is used to preview the printed output on the screen. This can be achieved by opening an OD_MEMORY device context to the printer driver and drawing the picture into the bit map. A BITBLT (Bit Block Logical Transfer) to the screen shows the resultant page. System fonts should be used instead of device fonts. Once the user has initiated the print, a PM application must execute the following steps. 1. Create a new thread. Then, on this new thread: 2. Open a device context. 3. Associate a presentation space. 4. Start the print job. 5. Query the device capabilities. 6. Format the page. 7. Start the next page. Repeat steps 6 through 7 for each page. 8. End the print job. For another print job, repeat from step 4. 9. Disassociate the presentation space. 10. Close the device context. The following sections describe each of the above steps in turn. ═══ 10.2.2.5.1. Creating a New Thread ═══ Once the print process has been confirmed by the user. the application must use a separate thread to perform the actual printing. This maintains user responsiveness and avoids displaying the hourglass pointer. While the printing is in progress, the application should dim certain menu options, such as drawing. Other options, such as page down, zoom, or help still must be available. ═══ 10.2.2.5.2. Opening a Queued Device Context ═══ Before you can send data to a printer using device functions, you must open a device context with DevOpenDC. The parameters of DevOpenDC are influenced by the queue and job properties the user has chosen previously. DevOpenDC accepts the following parameters as input: hab The anchor-block handle from a WinInitialize call. lType The type of device context. This always is OD_QUEUED to specify a queued device context. pszToken The device-information token. Always use an asterisk (*) for this parameter to force the system to get device information from the pdopData parameter. lCount The number of data elements supplied in the pdopData parameter. The minimum number of parameters for a queued device context is 4. pdopData The device-context data area. This is a pointer to a structure of the type DEVOPENSTRUC. The elements of this structure are described below. hdcComp The compatible-device-context handle. This must be NULL for a device context of type OD_QUEUED. DevOpenDC returns a device-context handle of type HDC. The handle is used in other functions beginning with the Dev prefix and for GpiCreatePS and GpiAssociate. The DEVOPENSTRUC structure contains all the data needed to define a device context. The individual elements of the DEVOPENSTRUC structure are described below. At least the first four structure members must be provided for queued device contexts. pszLogAddress Name of the queue. It is the pszName field of the PRQINFO3 structure. Note: For device contexts of type OD_INFO, pszLogAddress is the port name. This can be retrieved by calling SplQueryDevice using the pszPrinters device name. The pszLogAddr field in the PRQINFO3 structure is the port name. pszDriverName Character string identifying the printer driver, for example, LASERJET. The pszDriverName field of the PRQINFO3 structure, associated with the required print queue, gives the driver and device name, separated by a period, for example LASERJET.HP LaserJet IIID The pszDriverName field can contain only the name up to the period, for example LASERJET. pdriv This is a pointer to the job properties data returned by the printer driver from DevPostDeviceModes or the default job properties from pDriverData in the PRQINFO3 structure. Note: The DRIVDATA structure contains the particular device name to be used. Therefore, it is a programming error to set this parameter to NULL. pszDataType It is recommended that PM_Q_STD always be used for the data type. pszComment Optional character string that the printer object displays to the user in a job settings notebook. It is recommended that the application include its own name in this comment string. Note: The job title text is derived from the document name. pszQueueProcName Queue processor name (optional). The queue processor (also termed queue driver) name is available from the pszPrProc field of the PRQINFO3 structure. The default queue processor provided by the operating system is PMPRINT. The user also can install a queue processor (PMPLOT) that is used to provide reverse clipping for vector devices such as plotters. For specialized applications, it is possible to use an alternative queue processor to the default specified for the queue. The list of installed queue processors is available from the OS2SYS.INI file using the application name PM_SPOOLER_QP. pszQueueProcParams Queue processor parameters (optional). They can include information such as the number of copies you want to print and the size of the output area on the printed page. See PMPRINT/PMPLOT Queue Processor Parameters for details. pszSpoolerParams Spooler parameters (optional) are separated by spaces. They are used for scheduling print jobs and are as follows:  The form names that identify the paper to be used, for example, FORM=A4,A5,ENV. The form names are optional, but if they are provided, the spooler is able to hold off printing the jobs until the required form is installed in the printer. If the form name is not provided, the spooler attempts to print the job. The printer driver recognizes that there is a forms problem and displays a FORMS MISMATCH message box.  Priority of the print job, for example, PRTY=60. The priority is specified as an integer in the range 1 through 99; 99 is the highest. The default priority value is 50. The application can use the spooler priority parameter to prioritize its own jobs. However, it is not good practice for an application always to use priority 99 in an attempt to get its jobs printed first. pszNetworkParams Optional parameter that can be used to specify network options; for example, USER=JOESMITH. ═══ 10.2.2.5.3. Associating a Presentation Space ═══ In order to print, a device context must be associated with a GPI presentation space (PS). In most circumstances, a presentation space already exists for the screen. In such cases, the PS can be disassociated with the window device context and associated with the printer device context by using GpiAssociate, as shown in the following figure. Reassociating Presentation Space with Device Contexts If a presentation space does not exist or a different one is to be used, the application must call GpiCreatePS and use the GPI_ASSOC flag to associate the printer device context. Device-Independence Considerations The operating system supports true WYSIWYG. The same GPI functions the application used to create the picture or document on the display screen can be used to create the output on a printer. This is the major advantage of device independence. An application must be designed around the options provided by the PM to ensure device independence, as a display (VGA) typically is 96 dpi, while a printer typically is 300 dpi. Following are some application design considerations:  Use DevQueryHardopyCaps to determine the horizontal and vertical width of the form and the maximum printable area.  Create a presentation space with a presentation page size of 0 to ensure that the maximum window size and maximum page size are used.  Use device-independent coordinates, such as LO_ENGLISH, or TWIPS. If you program in pels, transferring your output from screen to hard copy will compress the image, as shown in the following figure. An Effect of Programming in Pels Reassociating a presentation space defined in pels or other device dependent units can affect the dimension of the picture. If the pels are not square on the display device, the shape and scale (aspect ratio) will be different as well. ═══ 10.2.2.5.4. Starting a Print Job ═══ The application signals the beginning of a print job by using DevEscape with the escape parameter DEVESC_STARTDOC. The application must specify a document name; usually this is related to the name of file being printed. Any GPI calls made before this DevEscape (DEVESC_STARTDOC) are ignored. ═══ 10.2.2.5.5. Querying the Device Capabilities ═══ DevQueryCaps can be used to provide over 40 pieces of information about a specific device-for example, default character box size, horizontal and vertical resolution, or number of device-specific fonts. Knowing that the device has only 1-bit color support (monochrome) might influence the application to use line style and patterns instead of colors for output. ═══ 10.2.2.5.6. Formatting the Page ═══ Before print processing actually starts, it is recommended that an application's modal dialog be displayed, showing page progress and enabling the user to cancel the print job. If the user presses Cancel on this dialog, the application must call DevEscape with the parameter DEVESC_ABORTDOC. This allows the spooler and printer driver to clean up. A job is not created in the queue. Usually the output on a page is generated by a series of GPI calls from the application. By calculating the size of character strings or graphics written to the presentation space, the application must be able to decide when to move to the next page in a multi-page document. ═══ 10.2.2.5.7. Starting the Next Page ═══ When the application has finished processing a page, it must call DevEscape with the DEVESC_NEWFRAME parameter. The progress dialog must be updated. The DevEscape DEVESC_NEWFRAME can be used to generate blank pages. The printer driver always issues a page eject whenever this DevEscape is received. Issuing the DEVESC_NEWFRAME escape does not reset any attributes or fonts. However, the bounds and any clipping regions are reset. ═══ 10.2.2.5.8. Ending the Print Job ═══ The end of a print document is signalled by the application's calling DevEscape with the DEVESC_ENDDOC parameter. The spooler returns a job identifier that can be used for job manipulation. The following figure shows the processing carried out by a printer driver as it receives device escapes and graphics from the GPI. Flow for Device Escapes Note: Each device-escape pair of DEVESC_STARTDOC and DEVESC_ENDDOC creates one print job in a spooler queue. If the application needs to create multiple print jobs, use the following sequence: DevOpenDC GpiCreatePS DevEsape(DEVESC_STARTDOC) . . . DevEsape(DEVESC_ENDDOC) DevEsape(DEVESC_STARTDOC) . . . DevEsape(DEVESC_ENDDOC) DevCloseDC ═══ 10.2.2.5.9. Disassociating the Presentation Space ═══ When the print job is complete, the presentation space can be disassociated with the printer device context using GpiAssociate with a NULL parameter. Then the presentation space can be reassociated with the display device context. ═══ 10.2.2.5.10. Closing the Device Context ═══ A device context is closed using DevCloseDC. The print thread must signal print termination to the main processing loop. The main loop can terminate the print thread and dismiss the Page Progress message box. An application can display a message box to the user indicating a successful print and show the job ID returned by the spooler. ═══ 10.2.2.5.11. Print-to-File Considerations ═══ Print-to-file means that the print data destined for a printer is stored in a file instead. The advantage of doing this is that the file can be used later, possibly on a different machine or different environment, and the data printed without requiring the original application. The system provides three ways to print to file:  The user can specify Print to file on the Output settings page of a printer object. When a print is requested, the system displays a dialog in which the user can enter a file name. This method is preferred because the application does not have to be aware; the user has full control of the system.  The application can specify OD_DIRECT on a DevOpenDC call. The pszLogAddress field of the DEVOPENSTRUC structure specifies the file name as shown in the following example: C:\TMP\MYPRINT.DAT \\SERVER\DISK1\MYPRINT.DAT -- UNC file name \\PIPE\PRTPIPE1 -- A pipe LPT1 -- A port device  The application can create the printer-specific format data and write it to a file using DosOpen. ═══ 10.2.2.5.12. Network Printing Considerations ═══ The architecture of PM requires a printer driver during the print job creation process to deal with queries, such as DevQueryHardcopyCaps, and to provide the job properties dialog by way of DevPostDeviceModes. To do any printing across a network, a locally installed printer driver is required. In some cases, such as when the network server does not run PM, this is an advantage, in that all the conversion to printer-specific commands can be done on the requestor. The printer object in the workplace provides seamless access to network printers; the user need only install the appropriate printer driver. The application programmer also is helped. A network printer that is accessed by the user has a hidden shadow on the requestor. The job properties for the shadow printer object can be altered and are stored on the requestor. This enables the user to configure one or more variations on the original configuration without requiring intervention from a system administrator to create many network printer objects, each with a slightly different default job property configuration. The shadow printer object is created on the requestor by creating a local queue and local device with no port connection. The application can enumerate these queues using SplEnumQueue, as before. The only difference is in the PRQINFO6 structure; there are two extra fields not in the PRQINFO3 structure. These two extra fields, named pszRemoteComputerName and pszRemoteQueueName contain the name of the remote server and the remote queue. The spooler uses these fields to automatically reroute print data, submitted by an application to the local shadow, to the appropriate network queue. The printer object creates a local shadow only when the network printer object has been used or modified, because there could be a large number of network printer objects, and the spooler does not know which one the user wants to use. The local shadow of a network printer object is created in the following cases:  When a file is dragged and dropped on the network printer object  When the network printer object is moved, copied, or shadowed outside its original server folder  When the printer or job properties are modified ═══ 10.2.2.5.13. Drag/Drop Protocol Considerations ═══ When an application data file is dropped on a printer object, the application can receive a DM_PRINTOBJECT message if the application is running currently. One DM_PRINTOBJECT parameter gives a DRAGITEM structure that describes the object that was dropped. The other parameter gives a PRINTDEST structure that contains all the parameters required to call DevPostDeviceModes and DevOpenDC. The PD_JOB_PROPERTY flag indicates to the application that the user has requested a job properties dialog before printing. If this flag is not set, the application must not display the job properties dialog; it must use the job properties passed in the PRINTDEST structure. The rest of the printing process follows the procedure described in Submitting a Queued Presentation Manager Print Job. ═══ 10.2.2.5.14. PMPRINT/PMPLOT Queue Processor Parameters ═══ How the queue processor processes a print job is controlled by the optional queue-processor parameters that you can specify in the pdopData parameter of DevOpenDC. The PM adds these parameter values to the spool file. The PMPRINT/PMPLOT queue processor parameters enable an application to do the following:  Specify the number of copies of a print job  Restrict printing to a specific area on the page  Specify which part of a picture is to be printed  Specify color output (if your printer allows this)  Specify the foreground and background colors in a monochrome print Note: The application need not use queue processor parameters if all that is required is a single copy of a picture, scaled to fit the page. These are the default settings of the queue-processor parameters. The first parameter (COP) is used for all spool-file formats. The remaining parameters are valid for PM_Q_STD spool files only. Because PM_Q_STD data are used mainly for graphic data, these parameters are described in relation to the printing of picture files. The PMPRINT/PMPLOT queue-processor parameters are separated by spaces and are: COP=n The COP parameter specifies the number of copies of the spool file that you want printed. The value of n must be an integer in the range of 1 through 999. The default is COP=1. ARE=C | w,h,l,t The ARE parameter determines the size and position of the output area. This is the area of the physical page to which printing is restricted. The default value of ARE=C means that the output area is the whole page. Note, however, that the printer cannot print outside its own device clip limits. To size and position the output area at a specific point on the page, use ARE=w,h,l,t, where: w, h are the width and height of the desired output area l, t are the offsets of the upper-left corner of the output area from the left (l) and from the top (t) of the maximum output area These four values must be given as percentages of the maximum output dimensions. The maximum output area is the area within the device clip limits. FIT=S | l,t The FIT parameter determines which part of the picture is to be printed. You can request the whole of the picture, scaled to fit the output area; or you can position the picture (actual size) anywhere within the output area. This could mean that the picture is clipped at the boundaries of the output area. The default value of FIT=S causes the output to be scaled until the larger of the height or width just fits within the defined output area. The aspect ratio of the picture is maintained. To print the picture in actual size, use FIT=l,t, where l,t are the coordinates of the point in the picture that you want positioned at the center of the output area: l is measured from the left edge of the picture, and t is measured from the top edge. The coordinates must be given as percentages of the actual dimensions of the picture. XFM=0 | 1 The XFM parameter enables you to override the picture-positioning and clipping instructions that are provided by the ARE and FIT parameters, including their defaults. The default value of XFM= allows the appearance of the output to be determined by the settings of the ARE and FIT parameters. A value of XFM=0 yields output as specified in the picture file. For example, applications that use many different forms can define different positions on each form for their output. COL=M | C The COL parameter enables you to specify color output if you have a color printer. A value of COL=M creates monochrome output (black foreground with no background color). This is supported by all devices. A value of COL=C creates color output. If you request color output on a monochrome device, the printer presentation driver tries to satisfy your request, which can cause problems because the only color available is black. For example, if the picture file specifies a red line on a blue background, both are drawn in black. The default is COL=M when you are addressing a monochrome printer and COL=C when you are addressing a color printer. MAP=N | A The MAP parameter enables you to decide how the neutral colors (those that are not specified in the picture file) are printed. The default value of MAP=N yields a normal representation of the screen picture on a printed page, which means that the page background is white and the foreground is black. A value of MAP=A provides the reverse of the normal representation: the background is black and the foreground is white on the printed page.. Note: Pictures from a spool file can be printed differently than those printed when the spooler is not selected, because the default setting without the spooler is to print pictures their actual size, whereas the default for the queue-processor FIT parameter is "scaled to fit" the output area. The queue-processor parameters must be separated by one or more blank spaces; for example, "COP=3 ARE=C FIT=S". The parameters can be listed in any order. Default values are used for parameters that are omitted or entered incorrectly. Bit-map or image data (data constructed by setting pels on or off) is not affected by the ARE and FIT parameters. Consequently, if your picture contains bit-map or image data, the printed version will be different from the screen version if you use these parameters. ═══ 10.2.2.5.15. Examples Using the ARE and FIT Parameters ═══ The application uses the ARE and FIT parameters to determine which part of the picture is printed, and where on the physical page it is printed. The following figure provides practical examples of how to use these parameters. Examples Using the ARE and FIT Parameters ═══ 10.2.3. Submitting a Direct Presentation Manager Print Job ═══ PM direct printing is done through a device context of type OD_DIRECT, as follows: 1. Output from the PM printer driver goes directly to the printer instead of to the spooler. 2. The application must specify OD_DIRECT in the DevOpenDC function. 3. The pszLogAddress field of the DEVOPENSTRUC structure is a port name (for example LPT1). The port name is held in the pszLogAddr field of the PRDINFO3 structure returned by SplEnumDevice or SplQueryDevice. 4. All fields following the pdriv field in the DEVOPENSTRUC structure are ignored by the system. The remaining steps in the printing process are the same as those for OD_QUEUED device contexts. ═══ 10.2.4. Submitting a Print Job Directly to the Spooler ═══ The spooler provides functions that enable applications to submit print data directly to a spool queue. Normally, these functions are used by printer drivers to add a print job to a spool queue. However, this is not a recommended method unless the application is special-purpose. The advantage of submitting print data directly to a spool queue is to bypass the GPI presentation layer. This can be useful, particularly, for sending print jobs to a network printer that is on a server that does not run the OS/2 operating system. However, there are certain requirements for direct spooling:  Because the data bypasses the printer presentation driver, it must be in a format the printer can understand. Therefore, the application must be aware of and send the printer-specific commands.  If the spooler is not active, the print jobs never will be printed. The following steps are required to create a print job using the spooler directly: 1. Use SplQmOpen to open the PM. (Functionally, this is similar to using DevOpenDC, which is detailed in Opening a Queued Device Context.) You must specify a queue name of PMQOPENDATA for the logical address element, pszLogAddress. PMQOPENDATA is a data structure, identical to DEVOPENSTRUC, to be used with the SplQmxxx functions. 2. Use SplQmStartDoc to signal the start of your document. (This is same as using DevEscape with DEVESC_STARTDOC as used in PM printing.) 3. Use SplQmWrite to write data to the spool file. 4. Use SplQmEndDoc to signal the end of your document. (This is the same as DevEscape with DEVESC_ENDDOC as used in PM printing.) 5. Use SplQmClose to close the PM. (Functionally, this is similar to DevCloseDC.) ═══ 10.2.5. Spooler Management and Configuration ═══ The spooler provides a set of functions that allows management of all aspects of the print subsystem. There are five categories:  Job querying and manipulation (SplxxxJob)  Queue creation, querying, and manipulation (SplxxxQueue)  Device creation, querying, and manipulation (SplxxxDevice  Listing ports, printer drivers, queue processors (SplEnumyyy)  Listing printers across a network (SplEnumPrinter) The symbol xxx typically represents Add, Delete, Enum, Query, and Set. For jobs and queues, xxx also includes Hold and Release. For devices, xxx includes Control. The symbol yyy is either Port, PrinterDriver, or QueueProcessor. It is anticipated that most applications will not use any spooler functions at all except SplEnumQueue, SplQueryQueue, and SplQueryDevice. However, there are some specialized applications that might use the spooler functions for the following:  An administrative tool to manage queues and jobs  An automatic printer object configurator A new printer object can be created by using SplCreateDevice and SplCreateQueue. The print subsystem recognizes that this has occurred and puts a printer object directly on the desktop. When the spooler is disabled, the following spooler functions do not return any results: SplControlDevice SplCopyJob SplDeleteJob SplEnumJob SplQueryJob SplReleaseJob SplSetJob No function is available to enable or disable the spooler under application control; this is a user decision. It is recommended that the spooler always be enabled. ═══ 10.2.5.1. Print Job Management ═══ Some sophisticated applications might need to manipulate jobs in the following ways after they have been spooled into a queue:  Modify the job parameters (for example, copies); use SplSetJob.  Increase the priority of a particular job; use SplSetJob.  Delete a job because a job based on newer data was created; use SplDeleteJob. ═══ 11. Presentation Spaces and Device Contexts ═══ A presentation space is a data structure maintained by the operating system in which information relevant to the graphic output is stored. The information is related to both the subsequent drawings (such as colors or line styles) and the presentation space resources (such as color tables or fonts). The first task in a graphics application is to define a presentation space, because so many of the GPI functions must operate within them. A presentation space is required for each output device currently in use by your application, including each separate window on the display screen. In almost all cases, the presentation space is set up to be device-independent, because the requirements of each possible output device are so different. Note: In some cases, it is possible to disassociate a presentation space from one device and associate it with another, thereby allowing the presentation space to be shared. To facilitate the device independence of the PM programming interface, all device-specific information is held in a device context. A device context is a data structure that identifies a particular instance of an output device and contains all the device-specific information, such as the logical name of the device and the presentation driver name. Each separate instance of an output device that you intend to use must be described in a device context. For example, if a single application uses more than one window, each of those windows must have its own window device context. The applicable device context, then, must be associated with the presentation space in order to send graphics data to that output device. This chapter describes presentation spaces and device contexts. The following topics are related to the information in this chapter:  Graphics primitives  Coordinate spaces and transformations  Graphics segments ═══ 11.1. About Presentation Spaces ═══ There are three types of presentation spaces:  Standard micro  Cached micro  Normal ═══ 11.1.1. Micro Presentation Spaces ═══ You need a micro presentation space if your application creates a separate presentation space for each output device instance and if its output is a simple drawing. Although run time memory requirements vary according to the graphics function an application uses, a typical micro presentation space graphical application uses 315KB of GPI, engine, and display memory resource (code and data). A micro presentation space cannot be reassociated with a different device. ═══ 11.1.1.1. Standard Micro Presentation Space ═══ Use a standard micro presentation space for drawing on any type of output device, provided the presentation space is not in retain mode or retain and draw mode. There are two different functions you can use to access a standard micro presentation space. The following table lists both functions and their considerations. ┌───────────────┬──────────────────────────────┬───────────────┐ │Function Name │Usage │Closing │ │ │ │Function │ ├───────────────┼──────────────────────────────┼───────────────┤ │GpiCreatePS │Accepts an anchor handle, a │GpiDestroyPS │ │ │device-context handle, and a │destroys a │ │ │presentation space size as │presentation │ │ │parameters. Creates both │space and │ │ │normal presentation spaces and│releases all │ │ │micro presentation spaces. │resources owned│ │ │ │by the │ │ │ │presentation │ │ │ │space. │ ├───────────────┼──────────────────────────────┼───────────────┤ │WinGetScreenPS │The presentation space │WinReleasePS │ │ │represents the entire display │ │ │ │screen. Warning: Exercise │ │ │ │caution when using this │ │ │ │function as the graphic output│ │ │ │can overlap individual │ │ │ │windows. │ │ └───────────────┴──────────────────────────────┴───────────────┘ ═══ 11.1.1.2. Cached Micro Presentation Space ═══ The window manager maintains a cache of micro presentation spaces for windows on a display screen. The cache is provided for applications that use a large number of windows, and where each window requires a temporary presentation-space device-context pair for a short sequence of output operations. These presentation spaces belong to the system rather than to your application and are allocated only on a temporary basis. Cached micro presentation spaces are provided by the window system rather than by the GPI. Their use is synchronized with other window activities. For example, you need not associate a cached micro presentation space with the display screen. The window manager does this for you. Cached micro presentation spaces offer the best system performance because, unlike normal presentation spaces and standard micro presentation spaces, they are not permanently allocated to an application. However, cached micro presentation spaces can be cumbersome to use because all the attributes must be initialized continually. Use a cached micro presentation space to send output only to a window on the display device. There are three different functions you can use to access a cached micro presentation space, each with its own considerations. These functions are listed in the following table. ┌───────────────┬──────────────────────────────┬───────────────┐ │Function Name │Usage │Closing │ │ │ │Function │ ├───────────────┼──────────────────────────────┼───────────────┤ │WinBeginPaint │Accepts a NULL presentation │WinEndPaint │ │ │space handle for a cached │automatically │ │ │micro presentation space. The │releases the │ │ │presentation space created by │presentation │ │ │this function is already │space, no │ │ │preassociated with the window │matter what │ │ │device context, making this │type. │ │ │the easiest function to use. │ │ │ │Usually this type of creation │ │ │ │is in response to a WM_PAINT │ │ │ │message. │ │ ├───────────────┼──────────────────────────────┼───────────────┤ │WinGetScreenPS │The presentation space │WinReleasePS │ │ │represents the entire display │ │ │ │screen. │ │ │ │Warning: Exercise caution │ │ │ │when using this function as │ │ │ │the graphic output can overlap│ │ │ │individual windows. │ │ ├───────────────┼──────────────────────────────┼───────────────┤ │WinGetPS │The presentation space can │WinReleasePS │ │ │represent the entire desktop, │ │ │ │or any other window. │ │ │ │The presentation space can be │ │ │ │used to process any message, │ │ │ │but it must be returned to the│ │ │ │cache when message processing │ │ │ │is complete. │ │ └───────────────┴──────────────────────────────┴───────────────┘ In general, use a cached micro presentation space to process a single paint message when no presentation space information needs to be remembered between messages. The presentation space must be both obtained and released during the processing of that message. All application information stored in a cached micro presentation space is lost as soon as it is released to the cache. You must provide a window handle on input to WinBeginPaint and WinGetPS. The resulting presentation space is defined specifically for that window, and cannot be reassociated. The cached micro presentation space is always:  Defined in pels-although you can change the units using GpiSetPS  Formatted GPIF_LONG  Given a suitable size by the system. When you finish using a cached micro presentation space, you do not have to disassociate it from the window device context because WinReleasePS or WinEndPaint performs the disassociation. This makes the cached micro presentation space available for use in other windows. The presentation space itself cannot be deleted. Cached micro presentation spaces are used serially. The next time you need a cached presentation space, access a new one using the appropriate function. Each time you get a cached micro presentation space, graphics attributes are reset to their default values. ═══ 11.1.2. Normal Presentation Spaces ═══ You must use a normal presentation space if you require your application to use the same presentation space to send output to multiple devices (a display screen and printer, for example), or if it uses the segment and retained-drawing functions to generate complex drawings. There is only one function you can use to create a normal presentation space: ┌───────────────┬──────────────────────────────┬───────────────┐ │Function Name │Usage │Closing │ │ │ │Function │ ├───────────────┼──────────────────────────────┼───────────────┤ │GpiCreatePS │Accepts an anchor handle, a │GpiDestroyPS │ │ │device-context handle, and a │destroys a │ │ │presentation space size as │presentation │ │ │parameters. Creates both │space and │ │ │normal presentation spaces and│releases │ │ │micro presentation spaces. │ │ └───────────────┴──────────────────────────────┴───────────────┘ If a normal presentation space is used, or if metafiling is carried out, more run time memory is used than if a micro presentation space was used. A normal presentation space requires 114KB more than a micro presentation space. ═══ 11.1.3. Modal Graphic Systems ═══ The graphic output sent to the presentation space is created by graphic primitives, such as straight or curved lines. How those primitives appear depends in part on the mode of the presentation space. In modal systems, certain information that modifies a graphic primitive is established before you use the instruction to draw the primitive. The following figure is an example of a red, solid line being drawn from (4,3) to (9,7). With PM's modal interface, the only value you need to supply to GpiLine is the end point (9,7). Line Drawn with GpiLine The line is drawn automatically with the current color, red, in the current line type, solid, and starting from the current position, (4,3). There are separate functions for specifying the current color, line type, and position. In nonmodal graphics systems, you supply information relevant to an instruction when you use that instruction. For example, you could use a line-drawing instruction in which you would specify that the line is to be green, dotted, and drawn from point a to point b. Those values or attributes are bound to a particular drawing instruction, and affect no other. If you are going to continue the line from point b to point c, you must again specify "green", "dotted", "point b", and finally, "point c". For the PM programming interface, the default values for the graphics primitives (or current values if the defaults have been modified) are stored in the presentation space along with the current position. While at first it might seem like many functions are necessary to perform one step, such as drawing a line, a modal graphics system actually saves resources. After you perform the first line draw, chances are that if you draw a second or third line, the line attributes are not likely to change; that is, the mode of the presentation space remains the same. Thus, the constant repetition of attributes in a nonmodal graphics system actually uses more resources if the desired output requires more than one or two graphics functions. It is possible to define graphics, and store their definitions, without sending them to a screen or a printer. In these situations, the concept of attribute currentness becomes relevant. The color of a line on a screen, for example, is the color that was current when you defined the line. This is not always the color that is current when the line is drawn. ═══ 11.1.4. Current Position ═══ The current position is the world-coordinate space position at which the next drawing request begins. It is part of the data stored in the presentation space. When you create or obtain a presentation space, the current position is set to the origin (0,0). The current position also is reset to (0,0) whenever a presentation space is associated with a different device context. Most drawing requests update the current position. If you draw a line from the origin to (3,5), for example, the current position is updated to (3,5). The current position also can be updated explicitly by GpiSetCurrentPosition or GpiMove. If you do not want the first drawing in a presentation space to start at (0,0), call GpiSetCurrentPosition first. ═══ 11.1.5. Primitive Attributes ═══ The graphics primitives and the functions that draw them are discussed in Line and Arc Primitives through Fonts. The primitive's function allows the attributes of the primitive to be set for all subsequent use of that primitive. The attributes are stored in data structures called bundles. There are functions that allow you to set the attributes of the primitives before the drawing of any primitive is performed. GpiSetAttrs allows you to not only specify the primitive for which the attributes are going to be set, but also, the settings for the specific attributes. GpiQueryAttrs returns the current values of specified attributes for specified primitives. Two other functions, GpiSetAttrMode and GpiQueryAttrMode, enable you to define or query the attribute mode settings, AM_PRESERVE and AM_NOPRESERVE. The AM_PRESERVE setting preserves the value of an attribute any time that attribute is changed. The previous value can be recovered easily if, for example, you need six dotted lines, one solid line, then six more dotted lines. The AM_NOPRESERVE setting discards the previous value of an attribute once the value is changed. The values of the attributes are presentation space resources. ═══ 11.2. Using Presentation Spaces ═══ You can use presentation-space functions to:  Create a normal, micro, or cached micro presentation space  Delete, save, or restore a presentation space  Define or determine the presentation space attributes ═══ 11.2.1. Obtaining and Creating a Presentation Space ═══ Normal presentation spaces and micro presentation spaces are created using GpiCreatePS. Cached micro presentation spaces are created using WinBeginPaint or WinGetPS. ═══ 11.2.2. Deleting a Presentation Space ═══ A presentation space consumes a considerable amount of memory, so you should delete it when your application no longer requires it. Use GpiDestroyPS to delete either a normal or micro presentation space. When you finish using a cached micro presentation space that you accessed with WinGetPS, release it with WinReleasePS. You need not delete a presentation space that you accessed with WinBeginPaint. PM does this for you when you call WinEndPaint. ═══ 11.2.3. Saving and Restoring a Presentation Space ═══ You can save certain attributes and resources of a presentation space, modify its fields, draw in the modified presentation space, then restore it with GpiSavePS and GpiRestorePS. When you call GpiSavePS, the graphics engine copies the following items from the current presentation space onto a special stack:  Primitive attributes  Transformation matrixes  Viewing limit  Clip path  Clip region  Current position  Loaded logical color table  Loaded logical font You can push the contents of a presentation space on the stack as many times as is necessary. GpiRestorePS pops the contents of a presentation space off the stack. ═══ 11.2.4. Presentation Spaces Review ═══ The following table summarizes the features and restrictions of each type of presentation space. Presentation Space Features and Restrictions ┌────────────────────┬─────────────┬─────────────┬──────────────┐ │Feature/Restriction │Normal │Standard │Cached Micro │ │ │ │Micro │ │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Device types │Any device │Any device │Video-display │ │supported │ │ │window only │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Number of supported │Multiple │One │One │ │devices │ │ │ │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Association │Associate and│Associate at │N/A. │ │ │disassociate │creation; │ │ │ │as required. │cannot │ │ │ │ │disassociate.│ │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Retained graphics │Yes │No │No │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Available GPI │All functions│All except │All except │ │functions │ │segment │segment │ │ │ │functions │functions │ ├────────────────────┼─────────────┼─────────────┼──────────────┤ │Memory │Highest │Medium memory│Quickest │ │considerations │memory usage │usage │allocation │ └────────────────────┴─────────────┴─────────────┴──────────────┘ ═══ 11.3. About Device Contexts ═══ Device contexts link presentation spaces to devices by converting device-independent presentation space information into device-dependent information. This conversion occurs in the presentation driver, a low-level program that is transparent to the application. A presentation driver is device-driver code that converts the application commands into output commands specific for each output device. After creating a device context, it must be associated with a presentation space before the drawing (or primitives) can be printed or displayed. When a presentation space and a device context are associated with each other, any output you direct to the presentation space is directed automatically at the device context and displayed on the physical device. For example, before you can draw a picture in a display window, the picture's graphics presentation space must be associated with the window's device context. Device contexts also give applications access to important device information such as screen dimensions or printer capabilities. As with presentation spaces, there are three types of device contexts:  Cached  Window  Normal ═══ 11.3.1. Cached Device Contexts ═══ A cached device context is one that already is associated with a cached presentation space when that space is obtained from the cache. ═══ 11.3.2. Window Device Contexts ═══ Window device contexts are a special type, in that they are the only device contexts obtained with WinOpenWindowDC. As their name implies, the output device they represent is a display window. WinOpenWindowDC accepts a window handle as input and returns the window device context handle. The window device context handle can then be associated with a standard micro presentation space or a normal presentation space. The window device context is closed automatically when its associated window is deleted. ═══ 11.3.3. Normal Device Contexts ═══ A normal device context (also called a standard or noncached device context) links a presentation space with any nonwindow output device. Use DevOpenDC to obtain a device context handle to one of the six normal device contexts listed in the following table. Each of the six normal device contexts must be closed by DevCloseDC before your application is closed. ┌────────────────────┬────────────────────┬────────────────────┐ │DC Type │Purpose │Usage │ ├────────────────────┼────────────────────┼────────────────────┤ │Queued │Links a presentation│Applications use │ │ │space with a printer│queued device │ │ │or plotter shared by│contexts to offload │ │ │multiple │printing control │ │ │applications sending│from the │ │ │spooled print jobs │application. │ │ │to the print queue. │ │ │ │Queued device │ │ │ │contexts store print│ │ │ │jobs by using a │ │ │ │program called print│ │ │ │spooler, which keeps│ │ │ │track of the order │ │ │ │in which the jobs │ │ │ │arrive at the │ │ │ │printer and in which│ │ │ │they are printed. │ │ ├────────────────────┼────────────────────┼────────────────────┤ │Direct │Links a presentation│Applications │ │ │space with a printer│normally do not use │ │ │or plotter, directly│direct device │ │ │bypassing the │contexts, unless │ │ │spooler and print │they are avoiding │ │ │queue. A direct │the queue (for │ │ │device context is │security reasons) or│ │ │used by the spooler │going directly to a │ │ │to process jobs as │dedicated machine. │ │ │they are removed │ │ │ │from the print │ │ │ │queue. │ │ ├────────────────────┼────────────────────┼────────────────────┤ │Information │Links a presentation│An application can │ │ │space with a printer│use an information │ │ │or plotter, directly│device context with │ │ │enabling device │lower memory │ │ │information to be │overhead, rather │ │ │queried, but │than use a direct │ │ │producing no output │device context, │ │ │on the device. │which could provide │ │ │ │the same │ │ │ │information. │ ├────────────────────┼────────────────────┼────────────────────┤ │Memory │Links a presentation│Applications use │ │ │space with a bit │memory device │ │ │map. │contexts for drawing│ │ │ │to the bit map and │ │ │ │using it as a source│ │ │ │or target of BitBlt │ │ │ │operations. │ ├────────────────────┼────────────────────┼────────────────────┤ │Metafile │A special device │Only applications │ │ │context that enables│that use metafiles │ │ │a picture output to │use metafile device │ │ │its associated │contexts. │ │ │presentation space │ │ │ │to be recorded in a │ │ │ │metafile for │ │ │ │interchange for │ │ │ │future use. │ │ ├────────────────────┼────────────────────┼────────────────────┤ │Metafile_NoQuery │Functionally │If attributes of the│ │ │identical to │presentation space │ │ │metafile; however, │are not to be │ │ │querying of │queried, this device│ │ │presentation space │context offers │ │ │attributes is not │improved performance│ │ │allowed. │over metafile. │ └────────────────────┴────────────────────┴────────────────────┘ ═══ 11.4. Using Device Contexts ═══ In addition to associating or disassociating presentation spaces with device contexts, you can use device context functions to:  Obtain or create a device context  Associate a device context with a presentation space  Close a device context  Retrieve information about a device's capabilities ═══ 11.4.1. Creating a Device Context ═══ You can create a normal device context by calling DevOpenDC. This function requires that you specify one of the six normal types. It also requires that you pass certain device-initialization data, including a logical address, the device-driver name, device-driver data, a description of the device type, and information about the queue (if the device is a queued device). The device-initialization data is passed in a DEVOPENSTRUC structure. The following figure is an example of this structure. typedef struct _DEVOPENSTRUC { /* dop */ PSZ pszLogAddress /* Logical-device address */ PSZ pszDriverName /* Device-driver name */ PDRIVDATA pdriv /* Pointer to extra driver data */ PSZ pszDataType /* Type of queued data */ PSZ pszComment /* Optional spooler info */ PSZ pszQueueProcName /* Queue-processor name */ PSZ pszQueueProcParams /* Queue-processor arguments */ PSZ pszSpoolerParams /* Spooler arguments */ PSZ pszNetworkParams /* Network arguments */ } DEVOPENSTRUC; The last four fields in this structure apply only to queued devices. The following figure shows how to create a nondisplay device context for a printer. HDC hdcPrinter; /* Handle of printer device context */ HAB hab; /* Anchor-block handle */ DEVOPENSTRUC dop; /* Device information */ dop.pszLogAddress = "lpt1"; /* Logical-device address */ dop.pszDriverName = "EPSON"; /* Device-driver name */ dop.pdriv = (PDRIVDATA) NULL; /* Pointer to driver data */ dop.pszDataType = "PM_Q_STD"; /* Standard queued data */ hdcPrinter = DevOpenDC(hab, OD_DIRECT, /* Direct device type */ "*", /* No data in OS2.INI */ 4, /* Use first 4 fields in dop structure */ (PDEVOPENDATA) &dop, (HDC) NULL); The following figure is an example of how to create a standard device context for a metafile. HDC hdcMeta; /* Handles of metafile */ /* and window DCs */ HAB hab; /* Anchor-block handle */ DEVOPENSTRUC dop; /* Device information */ dop.pszLogAddress = NULL; /* Logical-device address */ dop.pszDriverName = "DISPLAY"; /* Device-driver name */ hdcMeta = DevOpenDC(hab, OD_METAFILE, /* Metafile DC */ "*", /* No data in OS2.INI */ 2, /* Use first 2 fields in dop */ (PDEVOPENDATA) &dop, /* Structure for system info */ NULL) /* Compatible with screen */ ═══ 11.4.2. Associating Presentation Spaces with Device Contexts ═══ Drawing graphic objects requires a presentation space and a device context to direct output to a specific instance of an output device, such as a display window or a printer. This association enables the device context to identify the output device for that presentation space. Further, the device context identifies the particular instance of the output device, such as a printer or display window. A presentation space can be associated with only one device context at a time. The reverse is also true: a device context can be associated with only one presentation space at a time. The following figure shows how a presentation space is associated with a window device context. It is then disassociated from the window device context and associated with a printer device context. It cannot be associated with both device contexts simultaneously. WM_Create: hdcScreen = WinOpenWindowsDC (hwnd); phs = GpiCreatePS (...GPIA.Assoc); . . . WM_COMMAND: Case IDM_File PRINT: /* Device selection */ hdcPrinter = DevOpenDC (...); GpiAssociate (hps, NULL); /* Disconnect from screen */ GpiAssociate (hps, hdcPrinter); /* Connect to printer */ . . /* Output */ . GpiAssociate (hps, NULL); /* Disconnect from print */ GpiAssociate (hps, hdcScreen); /* Reconnect to screen */ . . . WM_PAINT: WinBeginPaint (hwnd, hps, NULL); . . /* Output */ . The following figure shows how to open a window device context and associate it with a normal presentation space. HDC hdcWin; /* Window device-context handle */ HPS hpsWin; /* Normal-presentation-space handle */ HWND hwndClient; /* Client-window handle */ HAB hab; /* Anchor-block handle */ SIZEL sizlPage; /* Presentation page */ hdcWin = WinOpenWindowDC(hwndClient); hpsWin = GpiCreatePS(hab, hdcWin, &sizlPage, PU_LOENGLISH | GPIA_ASSOC); Note: This type of code is used when the device context is defined before the presentation space. WinOpenWindowDC can be called only once for a particular window and returns an error if called a second time. WinQueryWindowDC can be used to obtain a window device context previously allocated using WinOpenWindowDC. The following figure shows how to create a presentation space with page units of 0.01 inch (PU_LOENGLISH) and associate it with a printer device context. As input to GpiCreatePS, you supply the height and width of the presentation page. HAB hab; /* Anchor-block handle */ HPS hpsPrinter; /* Presentation-space handle */ HDC hdcPrinter; /* Device-context handle */ SIZEL sizlPage; /* Page structure */ . . . hpsPrinter = GpiCreatePS(hab, hdcPrinter, &sizlPage, PU_LOENGLISH | GPIA_ASSOC); ═══ 11.4.3. Closing a Device Context ═══ To close a device context that your application opened with DevOpenDC, call DevCloseDC. However, you should not try to close a device context that you opened with WinOpenWindowDC. The operating system does this automatically when the associated window is deleted. ═══ 11.4.4. Determining Device Capabilities ═══ Once you have created a device context for a particular output device, you can determine the capabilities of that device by calling DevQueryCaps. This function retrieves the following information:  Device technology (whether the device is a raster or vector device)  Maximized window dimensions (if the device is a video display)  Page dimensions (if the device is a printer or plotter)  Character-box dimensions  Marker-box dimensions  Pel resolution  Color capabilities  Mix-mode capabilities You can use this information, for example, to select fonts, set up the presentation page, or create a new logical color table. ═══ 12. Paths ═══ A path is a graphics object composed of one or more figures drawn with graphic primitives. A path can be used for defining a filled area, a complex clipping shape, an outline, and for drawing geometric wide lines. The following topics are related to information in this chapter:  Presentation spaces and device contexts  Line and arc primitives  Area primitives  Color and mix attributes  Regions  Clipping ═══ 12.1. About Paths ═══ Paths provide several useful drawing techniques including:  An alternate means of generating filled or outlined irregular figures and nonrectangular shapes  An efficient means of producing hollow text in an outline font  The only means of clipping (restricting the area of interest of a picture) to circular, elliptical, or other nonrectangular figures  The only means of drawing lines with a thickness that can be transformed These techniques are respectively illustrated in the following figures: Drawing Techniques Achieved with Paths A path is similar to an area, but there are fundamental differences between the two. The following table describes their similarities and contrasts. ┌──────────────────────────────┬──────────────────────────────┐ │Paths │Areas │ ├──────────────────────────────┼──────────────────────────────┤ │Functions that define a path │Functions that define an area │ │are bracketed by GpiBeginPath │are bracketed by GpiBeginArea │ │and GpiEndPath. │and GpiEndArea. │ ├──────────────────────────────┼──────────────────────────────┤ │Paths are defined in world │Areas are defined in world │ │coordinates. │coordinates. │ ├──────────────────────────────┼──────────────────────────────┤ │Paths can be modified before │Areas are displayed │ │being displayed or used for │immediately on completion. │ │clipping. │ │ ├──────────────────────────────┼──────────────────────────────┤ │Paths can be used by │Areas cannot be used as │ │applications to perform │clipping regions. │ │clipping. │ │ ├──────────────────────────────┼──────────────────────────────┤ │Paths can be converted into │Areas cannot be converted into│ │graphics objects called │regions. │ │regions. │ │ ├──────────────────────────────┼──────────────────────────────┤ │Six operations can be │Only two operations can be │ │performed on paths, each │performed on areas (specified │ │requiring a separate function:│with options when creating the│ │ │area): │ │Outline │ │ │Fill │Outline │ │Modify │Fill │ │Stroke │ │ │Convert to clip path │ │ │Convert to region │ │ └──────────────────────────────┴──────────────────────────────┘ ═══ 12.1.1. Path Attributes ═══ Paths do not have a separate ...BUNDLE data structure associated with them. Their attributes are defined by LINEBUNDLE and AREABUNDLE. There are certain line attributes that apply only to geometric lines, or lines created with some path operations. Depending on the purpose of a path, only certain path attributes are in effect. These and the other path attributes are described in this chapter. When an application creates a presentation space, the path attributes are set to the default values shown in the following table. Path Attribute Default Values ┌────────────────┬────────────────┬────────────────────────────┐ │Attribute │Default Value │Function that Redefines │ │ │ │Attribute │ ├────────────────┼────────────────┼────────────────────────────┤ │Geometric width │None │GpiSetLineWidthGeom │ ├────────────────┼────────────────┼────────────────────────────┤ │End │LINEEND_FLAT │GpiSetLineEnd │ ├────────────────┼────────────────┼────────────────────────────┤ │Join │LINEJOIN_BEVEL │GpiSetLineJoin │ ├────────────────┼────────────────┼────────────────────────────┤ │Width │1.0 │GpiSetLineWidth │ ├────────────────┼────────────────┼────────────────────────────┤ │Type │LINETYPE_SOLID │GpiSetLineType │ ├────────────────┼────────────────┼────────────────────────────┤ │Color │CLR_NEUTRAL │GpiSetAttrs (LBB_COLOR) │ ├────────────────┼────────────────┼────────────────────────────┤ │Mix mode │FM_OVERPAINT │GpiSetAttrs (LBB_MIX_MODE) │ ├────────────────┼────────────────┼────────────────────────────┤ │Pattern symbol │Solid │GpiSetPattern │ ├────────────────┼────────────────┼────────────────────────────┤ │Pattern set │LCID_DEFAULT │GpiSetPatternSet │ ├────────────────┼────────────────┼────────────────────────────┤ │Reference point │(0,0) │GpiSetPatternRefPoint │ ├────────────────┼────────────────┼────────────────────────────┤ │Foreground color│CLR_NEUTRAL │GpiSetAttrs (ABB_COLOR) │ │ │(black on most │ │ │ │devices) │ │ ├────────────────┼────────────────┼────────────────────────────┤ │Background color│CLR_BACKGROUND │GpiSetAttrs (ABB_BACK_COLOR)│ │ │(white on most │ │ │ │devices) │ │ ├────────────────┼────────────────┼────────────────────────────┤ │Foreground mix │FM_OVERPAINT │GpiSetAttrs (ABB_MIX_MODE) │ ├────────────────┼────────────────┼────────────────────────────┤ │Background mix │BM_LEAVEALONE │GpiSetAttrs │ │ │ │(ABB_BACK_MIX_MODE) │ │ │ │Geometric width, End, and │ │ │ │Join take effect only when a│ │ │ │path is converted to a │ │ │ │geometric wide line using │ │ │ │GpiStrokePath or │ │ │ │GpiModifyPath. │ │ │ │Width, Type, Color, and Mix │ │ │ │mode take effect only when a│ │ │ │path is outlined using │ │ │ │GpiOutlinePath. │ │ │ │Pattern symbol, Pattern set,│ │ │ │and Reference point take │ │ │ │effect only when a path is │ │ │ │filled using GpiFillPath or │ │ │ │GpiStrokePath. │ └────────────────┴────────────────┴────────────────────────────┘ ═══ 12.1.2. Line Width and Geometric Width for Paths ═══ Cosmetic lines represent the mathematical ideal of a one-dimensional line. The width attribute associated with them is provided only for ease of drawing these lines larger than one pel. In contrast, geometric line width is not an attribute; it is a geometric property. To set the width of a geometric line, an application can use GpiSetLineWidthGeom. This geometric width takes effect only when a path is converted to a geometric wide line using GpiStrokePath or GpiModifyPath. If a geometric line is drawn before the geometric width is specified, the drawn line is defined by the cosmetic line width-usually 1-which results in the thinnest possible line for the currently associated device. A geometric line width has no default in the same way that the sides of a box, drawn with GpiBox, have no length until specified by the function. The value specified with GpiSetLineWidthGeom is the thickness of the line in world coordinates, and it is subject to scaling by the current transformations in effect at the time GpiModifyPath or GpiStrokePath is called. For example, if you apply a transform with a scaling factor of 0.5, for an object whose current geometric line width is four world coordinates, the width of the displayed line will be halved. In the floor plan shown in the following figure, the outer walls were drawn using geometric lines. All of the other objects were drawn using normal lines. Geometric Lines and Normal Lines Your application can determine the current geometric width by calling GpiQueryLineWidthGeom. ═══ 12.1.3. Line End ═══ The line end attribute specifies the shape of the unattached end of a geometric line. Lines whose shapes are partially defined by a geometric width have to be closed, unlike cosmetic lines that simply end. An application can draw geometric lines with square, flat, or round ends. Note: The end attribute takes effect only when a path is converted to a geometric width line using GpiStrokePath or GpiModifyPath. Set the current geometric line end attribute with GpiSetLineEnd. The attribute applies to all subsequent unattached lines within the path bracket. The following table describes the three standard line ends provided by the PM programming interface; you cannot define your own end types. Standard Geometric Line End Types ┌────────────────────────────────┬────────────────┬────────────┐ │Type │Identifier │Long Value │ ├────────────────────────────────┼────────────────┼────────────┤ │Flat, flush with line end │LINEEND_FLAT │1L │ ├────────────────────────────────┼────────────────┼────────────┤ │Round, past line end │LINEEND_ROUND │2L │ ├────────────────────────────────┼────────────────┼────────────┤ │Flat, but extends past line end │LINEEND_SQUARE │3L │ └────────────────────────────────┴────────────────┴────────────┘ The default line end type (LINEEND_DEFAULT) is identical to the LINEEND_FLAT type, and has a long value of 0L. The error linetype (LINEEND_ERROR) has a long value of -1L. The following figure illustrates these three types of line ends. Your application can determine the current geometric line end by calling GpiQueryLineEnd. Closing Unattached Geometric Lines A square line end extends the line by a distance that is half the width of the line. For example, if the line is six coordinate units wide, a square line end extends it by three coordinate units. A round line end is constructed by drawing a circle whose radius is half the width of the line. ═══ 12.1.4. Line Join ═══ The line join attribute specifies the shape formed by two intersecting geometric lines. Where one wide line joins another, the nature of the join must be defined. An application can select a beveled, rounded, or mitred line-join style. Note: The join attribute takes effect only when a path is converted to a geometric wide line using GpiStrokePath or GpiModifyPath. Set the current geometric line-join attribute with GpiSetLineJoin. The attribute applies to all subsequent intersection of lines within the path bracket. The following table describes the three standard line joins provided by the PM programming interface. You cannot define your own join types. Standard Geometric Line Join Types ┌────────────────────────────────┬────────────────┬────────────┐ │Type │Identifier │Long Value │ ├────────────────────────────────┼────────────────┼────────────┤ │Diagonal corner │LINEJOIN_BEVEL │1L │ ├────────────────────────────────┼────────────────┼────────────┤ │Rounded corner │LINEJOIN_ROUND │2L │ ├────────────────────────────────┼────────────────┼────────────┤ │90° angled corner │LINEJOIN_MITRE │3L │ └────────────────────────────────┴────────────────┴────────────┘ The default join type (LINEJOIN_DEFAULT) is identical to the LINEJOIN_BEVEL type, and has a long value of 0L. The error linetype (LINEJOIN_ERROR) has a long value of -1L. The following figure illustrates these three types of line joins. Your application can determine the current geometric line join using GpiQueryLineJoin. Joining Wide Lines ═══ 12.1.5. Cosmetic Line Attributes for Paths ═══ When a path is drawn as a cosmetic line with GpiOutlinePath, the following attributes are defined by the LINEBUNDLE data structure:  Line width  Line type  Line color  Line mix These attributes follow the current definitions and appear just as line primitives do. Since the line primitive has only a foreground color and mix attribute, the current color of the drawing surface affects the appearance of these paths more than it does the appearance of paths that define geometric lines. Those paths follow the area attributes and are affected by background color and background mix attributes as well. ═══ 12.1.6. Area Attributes for Paths ═══ When a path is drawn as a geometric line with GpiStrokePath or GpiModifyPath, the following attributes are defined by the AREABUNDLE data structure:  Pattern symbol  Pattern set  Pattern reference point  Area foreground color  Area background color  Area foreground mix  Area background mix Area attributes follow the current definitions and appear just as area primitives do. The operating system uses the pattern symbol to fill the interior of the path that defines the geometric line. Any alterations to the fill pattern or reference point affect the appearance of a geometric line just as it does an area. ═══ 12.1.7. Path Color and Mix Attributes ═══ The color attribute defines the color used to draw a primitive or an object. The mix attribute determines how the color of a primitive or an object is combined with the color of the drawing surface, or any other objects on the surface. Unlike the color and mix attributes for primitives, and certain other objects, the path color is defined by different attributes in different situations, as illustrated in the following figure. Path Objects Path colors are determined by the area color, area background color, area mix, and area background mix attributes if the path is stroked into a wide line. The cosmetic line path color is determined by the line color and mix attributes. The line color defines the color used to draw the output from any of the IBM OS/2 line functions called within the path. The line colors can change within the path bracket, just as they can within area brackets. The interaction of the line with the drawing-surface color is controlled by the line mix attribute, which also can vary within the path bracket. After the path is closed, the path can be stroked into a geometric (or wide) line. Depending on the construction options, the geometric line can be filled. The appearance of the pattern symbol used to fill the path depends on the area attributes. The definitions of the area color and background color depend on the pattern symbol. ═══ 12.1.8. Path Brackets ═══ The functions that create and define the path always are bracketed by the GpiBeginPath and GpiEndPath functions. Only one path can be defined between these two functions. However, within the path, there can be any number of figures. GpiBeginPath signals the start of a path definition. Each path you define becomes the current path and replaces any existing path in the presentation space. The current position is not changed by GpiBeginPath, although it is updated by any drawing instructions that follow. GpiBeginPath accepts as input only a path identifier of 1. This identifier is used by the functions performing path operations to identify the path. Due to the number of different operations that can be performed on paths, the path definition can contain both open and closed figures. If a figure does not start and end at the same coordinate point, it is classified as an open figure. Unlike an area bracket, if you use GpiSetCurrentPosition or GpiMove within a path definition, the current figure is not automatically closed. The PM provides a method of closing figures within a path. GpiCloseFigure (valid only in path brackets) closes a figure in the path whose start and end points are not the same, by drawing a straight line from the current position to the start position of the figure. Use GpiCloseFigure if you want the line join attribute to be applied between the start and end point of a figure. Do not use it if you want the line end attributes to be used as the start and end points for a geometric wide line. If the path definition contains full arc or box primitives, however, you must not close them using GpiCloseFigure. GpiBox and GpiFullArc generate completely closed figures and must not be used within another figure definition. To signal the end of the current path definition, use GpiEndPath. The path definition is constructed in the currently associated presentation space. The current position always is updated to the end point of the last line drawn. The functions that generate a path are enclosed in a path bracket. Applications can use the functions in the following list within a path bracket.  GpiBeginElement  GpiBox  GpiCallSegmentMatrix  GpiCharString  GpiCharStringAt  GpiCharStringPos  GpiCharStringPosAt  GpiCloseFigure  GpiComment  GpiCreateLogFont  GpiDeleteSetId  GpiElement  GpiEndElement  GpiEndPath  GpiFullArc  GpiGetData  GpiLabel  GpiLine  GpiMarker  GpiMove  GpiOffsetElementPointer  GpiPartialArc  GpiPointArc  GpiPolyFillet  GpiPolyFilletSharp  GpiPolyLine  GpiPolyMarker  GpiPolySpline  GpiPop  GpiPutData  GpiQueryArcParams  GpiQueryAttrMode  GpiQueryCurrentPosition  GpiSetArcParams  GpiSetAttrMode  GpiSetAttrs  GpiSetCharAngle  GpiSetCharBox  GpiSetCharDirection  GpiSetCharMode  GpiSetCharSet  GpiSetCharShear  GpiSetColor  GpiSetCp  GpiSetCurrentPosition  GpiSetEditMode  GpiSetLineEnd  GpiSetLineJoin  GpiSetLineType  GpiSetLineWidth  GpiSetMarker  GpiSetMarkerBox  GpiSetMarkerSet  GpiSetMix  GpiSetModelTransformMatrix Warning. Some GPI functions cannot be used while an open path definition exists. In particular, you cannot include image or area primitives in a path definition. ═══ 12.1.9. Path Operations ═══ The operations performed on a path determine which of the path attributes become applicable. Unlike specifying area brackets, the variety of operations also calls for separate functions instead of specifying options with GpiBeginPath. Specifically, the following six operations can be performed on a path:  Outline  Fill  Modify  Stroke  Convert to clip path  Convert to region There are other graphics operations provided by the PM -for example, transformations- that can apply to entities other than paths. Upon completion, GpiFillPath, GpiOutlinePath, GpiStrokePath, and GpiPathToRegion delete the current path definition. This path is not available for any subsequent operations. GpiModifyPath does not delete the current path definition. An application can modify a path before using one of the aforementioned functions. The first time your application calls GpiSetClipPath, the current path definition is converted into the current clip path. GpiSetClipPath deletes the path definition upon completion but not the clip path definition. A path definition can be stored in a graphics segment and, if that segment is retained, the path can be re-created as required. Segments are discussed in Creating and Drawing Retained Graphics. ═══ 12.1.10. Path Outline ═══ To draw the outline of the current path, use GpiOutlinePath. This function accepts a path identifier (which must be 1) as input. GpiOutlinePath does not create a geometric line; therefore, the cosmetic line attributes are used. GpiOutlinePath normally has the same effect as though the lines and arcs used to create the path were drawn without actually being part of the path. Any open figures within the path are not closed automatically. If the path contains character strings that use an outline font, the characters are not filled. The following functional sequence is recommended for drawing outline text or outline figures: ┌──────────────────────────────┬──────────────────────────────┐ │Function Name │Effect │ ├──────────────────────────────┼──────────────────────────────┤ │GpiBeginPath │Starts the path definition. │ ├──────────────────────────────┼──────────────────────────────┤ │GpiMove │Moves to the starting point of│ │ │the first figure. │ ├──────────────────────────────┼──────────────────────────────┤ │GpiCharString, GpiFullArc │Uses an outline font to │ │ │specify text or define the │ │ │lines in a figure. │ ├──────────────────────────────┼──────────────────────────────┤ │GpiEndPath │Ends the path. │ ├──────────────────────────────┼──────────────────────────────┤ │GpiOutlinePath │Draws the text or figure │ │ │outlines. │ └──────────────────────────────┴──────────────────────────────┘ If you are drawing a complex path, consisting of several character strings that use an outline font, it can take quite some time to produce. If you want to create a only rough draft, you might find it quicker to draw an outline instead of the filled path. This improves performance and might be acceptable for small characters. When they are small enough, hollow characters can look like filled characters. You can create hollow characters in either of two ways:  Outside a path, call GpiCreateLogFont. This enables you to define an outline font that uses hollow characters.  Inside a path, draw the characters, then display the path with GpiOutlinePath. Only the character outlines contribute to the path definition even if the font is not hollow. (This might cause ambiguous results.) Using outlined paths to create character outlines also can be used to define a clip path in the shape of a letter or word. ═══ 12.1.11. Path Fill ═══ To draw the current path and fill its interior using the current pattern symbol, use GpiFillPath. The path is deleted after the interior is filled. The boundary lines are considered part of the path interior and are drawn with this function. Any open figures in the path definition are closed automatically by GpiFillPath. This function accepts the path identifier (which must be 1) as input, and either of two construction options:  FPATH_ALTERNATE (the default)  FPATH_WINDING (must be selected if the path has been modified). Paths, like area primitives, can be filled in alternate mode or winding mode. If the path consists of multiple, intersecting figures, the path-fill mode affects the final appearance of the path. The following figure shows two identical paths that were filled, each using one of the two modes. Each path consists of a triangle drawn within a rectangle. The path on the left was filled using the alternate mode. The path on the right was filled using the winding mode. Alternate and Winding Fill Modes ═══ 12.1.11.1. Paths in Alternate Mode ═══ For paths drawn in alternate mode (as with area primitives), the following is true:  If you have to cross an odd number of boundaries in the path when drawing an imaginary line parallel to the x-axis, a point is included in the filled path from that point to positive infinity.  If you have to cross an even number of boundaries in the path when drawing an imaginary line parallel to the x-axis, a point is not included in the filled path from that point to positive infinity. The following figure shows how the operating system determines the filled portion for the path shown in the previous figure. The path outside the triangle, but inside the rectangle, is filled, because the imaginary lines drawn from those points in the positive x-direction intersect the path boundaries an odd number of times. Calculating Filled Paths Constructed in Alternate Mode Parts of the path with odd tallys are filled; parts with even tallys are not filled. ═══ 12.1.11.2. Paths in Winding Mode ═══ For paths drawn in winding mode (also like area primitives), the direction the boundaries in the path are drawn in determines whether a given point is included in the filled path. The drawn direction of a boundary line depends on both the graphics functions used to draw it and the world coordinates that define it. For box primitives, for example, if the specified diagonal corner is to the right, to the top, or both, of the current position, the box is drawn counterclockwise. If the specified diagonal corner is to the left, to the bottom, but not both, the box is drawn clockwise. For a polyline primitive, the direction of the boundary depends on the relative values of the start and end points of each line. For a polygon primitive, the direction of the boundary depends on the relative values of the specified vertices. To determine whether a given point is included in the filled path, count the number of boundary lines to be crossed to move from that point to infinity. For each boundary line drawn in one direction add one to the tally. For each boundary line drawn in the opposite direction, subtract one from the tally. A point is within the area if the result is nonzero. As with the alternate mode, the imaginary determining line is drawn in the positive x-direction from the point in question toward infinity. The following figure shows how the operating system determines the filled portion for the path shown in the figure before the previous one. Assume that both the rectangle and triangle were drawn in the same direction, whether clockwise or counterclockwise is immaterial. Both figures are filled, because the number of times the imaginary lines drawn from those points in the positive x-direction intersect the path boundaries is continuously summed. There is never a subtraction of a boundary tally to reduce the total to 0. Paths Constructed in the Same Direction in Winding Mode Parts of the path with nonzero tallys are filled; parts with zero tallys are not filled. If two figures, for example in the following figure, are drawn in different directions, the tally for the inner triangle is 0 and the area looks exactly as it does in alternate mode. Paths Constructed in Different Directions in Winding Mode Parts of the path with nonzero tallys are filled; parts with zero tallys are not filled. ═══ 12.1.12. Path Modification ═══ To convert the current path to one that describes the envelope of a geometric wide line, use GpiModifyPath. The current geometric line attributes are then applied to the figures within the path. The line end, line join, and geometric line width attributes all must be set before modify-path or stroke-path operations begin, because it is during those times that the attributes are applied. Cosmetic line attributes of width and type have no effect on geometric lines. GpiModifyPath accepts the path identifier (which must be 1) and the modification option MPATH_STROKE as input. Subsequently, the modified path can be filled to display the geometric wide line, but only in winding mode. Alternatively, the modified path can be converted into a clip path, but again, only in winding mode. Open figures within the path are not closed automatically. Figures not explicitly closed with GpiCloseFigure are drawn with line ends rather than line joins at their start and end points. If the figures within the path overlap, the geometric width envelope compensates so that the overlap portion is not drawn blank in XOR or exclusive-OR mode. Now the geometric lines can be scaled. Note: The current transforms are applied to the primitives inside a path bracket when the path is defined. This binds the path definition in device coordinates at that time. The path is unaffected by subsequent transformations, except for those (such as scaling) that affect the width of geometric (wide) lines. Since the geometric line width attribute is not applied until the path is converted into a wide line by GpiModifyPath or GpiStrokePath, the width of geometric lines is unaffected by earlier transformations directed at the path definition. After creating a path bracket, geometric wide lines can be constructed by either:  Stroking the path (GpiStrokePath),  Modifying the path (GpiModifyPath), then filling the path (GpiFillPath). GpiStrokePath is slightly more efficient, but GpiModifyPath and GpiFillPath offer more flexibility (by way of the fill options). After drawing the lines no alterations can be made. ═══ 12.1.13. Path-Stroking ═══ To modify and fill the current path in a single operation, use GpiStrokePath. Then the path is drawn immediately to the output device, with the current geometric line attributes applied to the figures within the path. Certain device drivers can use this function to optimize storage. GpiStrokePath automatically fills the path in winding mode with the current area pattern symbol. When GpiStrokePath is complete, the path definition is deleted from the device context. GpiStrokePath is subject to the same constraints as functions that perform simple line modification:  The line end, line join, and geometric line width attributes all must be set before stroke operations.  Cosmetic line attributes of width and type have no effect.  Any open figures within the path are not closed automatically.  If figures are not explicitly closed with GpiCloseFigure, they are drawn with line ends rather than line joins at their start and end points.  If the figures within the path overlap, the geometric width envelope compensates so that the overlap portion is not drawn blank when drawn in XOR (exclusive-OR) mode. This function accepts as input both the path identifier (which must be 1) and the stroke option (which must be 0L). When the operating system strokes a path, it draws a geometric line of specified width along the original figure that defined the path and then fills the wide line. If the original figure is not a closed shape, the operating system does not automatically close it before filling the path. The following figure shows the effects of GpiStrokePath on a box originally defined with normal (cosmetic) lines. Defining Lines with a Geometric Width The broken line is the figure defined within the path. The solid lines show the path after it has been converted. Each line has a geometric width of n coordinate units, and the line joins have been defined as beveled. After setting these attributes, the application can draw the line with GpiStrokePath. After the lines are drawn, an application can scale stroked paths with a scaling transformation. As an alternative to the GpiStrokePath, you can convert the path using GpiModifyPath, which does not draw the path on the current output device. To draw a modified path, use GpiFillPath, which draws the path and fills it with the current area-fill pattern in winding mode. A modified path cannot be filled in alternate mode. On some devices, it might be that the GpiStrokePath method works better than GpiModifyPath, followed by GpiFillPath. ═══ 12.1.14. Path Conversion to Clip Path ═══ Clipping is the process an application uses to limit graphics output to a specific area (called the clipping area) of the display or page. There are several clipping functions provided by the PM. However, if your application requires an irregular complex shape for a clipping area, it must define the shape with a path. To convert the path into a clipping boundary, use GpiSetClipPath. The clip path, as defined by this operation, becomes the current clip path for all subsequent drawing. This function accepts a path identifier and one of two construction options as input:  SCP_ALTERNATE (default)  SCP_WINDING (must be selected if the path has been modified) Unlike the path operations described previously, GpiSetClipPath accepts two different path identifiers:  1  0 (default). The default path identifier of 0 (SCP_RESET) resets the clip path to infinity, which displays the picture without clipping. If this value is selected, the current clip path definition is discarded instead of stored. For GpiSetClipPath, a path identifier of 1 (SCP_AND) causes the clip path to be redefined as the mathematical intersection of the stored clip path and the current path definition. For all other path operations, an identifier of 1 specifies the current path as the recipient of the operation. The only method of specifying the clip path as the current path, after GpiSetClipPath has been called, is to call GpiSetClipPath again: the first call with a path identifier of 0; the second, with a path identifier of 1. The path identifiers and the construction mode can be ORed together for certain effects. Any open figures within a path are closed automatically. The boundaries of the path are considered part of the interior, so any point on the boundary is not clipped. The following figure shows the result of clipping text with a triangular clip path. Triangular Clip Path ═══ 12.1.15. Path Conversion to Region ═══ To convert the current path to a region, use GpiPathToRegion. Then the new region can be modified using any of the region functions that allow the creation of irregular shaped regions. Any open figures in the path definition are closed automatically by GpiPathToRegion. Upon conversion, the current path definition is discarded just like it is when being converted to a clip path. When GpiPathToRegion is complete, the path definition is deleted automatically. This function accepts the path identifier (which must be 1) and one of two construction options as input:  FPATH_ALTERNATE (default)  FPATH_WINDING (must be selected if the path has been modified) ═══ 12.2. Using Paths ═══ You can use path functions to:  Draw geometric lines and filled polygons  Draw outline text  Create a triangular clip path ═══ 12.2.1. Drawing a Geometric (Wide) Line ═══ The following figure is an example of how to draw a straight line, 10 units wide with rounded ends. #define INCL_GPIPRIMITIVES #include void fncPATH01(void){ POINTL ptl; HPS hps; GpiSetLineWidthGeom(hps, 10L); /* Sets line width to ten */ GpiSetLineEnd(hps, LINEEND_ROUND); /* Sets line end to round */ GpiBeginPath(hps, 1L); /* Begins path */ ptl.x = 7; ptl.y = 15; GpiMove(hps, &ptl); /* Sets current position */ ptl.x = 450; ptl.y = 15; GpiLine(hps, &ptl); /* Draws line */ GpiEndPath(hps); /* Ends path */ GpiStrokePath(hps, 1L, 0L); /* Draws geometric line */ } /* fncPATH01 */ ═══ 12.2.2. Drawing Filled Polygons ═══ The following figure is an example of how to draw an empty triangle within a solid rectangle. #define INCL_GPIPATHS #include void fncPATH02(void){ HPS hps; POINTL aptl1[4] = { /* Array of points for triangle */ 50, 50, 100, 100, 150, 50, 50, 50 }; POINTL aptl2[5] = { /* Array of points for rectangle */ 25, 25, 25, 200, 200, 200, 200, 25, 25, 25 }; GpiBeginPath(hps, 1L); /* Begins path */ GpiMove(hps, aptl1); /* Sets current position */ GpiPolyLine(hps, 4L, aptl1); /* Plots points for triangle */ GpiMove(hps, aptl2); /* Sets current position */ GpiPolyLine(hps, 5L, aptl2); /* Plots points for rectangle */ GpiEndPath(hps); /* Ends path */ GpiFillPath(hps, 1L, FPATH_ALTERNATE); /* Draws triangle and rectangle */ } /* fncPATH02 */ ═══ 12.2.3. Drawing Outline Text ═══ The following figure shows an example of how to draw text from an outline font with GpiOutlinePath. #define INCL_GPIPRIMITIVES #include void fncPATH03(void){ LONG lcid = 1; /* Identifier for font */ FATTRS fattrs; /* Structure for font attributes */ SIZEF sizfx; /* Structure for character box */ POINTL ptl; /* Structure for starting point */ HPS hpsWin; fattrs.usRecordLength = sizeof(FATTRS); fattrs.fsSelection = FATTR_SEL_OUTLINE; /* Specifies outline font */ fattrs.lMatch = 0; /* System determines font */ fattrs.szFacename[0] = 0; fattrs.idRegistry = 0; fattrs.usCodePage = 0; fattrs.lMaxBaselineExt = 0; fattrs.lAveCharWidth = 0; fattrs.fsType = 0; fattrs.fsFontUse = FATTR_FONTUSE_OUTLINE; /* Specifies outline font */ GpiCreateLogFont(hpsWin,(PSTR8) NULL, lcid, &fattrs); GpiSetCharSet(hpsWin, lcid); /* Sets logical font */ sizfx.cx = MAKEFIXED(30, 0); /* Width of character box */ sizfx.cy = MAKEFIXED(30, 0); /* Height of character box */ GpiSetCharBox(hpsWin, &sizfx) /* Sets size of character box */ GpiBeginPath(hpsWin, 1L); /* Begins path */ ptl.x = 100; ptl.y = 200; GpiMove(hpsWin, &ptl); /* Sets current position */ GpiCharString(hpsWin, 7L, "Outline"); /* Establishes char. string */ GpiEndPath(hpsWin); /* Ends path */ GpiOutlinePath(hpsWin, 1L, 0L); /* Draws character string */ } /* fncPATH03 */ ═══ 12.2.4. Creating a Triangular Clip Path ═══ The following figure shows an example of how to create a triangular clip path and then write text into it. #define INCL_GPIPATHS #include void fncPATH04(void){ POINTL ptlStart; HPS hps; LONG i; POINTL aptl[4] = { /* Array of points for triangle */ 35, 45, 100, 100, 200, 45, 35, 45 }; GpiBeginPath(hps, 1L); /* Begins path bracket */ GpiMove(hps, aptl); /* Sets current position */ GpiPolyLine(hps, 4L, aptl); /* Plots points for triangle */ GpiEndPath(hps) /* Ends path bracket */ GpiSetClipPath(hps, 1L, SCP_ALTERNATE | SCP_AND); /* Write a block of text. */ ptlStart.x = 50; for (i = 50L; i < 110L; i += 10L) { ptlStart.y = i; GpiCharStringAt(hps, &ptlStart, 18L, "String of text!"); } /* for */ } /* fncPATH04 */ ═══ 13. Regions ═══ A region is a graphics object usually composed of one or more rectangles. Converted to clip regions, they are used mainly to define a clipping boundary, in device coordinates, for multiple intersecting rectangles. Clip regions provide the required clipping in an update region during WM_PAINT processing when it is necessary to repaint part of a window. Regions also can be used for area fill. The following topics are related to the information in this chapter:  Presentation spaces and device contexts  Area primitives  Color and mix modes  Coordinate spaces and transformations  Clipping ═══ 13.1. About Regions ═══ A region consists of one or more overlapping or separate rectangles in an application's device space. The sides of the rectangles are parallel to the x- and y-axes in the device coordinate space. An irregular, nonrectangular path can be converted into a region. However, unless otherwise specified, the assumption of this chapter is that a region is rectangular. If a region consists of intersecting rectangles, the intersecting sides are always perpendicular. If the rectangles have no common elements, the region is defined as separate rectangles. Unlike areas and paths, which are defined in world coordinates, regions are device-dependent and, so, are defined in device coordinates. The device coordinates are inclusive (inside the rectangle) at the bottom and left coordinate boundaries, and exclusive (outside the rectangle and clipped) at the top and right boundaries. Each region is created for the device that currently is associated with a presentation space. Also, after creation, regions are available for various operations; a region handle identifies the region for subsequent operations. The following figure shows a region that consists of two intersecting rectangles. An application defined the region by passing an array containing the coordinates for the two rectangles to GpiCreateRegion. The application then drew the region with GpiPaintRegion. Defining a Region This region comprises two overlapping rectangles. ═══ 13.1.1. System Implementation ═══ Regions are device-dependent objects and, therefore, are associated with a particular device. For this reason, when an application specifies a presentation space as input to one of the region functions, that presentation space must be associated with a device context. The associated device context serves to identify the device. Because a region is specific to the device for which it was created, a region should not be created for one device and then used for another. If the device is a printer, a metafile can be used to store region functions as escapes, and the resulting metafile can be displayed on any device. The appearance of the result of any region function is affected by differences in the pel:aspect ratio and device resolution on different printers. Most of the region-oriented functions use the RECTL structure to define the device-space coordinates of the rectangle. When an application creates a rectangle in a device space and passes its coordinates to a region function, the operating system excludes the top and rightmost edges of the rectangle. This means that an application must add 1 to the values in the xRight and yTop fields of the RECTL structure to obtain the desired dimensions. For example, if an application requires a region that measures 100-by-100 device units, with a lower-left corner at (10,10), xRight and yTop should be set to 111 instead of 110. ═══ 13.1.2. Region Attributes ═══ Regions do not have a distinct ...BUNDLE data structure associated with them. Unlike primitives or even paths, the purpose of regions is to provide a definition for an operation-not visual output. However, there are two functions that present the region as a visible entity. GpiPaintRegion paints a region in the presentation space. This function accepts only the region handle as input. GpiPaintRegion does not cause graphics orders to be added to the current segment. (Graphics orders are the smallest, most complete portions of a segment.) Therefore, in retain or draw-and-retain modes, you are advised to use paths or areas rather than regions to ensure the desired effect. GpiFrameRegion draws a frame around a region by tracing the inner perimeter with a rectangle of a specified size. This function accepts the region handle and the desired frame thickness as input. A region's visible output is controlled by the following AREABUNDLE attributes:  Pattern symbol  Pattern set  Pattern reference point  Area foreground color  Area background color  Area foreground mix These attributes follow the current definitions and appear just as area primitives do. The operating system uses the pattern symbol to fill the interior of the region. Any alterations to the fill pattern or reference point affects the appearance of a region, just as it does in an area. Because neither the painted region nor the region frame have boundary lines, no LINEBUNDLE attributes influence the appearance of a region resulting from GpiPaintRegion or GpiFrameRegion. ═══ 13.1.3. Region Creation ═══ Areas and paths are created and defined within a bracket. Regions are defined by a single function, GpiCreateRegion. As input to GpiCreateRegion, supply the total number of, and the coordinates for, each rectangle that contributes to the region. The following applies to region coordinates:  They define the bottom left and top right coordinates of each rectangle that makes up the region.  They must be in the range -32768 through +32767.  They always are device coordinates, because regions always are created and drawn in an application's device space. The output from GpiCreateRegion is the region handle, which identifies the region for subsequent operations. Because each region can be distinctly identified, the region functions allow applications to work with more than one region at a time. For example, an application can combine two regions with GpiCombineRegion or compare two regions with GpiEqualRegion. GpiQueryRegionRects retrieves the coordinates of the rectangles that make up a region, enabling an application to create a copy of that region. To create the copy, you supply, as input to a new GpiCreateRegion, the exact rectangles returned from GpiQueryRegionRects. ═══ 13.1.4. Region Operations ═══ The following operations can be performed on a region:  Creating Regions  Drawing Regions  Moving Regions  Determining Region Characteristics  Converting a Path to a Region  Converting a Region to a Clip Region  Deleting Regions ═══ 13.1.4.1. Creating Regions ═══ To create a rectangular region, call GpiCreateRegion. This function accepts, as input, the number of rectangles to be ORed into a single region and the coordinates of those rectangles. If the number of rectangles is 0, an empty region is created. To create a new region from regions that already exist, call GpiCombineRegion. This function accepts, as input, a region handle for the target region, a region handle for each of the two source regions, and an options flag that specifies the way the two source regions are combined. Note: The destination region can be either of the two source regions, in which case, that region is replaced by the new region. The rectangles are differentiated by one region's being distinctly "the first source rectangle" and the other region labeled "the second source rectangle". The order of the source rectangles affects the way GpiCombineRegion combines them. You can use GpiCombineRegion an indefinite number of times to form complex polygons. However, the function is limited to combining only two regions each time it is called. The two source regions must be created for the same type of device. Following are the five ways in which two regions can be combined: Option Result CRGN_OR Union of the two source regions CRGN_XOR Symmetric difference of the two source regions CRGN_COPY Source region 1 only; source region 2 is ignored CRGN_AND Intersection of the two source regions CRGN_DIFF Source region 1 minus source region 2 The effects of these different combining operations on overlapping regions are shown in The effects of these different combining operations on overlapping regions are shown in the following figure. Their effects on separate regions are shown in Their effects on separate regions are shown in the figure after the following figure. Combining Overlapping Regions The source regions are two overlapping rectangles. The regions that result from the various combine operations are shown as shaded areas. Output from GpiCombineRegion tells you whether the resulting region is a NULL region, rectangular region, or complex region. A complex region is any region defined by two or more rectangles. To change the definition of a region while keeping the same region handle, call GpiSetRegion. This function accepts, as input, the number and dimensions of the rectangles that now define the region, just as GpiCreateRegion does. However, GpiSetRegion also accepts the handle of the region to be updated. GpiSetRegion, like GpiCreateRegion, takes a region definition to be the union of a sequence of rectangles (that are effectively ORed together). In the case of GpiCreateRegion, a new region is created and its handle returned. In the case of GpiSetRegion, the previous definition is discarded and replaced by the new definition that is associated with the existing region handle. Combining Disjoint Regions The two source regions do not overlap. The regions that result from the various combine operations are shown as shaded areas. The result from a CRGN_AND combining of separate regions is a NULL region. ═══ 13.1.4.2. Moving a Region ═══ To move a region, call GpiOffsetRegion. This function accepts, as input, the region handle and an offset value that is added to every coordinate point of the region. GpiOffsetRegion moves a region by a specific number of device coordinates. By specifying positive or negative x- and y-values an application can move a region in any direction, relative to its current position. ═══ 13.1.4.3. Determining Region Characteristics ═══ Regions are used in many operations. There are several functions that determine the characteristics of regions because these characteristics influence the outcome of the operation being performed. To determine whether two regions are identical, call GpiEqualRegion. This function accepts, as input, the two region handles. Regions are identical if the only difference between them is an empty region. For example, a rectangular region whose lower-left corner is at 10,10 is not identical to a region whose lower-left corner is at 50,50, even if the regions have exactly the same dimensions. The two regions also must be of the same device class to be considered identical. To determine the rectangles that compose a region, call GpiQueryRegionRects, which retrieves the coordinates of a series of rectangles that, when ORed together, define the shape of the regions. Note: The individual regions returned may differ in size and number from those originally used to specify the region. GpiQueryRegionRects accepts, as input, the region handle and the maximum number of rectangles that can be returned. The division of the region into multiple rectangles is handled automatically by the PM. It is not necessary for an application to retrieve all the rectangles in a single function. Your application can call GpiQueryRegionRects any number of times. Therefore, the application must specify the maximum number of rectangles and the rectangle number to start from in each function. No assumptions can be made about the number and coordinates of rectangles returned except that they will define the specified region precisely. The purpose of specifying the number of rectangles in the query is to ensure that the system does not return more coordinates than can fit in the RECTL array. To determine whether a point is inside the borders of a region, call GpiPtInRegion. This function is especially useful in applications that must determine whether the mouse pointer is over a region. The particular point must be expressed in device coordinates. To determine whether any part of a specified rectangle lies within a region, call GpiRectInRegion. This function accepts, as input, the region handle and the rectangle as specified in device coordinates. To determine the coordinates of the smallest rectangle that encloses a region, call GpiQueryRegionBox. This function accepts the region handle as input. The output from this function tells you whether the bounding region is rectangular, NULL, or complex. ═══ 13.1.4.4. Converting a Region to a Clip Region ═══ Clipping is the process an application uses to limit graphics output to a specific area (called the clipping area) of the display or page. There are several clipping functions provided by the PM. However, if your application requires a clipping boundary in device coordinates, it must define the boundary with a region. To convert the region into a clipping boundary, call GpiSetClipRegion. The clip region, as defined by this operation, becomes the current clip region of all subsequent drawing operations. GpiSetClipRegion accepts, as input, the region handle. A NULL region handle sets the clip region to infinity, effectively performing no clipping. Unlike clip paths, the region that is no longer the current clip region is not deleted. It retains the effects of any changes made to it while it was a clip region, and it can be used with the other region functions, including being reselected as the clip region with GpiSetClipRegion. You do not have to deselect the current clip region before selecting another. Each selected clip region automatically replaces the one before it. If there is an existing clip region when you call GpiSetClipRegion, it reverts to a normal region, and its handle is returned. When you have selected the current clip region, none of the region functions described thus far can be used for that region. The following functions can be used with the current clip region:  GpiQueryClipBox  GpiIntersectClipRectangle  GpiExcludeClipRectangle  GpiOffsetClipRegion  GpiPtVisible  GpiRectVisible These functions are described in Clipping and Boundary Determination. All of these functions work in world coordinates, rather than device coordinates, and therefore, are subject to current transformations. GpiPtVisible and GpiRectVisible do not apply exclusively to clip regions. When the screen contents are altered (for example, when a window is sized), you have to be able to repair the part of the screen image affected by the change. The following figure illustrates the necessary region. Repairing the Screen with Clip Regions To improve performance of the drawing operation, you can restrict the redrawing and repair work to the affected parts of the screen. Use WinQueryUpdateRegion to determine whether graphics objects are totally outside the update region and need not be drawn at all. Graphics objects that are within, or are partly outside, the update region should be drawn, and the system will perform the required clipping automatically. Define a clipping region using the dimensions of the update region. Then call an appropriate GPI drawing request, such as GpiDrawChain, to redraw the screen contents. Any drawing that would occur outside the clip region is discarded according to the standard clipping rules. Only those graphics within the clip region are redrawn. ═══ 13.1.4.5. Deleting a Region ═══ To delete a region, call GpiDestroyRegion. This function accepts, as input, the region handle. If the region is the current clip region, it cannot be deleted. To delete a current clip region, first call GpiSetClipRegion and specify a NULL region handle. The region is no longer the current clip region and can be deleted. ═══ 13.2. Using Regions ═══ You can use the region functions to:  Create or delete a region  Combine regions  Compare regions  Move a region  Paint and frame a region  Locate a point with respect to a region  Determine the coordinates of region rectangles ═══ 13.2.1. Creating and Deleting a Region ═══ To create a region: 1. Create an array of RECTL structures containing the dimensions of the rectangles that will compose the region. 2. Call GpiCreateRegion to create the region. (This function returns a handle that identifies the region.) To delete a region, pass the handle returned by the GpiCreateRegion function to GpiDestroyRegion. The following figure shows how to create and delete a region. #include void fncREGN01(void){ HPS hps; /* Presentation-space handle */ HRGN hrgn; /* Region handle */ RECTL arcl[] = { 25, 50, /* Rectangle 1 */ 75, 100, 50, 75, /* Rectangle 2 */ 100, 150, 75, 125, /* Rectangle 3 */ 200, 175, 150, 75, /* Rectangle 4 */ 250, 150 }; hrgn = GpiCreateRegion(hps, /* Creates region */ sizeof(arcl) / sizeof (RECTL), /* Number of rectangles in region */ arcl); /* Array of rectangle structures */ . . /* Work with the region here. */ . GpiDestroyRegion(hps, hrgn); /* Destroys region identified by hrgn */ } /* fncREGN01 */ ═══ 13.2.2. Combining Regions ═══ To combine two regions: 1. Create a region that the operating system can use as the destination region when it combines the source regions. 2. Determine which of the five combining methods to use. 3. Call GpiCombineRegion. The following figure shows how to combine two regions by using the OR operation: #define INCL_GPIREGIONS #include void fncREGN02(void){ HPS hps; HRGN hrgn1, hrgn2, hrgn3; /* Region handles */ RECTL rcl1, rcl2; rcl1.xLeft = 50; rcl1.yBottom = 100; rcl1.xRight = 200; rcl1.yTop = 175; hrgn1 = GpiCreateRegion(hps, 1L, &rcl1); /* First source region */ rcl2.xLeft = 125; rcl2.yBottom = 150; rcl2.xRight = 225; rcl2.yTop = 200; hrgn2 = GpiCreateRegion(hps, 1L, &rcl2); /* Second source region */ hrgn3 = GpiCreateRegion(hps, 0L, (PRECTL) NULL); /* Destination region */ /* Combine the regions. */ GpiCombineRegion(hps, hrgn3, hrgn1, hrgn2, CRGN_OR); } /* fncREGN02 */ ═══ 13.2.3. Comparing Regions ═══ GpiEqualRegion determines whether two regions are identical. The following figure shows how to compare regions. #define INCL_GPIREGIONS #include void fncREGN03(void){ HPS hps; /* Presentation-space handle */ HRGN hrgn1, hrgn2; /* Region handles */ LONG lEqual; /* Return value for GpiEqualRegion */ RECTL rcl1, rcl2; /* Structures for region coordinates */ rcl1.xLeft = 50; rcl1.yBottom = 100; rcl1.xRight = 200; rcl1.yTop = 175; hrgn1 = GpiCreateRegion(hps, 1, &rcl1); /* Creates first region */ rcl2.xLeft = 125; rcl2.yBottom = 150; rcl2.xRight = 225; rcl2.yTop = 200; hrgn2 = GpiCreateRegion(hps, 1, &rcl2); /* Creates second region */ lEqual = GpiEqualRegion(hps, hrgn1, hrgn2); /* Compares regions */ if (lEqual == EQRGN_EQUAL) { . . /* Regions are equal. */ . } else if (lEqual == EQRGN_NOTEQUAL) { . . /* Regions are not equal. */ . } else if (lEqual == EQRGN_ERROR) { . . /* An error occurred. */ . } } /* fncREGN03 */ ═══ 13.2.4. Offsetting a Region ═══ GpiOffsetRegion moves a region, by a specified offset, from its current position (in world space). This function must be called with the address of a POINTL structure that contains an x and a y translation factor. The following figure shows how to offset a region. } /* fncREGN04 */ POINTL ptlNewPos; /* Structure for offset value */ ptlNewPos.x = 200; /* Sets x offset */ ptlNewPos.y = 10; /* Sets y offset */ GpiOffsetRegion(hps, hrgn, &ptlNewPos); /* Offsets region */ ═══ 13.2.5. Painting a Region ═══ GpiPaintRegion fills a region with the current fill pattern, using the colors and mix mode that appear in the current AREABUNDLE structure. GpiFrameRegion draws a frame around a region by tracing the perimeter of the region with a rectangle of a specified size. The following figure shows how to change the fill-pattern color to green, paint a region, and draw a frame around the region. SIZEL sizl; /* Structure for size of frame */ HPS hps; /* Presentation-space handle */ HRGN hrgn; /* Region handle */ GpiSetColor(hps, CLR_DARKPINK); GpiPaintRegion(hps, hrgn); /* Paint region dark pink */ GpiSetColor(hps, CLR_BLACK); sizl.cx = 5; sizl.cy = 5; GpiFrameRegion(hps, hrgn, &sizl); /* 5-by-5 black frame */ ═══ 13.2.6. Locating a Point with Respect to a Region ═══ To determine whether the mouse pointer lies within a region: 1. Retrieve the mouse-pointer coordinates and store them in a POINTL structure. 2. Call GpiPtInRegion, passing it a handle that identifies the appropriate region and the address of the POINTL structure from Step 1. 3. Examine the value that GpiPtInRegion returns to determine whether the point lies within the region. The following figure shows how to locate the mouse pointer with respect to a region. #define INCL_GPIREGIONS #include void fncREGN04(void){ POINTL ptlCurPos; /* Mouse coordinates */ HPS hps; /* Presentation-space handle */ HRGN hrgn; /* Region handle */ LONG lPosition; /* Return value for GpiPtInRegion */ /* Determine mouse coordinates and store in ptlCurPos. */ lPosition = GpiPtInRegion(hps, hrgn, &ptlCurPos); if (lPosition == PRGN_INSIDE) { . . /* Point lies within region. */ . } /* if */ else if (lPosition == PRGN_OUTSIDE) { . . /* Point lies outside region. */ . } /* else-if */ ═══ 13.2.7. Determining Coordinates of Rectangles in a Region ═══ If a region consists of more than one rectangle, you can call GpiQueryRegionRects to retrieve the coordinates of the lower-left and upper-right corners of each rectangle. If you use GpiQueryRegionRects to retrieve every rectangle requested to define a region, the function retrieves the coordinates of as many contiguous rectangles as required. GpiQueryRegionRects returns the coordinates of the rectangles that define a region to an array of RECTL structures, and returns the number of rectangles that were requested for the definition to the crcReturned field of the RGNRECT structure. Your RECTL array may not be large enough to hold all of the rectangles. Specify the maximum it can accept and request the remainder in subsequent functions if necessary. To determine the coordinates of the rectangles that form a region, follow these steps: 1. Create an array of RECTL structures that will receive the rectangle coordinates. More rectangles may be required to define the region than were required to create it. 2. Fill in the ircStart, crc, and usDirection fields of the RGNRECT structure. The crc field can specify more rectangles than will be returned by GpiQueryRegionRects. 3. Call GpiQueryRegionRects to retrieve the coordinates. The following figure shows how to determine the number of rectangles that define a region, the coordinates of the rectangles in that region, and how to create a new region using those coordinates. #define INCL_GPIREGIONS #include void fncREGN05(void){ RGNRECT rgnrc; /* Structure for region rectangles */ RECTL arcl1[5]; /* Array for determining rectangle count */ PRECTL parcl; /* Array for rectangle coordinates */ ULONG cRects = 0; /* Total number of rectangles in region */ HPS hps; HRGN hrgn3; rgnrc.ircStart = 1; /* Rectangle to start with */ rgnrc.crc = 5; /* Number of rectangles to query */ rgnrc.ulDirection = RECTDIR_LFRT_BOTTOP; /* Direction to query */ /**********************************************************************/ /* Determine the total number of rectangles in the region by */ /* repeatedly calling GpiQueryRegionRects with an array of 5 RECTL */ /* structures. The loop terminates when the function retrieves less */ /* than 5 rectangles. */ /**********************************************************************/ do { GpiQueryRegionRects(hps, /* Handle of presentation space */ hrgn3, /* Region to query */ (PRECTL) NULL, /* Gets all rectangles in region */ &rgnrc, /* Structure with rectangle data */ arcl1); /* Array of structures for coordinates */ cRects += rgnrc.crcReturned; } while (rgnrc.crcReturned == rgnrc.crc); /* While 5 rects retrieved */ //cRects = rgnrc.crcReturned + (rgnrc.ircStart - 1); rgnrc.ircStart = 0; /* Rectangle to start with */ rgnrc.crc = cRects; /* Number of rectangles to query */ /* Allocate enough memory for all RECTL structures. */ parcl = (PRECTL) malloc(cRects * sizeof(RECTL)); /* Fill array with coordinates of all rectangles. */ GpiQueryRegionRects(hps, /* Handle of presentation space */ hrgn3, /* Region to query */ (PRECTL) NULL, /* Gets all rectangles in region */ &rgnrc, /* Structure with rectangle data */ parcl); /* Array of structures for coordinates */ } /* fncREGN05 */ ═══ 14. Notices ═══ November 1996 The following paragraph does not apply to the United Kingdom or any country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time. It is possible that this publication may contain reference to, or information about, IBM products (machines and programs), programming, or services that are not announced in your country. Such references or information must not be construed to mean that IBM intends to announce such IBM products, programming, or services in your country. Requests for technical information about IBM products should be made to your IBM reseller or IBM marketing representative. ═══ 14.1. Copyright Notices ═══ COPYRIGHT LICENSE: This publication contains printed sample application programs in source language, which illustrate OS/2 programming techniques. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the OS/2 application programming interface. Each copy of any portion of these sample programs or any derivative work, which is distributed to others, must include a copyright notice as follows: "(C) (your company name) (year). All rights reserved." (C) Copyright International Business Machines Corporation 1994,1996. All rights reserved. Note to U.S. Government Users - Documentation related to restricted rights - Use, duplication or disclosure is subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp. ═══ 14.2. Disclaimers ═══ References in this publication to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Subject to IBM's valid intellectual property or other legally protectable rights, any functionally equivalent product, program, or service may be used instead of the IBM product, program, or service. The evaluation and verification of operation in conjunction with other products, except those expressly designated by IBM, are the responsibility of the user. IBM may have patents or pending patent applications covering subject matter in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing IBM Corporation 500 Columbus Avenue Thornwood, NY 10594 U.S.A. ═══ 14.3. Trademarks ═══ The following terms are trademarks of the IBM Corporation in the United States or other countries or both: IBM PM Presentation Manager OS/2 SAA System Application Architecture Workplace Shell The following terms are trademarks of other companies: C++ AT&T, Inc. Helvetica Linotype ═══ 14.4. Double-Byte Character Set (DBCS) ═══ Throughout this publication, you will see references to specific value for character strings. The values are for single-byte character set (SBCS). If you use the double-byte character set (DBCS), note that one DBCS character equals two SBCS characters. ═══ 15. Glossary ═══ This glossary defines many of the terms used in this book. It includes terms and definitions from the IBM Dictionary of Computing, as well as terms specific to the OS/2 operating system and the Presentation Manager. It is not a complete glossary for the entire OS/2 operating system; nor is it a complete dictionary of computer terms. Other primary sources for these definitions are:  The American National Standard Dictionary for Information Systems, ANSI X3.172-1990, copyrighted 1990 by the American National Standards Institute, 11 West 42nd Street, New York, New York 10036. These definitions are identified by the symbol (A) after the definition.  The Information Technology Vocabulary, developed by Subcommittee 1, Joint Technical Committee 1, of the International Organization for Standardization and the International Electrotechnical Commission (ISO/IEC JTC1/SC1). Definitions of published parts of this vocabulary are identified by the symbol (I) after the definition; definitions taken from draft international standards, committee drafts, and working papers being developed by ISO/IEC JTC1/SC1 are identified by the symbol (T) after the definition, indicating that final agreement has not yet been reached among the participating National Bodies of SC1. ═══ 15.1. Glossary Listing ═══ Select a starting letter of glossary terms: A N B O C P D Q E R F S G T H U I V J W K X L Y M Z ═══ Glossary - A ═══ accelerator -In SAA Common User Access architecture, a key or combination of keys that invokes an application-defined function. accelerator table -A table used to define which key strokes are treated as accelerators and the commands they are translated into. access mode -The manner in which an application gains access to a file it has opened. Examples of access modes are read-only, write-only, and read/write. access permission -All access rights that a user has regarding an object. (I) action -One of a set of defined tasks that a computer performs. Users request the application to perform an action in several ways, such as typing a command, pressing a function key, or selecting the action name from an action bar or menu. action bar -In SAA Common User Access architecture, the area at the top of a window that contains choices that give a user access to actions available in that window. action point -The current position on the screen at which the pointer is pointing. Contrast with hot spot and input focus. active program -A program currently running on the computer. An active program can be interactive (running and receiving input from the user) or noninteractive (running but not receiving input from the user). See also interactive program and noninteractive program. active window -The window with which the user is currently interacting. address space -(1) The range of addresses available to a program. (A) (2) The area of virtual storage available for a particular job. alphanumeric video output -Output to the logical video buffer when the video adapter is in text mode and the logical video buffer is addressed by an application as a rectangular array of character cells. American National Standard Code for Information Interchange -The standard code, using a coded character set consisting of 7-bit coded characters (8 bits including parity check), that is used for information interchange among data processing systems, data communication systems, and associated equipment. The ASCII set consists of control characters and graphic characters. (A) Note: IBM has defined an extension to ASCII code (characters 128-255). anchor -A window procedure that handles Presentation Manager message conversions between an icon procedure and an application. anchor block -An area of Presentation-Manager-internal resources to allocated process or thread that calls WinInitialize. anchor point -A point in a window used by a program designer or by a window manager to position a subsequently appearing window. ANSI -American National Standards Institute. APA -All points addressable. API -Application programming interface. application -A collection of software components used to perform specific types of work on a computer; for example, a payroll application, an airline reservation application, a network application. application object -In SAA Advanced Common User Access architecture, a form that an application provides for a user; for example, a spreadsheet form. Contrast with user object. application programming interface (API) -A functional interface supplied by the operating system or by a separately orderable licensed program that allows an application program written in a high-level language to use specific data or functions of the operating system or the licensed program. application-modal -Pertaining to a message box or dialog box for which processing must be completed before further interaction with any other window owned by the same application may take place. area -In computer graphics, a filled shape such as a solid rectangle. ASCII -American National Standard Code for Information Interchange. ASCIIZ -A string of ASCII characters that is terminated with a byte containing the value 0. aspect ratio -In computer graphics, the width-to-height ratio of an area, symbol, or shape. asynchronous (ASYNC) -(1) Pertaining to two or more processes that do not depend upon the occurrence of specific events such as common timing signals. (T) (2) Without regular time relationship; unexpected or unpredictable with respect to the execution of program instructions. See also synchronous. atom -A constant that represents a string. As soon as a string has been defined as an atom, the atom can be used in place of the string to save space. Strings are associated with their respective atoms in an atom table. See also integer atom. atom table -A table used to relate atoms with the strings that they represent. Also in the table is the mechanism by which the presence of a string can be checked. atomic operation -An operation that completes its work on an object before another operation can be performed on the same object. attribute -A characteristic or property that can be controlled, usually to obtain a required appearance; for example, the color of a line. See also graphics attributes and segment attributes. automatic link -In Information Presentation Facility (IPF), a link that begins a chain reaction at the primary window. When the user selects the primary window, an automatic link is activated to display secondary windows. AVIO -Advanced Video Input/Output. ═══ Glossary - B ═══ Bezier curve -(1) A mathematical technique of specifying smooth continous lines and surfaces, which require a starting point and a finishing point with several intermediate points that influence or control the path of the linking curve. Named after Dr. P. Bezier. (2) (D of C) In the AIX Graphics Library, a cubic spline approximation to a set of four control points that passes through the first and fourth control points and that has a continuous slope where two spline segments meet. Named after Dr. P. Bezier. background -(1) In multiprogramming, the conditions under which low-priority programs are executed. Contrast with foreground. (2) An active session that is not currently displayed on the screen. background color -The color in which the background of a graphic primitive is drawn. background mix -An attribute that determines how the background of a graphic primitive is combined with the existing color of the graphics presentation space. Contrast with mix. background program -In multiprogramming, a program that executes with a low priority. Contrast with foreground program. bit map -A representation in memory of the data displayed on an APA device, usually the screen. block -(1) A string of data elements recorded or transmitted as a unit. The elements may be characters, words, or logical records. (T) (2) To record data in a block. (3) A collection of contiguous records recorded as a unit. Blocks are separated by interblock gaps and each block may contain one or more records. (A) block device -A storage device that performs I/O operations on blocks of data called sectors. Data on block devices can be randomly accessed. Block devices are designated by a drive letter (for example, C:). blocking mode -A condition set by an application that determines when its threads might block. For example, an application might set the Pipemode parameter for the DosCreateNPipe function so that its threads perform I/O operations to the named pipe block when no data is available. border -A visual indication (for example, a separator line or a background color) of the boundaries of a window. boundary determination -An operation used to compute the size of the smallest rectangle that encloses a graphics object on the screen. breakpoint -(1) A point in a computer program where execution may be halted. A breakpoint is usually at the beginning of an instruction where halts, caused by external intervention, are convenient for resuming execution. (T) (2) A place in a program, specified by a command or a condition, where the system halts execution and gives control to the workstation user or to a specified program. broken pipe -When all of the handles that access one end of a pipe have been closed. bucket -One or more fields in which the result of an operation is kept. buffer -(1) A portion of storage used to hold input or output data temporarily. (2) To allocate and schedule the use of buffers. (A) button -A mechanism used to request or initiate an action. See also barrel buttons, bezel buttons, mouse button, push button, and radio button. byte pipe -Pipes that handle data as byte streams. All unnamed pipes are byte pipes. Named pipes can be byte pipes or message pipes. See byte stream. byte stream -Data that consists of an unbroken stream of bytes. ═══ Glossary - C ═══ cache -A high-speed buffer storage that contains frequently accessed instructions and data; it is used to reduce access time. cached micro presentation space -A presentation space from a Presentation-Manager-owned store of micro presentation spaces. It can be used for drawing to a window only, and must be returned to the store when the task is complete. CAD -Computer-Aided Design. call -(1) The action of bringing a computer program, a routine, or a subroutine into effect, usually by specifying the entry conditions and jumping to an entry point. (I) (A) (2) To transfer control to a procedure, program, routine, or subroutine. calling sequence -A sequence of instructions together with any associated data necessary to execute a call. (T) Cancel -An action that removes the current window or menu without processing it, and returns the previous window. cascaded menu -In the OS/2 operating system, a menu that appears when the arrow to the right of a cascading choice is selected. It contains a set of choices that are related to the cascading choice. Cascaded menus are used to reduce the length of a menu. See also cascading choice. cascading choice -In SAA Common User Access architecture, a choice in a menu that, when selected, produces a cascaded menu containing other choices. An arrow (->) appears to the right of the cascading choice. CASE statement -In PM programming, provides the body of a window procedure. There is usually one CASE statement for each message type supported by an application. CGA -Color graphics adapter. chained list -A list in which the data elements may be dispersed but in which each data element contains information for locating the next. (T)Synonymous with linked list. character -A letter, digit, or other symbol. character box -In computer graphics, the boundary that defines, in world coordinates, the horizontal and vertical space occupied by a single character from a character set. See also character mode. Contrast with character cell. character cell -The physical, rectangular space in which any single character is displayed on a screen or printer device. Position is addressed by row and column coordinates. Contrast with character box. character code -The means of addressing a character in a character set, sometimes called code point. character device -A device that performs I/O operations on one character at a time. Because character devices view data as a stream of bytes, character-device data cannot be randomly accessed. Character devices include the keyboard, mouse, and printer, and are referred to by name. character mode -A mode that, in conjunction with the font type, determines the extent to which graphics characters are affected by the character box, shear, and angle attributes. character set -(1) An ordered set of unique representations called characters; for example, the 26 letters of English alphabet, Boolean 0 and 1, the set of symbols in the Morse code, and the 128 ASCII characters. (A) (2) All the valid characters for a programming language or for a computer system. (3) A group of characters used for a specific reason; for example, the set of characters a printer can print. check box -In SAA Advanced Common User Access architecture, a square box with associated text that represents a choice. When a user selects a choice, an X appears in the check box to indicate that the choice is in effect. The user can clear the check box by selecting the choice again. Contrast with radio button. check mark - (1) (D of C) In SAA Advanced Common User Access architecture, a symbol that shows that a choice is currently in effect. (2) The symbol that is used to indicate a selected item on a pull-down menu. child process -In the OS/2 operating system, a process started by another process, which is called the parent process. Contrast with parent process. child window -A window that appears within the border of its parent window (either a primary window or another child window). When the parent window is resized, moved, or destroyed, the child window also is resized, moved, or destroyed; however, the child window can be moved or resized independently from the parent window, within the boundaries of the parent window. Contrast with parent window. choice -(1) An option that can be selected. The choice can be presented as text, as a symbol (number or letter), or as an icon (a pictorial symbol). (2) (D of C) In SAA Common User Access architecture, an item that a user can select. chord -(1) To press more than one button on a pointing device while the pointer is within the limits that the user has specified for the operating environment. (2) (D of C) In graphics, a short line segment whose end points lie on a circle. Chords are a means for producing a circular image from straight lines. The higher the number of chords per circle, the smoother the circular image. class -In object-oriented design or programming, a group of objects that share a common definition and that therefore share common properties, operations, and behavior. Members of the group are called instances of the class. class method -In System Object Model, an action that can be performed on a class object. Synonymous with factory method. class object -In System Object Model, the run-time implementation of a class. class style -The set of properties that apply to every window in a window class. client -(1) A functional unit that receives shared services from a server. (T) (2) A user, as in a client process that uses a named pipe or queue that is created and owned by a server process. client area -The part of the window, inside the border, that is below the menu bar. It is the user's work space, where a user types information and selects choices from selection fields. In primary windows, it is where an application programmer presents the objects that a user works on. client program -An application that creates and manipulates instances of classes. client window -The window in which the application displays output and receives input. This window is located inside the frame window, under the window title bar and any menu bar, and within any scroll bars. clip limits -The area of the paper that can be reached by a printer or plotter. clipboard -In SAA Common User Access architecture, an area of computer memory, or storage, that temporarily holds data. Data in the clipboard is available to other applications. clipping -In computer graphics, removing those parts of a display image that lie outside a given boundary. (I) (A) clipping area -The area in which the window can paint. clipping path -A clipping boundary in world-coordinate space. clock tick -The minimum unit of time that the system tracks. If the system timer currently counts at a rate of X Hz, the system tracks the time every 1/X of a second. Also known as time tick. CLOCK$ -Character-device name reserved for the system clock. code page -An assignment of graphic characters and control-function meanings to all code points. code point -(1) Synonym for character code. (2) (D of C) A 1-byte code representing one of 256 potential characters. code segment -An executable section of programming code within a load module. color dithering -See dithering. color graphics adapter (CGA) -An adapter that simultaneously provides four colors and is supported by all IBM Personal Computer and Personal System/2 models. command -The name and parameters associated with an action that a program can perform. command area -An area composed of a command field prompt and a command entry field. command entry field -An entry field in which users type commands. command line -On a display screen, a display line, sometimes at the bottom of the screen, in which only commands can be entered. command mode -A state of a system or device in which the user can enter commands. command prompt -A field prompt showing the location of the command entry field in a panel. Common Programming Interface (CPI) -Definitions of those application development languages and services that have, or are intended to have, implementations on and a high degree of commonality across the SAA environments. One of the three SAA architectural areas. See also Common User Access architecture. Common User Access (CUA) architecture - Guidelines for the dialog between a human and a workstation or terminal. One of the three SAA architectural areas. See also Common Programming Interface. compile -To translate a program written in a higher-level programming language into a machine language program. composite window -A window composed of other windows (such as a frame window, frame-control windows, and a client window) that are kept together as a unit and that interact with each other. computer-aided design (CAD) -The use of a computer to design or change a product, tool, or machine, such as using a computer for drafting or illustrating. COM1, COM2, COM3 -Character-device names reserved for serial ports 1 through 3. CON -Character-device name reserved for the console keyboard and screen. conditional cascaded menu -A pull-down menu associated with a menu item that has a cascade mini-push button beside it in an object's pop-up menu. The conditional cascaded menu is displayed when the user selects the mini-push button. container -In SAA Common User Access architecture, an object that holds other objects. A folder is an example of a container object. See also folder and object. contextual help -In SAA Common User Access Architecture, help that gives specific information about the item the cursor is on. The help is contextual because it provides information about a specific item as it is currently being used. Contrast with extended help. contiguous -Touching or joining at a common edge or boundary, for example, an unbroken consecutive series of storage locations. control -In SAA Advanced Common User Access architecture, a component of the user interface that allows a user to select choices or type information; for example, a check box, an entry field, a radio button. control area -A storage area used by a computer program to hold control information. (I) (A) Control Panel -In the Presentation Manager, a program used to set up user preferences that act globally across the system. Control Program -(1) The basic functions of the operating system, including DOS emulation and the support for keyboard, mouse, and video input/output. (2) A computer program designed to schedule and to supervise the execution of programs of a computer system. (I) (A) control window -A window that is used as part of a composite window to perform simple input and output tasks. Radio buttons and check boxes are examples. control word -An instruction within a document that identifies its parts or indicates how to format the document. coordinate space -A two-dimensional set of points used to generate output on a video display of printer. Copy -A choice that places onto the clipboard, a copy of what the user has selected. See also Cut and Paste. correlation -The action of determining which element or object within a picture is at a given position on the display. This follows a pick operation. coverpage window -A window in which the application's help information is displayed. CPI -Common Programming Interface. critical extended attribute -An extended attribute that is necessary for the correct operation of the system or a particular application. critical section -(1) In programming languages, a part of an asynchronous procedure that cannot be executed simultaneously with a certain part of another asynchronous procedure. (I) Note: Part of the other asynchronous procedure also is a critical section. (2) A section of code that is not reentrant; that is, code that can be executed by only one thread at a time. CUA architecture -Common User Access architecture. current position -In computer graphics, the position, in user coordinates, that becomes the starting point for the next graphics routine, if that routine does not explicitly specify a starting point. cursor -A symbol displayed on the screen and associated with an input device. The cursor indicates where input from the device will be placed. Types of cursors include text cursors, graphics cursors, and selection cursors. Contrast with pointer and input focus. Cut -In SAA Common User Access architecture, a choice that removes a selected object, or a part of an object, to the clipboard, usually compressing the space it occupied in a window. See also Copy and Paste. ═══ Glossary - D ═══ daisy chain -A method of device interconnection for determining interrupt priority by connecting the interrupt sources serially. data segment -A nonexecutable section of a program module; that is, a section of a program that contains data definitions. data structure -The syntactic structure of symbolic expressions and their storage-allocation characteristics. (T) data transfer -The movement of data from one object to another by way of the clipboard or by direct manipulation. DBCS -Double-byte character set. DDE -Dynamic data exchange. deadlock -(1) Unresolved contention for the use of a resource. (2) An error condition in which processing cannot continue because each of two elements of the process is waiting for an action by, or a response from, the other. (3) An impasse that occurs when multiple processes are waiting for the availability of a resource that will not become available because it is being held by another process that is in a similar wait state. debug -To detect, diagnose, and eliminate errors in programs. (T) decipoint -In printing, one tenth of a point. There are 72 points in an inch. default procedure -A function provided by the Presentation Manager Interface that may be used to process standard messages from dialogs or windows. default value -A value assumed when no value has been specified. Synonymous with assumed value. For example, in the graphics programming interface, the default line-type is 'solid'. definition list -A type of list that pairs a term and its description. delta -An application-defined threshold, or number of container items, from either end of the list. descendant -See child process. descriptive text -Text used in addition to a field prompt to give more information about a field. Deselect all -A choice that cancels the selection of all of the objects that have been selected in that window. Desktop Manager -In the Presentation Manager, a window that displays a list of groups of programs, each of which can be started or stopped. desktop window -The window, corresponding to the physical device, against which all other types of windows are established. detached process -A background process that runs independent of the parent process. detent -A point on a slider that represents an exact value to which a user can move the slider arm. device context -A logical description of a data destination such as memory, metafile, display, printer, or plotter. See also direct device context, information device context, memory device context, metafile device context, queued device context, and screen device context. device driver -A file that contains the code needed to attach and use a device such as a display, printer, or plotter. device space -(1) Coordinate space in which graphics are assembled after all GPI transformations have been applied. Device space is defined in device-specific units. (2) ( D of C) In computer graphics, a space defined by the complete set of addressable points of a display device. (A) dialog -The interchange of information between a computer and its user through a sequence of requests by the user and the presentation of responses by the computer. dialog box -In SAA Advanced Common User Access architecture, a movable window, fixed in size, containing controls that a user uses to provide information required by an application so that it can continue to process a user request. See also message box, primary window, secondary window. Also known as a pop-up window. Dialog Box Editor -A WYSIWYG editor that creates dialog boxes for communicating with the application user. dialog item -A component (for example, a menu or a button) of a dialog box. Dialog items are also used when creating dialog templates. dialog procedure -A dialog window that is controlled by a window procedure. It is responsible for responding to all messages sent to the dialog window. dialog tag language -A markup language used by the DTL compiler to create dialog objects. dialog template -The definition of a dialog box, which contains details of its position, appearance, and window ID, and the window ID of each of its child windows. direct device context -A logical description of a data destination that is a device other than the screen (for example, a printer or plotter), and where the output is not to go through the spooler. Its purpose is to satisfy queries. See also device context. direct manipulation -The user's ability to interact with an object by using the mouse, typically by dragging an object around on the Desktop and dropping it on other objects. direct memory access (DMA) -A technique for moving data directly between main storage and peripheral equipment without requiring processing of the data by the processing unit.(T) directory -A type of file containing the names and controlling information for other files or other directories. display point -Synonym for pel. dithering -(1) The process used in color displays whereby every other pel is set to one color, and the intermediate pels are set to another. Together they produce the effect of a third color at normal viewing distances. This process can only be used on solid areas of color; it does not work, for example, on narrow lines. (2) (D of C ) In computer graphics, a technique of interleaving dark and light pixels so that the resulting image looks smoothly shaded when viewed from a distance. DMA -Direct memory access. DOS Protect Mode Interface (DPMI) -An interface between protect mode and real mode programs. double-byte character set (DBCS) -A set of characters in which each character is represented by two bytes. Languages such as Japanese, Chinese, and Korean, which contain more characters than can be represented by 256 code points, require double-byte character sets. Since each character requires two bytes, the entering, displaying, and printing of DBCS characters requires hardware and software that can support DBCS. doubleword -A contiguous sequence of bits or characters that comprises two computer words and is capable of being addressed as a unit. (A) DPMI -DOS Protect Mode Interface. drag -In SAA Common User Access, to use a pointing device to move an object; for example, clicking on a window border, and dragging it to make the window larger. dragging -(1) In computer graphics, moving an object on the display screen as if it were attached to the pointer. (2) (D of C) In computer graphics, moving one or more segments on a display surface by translating. (I) (A) drawing chain -See segment chain. drop -To fix the position of an object that is being dragged, by releasing the select button of the pointing device. drop -To fix the position of an object that is being dragged, by releasing the select button of the pointing device. See also drag. DTL -Dialog tag language. dual-boot function -A feature of the OS/2 operating system that allows the user to start DOS from within the operating system, or an OS/2 session from within DOS. duplex -Pertaining to communication in which data can be sent and received at the same time. Synonymous with full duplex. dynamic data exchange (DDE) -A message protocol used to communicate between applications that share data. The protocol uses shared memory as the means of exchanging data between applications. dynamic data formatting -A formatting procedure that enables you to incorporate text, bit maps or metafiles in an IPF window at execution time. dynamic link library -A collection of executable programming code and data that is bound to an application at load time or run time, rather than during linking. The programming code and data in a dynamic link library can be shared by several applications simultaneously. dynamic linking -The process of resolving external references in a program module at load time or run time rather than during linking. dynamic segments -Graphics segments drawn in exclusive-OR mix mode so that they can be moved from one screen position to another without affecting the rest of the displayed picture. dynamic storage -(1) A device that stores data in a manner that permits the data to move or vary with time such that the specified data is not always available for recovery. (A) (2) A storage in which the cells require repetitive application of control signals in order to retain stored data. Such repetitive application of the control signals is called a refresh operation. A dynamic storage may use static addressing or sensing circuits. (A) (3) See also static storage. dynamic time slicing -Varies the size of the time slice depending on system load and paging activity. dynamic-link module -A module that is linked at load time or run time. ═══ Glossary - E ═══ EBCDIC -Extended binary-coded decimal interchange code. A coded character set consisting of 8-bit coded characters (9 bits including parity check), used for information interchange among data processing systems, data communications systems, and associated equipment. edge-triggered -Pertaining to an event semaphore that is posted then reset before a waiting thread gets a chance to run. The semaphore is considered to be posted for the rest of that thread's waiting period; the thread does not have to wait for the semaphore to be posted again. EGA -Extended graphics adapter. element -An entry in a graphics segment that comprises one or more graphics orders and that is addressed by the element pointer. EMS -Expanded Memory Specification. encapsulation -Hiding an object's implementation, that is, its private, internal data and methods. Private variables and methods are accessible only to the object that contains them. entry field -In SAA Common User Access architecture, an area where a user types information. Its boundaries are usually indicated. See also selection field. entry panel -A defined panel type containing one or more entry fields and protected information such as headings, prompts, and explanatory text. entry-field control -The component of a user interface that provides the means by which the application receives data entered by the user in an entry field. When it has the input focus, the entry field displays a flashing pointer at the position where the next typed character will go. environment segment -The list of environment variables and their values for a process. environment strings -ASCII text strings that define the value of environment variables. environment variables -Variables that describe the execution environment of a process. These variables are named by the operating system or by the application. Environment variables named by the operating system are PATH, DPATH, INCLUDE, INIT, LIB, PROMPT, and TEMP. The values of environment variables are defined by the user in the CONFIG.SYS file, or by using the SET command at the OS/2 command prompt. error message -An indication that an error has been detected. (A) event semaphore -A semaphore that enables a thread to signal a waiting thread or threads that an event has occurred or that a task has been completed. The waiting threads can then perform an action that is dependent on the completion of the signaled event. exception -An abnormal condition such as an I/O error encountered in processing a data set or a file. exclusive system semaphore -A system semaphore that can be modified only by threads within the same process. executable file -(1) A file that contains programs or commands that perform operations or actions to be taken. (2) A collection of related data records that execute programs. exit -To execute an instruction within a portion of a computer program in order to terminate the execution of that portion. Such portions of computer programs include loops, subroutines, modules, and so on. (T) Repeated exit requests return the user to the point from which all functions provided to the system are accessible. Contrast with cancel. expanded memory specification (EMS) -Enables DOS applications to access memory above the 1MB real mode addressing limit. extended attribute -An additional piece of information about a file object, such as its data format or category. It consists of a name and a value. A file object may have more than one extended attribute associated with it. extended help -In SAA Common User Access architecture, a help action that provides information about the contents of the application window from which a user requested help. Contrast with contextual help. extended-choice selection -A mode that allows the user to select more than one item from a window. Not all windows allow extended choice selection. Contrast with multiple-choice selection. extent -Continuous space on a disk or diskette that is occupied by or reserved for a particular data set, data space, or file. external link -In Information Presentation Facility, a link that connects external online document files. ═══ Glossary - F ═══ family-mode application -An application program that can run in the OS/2 environment and in the DOS environment; however, it cannot take advantage of many of the OS/2-mode facilities, such as multitasking, interprocess communication, and dynamic linking. FAT -File allocation table. FEA -Full extended attribute. field-level help -Information specific to the field on which the cursor is positioned. This help function is "contextual" because it provides information about a specific item as it is currently used; the information is dependent upon the context within the work session. FIFO -First-in-first-out. (A) file -A named set of records stored or processed as a unit. (T) file allocation table (FAT) -In IBM personal computers, a table used by the operating system to allocate space on a disk for a file, and to locate and chain together parts of the file that may be scattered on different sectors so that the file can be used in a random or sequential manner. file attribute -Any of the attributes that describe the characteristics of a file. File Manager -In the Presentation Manager, a program that displays directories and files, and allows various actions on them. file specification -The full identifier for a file, which includes its drive designation, path, file name, and extension. file system -The combination of software and hardware that supports storing information on a storage device. file system driver (FSD) -A program that manages file I\O and controls the format of information on the storage media. fillet -A curve that is tangential to the end points of two adjoining lines. See also polyfillet. filtering -An application process that changes the order of data in a queue. first-in-first-out (FIFO) -A queuing technique in which the next item to be retrieved is the item that has been in the queue for the longest time. (A) flag -(1) An indicator or parameter that shows the setting of a switch. (2) A character that signals the occurrence of some condition, such as the end of a word. (A) (3) (D of C) A characteristic of a file or directory that enables it to be used in certain ways. See also archive flag, hidden flag, and read-only flag. focus -See input focus. folder -A container used to organize objects. font -A particular size and style of typeface that contains definitions of character sets, marker sets, and pattern sets. Font Editor -A utility program provided with the IBM Developers Toolkit that enables the design and creation of new fonts. foreground program -(1) The program with which the user is currently interacting. Also known as interactive program. Contrast with background program. (2) (D of C) In multiprogramming, a high-priority program. frame -The part of a window that can contain several different visual elements specified by the application, but drawn and controlled by the Presentation Manager. The frame encloses the client area. frame styles -Standard window layouts provided by the Presentation Manager. FSD -File system driver. full-duplex -Synonym for duplex. full-screen application -An application that has complete control of the screen. function -(1) In a programming language, a block, with or without formal parameters, whose execution is invoked by means of a call. (2) A set of related control statements that cause one or more programs to be performed. function key -A key that causes a specified sequence of operations to be performed when it is pressed, for example, F1 and Alt-K. function key area -The area at the bottom of a window that contains function key assignments such as F1=Help. ═══ Glossary - G ═══ GDT -Global Descriptor Table. general protection fault -An exception condition that occurs when a process attempts to use storage or a module that has some level of protection assigned to it, such as I/O privilege level. See also IOPL code segment. Global Descriptor Table (GDT) -A table that defines code and data segments available to all tasks in an application. global dynamic-link module -A dynamic-link module that can be shared by all processes in the system that refer to the module name. global file-name character -Either a question mark (?) or an asterisk (*) used as a variable in a file name or file name extension when referring to a particular file or group of files. glyph -A graphic symbol whose appearance conveys information. GPI -Graphics programming interface. graphic primitive -In computer graphics, a basic element, such as an arc or a line, that is not made up of smaller parts and that is used to create diagrams and pictures. See also graphics segment. graphics -(1) A picture defined in terms of graphic primitives and graphics attributes. (2) (D of C) The making of charts and pictures. (3) Pertaining to charts, tables, and their creation. (4) See computer graphics, coordinate graphics, fixed-image graphics, interactive graphics, passive graphics, raster graphics. graphics attributes -Attributes that apply to graphic primitives. Examples are color, line type, and shading-pattern definition. See also segment attributes. graphics field -The clipping boundary that defines the visible part of the presentation-page contents. graphics mode -One of several states of a display. The mode determines the resolution and color content of the screen. graphics model space -The conceptual coordinate space in which a picture is constructed after any model transforms have been applied. Also known as model space. Graphics programming interface -The formally defined programming language that is between an IBM graphics program and the user of the program. graphics segment -A sequence of related graphic primitives and graphics attributes. See also graphic primitive. graying -The indication that a choice on a pull-down is unavailable. group -A collection of logically connected controls. For example, the buttons controlling paper size for a printer could be called a group. See also program group. ═══ Glossary - H ═══ handle -(1) An identifier that represents an object, such as a device or window, to the Presentation Interface. (2) (D of C) In the Advanced DOS and OS/2 operating systems, a binary value created by the system that identifies a drive, directory, and file so that the file can be found and opened. hard error -An error condition on a network that requires either that the system be reconfigured or that the source of the error be removed before the system can resume reliable operation. header -(1) System-defined control information that precedes user data. (2) The portion of a message that contains control information for the message, such as one or more destination fields, name of the originating station, input sequence number, character string indicating the type of message, and priority level for the message. heading tags -A document element that enables information to be displayed in windows, and that controls entries in the contents window controls placement of push buttons in a window, and defines the shape and size of windows. heap -An area of free storage available for dynamic allocation by an application. Its size varies according to the storage requirements of the application. help function -(1) A function that provides information about a specific field, an application panel, or information about the help facility. (2) (D of C) One or more display images that describe how to use application software or how to do a system operation. Help index -In SAA Common User Access architecture, a help action that provides an index of the help information available for an application. help panel -A panel with information to assist users that is displayed in response to a help request from the user. help window -A Common-User-Access-defined secondary window that displays information when the user requests help. hidden file -An operating system file that is not displayed by a directory listing. hide button -In the OS/2 operating system, a small, square button located in the right-hand corner of the title bar of a window that, when selected, removes from the screen all the windows associated with that window. Contrast with maximize button. See also restore button. hierarchical inheritance -The relationship between parent and child classes. An object that is lower in the inheritance hierarchy than another object, inherits all the characteristics and behaviors of the objects above it in the hierarchy. hierarchy -A tree of segments beginning with the root segment and proceeding downward to dependent segment types. high-performance file system (HPFS) -In the OS/2 operating system, an installable file system that uses high-speed buffer storage, known as a cache, to provide fast access to large disk volumes. The file system also supports the coexistence of multiple, active file systems on a single personal computer, with the capability of multiple and different storage devices. File names used with the HPFS can have as many as 254 characters. hit testing -The means of identifying which window is associated with which input device event. hook -A point in a system-defined function where an application can supply additional code that the system processes as though it were part of the function. hook chain -A sequence of hook procedures that are "chained" together so that each event is passed, in turn, to each procedure in the chain. hot spot -The part of the pointer that must touch an object before it can be selected. This is usually the tip of the pointer. Contrast with action point. HPFS -high-performance file system. hypergraphic link -A connection between one piece of information and another through the use of graphics. hypertext -A way of presenting information online with connections between one piece of information and another, called hypertext links. See also hypertext link. hypertext link -A connection between one piece of information and another. ═══ Glossary - I ═══ I/O operation -An input operation to, or output operation from a device attached to a computer. I-beam pointer -A pointer that indicates an area, such as an entry field in which text can be edited. icon -In SAA Advanced Common User Access architecture, a graphical representation of an object, consisting of an image, image background, and a label. Icons can represent items (such as a document file) that the user wants to work on, and actions that the user wants to perform. In the Presentation Manager, icons are used for data objects, system actions, and minimized programs. icon area -In the Presentation Manager, the area at the bottom of the screen that is normally used to display the icons for minimized programs. Icon Editor -The Presentation Manager-provided tool for creating icons. IDL -Interface Definition Language. image font -A set of symbols, each of which is described in a rectangular array of pels. Some of the pels in the array are set to produce the image of one of the symbols. Contrast with outline font. implied metaclass -Subclassing the metaclass of a parent class without a separate CSC for the resultant metaclass. indirect manipulation -Interaction with an object through choices and controls. information device context -A logical description of a data destination other than the screen (for example, a printer or plotter), but where no output will occur. Its purpose is to satisfy queries. See also device context. information panel -A defined panel type characterized by a body containing only protected information. Information Presentation Facility (IPF) -A facility provided by the OS/2 operating system, by which application developers can produce online documentation and context-sensitive online help panels for their applications. inheritance -The derivation of new (child) classes from existing (parent) classes. The new class inherits all the data and methods of the parent class without having to redefine them. input focus -(1) The area of a window where user interaction is possible using an input device, such as a mouse or the keyboard. (2) The position in the active window where a user's normal interaction with the keyboard will appear. input router -An internal OS/2 process that removes messages from the system queue. input/output control -A device-specific command that requests a function of a device driver. installable file system (IFS) -A file system in which software is installed when the operating system is started. instance -A single occurrence of an object class that has a particular behavior. instruction pointer -In System/38, a pointer that provides addressability for a machine interface instruction in a program. integer atom -An atom that represents a predefined system constant and carries no storage overhead. For example, names of window classes provided by Presentation Manager are expressed as integer atoms. interactive graphics -Graphics that can be moved or manipulated by a user at a terminal. interactive program -(1) A program that is running (active) and is ready to receive (or is receiving) input from a user. (2) A running program that can receive input from the keyboard or another input device. Compare with active program and contrast with noninteractive program. Also known as a foreground program. interchange file -A file containing data that can be sent from one Presentation Manager interface application to another. Interface Definition Language (IDL) -Language-neutral interface specification for a SOM class. interpreter -A program that translates and executes each instruction of a high-level programming language before it translates and executes. interprocess communication (IPC) -In the OS/2 operating system, the exchange of information between processes or threads through semaphores, pipes, queues, and shared memory. interval timer -(1) A timer that provides program interruptions on a program-controlled basis. (2) An electronic counter that counts intervals of time under program control. IOCtl -Input/output control. IOPL -Input/output privilege level. IOPL code segment -An IOPL executable section of programming code that enables an application to directly manipulate hardware interrupts and ports without replacing the device driver. See also privilege level. IPC -Interprocess communication. IPF -Information Presentation Facility. IPF compiler -A text compiler that interpret tags in a source file and converts the information into the specified format. IPF tag language -A markup language that provides the instructions for displaying online information. item -A data object that can be passed in a DDE transaction. ═══ Glossary - J ═══ journal -A special-purpose file that is used to record changes made in the system. ═══ Glossary - K ═══ Kanji -A graphic character set used in Japanese ideographic alphabets. KBD$ -Character-device name reserved for the keyboard. kernel -The part of an operating system that performs basic functions, such as allocating hardware resources. kerning -The design of graphics characters so that their character boxes overlap. Used to space text proportionally. keyboard accelerator -A keystroke that generates a command message for an application. keyboard augmentation -A function that enables a user to press a keyboard key while pressing a mouse button. keyboard focus -A temporary attribute of a window. The window that has a keyboard focus receives all keyboard input until the focus changes to a different window. Keys help -In SAA Common User Access architecture, a help action that provides a listing of the application keys and their assigned functions. ═══ Glossary - L ═══ label -In a graphics segment, an identifier of one or more elements that is used when editing the segment. LAN -local area network. language support procedure -A function provided by the Presentation Manager Interface for applications that do not, or cannot (as in the case of COBOL and FORTRAN programs), provide their own dialog or window procedures. lazy drag -See pickup and drop. lazy drag set -See pickup set. LDT -In the OS/2 operating system, Local Descriptor Table. LIFO stack -A stack from which data is retrieved in last-in, first-out order. linear address -A unique value that identifies the memory object. linked list -Synonym for chained list. list box -In SAA Advanced Common User Access architecture, a control that contains scrollable choices from which a user can select one choice. Note: In CUA architecture, this is a programmer term. The end user term is selection list. list button -A button labeled with an underlined down-arrow that presents a list of valid objects or choices that can be selected for that field. list panel -A defined panel type that displays a list of items from which users can select one or more choices and then specify one or more actions to work on those choices. load time -The point in time at which a program module is loaded into main storage for execution. load-on-call -A function of a linkage editor that allows selected segments of the module to be disk resident while other segments are executing. Disk resident segments are loaded for execution and given control when any entry point that they contain is called. local area network (LAN) -(1) A computer network located on a user's premises within a limited geographical area. Communication within a local area network is not subject to external regulations; however, communication across the LAN boundary may be subject to some form of regulation. (T) Note: A LAN does not use store and forward techniques. (2) A network inwhich a set of devices are connected to one another for communication and that can be connected to a larger network. Local Descriptor Table (LDT) -Defines code and data segments specific to a single task. lock -A serialization mechanism by means of which a resource is restricted for use by the holder of the lock. logical storage device -A device that the user can map to a physical (actual) device. LPT1, LPT2, LPT3 -Character-device names reserved for parallel printers 1 through 3. ═══ Glossary - M ═══ main window -The window that is positioned relative to the desktop window. manipulation button -The button on a pointing device a user presses to directly manipulate an object. map -(1) A set of values having a defined correspondence with the quantities or values of another set. (I) (A) (2) To establish a set of values having a defined correspondence with the quantities or values of another set. (I) marker box -In computer graphics, the boundary that defines, in world coordinates, the horizontal and vertical space occupied by a single marker from a marker set. marker symbol -A symbol centered on a point. Graphs and charts can use marker symbols to indicate the plotted points. marquee box -The rectangle that appears during a selection technique in which a user selects objects by drawing a box around them with a pointing device. Master Help Index -In the OS/2 operating system, an alphabetic list of help topics related to using the operating system. maximize -To enlarge a window to its largest possible size. media window -The part of the physical device (display, printer, or plotter) on which a picture is presented. memory block -Part memory within a heap. memory device context -A logical description of a data destination that is a memory bit map. See also device context. memory management -A feature of the operating system for allocating, sharing, and freeing main storage. memory object -Logical unit of memory requested by an application, which forms the granular unit of memory manipulation from the application viewpoint. menu -In SAA Advanced Common User Access architecture, an extension of the menu bar that displays a list of choices available for a selected choice in the menu bar. After a user selects a choice in menu bar, the corresponding menu appears. Additional pop-up windows can appear from menu choices. menu bar -In SAA Advanced Common User Access architecture, the area near the top of a window, below the title bar and above the rest of the window, that contains choices that provide access to other menus. menu button -The button on a pointing device that a user presses to view a pop-up menu associated with an object. message -(1) In the Presentation Manager, a packet of data used for communication between the Presentation Manager interface and Presentation Manager applications (2) In a user interface, information not requested by users but presented to users by the computer in response to a user action or internal process. message box -(1) A dialog window predefined by the system and used as a simple interface for applications, without the necessity of creating dialog-template resources or dialog procedures. (2) (D of C) In SAA Advanced Common User Access architecture, a type of window that shows messages to users. See also dialog box, primary window, secondary window. message filter -The means of selecting which messages from a specific window will be handled by the application. message queue -A sequenced collection of messages to be read by the application. message stream mode -A method of operation in which data is treated as a stream of messages. Contrast with byte stream. metacharacter -See global file-name character. metaclass -The conjunction of an object and its class information; that is, the information pertaining to the class as a whole, rather than to a single instance of the class. Each class is itself an object, which is an instance of the metaclass. metafile -A file containing a series of attributes that set color, shape and size, usually of a picture or a drawing. Using a program that can interpret these attributes, a user can view the assembled image. metafile device context -A logical description of a data destination that is a metafile, which is used for graphics interchange. See also device context. metalanguage -A language used to specify another language. For example, data types can be described using a metalanguage so as to make the descriptions independent of any one computer language. method -A function that defines a behavior for a class or object. method override -The replacement, by a child class, of the implementation of a method inherited from a parent and an ancestor class. mickey -A unit of measurement for physical mouse motion whose value depends on the mouse device driver currently loaded. micro presentation space -A graphics presentation space in which a restricted set of the GPI function calls is available. minimize -To remove from the screen all windows associated with an application and replace them with an icon that represents the application. mix -An attribute that determines how the foreground of a graphic primitive is combined with the existing color of graphics output. Also known as foreground mix. Contrast with background mix. mixed character string -A string containing a mixture of one-byte and Kanji or Hangeul (two-byte) characters. mnemonic -(1) A method of selecting an item on a pull-down by means of typing the highlighted letter in the menu item. (2) (D of C) In SAA Advanced Common User Access architecture, usually a single character, within the text of a choice, identified by an underscore beneath the character. If all characters in a choice already serve as mnemonics for other choices, another character, placed in parentheses immediately following the choice, can be used. When a user types the mnemonic for a choice, the choice is either selected or the cursor is moved to that choice. modal dialog box -In SAA Advanced Common User Access architecture, a type of movable window, fixed in size, that requires a user to enter information before continuing to work in the application window from which it was displayed. Contrast with modeless dialog box. Also known as a serial dialog box. Contrast with parallel dialog box. Note: In CUA architecture, this is a programmer term. The end user term is pop-up window. model space -See graphics model space. modeless dialog box -In SAA Advanced Common User Access architecture, a type of movable window, fixed in size, that allows users to continue their dialog with the application without entering information in the dialog box. Also known as a parallel dialog box. Contrast with modal dialog box. Note: In CUA architecture, this is a programmer term. The end user term is pop-up window. module definition file -A file that describes the code segments within a load module. For example, it indicates whether a code segment is loadable before module execution begins (preload), or loadable only when referred to at run time (load-on-call). mouse -In SAA usage, a device that a user moves on a flat surface to position a pointer on the screen. It allows a user to select a choice o function to be performed or to perform operations on the screen, such as dragging or drawing lines from one position to another. MOUSE$ -Character-device name reserved for a mouse. multiple-choice selection -In SAA Basic Common User Access architecture, a type of field from which a user can select one or more choices or select none. See also check box. Contrast with extended-choice selection. multiple-line entry field -In SAA Advanced Common User Access architecture, a control into which a user types more than one line of information. See also single-line entry field. multitasking -The concurrent processing of applications or parts of applications. A running application and its data are protected from other concurrently running applications. mutex semaphore -(Mutual exclusion semaphore). A semaphore that enables threads to serialize their access to resources. Only the thread that currently owns the mutex semaphore can gain access to the resource, thus preventing one thread from interrupting operations being performed by another. muxwait semaphore -(Multiple wait semaphore). A semaphore that enables a thread to wait either for multiple event semaphores to be posted or for multiple mutex semaphores to be released. Alternatively, a muxwait semaphore can be set to enable a thread to wait for any ONE of the event or mutex semaphores in the muxwait semaphore's list to be posted or released. ═══ Glossary - N ═══ named pipe -A named buffer that provides client-to-server, server-to-client, or full duplex communication between unrelated processes. Contrast with unnamed pipe. national language support (NLS) -The modification or conversion of a United States English product to conform to the requirements of another language or country. This can include the enabling or retrofitting of a product and the translation of nomenclature, MRI, or documentation of a product. nested list -A list that is contained within another list. NLS -national language support. non-8.3 file-name format -A file-naming convention in which file names can consist of up to 255 characters. See also 8.3 file-name format. noncritical extended attribute -An extended attribute that is not necessary for the function of an application. nondestructive read -Reading that does not erase the data in the source location. (T) noninteractive program -A running program that cannot receive input from the keyboard or other input device. Compare with active program, and contrast with interactive program. nonretained graphics -Graphic primitives that are not remembered by the Presentation Manager interface when they have been drawn. Contrast with retained graphics. null character (NUL) -(1) Character-device name reserved for a nonexistent (dummy) device. (2) (D of C) A control character that is used to accomplish media-fill or time-fill and that may be inserted into or removed from a sequence of characters without affecting the meaning of the sequence; however, the control of equipment or the format may be affected by this character. (I) (A) null-terminated string -A string of (n+1) characters where the (n+1)th character is the 'null' character (0x00) Also known as 'zero-terminated' string and 'ASCIIZ' string. ═══ Glossary - O ═══ object -A set of data and actions that can be performed on that data. Object Interface Definition Language (OIDL) -Specification language used in SOM Version 1 for defining classes. Replaced by Interface Definition Language (IDL). object window -A window that does not have a parent but which might have child windows. An object window cannot be presented on a device. OIDL -Object Interface Definition Language. open -To start working with a file, directory, or other object. ordered list -Vertical arrangements of items, with each item in the list preceded by a number or letter. outline font -A set of symbols, each of which is created as a series of lines and curves. Synonymous with vector font. Contrast with image font. output area -An area of storage reserved for output. (A) owner window -A window into which specific events that occur in another (owned) window are reported. ownership -The determination of how windows communicate using messages. owning process -The process that owns the resources that might be shared with other processes. ═══ Glossary - P ═══ page -(1) A 4KB segment of contiguous physical memory. (2) (D of C) A defined unit of space on a storage medium. page viewport -A boundary in device coordinates that defines the area of the output device in which graphics are to be displayed. The presentation-page contents are transformed automatically to the page viewport in device space. paint -(1) The action of drawing or redrawing the contents of a window. (2) In computer graphics, to shade an area of a display image; for example, with crosshatching or color. panel -In SAA Basic Common User Access architecture, a particular arrangement of information that is presented in a window or pop-up. If some of the information is not visible, a user can scroll through the information. panel area -An area within a panel that contains related information. The three major Common User Access-defined panel areas are the action bar, the function key area, and the panel body. panel area separator -In SAA Basic Common User Access architecture, a solid, dashed, or blank line that provides a visual distinction between two adjacent areas of a panel. panel body -The portion of a panel not occupied by the action bar, function key area, title or scroll bars. The panel body can contain protected information, selection fields, and entry fields. The layout and content of the panel body determine the panel type. panel body area -See client area. panel definition -A description of the contents and characteristics of a panel. A panel definition is the application developer's mechanism for predefining the format to be presented to users in a window. panel ID -In SAA Basic Common User Access architecture, a panel identifier, located in the upper-left corner of a panel. A user can choose whether to display the panel ID. panel title -In SAA Basic Common User Access architecture, a particular arrangement of information that is presented in a window or pop-up. If some of the information is not visible, a user can scroll through the information. paper size -The size of paper, defined in either standard U.S. or European names (for example, A, B, A4), and measured in inches or millimeters respectively. parallel dialog box -See modeless dialog box. parameter list -A list of values that provides a means of associating addressability of data defined in a called program with data in the calling program. It contains parameter names and the order in which they are to be associated in the calling and called program. parent process -In the OS/2 operating system, a process that creates other processes. Contrast with child process. parent window -In the OS/2 operating system, a window that creates a child window. The child window is drawn within the parent window. If the parent window is moved, resized, or destroyed, the child window also will be moved, resized, or destroyed. However, the child window can be moved and resized independently from the parent window, within the boundaries of the parent window. Contrast with child window. partition -(1) A fixed-size division of storage. (2) On an IBM personal computer fixed disk, one of four possible storage areas of variable size; one may be accessed by DOS, and each of the others may be assigned to another operating system. Paste -A choice in the Edit pull-down that a user selects to move the contents of the clipboard into a preselected location. See also Copy and Cut. path -The route used to locate files; the storage location of a file. A fully qualified path lists the drive identifier, directory name, subdirectory name (if any), and file name with the associated extension. PDD -Physical device driver. peeking -An action taken by any thread in the process that owns the queue to examine queue elements without removing them. pel -(1) The smallest area of a display screen capable of being addressed and switched between visible and invisible states. Synonym for display point, pixel, and picture element. (2) (D of C) Picture element. persistent object -An object whose instance data and state are preserved between system shutdown and system startup. physical device driver (PDD) -A system interface that handles hardware interrupts and supports a set of input and output functions. pick -To select part of a displayed object using the pointer. pickup -To add an object or set of objects to the pickup set. pickup and drop -A drag operation that does not require the direct manipulation button to be pressed for the duration of the drag. pickup set -The set of objects that have been picked up as part of a pickup and drop operation. picture chain -See segment chain. picture element -(1) Synonym for pel. (2) (D of C) In computer graphics, the smallest element of a display surface that can be independently assigned color and intensity. (T) . (3) The area of the finest detail that can be reproduced effectively on the recording medium. PID -Process identification. pipe -(1) A named or unnamed buffer used to pass data between processes. A process reads from or writes to a pipe as if the pipe were a standard-input or standard-output file. See also named pipe and unnamed pipe. (2) (D of C) To direct data so that the output from one process becomes the input to another process. The standard output of one command can be connected to the standard input of another with the pipe operator (|). pixel -(1) Synonym for pel. (2) (D of C) Picture element. plotter -An output unit that directly produces a hardcopy record of data on a removable medium, in the form of a two-dimensional graphic representation. (T) PM -Presentation Manager. pointer -(1) The symbol displayed on the screen that is moved by a pointing device, such as a mouse. The pointer is used to point at items that users can select. Contrast with cursor. (2) A data element that indicates the location of another data element. (T) POINTER$ -Character-device name reserved for a pointer device (mouse screen support). pointing device -In SAA Advanced Common User Access architecture, an instrument, such as a mouse, trackball, or joystick, used to move a pointer on the screen. pointings -Pairs of x-y coordinates produced by an operator defining positions on a screen with a pointing device, such as a mouse. polyfillet -A curve based on a sequence of lines. The curve is tangential to the end points of the first and last lines, and tangential also to the midpoints of all other lines. See also fillet. polygon -One or more closed figures that can be drawn filled, outlined, or filled and outlined. polyline -A sequence of adjoining lines. polymorphism -The ability to have different implementations of the same method for two or more classes of objects. pop -To retrieve an item from a last-in-first-out stack of items. Contrast with push. pop-up menu -A menu that lists the actions that a user can perform on an object. The contents of the pop-up menu can vary depending on the context, or state, of the object. pop-up window -(1) A window that appears on top of another window in a dialog. Each pop-up window must be completed before returning to the underlying window. (2) (D of C) In SAA Advanced Common User Access architecture, a movable window, fixed in size, in which a user provides information required by an application so that it can continue to process a user request. presentation drivers -Special purpose I/O routines that handle field device-independent I/O requests from the PM and its applications. Presentation Manager (PM) -The interface of the OS/2 operating system that presents, in windows a graphics-based interface to applications and files installed and running under the OS/2 operating system. presentation page -The coordinate space in which a picture is assembled for display. presentation space (PS) -(1) Contains the device-independent definition of a picture. (2) (D of C) The display space on a display device. primary window -In SAA Common User Access architecture, the window in which the main interaction between the user and the application takes place. In a multiprogramming environment, each application starts in its own primary window. The primary window remains for the duration of the application, although the panel displayed will change as the user's dialog moves forward. See also secondary window. primitive -In computer graphics, one of several simple functions for drawing on the screen, including, for example, the rectangle, line, ellipse, polygon, and so on. primitive attribute -A specifiable characteristic of a graphic primitive. See graphics attributes. print job -The result of sending a document or picture to be printed. Print Manager -In the Presentation Manager, the part of the spooler that manages the spooling process. It also allows users to view print queues and to manipulate print jobs. privilege level -A protection level imposed by the hardware architecture of the IBM personal computer. There are four privilege levels (number 0 through 3). Only certain types of programs are allowed to execute at each privilege level. See also IOPL code segment. procedure call -In programming languages, a language construct for invoking execution of a procedure. process -An instance of an executing application and the resources it is using. program -A sequence of instructions that a computer can interpret and execute. program details -Information about a program that is specified in the Program Manager window and is used when the program is started. program group -In the Presentation Manager, several programs that can be acted upon as a single entity. program name -The full file specification of a program. Contrast with program title. program title -The name of a program as it is listed in the Program Manager window. Contrast with program name. prompt -A displayed symbol or message that requests input from the user or gives operational information; for example, on the display screen of an IBM personal computer, the DOS A> prompt. The user must respond to the prompt in order to proceed. protect mode -A method of program operation that limits or prevents access to certain instructions or areas of storage. Contrast with real mode. protocol -A set of semantic and syntactic rules that determines the behavior of functional units in achieving communication. (I) pseudocode -An artificial language used to describe computer program algorithms without using the syntax of any particular programming language. (A) pull-down -(1) An action bar extension that displays a list of choices available for a selected action bar choice. After users select an action bar choice, the pull-down appears with the list of choices. Additional pop-up windows may appear from pull-down choices to further extend the actions available to users. (2) (D of C) In SAA Common User Access architecture, pertaining to a choice in an action bar pull-down. push -To add an item to a last-in-first-out stack of items. Contrast with pop. push button -In SAA Advanced Common User Access architecture, a rectangle with text inside. Push buttons are used in windows for actions that occur immediately when the push button is selected. putback -To remove an object or set of objects from the lazy drag set. This has the effect of undoing the pickup operation for those objects putdown -To drop the objects in the lazy drag set on the target object. ═══ Glossary - Q ═══ queue -(1) A linked list of elements waiting to be processed in FIFO order. For example, a queue may be a list of print jobs waiting to be printed. (2) (D of C) A line or list of items waiting to be processed; for example, work to be performed or messages to be displayed. queued device context -A logical description of a data destination (for example, a printer or plotter) where the output is to go through the spooler. See also device context. ═══ Glossary - R ═══ radio button -(1) A control window, shaped like a round button on the screen, that can be in a checked or unchecked state. It is used to select a single item from a list. Contrast with check box. (2) In SAA Advanced Common User Access architecture, a circle with text beside it. Radio buttons are combined to show a user a fixed set of choices from which only one can be selected. The circle is partially filled when a choice is selected. RAS -Reliability, availability, and serviceability. raster -(1) In computer graphics, a predetermined pattern of lines that provides uniform coverage of a display space. (T) (2) The coordinate grid that divides the display area of a display device. (A) read-only file -A file that can be read from but not written to. real mode -A method of program operation that does not limit or prevent access to any instructions or areas of storage. The operating system loads the entire program into storage and gives the program access to all system resources. Contrast with protect mode. realize -To cause the system to ensure, wherever possible, that the physical color table of a device is set to the closest possible match in the logical color table. recursive routine -A routine that can call itself, or be called by another routine that was called by the recursive routine. reentrant -The attribute of a program or routine that allows the same copy of the program or routine to be used concurrently by two or more tasks. reference phrase -(1) A word or phrase that is emphasized in a device-dependent manner to inform the user that additional information for the word or phrase is available. (2) (D of C) In hypertext, text that is highlighted and preceded by a single-character input field used to signify the existence of a hypertext link. reference phrase help -In SAA Common User Access architecture, highlighted words or phrases within help information that a user selects to get additional information. refresh -To update a window, with changed information, to its current status. region -A clipping boundary in device space. register -A part of internal storage having a specified storage capacity and usually intended for a specific purpose. (T) remote file system -A file-system driver that gains access to a remote system without a block device driver. resource -The means of providing extra information used in the definition of a window. A resource can contain definitions of fonts, templates, accelerators, and mnemonics; the definitions are held in a resource file. resource file -A file containing information used in the definition of a window. Definitions can be of fonts, templates, accelerators, and mnemonics. restore -To return a window to its original size or position following a sizing or moving action. retained graphics -Graphic primitives that are remembered by the Presentation Manager interface after they have been drawn. Contrast with nonretained graphics. return code -(1) A value returned to a program to indicate the results of an operation requested by that program. (2) A code used to influence the execution of succeeding instructions.(A) reverse video -(1) A form of highlighting a character, field, or cursor by reversing the color of the character, field, or cursor with its background; for example, changing a red character on a black background to a black character on a red background. (2) In SAA Basic Common User Access architecture, a screen emphasis feature that interchanges the foreground and background colors of an item. REXX Language -Restructured Extended Executor. A procedural language that provides batch language functions along with structured programming constructs such as loops; conditional testing and subroutines. RGB -(1) Color coding in which the brightness of the additive primary colors of light, red, green, and blue, are specified as three distinct values of white light. (2) Pertaining to a color display that accepts signals representing red, green, and blue. roman -Relating to a type style with upright characters. root segment -In a hierarchical database, the highest segment in the tree structure. round-robin scheduling -A process that allows each thread to run for a specified amount of time. run time -(1) Any instant at which the execution of a particular computer program takes place. (T) (2) The amount of time needed for the execution of a particular computer program. (T) (3) The time during which an instruction in an instruction register is decoded and performed. Synonym for execution time. ═══ Glossary - S ═══ SAA -Systems Application Architecture. SBCS -Single-byte character set. scheduler -A computer program designed to perform functions such as scheduling, initiation, and termination of jobs. screen -In SAA Basic Common User Access architecture, the physical surface of a display device upon which information is shown to a user. screen device context -A logical description of a data destination that is a particular window on the screen. See also device context. SCREEN$ -Character-device name reserved for the display screen. scroll bar -In SAA Advanced Common User Access architecture, a part of a window, associated with a scrollable area, that a user interacts with to see information that is not currently allows visible. scrollable entry field -An entry field larger than the visible field. scrollable selection field -A selection field that contains more choices than are visible. scrolling -Moving a display image vertically or horizontally in a manner such that new data appears at one edge, as existing data disappears at the opposite edge. secondary window -A window that contains information that is dependent on information in a primary window and is used to supplement the interaction in the primary window. sector -On disk or diskette storage, an addressable subdivision of a track used to record one block of a program or data. segment -See graphics segment. segment attributes -Attributes that apply to the segment as an entity, as opposed to the individual primitives within the segment. For example, the visibility or detectability of a segment. segment chain -All segments in a graphics presentation space that are defined with the 'chained' attribute. Synonym for picture chain. segment priority -The order in which segments are drawn. segment store -An area in a normal graphics presentation space where retained graphics segments are stored. select -To mark or choose an item. Note that select means to mark or type in a choice on the screen; enter means to send all selected choices to the computer for processing. select button -The button on a pointing device, such as a mouse, that is pressed to select a menu choice. Also known as button 1. selection cursor -In SAA Advanced Common User Access architecture, a visual indication that a user has selected a choice. It is represented by outlining the choice with a dotted box. See also text cursor. selection field -(1) In SAA Advanced Common User Access architecture, a set of related choices. See also entry field. (2) In SAA Basic Common User Access architecture, an area of a panel that cannot be scrolled and contains a fixed number of choices. semantics -The relationships between symbols and their meanings. semaphore -An object used by applications for signalling purposes and for controlling access to serially reusable resources. separator -In SAA Advanced Common User Access architecture, a line or color boundary that provides a visual distinction between two adjacent areas. serial dialog box -See modal dialog box. serialization -The consecutive ordering of items. serialize -To ensure that one or more events occur in a specified sequence. serially reusable resource (SRR) -A logical resource or object that can be accessed by only one task at a time. session -(1) A routing mechanism for user interaction via the console; a complete environment that determines how an application runs and how users interact with the application. OS/2 can manage more than one session at a time, and more than one process can run in a session. Each session has its own set of environment variables that determine where OS/2 looks for dynamic-link libraries and other important files. (2) (D of C) In the OS/2 operating system, one instance of a started program or command prompt. Each session is separate from all other sessions that might be running on the computer. The operating system is responsible for coordinating the resources that each session uses, such as computer memory, allocation of processor time, and windows on the screen. Settings Notebook -A control window that is used to display the settings for an object and to enable the user to change them. shadow -An object that refers to another object. A shadow is not a copy of another object, but is another representation of the object. shadow box -The area on the screen that follows mouse movements and shows what shape the window will take if the mouse button is released. shared data -Data that is used by two or more programs. shared memory -In the OS/2 operating system, a segment that can be used by more than one program. shear -In computer graphics, the forward or backward slant of a graphics symbol or string of such symbols relative to a line perpendicular to the baseline of the symbol. shell -(1) A software interface between a user and the operating system of a computer. Shell programs interpret commands and user interactions on devices such as keyboards, pointing devices, and touch-sensitive screens, and communicate them to the operating system. (2) Software that allows a kernel program to run under different operating-system environments. shutdown -The process of ending operation of a system or a subsystem, following a defined procedure. sibling processes -Child processes that have the same parent process. sibling windows -Child windows that have the same parent window. simple list -A list of like values; for example, a list of user names. Contrast with mixed list. single-byte character set (SBCS) -A character set in which each character is represented by a one-byte code. Contrast with double-byte character set. slider box -In SAA Advanced Common User Access architecture: a part of the scroll bar that shows the position and size of the visible information in a window relative to the total amount of information available. Also known as thumb mark. SOM -System Object Model. source file -A file that contains source statements for items such as high-level language programs and data description specifications. source statement -A statement written in a programming language. specific dynamic-link module -A dynamic-link module created for the exclusive use of an application. spin button -In SAA Advanced Common User Access architecture, a type of entry field that shows a scrollable ring of choices from which a user can select a choice. After the last choice is displayed, the first choice is displayed again. A user can also type a choice from the scrollable ring into the entry field without interacting with the spin button. spline -A sequence of one or more Bezier curves. spooler -A program that intercepts the data going to printer devices and writes it to disk. The data is printed or plotted when it is complete and the required device is available. The spooler prevents output from different sources from being intermixed. stack -A list constructed and maintained so that the next data element to be retrieved is the most recently stored. This method is characterized as last-in-first-out (LIFO). standard window -A collection of window elements that form a panel. The standard window can include one or more of the following window elements: sizing borders, system menu icon, title bar, maximize/minimize/restore icons, action bar and pull-downs, scroll bars, and client area. static control -The means by which the application presents descriptive information (for example, headings and descriptors) to the user. The user cannot change this information. static storage -(1) A read/write storage unit in which data is retained in the absence of control signals. (A) Static storage may use dynamic addressing or sensing circuits. (2) Storage other than dynamic storage. (A) style -See window style. subclass -A class that is a child of another class. See also Inheritance. subdirectory -In an IBM personal computer, a file referred to in a root directory that contains the names of other files stored on the diskette or fixed disk. swapping -(1) A process that interchanges the contents of an area of real storage with the contents of an area in auxiliary storage. (I) (A) (2) In a system with virtual storage, a paging technique that writes the active pages of a job to auxiliary storage and reads pages of another job from auxiliary storage into real storage. (3) The process of temporarily removing an active job from main storage, saving it on disk, and processing another job in the area of main storage formerly occupied by the first job. switch -(1) In SAA usage, to move the cursor from one point of interest to another; for example, to move from one screen or window to another or from a place within a displayed image to another place on the same displayed image. (2) In a computer program, a conditional instruction and an indicator to be interrogated by that instruction. (3) A device or programming technique for making a selection, for example, a toggle, a conditional jump. switch list -See Task List. symbolic identifier -A text string that equates to an integer value in an include file, which is used to identify a programming object. symbols -In Information Presentation Facility, a document element used to produce characters that cannot be entered from the keyboard. synchronous -Pertaining to two or more processes that depend upon the occurrence of specific events such as common timing signals. (T) See also asynchronous. System Menu -In the Presentation Manager, the pull-down in the top left corner of a window that allows it to be moved and sized with the keyboard. System Object Model (SOM) -A mechanism for language-neutral, object-oriented programming in the OS/2 environment. system queue -The master queue for all pointer device or keyboard events. system-defined messages -Messages that control the operations of applications and provides input an other information for applications to process. Systems Application Architecture (SAA) -A set of IBM software interfaces, conventions, and protocols that provide a framework for designing and developing applications that are consistent across systems. ═══ Glossary - T ═══ table tags -In Information Presentation Facility, a document element that formats text in an arrangement of rows and columns. tag -(1) One or more characters attached to a set of data that contain information about the set, including its identification. (I) (A) (2) In Generalized Markup Language markup, a name for a type of document or document element that is entered in the source document to identify it. target object -An object to which the user is transferring information. Task List -In the Presentation Manager, the list of programs that are active. The list can be used to switch to a program and to stop programs. terminate-and-stay-resident (TSR) -Pertaining to an application that modifies an operating system interrupt vector to point to its own location (known as hooking an interrupt). text -Characters or symbols. text cursor -A symbol displayed in an entry field that indicates where typed input will appear. text window -Also known as the VIO window. text-windowed application -The environment in which the operating system performs advanced-video input and output operations. thread -A unit of execution within a process. It uses the resources of the process. thumb mark -The portion of the scroll bar that describes the range and properties of the data that is currently visible in a window. Also known as a slider box. thunk -Term used to describe the process of address conversion, stack and structure realignment, etc., necessary when passing control between 16-bit and 32-bit modules. tilde -A mark used to denote the character that is to be used as a mnemonic when selecting text items within a menu. time slice -(1) An interval of time on the processing unit allocated for use in performing a task. After the interval has expired, processing-unit time is allocated to another task, so a task cannot monopolize processing-unit time beyond a fixed limit. (2) In systems with time sharing, a segment of time allocated to a terminal job. time-critical process -A process that must be performed within a specified time after an event has occurred. timer -A facility provided under the Presentation Manager, whereby Presentation Manager will dispatch a message of class WM_TIMER to a particular window at specified intervals. This capability may be used by an application to perform a specific processing task at predetermined intervals, without the necessity for the application to explicitly keep track of the passage of time. timer tick -See clock tick. title bar -In SAA Advanced Common User Access architecture, the area at the top of each window that contains the window title and system menu icon. When appropriate, it also contains the minimize, maximize, and restore icons. Contrast with panel title. TLB -Translation lookaside buffer. transaction -An exchange between a workstation and another device that accomplishes a particular action or result. transform -(1) The action of modifying a picture by scaling, shearing, reflecting, rotating, or translating. (2) The object that performs or defines such a modification; also referred to as a transformation. Translation lookaside buffer (TLB) -A hardware-based address caching mechanism for paging information. Tree -In the Presentation Manager, the window in the File Manager that shows the organization of drives and directories. truncate -(1) To terminate a computational process in accordance with some rule (A) (2) To remove the beginning or ending elements of a string. (3) To drop data that cannot be printed or displayed in the line width specified or available. (4) To shorten a field or statement to a specified length. TSR -Terminate-and-stay-resident. unnamed pipe -A circular buffer, created in memory, used by related processes to communicate with one another. Contrast with named pipe. unordered list -In Information Presentation Facility, a vertical arrangement of items in a list, with each item in the list preceded by a special character or bullet. update region -A system-provided area of dynamic storage containing one or more (not necessarily contiguous) rectangular areas of a window that are visually invalid or incorrect, and therefore are in need of repainting. user interface -Hardware, software, or both that allows a user to interact with and perform operations on a system, program, or device. User Shell -A component of OS/2 that uses a graphics-based, windowed interface to allow the user to manage applications and files installed and running under OS/2. utility program -(1) A computer program in general support of computer processes; for example, a diagnostic program, a trace program, a sort program. (T) (2) A program designed to perform an everyday task such as copying data from one storage device to another. (A) ═══ Glossary - U ═══ There are no glossary terms for this starting letter. ═══ Glossary - V ═══ value set control -A visual component that enables a user to select one choice from a group of mutually exclusive choices. vector font -A set of symbols, each of which is created as a series of lines and curves. Synonymous with outline font. Contrast with image font. VGA -Video graphics array. view -A way of looking at an object's information. viewing pipeline -The series of transformations applied to a graphic object to map the object to the device on which it is to be presented. viewing window -A clipping boundary that defines the visible part of model space. VIO -Video Input/Output. virtual memory (VM) -Synonymous with virtual storage. virtual storage -(1) The storage space that may be regarded as addressable main storage by the user of a computer system in which virtual addresses are mapped into real addresses. The size of virtual storage is limited by the addressing scheme of the computer system and by the amount of auxiliary storage available, not by the actual number of main storage locations. (I) (A) (2) Addressable space that is apparent to the user as the processor storage space, from which the instructions and the data are mapped into the processor storage locations. (3) Synonymous with virtual memory. visible region -A window's presentation space, clipped to the boundary of the window and the boundaries of any overlying window. volume -(1) A file-system driver that uses a block device driver for input and output operations to a local or remote device. (I) (2) A portion of data, together with its data carrier, that can be handled conveniently as a unit. ═══ Glossary - W ═══ wildcard character -Synonymous with global file-name character. window -(1) A portion of a display surface in which display images pertaining to a particular application can be presented. Different applications can be displayed simultaneously in different windows. (A) (2) An area of the screen with visible boundaries within which information is displayed. A window can be smaller than or the same size as the screen. Windows can appear to overlap on the screen. window class -The grouping of windows whose processing needs conform to the services provided by one window procedure. window coordinates -A set of coordinates by which a window position or size is defined; measured in device units, or pels. window handle -Unique identifier of a window, generated by Presentation Manager when the window is created, and used by applications to direct messages to the window. window procedure -Code that is activated in response to a message. The procedure controls the appearance and behavior of its associated windows. window rectangle -The means by which the size and position of a window is described in relation to the desktop window. window resource -A read-only data segment stored in the .EXE file of an application o the .DLL file of a dynamic link library. window style -The set of properties that influence how events related to a particular window will be processed. window title -In SAA Advanced Common User Access architecture, the area in the title bar that contains the name of the application and the OS/2 operating system file name, if applicable. Workplace Shell -The OS/2 object-oriented, graphical user interface. workstation -(1) A display screen together with attachments such as a keyboard, a local copy device, or a tablet. (2) (D of C) One or more programmable or nonprogrammable devices that allow a user to do work. world coordinates -A device-independent Cartesian coordinate system used by the application program for specifying graphical input and output. (I) (A) world-coordinate space -Coordinate space in which graphics are defined before transformations are applied. WYSIWYG -What-You-See-Is-What-You-Get. A capability of a text editor to continually display pages exactly as they will be printed. ═══ Glossary - X ═══ There are no glossary terms for this starting letter. ═══ Glossary - Y ═══ There are no glossary terms for this starting letter. ═══ Glossary - Z ═══ z-order -The order in which sibling windows are presented. The topmost sibling window obscures any portion of the siblings that it overlaps; the same effect occurs down through the order of lower sibling windows. zooming -The progressive scaling of an entire display image in order to give the visual impression of movement of all or part of a display group toward or away from an observer. (I) (A) 8.3 file-name format -A file-naming convention in which file names are limited to eight characters before and three characters after a single dot. Usually pronounced "eight-dot-three." See also non-8.3 file-name format. ═══ IBM Trademark ═══ Trademark of the IBM Corporation. ═══ Trademarks ═══ Trademark of AT&T, Inc. ═══ Trademarks ═══ Trademark of the Adobe Systems Inc. ═══ Trademarks ═══ Trademark of the Microsoft Corporation. ═══ Trademarks ═══ Trademark of Linotype. ═══ Trademarks ═══ Trademark of Monotype Corporation, Limited. ═══ Trademarks ═══ Trademark of Intel Coporation.