Jump to content

GPIGuide - Creating and Drawing Retained Graphics: Difference between revisions

From EDM2
No edit summary
Line 1: Line 1:
{{IBM-Reprint}}
{{GPIGuide}}
There are two types of graphics output in the OS/2 operating system:
There are two types of graphics output in the OS/2 operating system:



Revision as of 04:24, 4 May 2025

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

GPI Guide and Reference
  1. How to Use the GPI Guide and Reference
  2. Graphics Functions
  3. Data Types
  4. Graphics Orders
  5. Graphics Orders Data Types
  6. Errors
  7. Area and Polygon Primitives
  8. Bit Maps
  9. Creating and Drawing Retained Graphics
  10. Character String Primitives
  11. Clipping and Boundary Determination
  12. Color and Mix Attributes
  13. Correlation
  14. Coordinate Spaces and Transformations
  15. Editing Retained Graphics and Graphics Segments
  16. Fonts
  17. Graphics Attributes
  18. Line and Arc Primitives
  19. Marker Primitives
  20. Matrix Multiplication
  21. Metafiles
  22. Print Job Submission and Manipulation
  23. Presentation Spaces and Device Contexts
  24. Paths
  25. Regions
  26. Notices
  27. Glossary

There are two types of graphics output in the OS/2 operating system:

  • Retained graphics, which are stored in segments and can be redrawn or edited when necessary.
  • Nonretained graphics, which are drawn immediately but not stored and therefore cannot be used again without repeating the graphics functions needed to re-create the picture.

This chapter describes the advantages of using retained graphics and provides information on creating and drawing retained graphics. The following topics are related to the information in this chapter:

  • Presentation spaces and device contexts
  • Coordinate spaces and transformations
  • Editing retained graphics and graphics segments

About Creating and Drawing Retained Graphics

An application draws by calling graphics functions. Applications store retained graphics in segments, which can be edited. This means that the retained image can be modified without having to re-create the unmodified portion using multiple GPI functions.

When using nonretained graphics, the output appears on the output device (for example, a window) immediately. However, if part of the picture is erased or must be repeated, the application must call the same graphics functions a second, or even a third time.

There are many other advantages to using retained graphics, including:

  • Convenience - An application can draw retained graphics with a single function that accesses the storage area containing all the individual functions necessary for the object.
  • Flexibility - An application can redraw graphics retained in the segment store to any number of device contexts.
  • Editing - An application can modify an object without having to call all the functions necessary to re-create the picture. Individual segments can be moved, scaled, or rotated; then, redrawn.
Editing the graphics within a segment is described in Editing Retained Graphics and Graphics Segments.
  • Power - An application can access the more powerful and useful graphics functions only when graphics are stored in segments.
  • Organization - An application can use segments to store the components that will be assembled into the final picture.

Primarily, a graphics segment is a means of grouping and storing graphics primitives and their attributes. Although the graphics within a segment usually are related in some way, they do not have to be. A segment might contain a number of unrelated GPI functions that you want to keep and execute at specific times.

Retained graphics do affect application performance, however, in that a normal presentation space requires 114KB of main memory more than a micro presentation space, and using the drawing mode DM_RETAIN adds an additional 46KB.

Note: Your application can have up to 16KB (16378) segments in the segment store of a single presentation space. The size of an individual segment is limited only by the amount of storage available to you.

Do not confuse a graphics segment with a memory segment.

Drawing Modes

When you create a presentation space, the drawing mode is set to draw. Your application can change this mode using GpiSetDrawingMode. The two additional drawing modes provided by the PM are retain (DM_RETAIN) and draw-and-retain (DM_DRAWANDRETAIN). Your application can determine which drawing mode is set by using GpiQueryDrawingMode.

The drawing mode that you select becomes current for the presentation space, and it can be changed any number of times. Select the appropriate drawing mode before creating a segment. The drawing mode affects the segment type.

Draw Mode

In draw mode, graphics output is provided immediately to the currently associated device and is not retained in a segment store. When the graphics have been drawn, they cannot be used again unless they are re-created. For example, when a window containing draw mode graphics is moved or sized, the graphics have to be re-created by the application.

Draw mode graphics are suitable if an application is creating fairly simple graphics quickly or is maintaining its own graphics database. In the latter case, there is nothing to gain by retaining graphics.

A segment created when the drawing mode is DM_DRAW, is called a nonretained segment. While it might sound contradictory, nonretained segments have certain advantages that are described in Nonretained Graphic Segments.

Retain Mode

In retain mode, graphics are retained in the segment store only. They are not directed to the current device as they are created.

In retain mode, the presentation space does not have to be associated with a device context when graphics are being defined. It is possible to define graphics and store their definitions without sending them to a display screen or printer. The concept of attribute currentness, however, is relevant only when you are drawing graphics to an output device. For example, the color or other attribute that is current when you define a primitive is the color in which the line is drawn. That color or other attribute might not be the color that is current when you actually draw the primitive. This is described in Attribute Currentness.

