home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
clines.zip
/
CUSTSTL.CPP
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
7KB
|
228 lines
/****************************************************************/
/* CUSTSTL.CPP */
/* Custom line style module */
/* By Nick Hodapp, 1994 */
/* */
/* For OS/2 Developer Magazine */
/* */
/****************************************************************/
#define INCL_DOS
#define INCL_GPI
#include <os2.h>
#include <math.h>
#include <stdlib.h>
#include <memory.h>
#define MAX_INTERNAL_LINE_SEGS 1000
#define MAX_STYLES 200
#define CUSTOM_STYLE_OFFSET 10
/* Round x up */
#define ROUND(x) x - (long)x > 0.5 ? x + 1 : x
/* Custom line style structures */
typedef struct lineSegStruct {
POINTL point1,
point2;
} LINESEG, *PLINESEG;
typedef struct styleStruct {
USHORT usSegWidth;
USHORT usNumSegs;
PLINESEG segments;
} STYLE, *PSTYLE;
/* Global line style data */
STYLE styleList[MAX_STYLES];
LONG glCurrLineStyle;
POINTL lineOut[MAX_INTERNAL_LINE_SEGS];
/* Loads a line style from the supplied resource file */
/* Returns line assigned style number */
/* Resource format: */
/* RCDATA Resource_Id { */
/* NumSegs, StyleWidth, Seg1.x1, Seg1.y1, Seg1.x2, Seg1.y2, */
/* Seg2.x1, Seg2.y1, Seg2.x2, Seg2.y2, ... */
/* } */
LONG GpiLoadLineStyle(HMODULE resource, LONG resourceID)
{
ULONG currStyle, i, j;
PSHORT resourceData;
static BOOL firstLoad = TRUE;
/* Initialize styleList on first call only */
if (firstLoad) {
memset(styleList, 0, sizeof(styleList));
firstLoad = FALSE;
}
/* Locate a free style offset */
for (currStyle = 0 ; currStyle < MAX_STYLES ; currStyle++)
if (!(styleList[currStyle].usNumSegs)) break;
if (currStyle == MAX_STYLES) return 0L;
/* Load the resource */
DosGetResource(resource, RT_RCDATA, resourceID, (PPVOID)&resourceData);
/* Set usNumSegs, allocate usNumSegs LINESEG's */
styleList[currStyle].usNumSegs = resourceData[0];
styleList[currStyle].segments = (PLINESEG)malloc(*resourceData * sizeof(LINESEG));
/* Copy the style width */
styleList[currStyle].usSegWidth = resourceData[1];
/* Copy the style segment points */
for (j = 0, i = 2 ; j < resourceData[0] ; j++) {
styleList[currStyle].segments[j].point1.x = resourceData[i++];
styleList[currStyle].segments[j].point1.y = resourceData[i++];
styleList[currStyle].segments[j].point2.x = resourceData[i++];
styleList[currStyle].segments[j].point2.y = resourceData[i++];
}
/* Free the resource */
DosFreeResource(resourceData);
/* Return the assigned style number */
return currStyle + CUSTOM_STYLE_OFFSET;
}
/* Frees the data associated with a custom line style so that */
/* the style number may be re-used. */
/* Returns FALSE on failure */
BOOL GpiFreeLineStyle(LONG lStyle)
{
/* Predefined style returns FALSE */
if (lStyle < CUSTOM_STYLE_OFFSET) return FALSE;
/* Free the style data */
lStyle -= CUSTOM_STYLE_OFFSET;
styleList[lStyle].usNumSegs = 0;
styleList[lStyle].usSegWidth = 0;
free(styleList[lStyle].segments);
/* return OK */
return TRUE;
}
/* Replacement for GpiSetLineType() */
/* Sets line type. Does not perform management of different */
/* styles between separate PS's except for default predefined */
/* line styles... */
/* Returns FALSE on falure */
BOOL nphSetLineType(HPS hps, LONG lStyle)
{
ULONG i;
// Set global glCurrLineStyle variable
glCurrLineStyle = lStyle;
/* Determine if requested line style is GPI or custom */
if (lStyle < CUSTOM_STYLE_OFFSET)
return GpiSetLineType(hps, lStyle);
/* Set GPI line style to solid */
return GpiSetLineType(hps, LINETYPE_SOLID);
}
/* Replacement for GpiLine(). Checks current line style, then */
/* plots accordingly. Predefined line styles are routed to */
/* normal GpiLine(). */
/* Returns correlation/error code from GpiLine(), */
/* GpiPolyLineDisjoint() */
LONG nphLine(HPS hps, PPOINTL pEndPoint)
{
POINTL startPoint;
LONG startX,
startY,
lStyle,
opp, adj,
currSegLength,
j, k, l;
double sinSegAngle,
cosSegAngle;
/* Check to see if the current line style is GPI or custom */
/* If GPI, draw the line segment normally */
if (glCurrLineStyle < CUSTOM_STYLE_OFFSET)
return GpiLine(hps, pEndPoint);
else
lStyle = glCurrLineStyle - CUSTOM_STYLE_OFFSET;
/* Determine the current position within the ps */
if (!(GpiQueryCurrentPosition(hps, &startPoint)))
return FALSE;
/* Determine opp/adj sides to virtual triangle */
opp = pEndPoint->y - startPoint.y;
adj = pEndPoint->x - startPoint.x;
/* Calculate output line segment length in units */
/* Use an integer sqrt() function here for speed.... */
currSegLength = (LONG)sqrt((double)((opp * opp) + (adj * adj)));
if (!currSegLength) return 0L;
/* Calculate sin/cos of the angle set by the output line */
sinSegAngle = (double)(double)opp / (double)currSegLength;
cosSegAngle = (double)(double)adj / (double)currSegLength;
/* Loop through line style sub-segments */
for (j = 0, l = 0 ; j < (currSegLength / styleList[lStyle].usSegWidth) - 1 ; j++) {
/* Calculate current segment starting position */
startX = (j * styleList[lStyle].usSegWidth * cosSegAngle) + startPoint.x;
startY = (j * styleList[lStyle].usSegWidth * sinSegAngle) + startPoint.y;
/* Loop through current sub-segment points to translate */
/* and rotate to correct position along output path */
for (k = 0 ; k < styleList[lStyle].usNumSegs ; k++) {
lineOut[l].x = ROUND( ((styleList[lStyle].segments[k].point1.x * cosSegAngle - \
styleList[lStyle].segments[k].point1.y * sinSegAngle) + startX));
lineOut[l++].y = ROUND( ((styleList[lStyle].segments[k].point1.x * sinSegAngle + \
styleList[lStyle].segments[k].point1.y * cosSegAngle) + startY));
lineOut[l].x = ROUND( ((styleList[lStyle].segments[k].point2.x * cosSegAngle - \
styleList[lStyle].segments[k].point2.y * sinSegAngle) + startX));
lineOut[l++].y = ROUND( ((styleList[lStyle].segments[k].point2.x * sinSegAngle + \
styleList[lStyle].segments[k].point2.y * cosSegAngle) + startY));
}
}
/* Add a straight trailer to end of output line segment */
lineOut[l].x = (j * styleList[lStyle].usSegWidth * cosSegAngle) + startPoint.x;
lineOut[l++].y = (j * styleList[lStyle].usSegWidth * sinSegAngle) + startPoint.y;
lineOut[l].x = pEndPoint->x;
lineOut[l++].y = pEndPoint->y;
/* Plot the line with GpiPolyLineDisjoint() */
return GpiPolyLineDisjoint(hps, l, lineOut);
/* If driver incorrectly processes GpiPolyLineDisjoint(), */
/* revert to GpiMove() -> GpiLine()... */
/* for (j = 0 ; j < l ; j++) {
GpiMove(hps, &lineOut[j]);
GpiLine(hps, &lineOut[++j]);
}
*/
}