home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tk42r2s.zip
/
tk4.2
/
os2
/
tkOS2Draw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-07-26
|
69KB
|
2,101 lines
/*
* tkOS2Draw.c --
*
* This file contains the Xlib emulation functions pertaining to
* actually drawing objects on a window.
*
* Copyright (c) 1996-1998 Illya Vaes
* Copyright (c) 1995 Sun Microsystems, Inc.
* Copyright (c) 1994 Software Research Associates, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tkOS2Int.h"
#define PI 3.14159265358979
#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180)
/*
* Translation tables between X gc values and OS/2 GPI line attributes.
*/
static int lineStyles[] = {
LINETYPE_SOLID, /* LineSolid */
LINETYPE_SHORTDASH, /* LineOnOffDash */
LINETYPE_SHORTDASH /* LineDoubleDash EXTRA PROCESSING NECESSARY */
};
static int capStyles[] = {
LINEEND_FLAT, /* CapNotLast EXTRA PROCESSING NECESSARY */
LINEEND_FLAT, /* CapButt */
LINEEND_ROUND, /* CapRound */
LINEEND_SQUARE /* CapProjecting */
};
static int joinStyles[] = {
LINEJOIN_MITRE, /* JoinMiter */
LINEJOIN_ROUND, /* JoinRound */
LINEJOIN_BEVEL /* JoinBevel */
};
/*
* Translation table between X gc functions and OS/2 GPI mix attributes.
*/
static int mixModes[] = {
FM_ZERO, /* GXclear */
FM_AND, /* GXand */
FM_MASKSRCNOT, /* GXandReverse */
FM_OVERPAINT, /* GXcopy */
FM_SUBTRACT, /* GXandInverted */
FM_LEAVEALONE, /* GXnoop */
FM_XOR, /* GXxor */
FM_OR, /* GXor */
FM_NOTMERGESRC, /* GXnor */
FM_NOTXORSRC, /* GXequiv */
FM_INVERT, /* GXinvert */
FM_MERGESRCNOT, /* GXorReverse */
FM_NOTCOPYSRC, /* GXcopyInverted */
FM_MERGENOTSRC, /* GXorInverted */
FM_NOTMASKSRC, /* GXnand */
FM_ONE /* GXset */
};
/*
* Translation table between X gc functions and OS/2 GPI BitBlt raster op modes.
* Some of the operations defined in X don't have names, so we have to construct
* new opcodes for those functions. This is arcane and probably not all that
* useful, but at least it's accurate.
*/
#define NOTSRCAND (LONG)0x0022 /* dest = (NOT source) AND dest */
#define NOTSRCINVERT (LONG)0x0099 /* dest = (NOT source) XOR dest */
#define SRCORREVERSE (LONG)0x00dd /* dest = source OR (NOT dest) */
#define SRCNAND (LONG)0x0077 /* dest = (NOT source) OR (NOT dest) */
static int bltModes[] = {
ROP_ZERO, /* GXclear */
ROP_SRCAND, /* GXand */
ROP_SRCERASE, /* GXandReverse */
ROP_SRCCOPY, /* GXcopy */
NOTSRCAND, /* GXandInverted */
ROP_PATCOPY, /* GXnoop */
ROP_SRCINVERT, /* GXxor */
ROP_SRCPAINT, /* GXor */
ROP_NOTSRCERASE, /* GXnor */
NOTSRCINVERT, /* GXequiv */
ROP_DSTINVERT, /* GXinvert */
SRCORREVERSE, /* GXorReverse */
ROP_NOTSRCCOPY, /* GXcopyInverted */
ROP_MERGEPAINT, /* GXorInverted */
SRCNAND, /* GXnand */
ROP_ONE /* GXset */
};
/*
* The following raster op uses the source bitmap as a mask for the
* pattern. This is used to draw in a foreground color but leave the
* background color transparent.
*/
#define MASKPAT 0x00e2 /* dest = (src & pat) | (!src & dst) */
/*
* The following two raster ops are used to copy the foreground and background
* bits of a source pattern as defined by a stipple used as the pattern.
*/
#define COPYFG 0x00ca /* dest = (pat & src) | (!pat & dst) */
#define COPYBG 0x00ac /* dest = (!pat & src) | (pat & dst) */
/*
* Macros used later in the file.
*/
#ifndef MIN
#define MIN(a,b) ((a>b) ? b : a)
#endif
#ifndef MAX
#define MAX(a,b) ((a<b) ? b : a)
#endif
/*
* Forward declarations for procedures defined in this file:
*/
static POINTL * ConvertPoints (Drawable d, XPoint *points, int npoints,
int mode, RECTL *bbox);
static void DrawOrFillArc (Display *display,
Drawable d, GC gc, int x, int y,
unsigned int width, unsigned int height,
int angle1, int angle2, int fill);
static void RenderObject (HPS hps, GC gc, Drawable d,
XPoint* points, int npoints, int mode,
PLINEBUNDLE lineBundle, int func);
static void TkOS2SetStipple(HPS destPS, HPS bmpPS, HBITMAP stipple,
LONG x, LONG y, LONG *oldPatternSet,
PPOINTL oldRefPoint);
static void TkOS2UnsetStipple(HPS destPS, HPS bmpPS, HBITMAP stipple,
LONG oldPatternSet, PPOINTL oldRefPoint);
/*
*----------------------------------------------------------------------
*
* TkOS2GetDrawablePS --
*
* Retrieve the Presentation Space from a drawable.
*
* Results:
* Returns the window PS for windows. Returns the associated memory PS
* for pixmaps.
*
* Side effects:
* Sets up the palette for the presentation space, and saves the old
* presentation space state in the passed in TkOS2PSState structure.
*
*----------------------------------------------------------------------
*/
HPS
TkOS2GetDrawablePS(display, d, state)
Display *display;
Drawable d;
TkOS2PSState* state;
{
HPS hps;
TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
Colormap cmap;
if (todPtr->type != TOD_BITMAP) {
TkWindow *winPtr = todPtr->window.winPtr;
hps = WinGetPS(todPtr->window.handle);
if (winPtr == NULL) {
cmap = DefaultColormap(display, DefaultScreen(display));
} else {
cmap = winPtr->atts.colormap;
}
state->palette = TkOS2SelectPalette(hps, todPtr->window.handle, cmap);
} else {
hps = todPtr->bitmap.hps;
cmap = todPtr->bitmap.colormap;
state->palette = TkOS2SelectPalette(hps, todPtr->bitmap.parent, cmap);
}
return hps;
}
/*
*----------------------------------------------------------------------
*
* TkOS2ReleaseDrawablePS --
*
* Frees the resources associated with a drawable's DC.
*
* Results:
* None.
*
* Side effects:
* Restores the old bitmap handle to the memory DC for pixmaps.
*
*----------------------------------------------------------------------
*/
void
TkOS2ReleaseDrawablePS(d, hps, state)
Drawable d;
HPS hps;
TkOS2PSState *state;
{
ULONG changed;
HPAL oldPal;
TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
oldPal = GpiSelectPalette(hps, state->palette);
if (todPtr->type != TOD_BITMAP) {
WinRealizePalette(TkOS2GetHWND(d), hps, &changed);
WinReleasePS(hps);
} else {
WinRealizePalette(todPtr->bitmap.parent, hps, &changed);
}
}
/*
*----------------------------------------------------------------------
*
* ConvertPoints --
*
* Convert an array of X points to an array of OS/2 GPI points.
*
* Results:
* Returns the converted array of POINTLs.
*
* Side effects:
* Allocates a block of memory that should not be freed.
*
*----------------------------------------------------------------------
*/
static POINTL *
ConvertPoints(d, points, npoints, mode, bbox)
Drawable d;
XPoint *points;
int npoints;
int mode; /* CoordModeOrigin or CoordModePrevious. */
RECTL *bbox; /* Bounding box of points. */
{
static POINTL *os2Points = NULL; /* Array of points that is reused. */
static int nOS2Points = -1; /* Current size of point array. */
LONG windowHeight;
int i;
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
/*
* To avoid paying the cost of a malloc on every drawing routine,
* we reuse the last array if it is large enough.
*/
if (npoints > nOS2Points) {
if (os2Points != NULL) {
ckfree((char *) os2Points);
}
os2Points = (POINTL *) ckalloc(sizeof(POINTL) * npoints);
if (os2Points == NULL) {
nOS2Points = -1;
return NULL;
}
nOS2Points = npoints;
}
/* Convert to PM Coordinates */
bbox->xLeft = bbox->xRight = points[0].x;
bbox->yTop = bbox->yBottom = windowHeight - points[0].y;
if (mode == CoordModeOrigin) {
for (i = 0; i < npoints; i++) {
os2Points[i].x = points[i].x;
/* convert to PM */
os2Points[i].y = windowHeight - points[i].y;
bbox->xLeft = MIN(bbox->xLeft, os2Points[i].x);
/* Since GpiBitBlt excludes top & right, add one */
bbox->xRight = MAX(bbox->xRight, os2Points[i].x + 1);
/* y: min and max switched for PM */
bbox->yTop = MAX(bbox->yTop, os2Points[i].y + 1);
bbox->yBottom = MIN(bbox->yBottom, os2Points[i].y);
}
} else {
os2Points[0].x = points[0].x;
os2Points[0].y = windowHeight - points[0].y;
for (i = 1; i < npoints; i++) {
os2Points[i].x = os2Points[i-1].x + points[i].x;
/* convert to PM */
os2Points[i].y = os2Points[i-1].y -
(windowHeight - points[i].y);
bbox->xLeft = MIN(bbox->xLeft, os2Points[i].x);
/* Since GpiBitBlt excludes top & right, add one */
bbox->xRight = MAX(bbox->xRight, os2Points[i].x + 1);
/* y: min and max switched for PM */
bbox->yTop = MAX(bbox->yTop, os2Points[i].y + 1);
bbox->yBottom = MIN(bbox->yBottom, os2Points[i].y);
}
}
return os2Points;
}
/*
*----------------------------------------------------------------------
*
* XCopyArea --
*
* Copies data from one drawable to another using block transfer
* routines.
*
* Results:
* None.
*
* Side effects:
* Data is moved from a window or bitmap to a second window or
* bitmap.
*
*----------------------------------------------------------------------
*/
void
XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y)
Display* display;
Drawable src;
Drawable dest;
GC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
{
HPS srcPS, destPS;
TkOS2PSState srcState, destState;
TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
BOOL rc;
LONG windowHeight;
HRGN oldReg;
/* Translate the Y coordinates to PM coordinates */
/* Determine height of window */
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)dest);
aPoints[0].x = dest_x;
aPoints[0].y = windowHeight - dest_y - height;
aPoints[1].x = dest_x + width;
aPoints[1].y = windowHeight - dest_y;
aPoints[2].x = src_x;
if (src != dest) {
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)src);
}
aPoints[2].y = windowHeight - src_y - height;
srcPS = TkOS2GetDrawablePS(display, src, &srcState);
if (src != dest) {
destPS = TkOS2GetDrawablePS(display, dest, &destState);
} else {
destPS = srcPS;
}
/*
if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
if (GpiSetClipRegion(destPS, (HRGN) clipPtr->value.region, &oldReg)
!= RGN_ERROR) {
POINTL offset;
offset.x = gc->clip_x_origin;
*/
/* Reverse Y coordinates */
/*
offset.y = - gc->clip_y_origin;
rc = GpiOffsetClipRegion(destPS, &offset);
#ifdef DEBUG
printf("GpiOffsetClipRegion %dx%d into %x %s\n", offset.x,
offset.y, destPS, rc == RGN_NULL ? "RGN_NULL" :
(rc == RGN_RECT ? "RGN_RECT" :
(rc == RGN_COMPLEX ? "RGN_COMPLEX" :
"RGN_ERROR")));
#endif
}
#ifdef DEBUG
else {
printf("GpiSetClipRegion %x into %x RGN_ERROR\n",
clipPtr->value.region, destPS);
}
#endif
}
*/
rc = GpiBitBlt(destPS, srcPS, 3, aPoints, bltModes[gc->function],
BBO_IGNORE);
if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
GpiSetClipRegion(destPS, oldReg, &oldReg);
}
if (src != dest) {
TkOS2ReleaseDrawablePS(dest, destPS, &destState);
}
TkOS2ReleaseDrawablePS(src, srcPS, &srcState);
}
/*
*----------------------------------------------------------------------
*
* XCopyPlane --
*
* Copies a bitmap from a source drawable to a destination
* drawable. The plane argument specifies which bit plane of
* the source contains the bitmap. Note that this implementation
* ignores the gc->function.
*
* Results:
* None.
*
* Side effects:
* Changes the destination drawable.
*
*----------------------------------------------------------------------
*/
void
XCopyPlane(display, src, dest, gc, src_x, src_y, width, height, dest_x,
dest_y, plane)
Display* display;
Drawable src;
Drawable dest;
GC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
unsigned long plane;
{
HPS srcPS, destPS;
TkOS2PSState srcState, destState;
TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
LONG oldPattern;
LONG oldMix, oldBackMix;
LONG oldColor, oldBackColor;
LONG srcWindowHeight, destWindowHeight;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
LONG rc;
HRGN oldReg;
/* Translate the Y coordinates to PM coordinates */
destWindowHeight = TkOS2WindowHeight((TkOS2Drawable *)dest);
if (src != dest) {
srcWindowHeight = TkOS2WindowHeight((TkOS2Drawable *)src);
} else {
srcWindowHeight = destWindowHeight;
}
aPoints[0].x = dest_x;
aPoints[0].y = destWindowHeight - dest_y - height;
aPoints[1].x = dest_x + width;
aPoints[1].y = destWindowHeight - dest_y;
aPoints[2].x = src_x;
aPoints[2].y = srcWindowHeight - src_y - height;
display->request++;
if (plane != 1) {
panic("Unexpected plane specified for XCopyPlane");
}
srcPS = TkOS2GetDrawablePS(display, src, &srcState);
if (src != dest) {
destPS = TkOS2GetDrawablePS(display, dest, &destState);
} else {
destPS = srcPS;
}
if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {
/*
* Case 1: opaque bitmaps. Windows handles the conversion
* from one bit to multiple bits by setting 0 to the
* foreground color, and 1 to the background color (seems
* backwards, but there you are).
*/
if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
if (GpiSetClipRegion(destPS, (HRGN) clipPtr->value.region, &oldReg)
!= RGN_ERROR) {
POINTL offset;
offset.x = gc->clip_x_origin;
/* Reverse Y coordinates */
offset.y = - gc->clip_y_origin;
GpiOffsetClipRegion(destPS, &offset);
}
}
oldColor = GpiQueryColor(destPS);
oldBackColor = GpiQueryBackColor(destPS);
oldMix = GpiQueryMix(destPS);
oldBackMix = GpiQueryBackMix(destPS);
/*
rc= GpiSetColor(destPS, gc->foreground);
*/
rc= GpiSetColor(destPS, gc->background);
/*
rc= GpiSetBackColor(destPS, gc->background);
*/
rc= GpiSetBackColor(destPS, gc->foreground);
rc = GpiBitBlt(destPS, srcPS, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
rc= GpiSetColor(destPS, oldColor);
rc= GpiSetBackColor(destPS, oldBackColor);
rc= GpiSetMix(destPS, oldMix);
rc= GpiSetBackMix(destPS, oldBackMix);
GpiSetClipRegion(destPS, oldReg, &oldReg);
} else if (clipPtr->type == TKP_CLIP_PIXMAP) {
if (clipPtr->value.pixmap == src) {
/*
* Case 2: transparent bitmaps are handled by setting the
* destination to the foreground color whenever the source
* pixel is set.
*/
oldColor = GpiQueryColor(destPS);
oldBackColor = GpiQueryBackColor(destPS);
oldPattern = GpiQueryPattern(destPS);
GpiSetColor(destPS, gc->foreground);
rc= GpiSetBackColor(destPS, gc->background);
GpiSetPattern(destPS, PATSYM_SOLID);
rc = GpiBitBlt(destPS, srcPS, 3, aPoints, MASKPAT, BBO_IGNORE);
GpiSetPattern(destPS, oldPattern);
GpiSetBackColor(destPS, oldBackColor);
GpiSetColor(destPS, oldColor);
} else {
/*
* Case 3: two arbitrary bitmaps. Copy the source rectangle
* into a color pixmap. Use the result as a brush when
* copying the clip mask into the destination.
*/
HPS memPS, maskPS;
BITMAPINFOHEADER2 bmpInfo;
HBITMAP bitmap, oldBitmap;
TkOS2PSState maskState;
oldColor = GpiQueryColor(destPS);
oldPattern = GpiQueryPattern(destPS);
maskPS = TkOS2GetDrawablePS(display, clipPtr->value.pixmap,
&maskState);
memPS = WinGetScreenPS(HWND_DESKTOP);
bmpInfo.cbFix = sizeof(BITMAPINFOHEADER2);
bmpInfo.cx = width;
bmpInfo.cy = height;
bmpInfo.cPlanes = 1;
bmpInfo.cBitCount = 1;
bitmap = GpiCreateBitmap(memPS, &bmpInfo, 0L, NULL, NULL);
oldBitmap = GpiSetBitmap(memPS, bitmap);
/*
* Set foreground bits. We create a new bitmap containing
* (source AND mask), then use it to set the foreground color
* into the destination.
*/
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = 0; /* dest_x = 0 */
aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
aPoints[1].x = width;
aPoints[1].y = destWindowHeight;
aPoints[2].x = src_x;
aPoints[2].y = srcWindowHeight - src_y - height;
rc = GpiBitBlt(memPS, srcPS, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = 0; /* dest_x = 0 */
aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
aPoints[1].x = dest_x + width;
aPoints[1].y = destWindowHeight;
aPoints[2].x = dest_x - gc->clip_x_origin;
aPoints[2].y = srcWindowHeight - dest_y + gc->clip_y_origin -
height;
rc = GpiBitBlt(memPS, maskPS, 3, aPoints, ROP_SRCAND, BBO_IGNORE);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = dest_x;
aPoints[0].y = destWindowHeight - dest_y - height;
aPoints[1].x = dest_x + width;
aPoints[1].y = destWindowHeight - dest_y;
aPoints[2].x = 0; /* src_x = 0 */
aPoints[2].y = srcWindowHeight - height; /* src_y = 0 */
GpiSetColor(destPS, gc->foreground);
GpiSetPattern(destPS, PATSYM_SOLID);
rc = GpiBitBlt(destPS, memPS, 3, aPoints, MASKPAT, BBO_IGNORE);
/*
* Set background bits. Same as foreground, except we use
* ((NOT source) AND mask) and the background brush.
*/
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = 0; /* dest_x = 0 */
aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
aPoints[1].x = width;
aPoints[1].y = destWindowHeight;
aPoints[2].x = src_x;
aPoints[2].y = srcWindowHeight - src_y - height;
rc = GpiBitBlt(memPS, srcPS, 3, aPoints, ROP_NOTSRCCOPY,
BBO_IGNORE);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = 0; /* dest_x = 0 */
aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
aPoints[1].x = dest_x + width;
aPoints[1].y = destWindowHeight;
aPoints[2].x = dest_x - gc->clip_x_origin;
aPoints[2].y = destWindowHeight - dest_y + gc->clip_y_origin -
height;
rc = GpiBitBlt(memPS, maskPS, 3, aPoints, ROP_SRCAND, BBO_IGNORE);
GpiSetColor(destPS, gc->background);
GpiSetPattern(destPS, PATSYM_SOLID);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = dest_x;
aPoints[0].y = destWindowHeight - dest_y - height;
aPoints[1].x = dest_x + width;
aPoints[1].y = destWindowHeight - dest_y;
aPoints[2].x = 0; /* src_x = 0 */
aPoints[2].y = srcWindowHeight - height; /* src_y = 0 */
rc = GpiBitBlt(destPS, memPS, 3, aPoints, MASKPAT, BBO_IGNORE);
TkOS2ReleaseDrawablePS(clipPtr->value.pixmap, maskPS, &maskState);
GpiSetPattern(destPS, oldPattern);
GpiSetColor(destPS, oldColor);
GpiSetBitmap(memPS, oldBitmap);
GpiDeleteBitmap(bitmap);
WinReleasePS(memPS);
}
}
if (src != dest) {
TkOS2ReleaseDrawablePS(dest, destPS, &destState);
}
TkOS2ReleaseDrawablePS(src, srcPS, &srcState);
}
/*
*----------------------------------------------------------------------
*
* TkPutImage --
*
* Copies a subimage from an in-memory image to a rectangle of
* of the specified drawable.
*
* Results:
* None.
*
* Side effects:
* Draws the image on the specified drawable.
*
*----------------------------------------------------------------------
*/
void
TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x,
dest_y, width, height)
unsigned long *colors; /* Array of pixel values used by this
* image. May be NULL. */
int ncolors; /* Number of colors used, or 0. */
Display* display;
Drawable d; /* Destination drawable. */
GC gc;
XImage* image; /* Source image. */
int src_x, src_y; /* Offset of subimage. */
int dest_x, dest_y; /* Position of subimage origin in
* drawable. */
unsigned int width, height; /* Dimensions of subimage. */
{
HPS hps;
LONG rc;
TkOS2PSState state;
BITMAPINFOHEADER2 bmpInfo;
BITMAPINFO2 *infoPtr;
char *data;
LONG windowHeight;
/* Translate the Y coordinates to PM coordinates */
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
display->request++;
hps = TkOS2GetDrawablePS(display, d, &state);
rc = GpiSetMix(hps, mixModes[gc->function]);
if (image->bits_per_pixel == 1) {
/* Bitmap must be reversed in OS/2 wrt. the Y direction */
/* This is done best in a modified version of TkAlignImageData */
data = TkAlignImageData(image, sizeof(ULONG), MSBFirst);
bmpInfo.cbFix = 16L;
bmpInfo.cx = image->width;
bmpInfo.cy = image->height;
bmpInfo.cPlanes = 1;
bmpInfo.cBitCount = 1;
rc = GpiSetBitmapBits(hps, windowHeight - dest_y - height, height,
(PBYTE)data, (BITMAPINFO2*) &bmpInfo);
ckfree(data);
} else {
int usePalette;
/*
* Do not use a palette for TrueColor images.
*/
usePalette = (image->bits_per_pixel < 24);
if (usePalette) {
infoPtr = (BITMAPINFO2*) ckalloc(sizeof(BITMAPINFO2)
+ sizeof(RGB2)*ncolors);
} else {
infoPtr = (BITMAPINFO2*) ckalloc(sizeof(BITMAPINFO2));
}
if (infoPtr == NULL) return;
/* Bitmap must be reversed in OS/2 wrt. the Y direction */
data = TkOS2ReverseImageLines(image, height);
infoPtr->cbFix = sizeof(BITMAPINFOHEADER2);
infoPtr->cx = width;
infoPtr->cy = height;
infoPtr->cPlanes = 1;
infoPtr->cBitCount = image->bits_per_pixel;
infoPtr->ulCompression = BCA_UNCOMP;
infoPtr->cbImage = 0;
infoPtr->cxResolution = aDevCaps[CAPS_HORIZONTAL_RESOLUTION];
infoPtr->cyResolution = aDevCaps[CAPS_VERTICAL_RESOLUTION];
infoPtr->cclrUsed = 0;
infoPtr->cclrImportant = 0;
infoPtr->usUnits = BRU_METRIC;
infoPtr->usReserved = 0;
infoPtr->usRecording = BRA_BOTTOMUP;
infoPtr->usRendering = BRH_NOTHALFTONED;
infoPtr->cSize1 = 0L;
infoPtr->cSize2 = 0L;
infoPtr->ulColorEncoding = BCE_RGB;
infoPtr->ulIdentifier = 0L;
if (usePalette) {
BOOL palManager = FALSE;
if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
palManager = TRUE;
}
if (palManager) {
rc = GpiQueryPaletteInfo(GpiQueryPalette(hps), hps, 0, 0,
ncolors, (PLONG) &infoPtr->argbColor);
} else {
rc = GpiQueryLogColorTable(hps, 0, 0, ncolors,
(PLONG) &infoPtr->argbColor);
}
} else {
infoPtr->cclrUsed = 0;
}
rc = GpiSetBitmapBits(hps, windowHeight - dest_y - height, height,
(PBYTE)data, infoPtr);
ckfree((char *)infoPtr);
ckfree(data);
}
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* XDrawString --
*
* Draw a single string in the current font.
*
* Results:
* None.
*
* Side effects:
* Renders the specified string in the drawable.
*
*----------------------------------------------------------------------
*/
void
XDrawString(display, d, gc, x, y, string, length)
Display* display;
Drawable d;
GC gc;
int x;
int y;
_Xconst char* string;
int length;
{
HPS hps;
SIZEF oldCharBox;
LONG oldFont = 0L;
LONG oldHorAlign, oldVerAlign;
LONG oldBackMix;
LONG oldColor, oldBackColor = 0L;
POINTL oldRefPoint;
LONG oldPattern;
HBITMAP oldBitmap;
POINTL noShear= {0, 1};
TkOS2PSState state;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
CHARBUNDLE cBundle;
AREABUNDLE aBundle;
LONG windowHeight, l;
char *str;
POINTL refPoint;
BOOL rc;
display->request++;
if (d == None) {
return;
}
hps = TkOS2GetDrawablePS(display, d, &state);
GpiSetMix(hps, mixModes[gc->function]);
/* If this is an outline font, set the char box */
if (logfonts[(LONG)gc->font].outline) {
rc = GpiQueryCharBox(hps, &oldCharBox);
rc = TkOS2ScaleFont(hps, logfonts[(LONG)gc->font].deciPoints, 0);
}
/* Translate the Y coordinates to PM coordinates */
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
y = windowHeight - y;
if ((gc->fill_style == FillStippled || gc->fill_style == FillOpaqueStippled)
&& gc->stipple != None) {
TkOS2Drawable *todPtr = (TkOS2Drawable *)gc->stipple;
HDC dcMem;
HPS psMem;
DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
SIZEL sizl = {0,0}; /* use same page size as device */
HBITMAP bitmap;
BITMAPINFOHEADER2 bmpInfo;
RECTL rect;
POINTL textBox[TXTBOX_COUNT];
if (todPtr->type != TOD_BITMAP) {
panic("unexpected drawable type in stipple");
}
/*
* Select stipple pattern into destination PS.
* gc->ts_x_origin and y_origin are relative to origin of the
* destination drawable, while PatternRefPoint is in world coords.
*/
dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
NULLHANDLE);
if (dcMem == DEV_ERROR) {
return;
}
psMem = GpiCreatePS(hab, dcMem, &sizl,
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
if (psMem == GPI_ERROR) {
DevCloseDC(dcMem);
return;
}
/*
* Compute the bounding box and create a compatible bitmap.
*/
rc = WinQueryWindowRect(((TkOS2Drawable *)d)->bitmap.parent, &rect);
bmpInfo.cbFix = 16L;
/*
bmpInfo.cx = rect.xRight - rect.xLeft;
bmpInfo.cy = rect.yTop - rect.yBottom;
*/
bmpInfo.cx = xScreen;
bmpInfo.cy = yScreen;
bmpInfo.cPlanes = 1;
bmpInfo.cBitCount = display->screens[display->default_screen].root_depth;
bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
oldBitmap = GpiSetBitmap(psMem, bitmap);
refPoint.x = gc->ts_x_origin;
refPoint.y = windowHeight - gc->ts_y_origin;
/* The bitmap mustn't be selected in the HPS */
TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
GpiQueryTextAlignment(psMem, &oldHorAlign, &oldVerAlign);
GpiSetTextAlignment(psMem, TA_LEFT, TA_BASE);
GpiQueryAttrs(psMem, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
oldColor = cBundle.lColor;
cBundle.lColor = gc->foreground;
rc = GpiSetAttrs(psMem, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
aBundle.lColor = gc->foreground;
rc = GpiSetAttrs(hps, PRIM_AREA, LBB_COLOR, 0L, (PBUNDLE)&aBundle);
oldBackMix = GpiQueryBackMix(psMem);
rc = GpiSetBackMix(psMem, BM_LEAVEALONE);
oldBackColor = GpiQueryBackColor(psMem);
GpiSetBackColor(psMem, CLR_FALSE);
if (gc->font != None) {
rc = GpiCreateLogFont(psMem, NULL, (LONG)gc->font,
&(logfonts[(LONG)gc->font].fattrs));
oldFont = GpiQueryCharSet(psMem);
rc = GpiSetCharSet(psMem, (LONG)gc->font);
/* Set slant if necessary */
if (logfonts[(LONG)gc->font].setShear) {
rc = GpiSetCharShear(psMem, &(logfonts[(LONG)gc->font].shear));
}
/* If this is an outline font, set the char box */
if (logfonts[(LONG)gc->font].outline) {
rc = TkOS2ScaleFont(psMem, logfonts[(LONG)gc->font].deciPoints,
0);
}
}
refPoint.x = x;
refPoint.y = y;
rc = GpiSetCurrentPosition(psMem, &refPoint);
rc = GpiQueryTextBox(psMem, length, (PCH)string, TXTBOX_COUNT, textBox);
aPoints[0].x = refPoint.x + textBox[TXTBOX_BOTTOMLEFT].x;
aPoints[0].y = refPoint.y + textBox[TXTBOX_BOTTOMLEFT].y;
aPoints[1].x = refPoint.x + textBox[TXTBOX_TOPRIGHT].x;
aPoints[1].y = refPoint.y + textBox[TXTBOX_TOPRIGHT].y;
aPoints[2].x = refPoint.x + textBox[TXTBOX_BOTTOMLEFT].x;
aPoints[2].y = refPoint.y + textBox[TXTBOX_BOTTOMLEFT].y;
/*
* The following code is tricky because fonts are rendered in multiple
* colors. First we draw onto a black background and copy the white
* bits. Then we draw onto a white background and copy the black bits.
* Both the foreground and background bits of the font are ANDed with
* the stipple pattern as they are copied.
*/
rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ZERO, BBO_IGNORE);
/* only 512 bytes allowed in string */
rc = GpiSetCurrentPosition(psMem, &refPoint);
l = length;
str = (char *)string;
while (length>512) {
rc = GpiCharString(psMem, l, (PCH)str);
l -= 512;
str += 512;
}
rc = GpiCharString(psMem, l, (PCH)str);
rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ea, BBO_IGNORE);
rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ONE, BBO_IGNORE);
/* only 512 bytes allowed in string */
rc = GpiSetCurrentPosition(psMem, &refPoint);
l = length;
str = (char *)string;
while (length>512) {
rc = GpiCharString(psMem, 512, (PCH)str);
l -= 512;
str += 512;
}
rc = GpiCharString(psMem, l, (PCH)str);
rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ba, BBO_IGNORE);
/*
* Destroy the temporary bitmap and restore the device context.
*/
GpiSetBitmap(psMem, oldBitmap);
GpiDeleteBitmap(bitmap);
GpiDestroyPS(psMem);
DevCloseDC(dcMem);
if (gc->font != None) {
/* Set slant if necessary */
if (logfonts[(LONG)gc->font].setShear) {
rc = GpiSetCharShear(hps, &noShear);
}
rc = GpiSetCharSet(hps, oldFont);
}
rc = GpiSetBackMix(hps, oldBackMix);
cBundle.lColor = oldColor;
rc = GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
/* The bitmap must be reselected in the HPS */
TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
oldPattern, &oldRefPoint);
} else {
GpiQueryTextAlignment(hps, &oldHorAlign, &oldVerAlign);
GpiSetTextAlignment(hps, TA_LEFT, TA_BASE);
GpiQueryAttrs(hps, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
oldColor = cBundle.lColor;
cBundle.lColor = gc->foreground;
rc = GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
oldBackMix = GpiQueryBackMix(hps);
/* We get a crash in PMMERGE.DLL on anything other than BM_LEAVEALONE */
GpiSetBackMix(hps, BM_LEAVEALONE);
if (gc->font != None) {
rc = GpiCreateLogFont(hps, NULL, (LONG)gc->font,
&(logfonts[(LONG)gc->font].fattrs));
oldFont = GpiQueryCharSet(hps);
rc = GpiSetCharSet(hps, (LONG)gc->font);
/* Set slant if necessary */
if (logfonts[(LONG)gc->font].setShear) {
GpiSetCharShear(hps, &(logfonts[(LONG)gc->font].shear));
}
/* If this is an outline font, set the char box */
if (logfonts[(LONG)gc->font].outline) {
rc= TkOS2ScaleFont(hps, logfonts[(LONG)gc->font].deciPoints, 0);
}
}
refPoint.x = x;
refPoint.y = y;
/* only 512 bytes allowed in string */
rc = GpiSetCurrentPosition(hps, &refPoint);
l = length;
str = (char *)string;
while (l>512) {
rc = GpiCharString(hps, 512, (PCH)str);
l -= 512;
str += 512;
}
rc = GpiCharString(hps, l, (PCH)str);
rc = GpiSetCharSet(hps, LCID_DEFAULT);
rc = GpiDeleteSetId(hps, (LONG)gc->font);
if (gc->font != None) {
/* Set slant if necessary */
if (logfonts[(LONG)gc->font].setShear) {
GpiSetCharShear(hps, &noShear);
}
GpiSetCharSet(hps, oldFont);
}
GpiSetBackMix(hps, oldBackMix);
GpiSetBackColor(hps, oldBackColor);
cBundle.lColor = oldColor;
GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
GpiSetTextAlignment(hps, oldHorAlign, oldVerAlign);
}
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* XFillRectangles --
*
* Fill multiple rectangular areas in the given drawable.
*
* Results:
* None.
*
* Side effects:
* Draws onto the specified drawable.
*
*----------------------------------------------------------------------
*/
void
XFillRectangles(display, d, gc, rectangles, nrectangles)
Display* display;
Drawable d;
GC gc;
XRectangle* rectangles;
int nrectangles;
{
HPS hps;
int i;
RECTL rect;
TkOS2PSState state;
LONG windowHeight;
POINTL refPoint;
LONG oldPattern, oldBitmap;
TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
LONG rc;
if (d == None) {
return;
}
windowHeight = TkOS2WindowHeight(todPtr);
hps = TkOS2GetDrawablePS(display, d, &state);
GpiSetMix(hps, mixModes[gc->function]);
if ((gc->fill_style == FillStippled
|| gc->fill_style == FillOpaqueStippled)
&& gc->stipple != None) {
HBITMAP bitmap;
BITMAPINFOHEADER2 bmpInfo;
LONG rc;
DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
SIZEL sizl = {0,0}; /* use same page size as device */
HDC dcMem;
HPS psMem;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
POINTL oldRefPoint;
todPtr = (TkOS2Drawable *)gc->stipple;
if (todPtr->type != TOD_BITMAP) {
panic("unexpected drawable type in stipple");
}
/*
* Select stipple pattern into destination dc.
*/
refPoint.x = gc->ts_x_origin;
/* Translate Xlib y to PM y */
refPoint.y = windowHeight - gc->ts_y_origin;
/* The bitmap mustn't be selected in the HPS */
TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
NULLHANDLE);
if (dcMem == DEV_ERROR) {
return;
}
psMem = GpiCreatePS(hab, dcMem, &sizl,
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
if (psMem == GPI_ERROR) {
DevCloseDC(dcMem);
return;
}
/*
* For each rectangle, create a drawing surface which is the size of
* the rectangle and fill it with the background color. Then merge the
* result with the stipple pattern.
*/
for (i = 0; i < nrectangles; i++) {
bmpInfo.cbFix = 16L;
bmpInfo.cx = rectangles[i].width + 1;
bmpInfo.cy = rectangles[i].height + 1;
bmpInfo.cPlanes = 1;
bmpInfo.cBitCount = 1;
bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
oldBitmap = GpiSetBitmap(psMem, bitmap);
/* Translate the Y coordinates to PM coordinates */
rect.xLeft = 0;
rect.xRight = rectangles[i].width + 1;
rect.yBottom = 0;
rect.yTop = rectangles[i].height + 1;
oldPattern = GpiQueryPattern(psMem);
GpiSetPattern(psMem, PATSYM_SOLID);
rc = WinFillRect(psMem, &rect, gc->foreground);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = rectangles[i].x;
aPoints[0].y = windowHeight - rectangles[i].y -
rectangles[i].height;
aPoints[1].x = rectangles[i].x + rectangles[i].width + 1;
aPoints[1].y = windowHeight - rectangles[i].y + 1;
aPoints[2].x = 0;
aPoints[2].y = 0;
rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
if (gc->fill_style == FillOpaqueStippled) {
rc = WinFillRect(psMem, &rect, gc->background);
rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYBG, BBO_IGNORE);
}
GpiSetPattern(psMem, oldPattern);
GpiDeleteBitmap(bitmap);
}
GpiDestroyPS(psMem);
DevCloseDC(dcMem);
/* The bitmap must be reselected in the HPS */
TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
oldPattern, &oldRefPoint);
} else {
for (i = 0; i < nrectangles; i++) {
rect.xLeft = rectangles[i].x;
rect.xRight = rect.xLeft + rectangles[i].width;
rect.yBottom = windowHeight - rectangles[i].y -
rectangles[i].height;
rect.yTop = windowHeight - rectangles[i].y;
rc = WinFillRect(hps, &rect, gc->foreground);
GpiSetPattern(hps, oldPattern);
}
}
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* RenderObject --
*
* This function draws a shape using a list of points, a
* stipple pattern, and the specified drawing function.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
RenderObject(hps, gc, d, points, npoints, mode, pLineBundle, func)
HPS hps;
GC gc;
Drawable d;
XPoint* points;
int npoints;
int mode;
PLINEBUNDLE pLineBundle;
int func;
{
RECTL rect;
LINEBUNDLE oldLineBundle;
LONG oldPattern;
LONG oldColor;
POINTL oldRefPoint;
POINTL *os2Points;
POINTL refPoint;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
LONG windowHeight;
POLYGON polygon;
pLineBundle->lColor = gc->foreground;
pLineBundle->lGeomWidth = gc->line_width;
if ( func == TOP_POLYGONS) {
pLineBundle->usType = LINETYPE_INVISIBLE;
} else {
pLineBundle->usType = lineStyles[gc->line_style];
}
pLineBundle->usEnd = capStyles[gc->cap_style];
pLineBundle->usJoin = joinStyles[gc->join_style];
/* os2Points/rect get *PM* coordinates handed to it by ConvertPoints */
os2Points = ConvertPoints(d, points, npoints, mode, &rect);
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
if ((gc->fill_style == FillStippled
|| gc->fill_style == FillOpaqueStippled)
&& gc->stipple != None) {
TkOS2Drawable *todPtr = (TkOS2Drawable *)gc->stipple;
DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
SIZEL sizl = {0,0}; /* use same page size as device */
HDC dcMem;
HPS psMem;
LONG width, height;
int i;
HBITMAP bitmap, oldBitmap;
BITMAPINFOHEADER2 bmpInfo;
if (todPtr->type != TOD_BITMAP) {
panic("unexpected drawable type in stipple");
}
width = rect.xRight - rect.xLeft;
/* PM coordinates are just reverse: top - bottom */
height = rect.yTop - rect.yBottom;
/*
* Select stipple pattern into destination hps.
*/
refPoint.x = gc->ts_x_origin;
/* Translate Xlib y to PM y */
refPoint.y = windowHeight - gc->ts_y_origin;
TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
/*
* Create temporary drawing surface containing a copy of the
* destination equal in size to the bounding box of the object.
*/
dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
NULLHANDLE);
if (dcMem == DEV_ERROR) {
return;
}
psMem = GpiCreatePS(hab, dcMem, &sizl,
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
if (psMem == GPI_ERROR) {
DevCloseDC(dcMem);
return;
}
TkOS2SelectPalette(psMem, HWND_DESKTOP, todPtr->bitmap.colormap);
/*
* X filling includes top and left sides, excludes bottom and right sides.
* PM filling (WinFillRect) and BitBlt-ing (GpiBitBlt) includes bottom and
* left sides, excludes top and right sides.
* NB! X fills a box exactly as wide and high as width and height specify,
* while PM cuts one pixel off the right and top.
* => decrement y (X Window System) by one / increment y (PM) by one AND
* increment height by one, and increment width by one.
*/
bmpInfo.cbFix = sizeof(BITMAPINFOHEADER2);
bmpInfo.cx = width + 1;
bmpInfo.cy = height + 1;
bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
oldBitmap = GpiSetBitmap(psMem, bitmap);
rc = GpiSetAttrs(psMem, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH
| LBB_TYPE | LBB_END | LBB_JOIN, 0L, pLineBundle);
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = 0; /* dest_x 0 */
aPoints[0].y = 0; /* dest_y 0 */
aPoints[1].x = width + 1; /* dest_x + width */
aPoints[1].y = height + 1; /* dest_y + height */
aPoints[2].x = rect.xLeft;
aPoints[2].y = rect.yBottom;
GpiBitBlt(psMem, hps, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
/*
* Translate the object to 0,0 for rendering in the temporary drawing
* surface.
*/
for (i = 0; i < npoints; i++) {
os2Points[i].x -= rect.xLeft;
os2Points[i].y -= rect.yBottom;
}
/*
* Draw the object in the foreground color and copy it to the
* destination wherever the pattern is set.
*/
rc = GpiSetColor(psMem, gc->foreground);
rc = GpiSetPattern(psMem, PATSYM_SOLID);
if (func == TOP_POLYGONS) {
rc = GpiSetCurrentPosition(psMem, os2Points);
polygon.ulPoints = npoints-1;
polygon.aPointl = os2Points+1;
rc = GpiPolygons(psMem, 1, &polygon, POLYGON_BOUNDARY |
(gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
: POLYGON_WINDING,
POLYGON_INCL);
} else { /* TOP_POLYLINE */
rc = GpiSetCurrentPosition(psMem, os2Points);
rc = GpiBeginPath(psMem, 1);
rc = GpiPolyLine(psMem, npoints-1, os2Points+1);
rc = GpiEndPath(psMem);
rc = GpiStrokePath(psMem, 1, 0);
}
aPoints[0].x = rect.xLeft; /* dest_x */
aPoints[0].y = rect.yBottom;
aPoints[1].x = rect.xRight; /* dest_x + width */
aPoints[1].y = rect.yTop; /* dest_y */
aPoints[2].x = 0; /* src_x 0 */
aPoints[2].y = 0; /* Src_y */
rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
/*
* If we are rendering an opaque stipple, then draw the polygon in the
* background color and copy it to the destination wherever the pattern
* is clear.
*/
if (gc->fill_style == FillOpaqueStippled) {
GpiSetColor(psMem, gc->background);
if (func == TOP_POLYGONS) {
polygon.ulPoints = npoints;
polygon.aPointl = os2Points;
rc = GpiPolygons(psMem, 1, &polygon,
(gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
: POLYGON_WINDING,
0);
} else { /* TOP_POLYLINE */
rc = GpiBeginPath(psMem, 1);
rc = GpiPolyLine(psMem, npoints, os2Points);
rc = GpiEndPath(psMem);
rc = GpiStrokePath(psMem, 1, 0);
}
rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYBG, BBO_IGNORE);
}
/* end of using 254 */
TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
oldPattern, &oldRefPoint);
GpiDestroyPS(psMem);
DevCloseDC(dcMem);
} else {
GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
&oldLineBundle);
rc = GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE
| LBB_END | LBB_JOIN, 0L, pLineBundle);
oldColor = GpiQueryColor(hps);
oldPattern = GpiQueryPattern(hps);
rc = GpiSetColor(hps, gc->foreground);
rc = GpiSetPattern(hps, PATSYM_SOLID);
rc = GpiSetMix(hps, mixModes[gc->function]);
if (func == TOP_POLYGONS) {
rc = GpiSetCurrentPosition(hps, os2Points);
polygon.ulPoints = npoints-1;
polygon.aPointl = os2Points+1;
rc = GpiPolygons(hps, 1, &polygon, POLYGON_BOUNDARY |
(gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
: POLYGON_WINDING,
POLYGON_INCL);
} else { /* TOP_POLYLINE */
rc = GpiSetCurrentPosition(hps, os2Points);
rc = GpiBeginPath(hps, 1);
rc = GpiPolyLine(hps, npoints-1, os2Points+1);
rc = GpiEndPath(hps);
rc = GpiStrokePath(hps, 1, 0);
}
GpiSetColor(hps, oldColor);
GpiSetPattern(hps, oldPattern);
GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
&oldLineBundle);
}
}
/*
*----------------------------------------------------------------------
*
* XDrawLines --
*
* Draw connected lines.
*
* Results:
* None.
*
* Side effects:
* Renders a series of connected lines.
*
*----------------------------------------------------------------------
*/
void
XDrawLines(display, d, gc, points, npoints, mode)
Display* display;
Drawable d;
GC gc;
XPoint* points;
int npoints;
int mode;
{
LINEBUNDLE lineBundle;
TkOS2PSState state;
HPS hps;
if (d == None) {
return;
}
hps = TkOS2GetDrawablePS(display, d, &state);
RenderObject(hps, gc, d, points, npoints, mode, &lineBundle, TOP_POLYLINE);
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* XFillPolygon --
*
* Draws a filled polygon.
*
* Results:
* None.
*
* Side effects:
* Draws a filled polygon on the specified drawable.
*
*----------------------------------------------------------------------
*/
void
XFillPolygon(display, d, gc, points, npoints, shape, mode)
Display* display;
Drawable d;
GC gc;
XPoint* points;
int npoints;
int shape;
int mode;
{
LINEBUNDLE lineBundle;
TkOS2PSState state;
HPS hps;
if (d == None) {
return;
}
hps = TkOS2GetDrawablePS(display, d, &state);
RenderObject(hps, gc, d, points, npoints, mode, &lineBundle, TOP_POLYGONS);
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* XDrawRectangle --
*
* Draws a rectangle.
*
* Results:
* None.
*
* Side effects:
* Draws a rectangle on the specified drawable.
*
*----------------------------------------------------------------------
*/
void
XDrawRectangle(display, d, gc, x, y, width, height)
Display* display;
Drawable d;
GC gc;
int x;
int y;
unsigned int width;
unsigned int height;
{
LINEBUNDLE lineBundle, oldLineBundle;
TkOS2PSState state;
LONG oldPattern;
HPS hps;
POINTL oldCurrent, changePoint;
LONG windowHeight;
if (d == None) {
return;
}
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
hps = TkOS2GetDrawablePS(display, d, &state);
GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
&oldLineBundle);
lineBundle.lColor = gc->foreground;
lineBundle.lGeomWidth = gc->line_width;
lineBundle.usType = LINETYPE_SOLID;
GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
&lineBundle);
oldPattern = GpiQueryPattern(hps);
GpiSetPattern(hps, PATSYM_NOSHADE);
GpiSetMix(hps, mixModes[gc->function]);
GpiQueryCurrentPosition(hps, &oldCurrent);
changePoint.x = x;
/* Translate the Y coordinates to PM coordinates */
changePoint.y = windowHeight - y;
GpiSetCurrentPosition(hps, &changePoint);
/*
* Now put other point of box in changePoint.
*/
changePoint.x += width;
changePoint.y -= height; /* PM coordinates are reverse */
GpiBox(hps, DRO_OUTLINE, &changePoint, 0L, 0L);
GpiSetCurrentPosition(hps, &oldCurrent);
GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
&oldLineBundle);
GpiSetPattern(hps, oldPattern);
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* XDrawArc --
*
* Draw an arc.
*
* Results:
* None.
*
* Side effects:
* Draws an arc on the specified drawable.
*
*----------------------------------------------------------------------
*/
void
XDrawArc(display, d, gc, x, y, width, height, angle1, angle2)
Display* display;
Drawable d;
GC gc;
int x;
int y;
unsigned int width;
unsigned int height;
int angle1;
int angle2;
{
display->request++;
DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, 0);
}
/*
*----------------------------------------------------------------------
*
* XFillArc --
*
* Draw a filled arc.
*
* Results:
* None.
*
* Side effects:
* Draws a filled arc on the specified drawable.
*
*----------------------------------------------------------------------
*/
void
XFillArc(display, d, gc, x, y, width, height, angle1, angle2)
Display* display;
Drawable d;
GC gc;
int x;
int y;
unsigned int width;
unsigned int height;
int angle1;
int angle2;
{
display->request++;
DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, 1);
}
/*
*----------------------------------------------------------------------
*
* DrawOrFillArc --
*
* This procedure handles the rendering of drawn or filled
* arcs and chords.
*
* Results:
* None.
*
* Side effects:
* Renders the requested arc.
*
*----------------------------------------------------------------------
*/
static void
DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, fill)
Display *display;
Drawable d;
GC gc;
int x, y; /* left top */
unsigned int width, height;
int angle1; /* angle1: three-o'clock (deg*64) */
int angle2; /* angle2: relative (deg*64) */
int fill; /* ==0 draw, !=0 fill */
{
HPS hps;
LONG oldColor, oldMix, oldPattern;
LINEBUNDLE lineBundle, oldLineBundle;
AREABUNDLE aBundle;
int sign;
POINTL center, curPt;
TkOS2PSState state;
LONG windowHeight;
ARCPARAMS arcParams, oldArcParams;
double a1sin, a1cos;
TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
POINTL refPoint;
if (d == None) {
return;
}
a1sin = sin(XAngleToRadians(angle1));
a1cos = cos(XAngleToRadians(angle1));
windowHeight = TkOS2WindowHeight(todPtr);
/* Translate the Y coordinates to PM coordinates */
y = windowHeight - y;
/* Translate angles back to positive degrees */
angle1 = abs(angle1 / 64);
if (angle2 < 0) {
sign = -1;
/*
* Not only the sweep but also the starting angle gets computed
* counter-clockwise when Arc Param Q is negative (p*q actually).
*/
angle1 = 360 - angle1;
}
else {
sign = 1;
}
angle2 = abs(angle2 / 64);
hps = TkOS2GetDrawablePS(display, d, &state);
oldColor = GpiQueryColor(hps);
oldPattern = GpiQueryPattern(hps);
oldMix = GpiQueryMix(hps);
GpiSetColor(hps, gc->foreground);
GpiSetPattern(hps, PATSYM_SOLID);
GpiSetMix(hps, mixModes[gc->function]);
/*
* Now draw a filled or open figure.
*/
GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
&oldLineBundle);
if ((gc->fill_style == FillStippled || gc->fill_style == FillOpaqueStippled)
&& gc->stipple != None) {
HBITMAP bitmap, oldBitmap;
BITMAPINFOHEADER2 bmpInfo;
LONG rc;
DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
SIZEL sizl = {0,0}; /* use same page size as device */
HDC dcMem;
HPS psMem;
POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
POINTL oldRefPoint;
todPtr = (TkOS2Drawable *)gc->stipple;
if (todPtr->type != TOD_BITMAP) {
panic("unexpected drawable type in stipple");
}
/*
* Select stipple pattern into destination dc.
*/
/* Translate Xlib y to PM y */
refPoint.x = gc->ts_x_origin;
refPoint.y = windowHeight - gc->ts_y_origin;
dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
NULLHANDLE);
if (dcMem == DEV_ERROR) {
return;
}
psMem = GpiCreatePS(hab, dcMem, &sizl,
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
if (psMem == GPI_ERROR) {
DevCloseDC(dcMem);
return;
}
rc = GpiQueryArcParams(psMem, &oldArcParams);
arcParams.lP = width / 2;
arcParams.lQ = sign * (height / 2);
arcParams.lR = 0;
arcParams.lS = 0;
rc = GpiSetArcParams(psMem, &arcParams);
/*
* Draw the object in the foreground color and copy it to the
* destination wherever the pattern is set.
*/
rc = GpiSetColor(psMem, gc->foreground);
/*
* X filling includes top and left sides, excludes bottom and right sides.
* PM filling (WinFillRect) and BitBlt-ing (GpiBitBlt) includes bottom and
* left sides, excludes top and right sides.
* NB! X fills a box exactly as wide and high as width and height specify,
* while PM cuts one pixel off the right and top.
* => decrement y (X Window System) by one / increment y (PM) by one AND
* increment height by one, and increment width by one.
*/
bmpInfo.cbFix = 16L;
/* Bitmap must be able to contain a thicker line! */
bmpInfo.cx = width + gc->line_width + 1;
bmpInfo.cy = height + gc->line_width + 1;
bmpInfo.cPlanes = 1;
bmpInfo.cBitCount= display->screens[display->default_screen].root_depth;
bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
oldBitmap = GpiSetBitmap(psMem, bitmap);
TkOS2SelectPalette(psMem, HWND_DESKTOP, todPtr->bitmap.colormap);
/* Line width! */
aPoints[0].x = 0;
aPoints[0].y = 0;
aPoints[1].x = width + gc->line_width + 1;
aPoints[1].y = height + gc->line_width + 1;
aPoints[2].x = x - (gc->line_width/2);
aPoints[2].y = y - height + 1 - (gc->line_width/2);
rc = GpiBitBlt(psMem, hps, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
/* The bitmap mustn't be selected in the HPS */
TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
/* Drawing */
/* Center of arc is at x+(0.5*width),y-(0.5*height) */
/* Translate to 0,0 for rendering in psMem */
center.x = (0.5 * width) + (gc->line_width/2);
center.y = (0.5 * height) + (gc->line_width/2);
lineBundle.lColor = gc->foreground;
lineBundle.lGeomWidth = gc->line_width;
lineBundle.usType = LINETYPE_SOLID;
rc = GpiSetAttrs(psMem, PRIM_LINE,
LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
0L, &lineBundle);
aBundle.lColor = gc->foreground;
rc = GpiSetAttrs(psMem, PRIM_AREA, LBB_COLOR, 0L, (PBUNDLE)&aBundle);
if (!fill) {
curPt.x = center.x + (int) (0.5 * width * a1cos);
curPt.y = center.y + (int) (0.5 * height * a1sin);
rc = GpiSetCurrentPosition(psMem, &curPt);
rc = GpiBeginPath(psMem, 1);
rc= GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiEndPath(psMem);
rc = GpiStrokePath(psMem, 1, 0);
} else {
curPt.x = center.x + (int) (0.5 * width * a1cos);
curPt.y = center.y + (int) (0.5 * height * a1sin);
rc = GpiSetCurrentPosition(psMem, &curPt);
if (gc->arc_mode == ArcChord) {
/* Chord */
/*
* See GPI reference: first do GpiPartialArc with invisible,
* line then again with visible line, in an Area for filling.
*/
rc = GpiSetLineType(psMem, LINETYPE_INVISIBLE);
rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiSetLineType(psMem, LINETYPE_SOLID);
rc = GpiBeginArea(psMem, BA_NOBOUNDARY|BA_ALTERNATE);
rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiEndArea(psMem);
} else if ( gc->arc_mode == ArcPieSlice ) {
/* Pie */
rc = GpiSetCurrentPosition(psMem, ¢er);
rc = GpiBeginArea(psMem, BA_NOBOUNDARY|BA_ALTERNATE);
rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiLine(psMem, ¢er);
rc = GpiEndArea(psMem);
}
}
/* Translate the Y coordinates to PM coordinates */
aPoints[0].x = x - (gc->line_width/2);
aPoints[0].y = y - height + 1 - (gc->line_width/2);
aPoints[1].x = x + width + 1 + (gc->line_width/2);
aPoints[1].y = y + 2 + (gc->line_width/2);
aPoints[2].x = 0;
aPoints[2].y = 0;
rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
GpiSetAttrs(psMem, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
&oldLineBundle);
/*
* Destroy the temporary bitmap and restore the device context.
*/
GpiSetBitmap(psMem, oldBitmap);
GpiDeleteBitmap(bitmap);
GpiDestroyPS(psMem);
DevCloseDC(dcMem);
/* The bitmap must be reselected in the HPS */
TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
oldPattern, &oldRefPoint);
} else {
/* Not stippled */
rc = GpiQueryArcParams(hps, &oldArcParams);
arcParams.lP = width / 2;
arcParams.lQ = sign * (height / 2);
arcParams.lR = 0;
arcParams.lS = 0;
rc = GpiSetArcParams(hps, &arcParams);
/* Center of arc is at x+(0.5*width),y-(0.5*height) */
center.x = x + (0.5 * width);
center.y = y - (0.5 * height); /* PM y coordinate reversed */
lineBundle.lColor = gc->foreground;
lineBundle.lGeomWidth = gc->line_width;
lineBundle.usType = LINETYPE_SOLID;
rc = GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
0L, &lineBundle);
if (!fill) {
/* direction of arc is determined by arc parameters, while angles
* are always positive
* p*q > r*s -> direction counterclockwise
* p*q < r*s -> direction clockwise
* p*q = r*s -> straight line
* When comparing the Remarks for function GpiSetArcParams in the
* GPI Guide and Reference with the Xlib Programming Manual
* (Fig.6-1), * the 3 o'clock point of the unit arc is defined by
* (p,s) and the 12 * o'clock point by (r,q), when measuring from
* (0,0) -> (cx+p, cy+s) and * (cx+r, cy+q) from center of arc at
* (cx, cy). => p = 0.5 width, q = (sign*)0.5 height, r=s=0
* GpiPartialArc draws a line from the current point to the start
* of the partial arc, so we have to set the current point to it
* first.
* this is (cx+0.5*width*cos(angle1), cy+0.5*height*sin(angle1))
*/
curPt.x = center.x + (int) (0.5 * width * a1cos);
curPt.y = center.y + (int) (0.5 * height * a1sin);
rc = GpiSetCurrentPosition(hps, &curPt);
rc = GpiBeginPath(hps, 1);
rc= GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiEndPath(hps);
rc = GpiStrokePath(hps, 1, 0);
} else {
curPt.x = center.x + (int) (0.5 * width * a1cos);
curPt.y = center.y + (int) (0.5 * height * a1sin);
rc = GpiSetCurrentPosition(hps, &curPt);
if (gc->arc_mode == ArcChord) {
/* Chord */
/*
* See GPI reference: first do GpiPartialArc with invisible
* line, then again with visible line, in an Area for filling.
*/
GpiSetLineType(hps, LINETYPE_INVISIBLE);
GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
GpiSetLineType(hps, LINETYPE_SOLID);
rc = GpiBeginArea(hps, BA_NOBOUNDARY|BA_ALTERNATE);
rc = GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
rc = GpiEndArea(hps);
} else if ( gc->arc_mode == ArcPieSlice ) {
/* Pie */
GpiSetCurrentPosition(hps, ¢er);
GpiBeginArea(hps, BA_NOBOUNDARY|BA_ALTERNATE);
rc = GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
GpiLine(hps, ¢er);
GpiEndArea(hps);
}
}
GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
&oldLineBundle);
} /* not Stippled */
GpiSetPattern(hps, oldPattern);
GpiSetColor(hps, oldColor);
GpiSetMix(hps, oldMix);
rc = GpiSetArcParams(hps, &oldArcParams);
TkOS2ReleaseDrawablePS(d, hps, &state);
}
/*
*----------------------------------------------------------------------
*
* TkScrollWindow --
*
* Scroll a rectangle of the specified window and accumulate
* a damage region.
*
* Results:
* Returns 0 if the scroll genereated no additional damage.
* Otherwise, sets the region that needs to be repainted after
* scrolling and returns 1.
*
* Side effects:
* Scrolls the bits in the window.
*
*----------------------------------------------------------------------
*/
int
TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
Tk_Window tkwin; /* The window to be scrolled. */
GC gc; /* GC for window to be scrolled. */
int x, y, width, height; /* Position rectangle to be scrolled. */
int dx, dy; /* Distance rectangle should be moved. */
TkRegion damageRgn; /* Region to accumulate damage in. */
{
HWND hwnd = TkOS2GetHWND(Tk_WindowId(tkwin));
RECTL scrollRect;
LONG lReturn;
LONG windowHeight;
windowHeight = TkOS2WindowHeight((TkOS2Drawable *)Tk_WindowId(tkwin));
/* Translate the Y coordinates to PM coordinates */
y = windowHeight - y;
dy = -dy;
scrollRect.xLeft = x;
scrollRect.yTop = y;
scrollRect.xRight = x + width;
scrollRect.yBottom = y - height; /* PM coordinate reversed */
/* Hide cursor, just in case */
WinShowCursor(hwnd, FALSE);
lReturn = WinScrollWindow(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,
NULL, 0);
/* Show cursor again */
WinShowCursor(hwnd, TRUE);
return ( lReturn == RGN_NULL ? 0 : 1);
}
/*
*----------------------------------------------------------------------
*
* TkOS2SetStipple --
*
* Set the pattern set of a HPS to a "stipple" (bitmap).
*
* Results:
* Returns the old pattern set and reference point.
*
* Side effects:
* Unsets the bitmap in/from "its" HPS, appoints a bitmap ID to it,
* sets that ID as the pattern set, with its reference point as given.
*
*----------------------------------------------------------------------
*/
void
TkOS2SetStipple(destPS, bmpPS, stipple, x, y, oldPatternSet, oldRefPoint)
HPS destPS; /* The HPS to receive the stipple. */
HPS bmpPS; /* The HPS of the stipple-bitmap. */
HBITMAP stipple; /* Stipple-bitmap. */
LONG x, y; /* Reference point for the stipple. */
LONG *oldPatternSet; /* Pattern set that was in effect in the HPS. */
PPOINTL oldRefPoint; /* Reference point that was in effect. */
{
POINTL refPoint;
refPoint.x = x;
refPoint.y = y;
rc = GpiQueryPatternRefPoint(destPS, oldRefPoint);
rc = GpiSetPatternRefPoint(destPS, &refPoint);
*oldPatternSet = GpiQueryPatternSet(destPS);
GpiSetBitmap(bmpPS, NULLHANDLE);
rc = GpiSetBitmapId(destPS, stipple, 254L);
rc = GpiSetPatternSet(destPS, 254L);
}
/*
*----------------------------------------------------------------------
*
* TkOS2UnsetStipple --
*
* Unset the "stipple" (bitmap) from a HPS.
*
* Results:
* None.
*
* Side effects:
* Resets the pattern set and refpoint of the hps to their original
* (given) values and reassociates the bitmap with its "own" HPS.
*
*----------------------------------------------------------------------
*/
void
TkOS2UnsetStipple(destPS, bmpPS, stipple, oldPatternSet, oldRefPoint)
HPS destPS; /* The HPS to give up the stipple. */
HPS bmpPS; /* The HPS of the stipple-bitmap. */
HBITMAP stipple; /* Stipple-bitmap. */
LONG oldPatternSet; /* Pattern set to be put back in effect. */
PPOINTL oldRefPoint; /* Reference point to put back in effect. */
{
rc = GpiSetPatternSet(destPS, oldPatternSet);
rc = GpiSetPatternRefPoint(destPS, oldRefPoint);
rc = GpiDeleteSetId(destPS, 254L);
/* end of using 254 */
/* The bitmap must be reselected in the HPS */
GpiSetBitmap(bmpPS, stipple);
}