Many of the GPI queries that return current attribute values are invalid in retain mode because current attribute values have no effect when graphics are not sent to an output device.

Draw-and-Retain Mode

In draw-and-retain mode, graphics are both drawn on the current device as they are created and stored for later use. The GPI queries that return current attribute values are valid in draw-and-retain mode.

Creating a Graphics Segment

Your application signals the start of a graphics segment using GpiOpenSegment, which is valid only in a normal presentation space. The following figure is an example of two segments in a presentation space.

    Presentation Space
                          ┌─────────────────────────────────────┐
                          │                                     │
                          │   Graphics Segment 1                │
                          │   ┌────────────┐                    │
                          │   │            │                    │
GpiOpenSegment (hps,1L);  │   │            │                    │
GpiSet... (hps,...);    ──┼───┼──────      │                    │
GpiLine (hps,...);      ──┼───┼──          │                    │
GpiCloseSegment (hps);    │   │            │  Graphics Segment 2│
                          │   │            │  ┌────────────┐    │
                          │   │            │  │            │    │
                          │   └────────────┘  │            │    │
                          │                   │            │    │
GpiOpenSegment (hps,2L);  │                   │            │    │
GpiSet... (hps,...);    ──┼───────────────────┼─────       │    │
GpiLine (hps,...);      ──┼───────────────────┼──          │    │
GpiCloseSegment (hps);    │                   │            │    │
                          │                   └────────────┘    │
                          │                                     │
                          │                                     │
                          └─────────────────────────────────────┘

Graphics Segments in a Presentation Space

GpiOpenSegment accepts, as input, the presentation space handle and a long integer value, which names each segment.

OS/2 applications identify segments with long integer values. If you want to refer to the segment individually in later graphics operations (for example, to edit the segment) the identifier you supply must be greater than 0 and unique within the presentation space.

If you do not want to refer to the segment individually after it is created, you can give the segment an identifier of 0. You might do this when you are creating nonretained segments, for example. Any number of segments can have the 0 identifier. They are referred to throughout this book as zero segments.

To determine which names already have been used in a presentation space, use GpiQuerySegmentNames. This function returns an array of segment names for all retained segments, excluding zero segments, within a specified name range.

Segments do not have to be named in consecutive order (although it is recommended for organizational purposes) because the segment order can be changed using GpiSetSegmentPriority.

Filling a Graphics Segment

After a graphics segment is opened, the GPI functions that follow become a part of a retained segment and are executed every time the segment itself is drawn.

The typical GPI functions that would be called are those that:

  • Create graphics primitives - such as lines or markers.
  • Assign attributes to those primitives - such as color or line type.

However, there are a few GPI functions that you cannot call while there is an open segment - for example a second GpiOpenSegment. These functions are identified in GPI Function Context.

A presentation space can contain many segments. Each time you open a new segment, many attributes reset themselves to default values. Therefore, the current position and attribute values that apply before you call GpiOpenSegment cannot be guaranteed to be in effect after you call the function. Beginning each segment with a number of attribute-setting requests and, possibly, with GpiSetCurrentPosition, is recommended. Your application also might take advantage of GpiSetDefAttrs, for example, to minimize the number of attributes that must be dealt with upon opening a new segment.

Closing a Graphics Segment

When you have finished creating a graphics segment, close it using GpiCloseSegment. There can be only one open segment at a time in a single graphics presentation space, so you must close one segment before going on to the next.

There is some degree of clean-up processing associated with using GpiCloseSegment, known as close-segment processing, that can make current attribute values unreliable. For more information about the effects of GpiOpenSegment and GpiCloseSegment on current attributes, see Graphics Attributes.

Segment Attributes

Each segment, whether retained or nonretained, 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. However, only two are described in this chapter: chained (ATTR_CHAINED) and fast-chained (ATTR_FASTCHAIN).

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. The chained and fast-chained attributes are set ON. Your application can alter these values using GpiSetInitialSegmentAttrs or retrieve the values of the current initial attributes using GpiQueryInitialSegmentAttrs.

Chained Attribute

When you define a segment with the chained attribute switched ON, that segment becomes a part of the segment chain and is called a chained segment. The segment chain is composed of all chained segments defined in a single presentation space. Segments can be chained together so that they can be drawn as a group. By default, each new segment is chained to the previous segment.

There can be only one segment chain at a time in a single presentation space, and all chained segments are chained to each other in the order in which you created them. Zero segments must have the chained attribute.

Usually, a logical relationship exists between the segments in a segment chain, although this is not a requirement. The whole segment chain can be drawn using GpiDrawChain. Each segment in the chain is called a root segment. Root segments are affected by those GPI functions that act on the segment chain, but they also can be manipulated independently of the chain.

Segments that are defined with the chained attribute switched OFF are called unchained segments. Your application can switch off the chain attribute using GpiSetInitialSegmentAttrs (hps, ATTR_CHAIN, ATTR_OFF). Unchained segments always are retained when they are created, regardless of the current drawing-mode parameter. An unchained segment must have a unique name.

