Jump to content

GPIGuide - Regions: Difference between revisions

From EDM2
Created page with "{{IBM-Reprint}} {{GPIGuide}} 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 infor..."
 
Ak120 (talk | contribs)
mNo edit summary
 
(One intermediate revision by one other user not shown)
Line 11: Line 11:


== About Regions ==
== 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.
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.


Line 27: Line 26:


=== System Implementation ===
=== 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.
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.


Line 35: Line 33:


=== Region Attributes ===
=== 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.
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.


Line 49: Line 46:
* Area background color
* Area background color
* Area foreground mix
* 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.
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.


Line 55: Line 51:


=== Region Creation ===
=== 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:
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 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 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.
* 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.
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.


Line 66: Line 60:


=== Region Operations ===
=== Region Operations ===
The following operations can be performed on a region:
The following operations can be performed on a region:
* Creating Regions
* Creating Regions
Line 77: Line 70:


==== Creating Regions ====
==== 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 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.


Line 108: Line 100:


==== Moving a Region ====
==== 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.
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.


Line 114: Line 105:


==== Determining Region Characteristics ====
==== 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.
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.


Line 136: Line 126:


==== Converting a Region to a Clip Region ====
==== 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.
Clipping is the process an application uses to limit graphics output to a specific area (called the clipping area) of the display or page.


Line 154: Line 143:
* GpiPtVisible
* GpiPtVisible
* GpiRectVisible
* GpiRectVisible
 
These functions are described in [[GPIGuide - Clipping and Boundary Determination|Clipping and Boundary Determination]]. All of these functions work in world coordinates, rather than device coordinates, and therefore, are subject to current transformations.
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.
[[GpiPtVisible]] and [[GpiRectVisible]] do not apply exclusively to clip regions.
Line 170: Line 158:


==== Deleting a Region ====
==== 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.
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.


== Using Regions ==
== Using Regions ==
You can use the region functions to:
You can use the region functions to:
* Create or delete a region
* Create or delete a region
Line 185: Line 171:


=== Creating and Deleting a Region ===
=== Creating and Deleting a Region ===
To create a region:
To create a region:
# Create an array of [[RECTL]] structures containing the dimensions of the rectangles that will compose the region.
# Create an array of [[RECTL]] structures containing the dimensions of the rectangles that will compose the region.
Line 193: Line 178:


The following figure shows how to create and delete a region.
The following figure shows how to create and delete a region.
<pre>
<pre>
#include <os2.h>
#include <os2.h>
Line 220: Line 204:


=== Combining Regions ===
=== Combining Regions ===
To combine two regions:
To combine two regions:
# Create a region that the operating system can use as the destination region when it combines the source regions.
# Create a region that the operating system can use as the destination region when it combines the source regions.
Line 227: Line 210:


The following figure shows how to combine two regions by using the OR operation:
The following figure shows how to combine two regions by using the OR operation:
<pre>
<pre>
#define INCL_GPIREGIONS
#define INCL_GPIREGIONS
Line 252: Line 234:


=== Comparing Regions ===
=== Comparing Regions ===
[[GpiEqualRegion]] determines whether two regions are identical. The following figure shows how to compare regions.
[[GpiEqualRegion]] determines whether two regions are identical. The following figure shows how to compare regions.


Line 295: Line 276:


=== Offsetting a Region ===
=== 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.
[[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.


Line 309: Line 289:


=== Painting a Region ===
=== 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.
[[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.
<pre>
<pre>
     SIZEL sizl;                        /* Structure for size of frame */
     SIZEL sizl;                        /* Structure for size of frame */
Line 333: Line 311:


The following figure shows how to locate the mouse pointer with respect to a region.
The following figure shows how to locate the mouse pointer with respect to a region.
<pre>
<pre>
#define INCL_GPIREGIONS
#define INCL_GPIREGIONS
Line 358: Line 335:


=== Determining Coordinates of Rectangles in a Region ===
=== 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 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.


Line 369: Line 345:


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.
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.
<pre>
<pre>
#define INCL_GPIREGIONS
#define INCL_GPIREGIONS

Latest revision as of 12:17, 16 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

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

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.

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.

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.

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.

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

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:

  • 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 following figure. 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.

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.

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.

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.

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.

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

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 <os2.h>
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 */

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 <os2.h>
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 */

Comparing Regions

GpiEqualRegion determines whether two regions are identical. The following figure shows how to compare regions.

#define INCL_GPIREGIONS
#include <os2.h>
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 */

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 */

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         */

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 <os2.h>
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 */

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 <os2.h>
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 */