There are a number of reasons for defining a segment as unchained. For example, a particular segment might not belong to the picture that is defined by the segment chain. You also are likely to define as unchained any segment that belongs to the picture but that has no single, fixed place in the segment chain. A car wheel, for example, could be defined once but drawn four times in a picture of a car. It would have no single, fixed place in the segment chain, but would be included four times in the picture by being called from one or more root segments.

A segment is called from another segment by including GpiCallSegmentMatrix in the calling segment. A segment and the segments it calls logically are one object. An important point about called segments is that they assume the primitive attribute settings of the calling segment. Of course, you can change the attribute settings within the called segment if the inherited values are inappropriate.

A closed, unchained segment can be called from any other segment. Chained segments, however, cannot be called from other segments.

Fast-Chained Attribute

The fast-chained attribute applies only to chained segments. It prevents primitive attributes from being reset to their default values at the beginning of the segment, an aid to performance. There is unnecessary overhead in resetting attributes to their defaults if either of the following is true:

  • You are going to change the default values of the attributes at the start of the segment.
  • You know that attributes have not been altered previously from their default values.

The fast-chained attribute is switched ON by default, and you should leave it on unless you specifically want attributes to be set to their default values. To turn off the fast-chained attribute, call GpiSetInitialSegmentAttrs (hps, ATTR_FASTCHAIN, ATTR_OFF).

Actual Drawing Mode

The drawing mode, as defined by GpiSetDrawingMode, works in conjunction with the segment status to produce the actual drawing mode. It is the actual drawing mode that determines whether graphics are:

  • Drawn directly to the output device
  • Retained in the segment store
  • Both drawn and retained

The actual drawing mode is summarized in the following table.

GpiSetDrawingMode parameter Chained Segment Unchained Segment Outside of any segment
DM_DRAWANDRETAIN draw-and-retain retain draw
DM_RETAIN retain retain draw
DM_DRAW draw retain draw

As you can see in the preceding table, graphics within chained segments always conform to the current drawing mode parameter. That is, they are drawn in DM_DRAW mode, retained in DM_RETAIN mode, and both drawn and retained in DM_DRAWANDRETAIN mode.

Graphics in unchained segments always are retained, regardless of the current drawing-mode parameter. You cannot retain segments created when the current drawing-mode parameter is DM_DRAW, unless they are unchained segments.

Similarly, graphics outside segments always are drawn without being retained. You cannot retain primitives outside segments, regardless of the current drawing mode.

Note: A micro presentation space has no segment store. Therefore, you cannot create graphics segments in a micro presentation space, nor can you change the drawing mode, which is always DM_DRAW.

Drawing a Retained Graphic

Your application can draw a complete segment chain with GpiDrawChain. The segments are drawn in the order in which they appear in the chain. For example, the segments in the following figure are drawn in the following order:

  1. Root segment 1
  2. Unchained segment A
  3. Unchained segment B
  4. Root segment 2
  5. Unchained segment B
  6. Root segment 3

Chained and Called Segments

Segment A is called by root segment 1, and segment B is called by both segment A and root segment 2. Segment C calls segment D. Both C and D are unchained segments that are not called from the segment chain, and consequently, are not part of the segment chain.

GpiSetSegmentPriority changes the position of a root segment (which must not be a zero segment) in the chain. As input to this function, you supply the name of the segment you want to reorder and the name of a reference segment. The reference segment is the segment that either will be immediately before, or immediately after, the reordered segment's new position in the chain.

If the segment you are moving is to come after the reference segment in the chain, it is said to have a higher priority (HIGHER_PRI). If it is to come before the reference segment, it is said to have a lower priority (LOWER_PRI). The nearer a segment is to the end of the chain, the higher its priority.

If you supply the name of an unchained segment as input to GpiSetSegmentPriority, the segment is added to the chain in the position you specify. To learn the position of a segment in the chain, use GpiQuerySegmentPriority.

If your application called the following functions:

GpiSetSegmentPriority (hps, C, 2, LOWER_PRI)
GpiSetSegmentPriority (hps, 3, 0, HIGHER_PRI)
GpiSetSegmentPriority (hps, B, 0, LOWER_PRI)

the segment chain in the previous figure would appear as in the following figure; and GpiDrawChain would draw the segments in the following order:

  1. Root segment 3
  2. Root segment 1
  3. Unchained segment A
  4. Unchained segment B
  5. Segment C
  6. Unchained segment D
  7. Root segment 2
  8. Unchained segment B
  9. Segment B

Chained and called segments reordered using GpiSetSegmentPriority

Segment Priority

The priority of a segment, in conjunction with the current foreground and background mix attributes, affects how the picture is presented to the user. The segment with the highest priority is drawn last, and appears on top of the previously drawn primitives. Picture components in segments with low priorities risk being drawn over and never seen by the user. The mix attributes affect the graphics functions within each segment.

GpiDrawSegment

GpiDrawSegment accepts as input any segment name.