home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / clines.zip / CUSTSTL.CPP next >
C/C++ Source or Header  |  1994-10-27  |  7KB  |  228 lines

  1. /****************************************************************/
  2. /* CUSTSTL.CPP                                                  */
  3. /* Custom line style module                                     */
  4. /* By Nick Hodapp, 1994                                         */
  5. /*                                                              */
  6. /* For OS/2 Developer Magazine                                  */
  7. /*                                                              */
  8. /****************************************************************/
  9. #define INCL_DOS
  10. #define INCL_GPI
  11.  
  12. #include <os2.h>
  13. #include <math.h>
  14. #include <stdlib.h>
  15. #include <memory.h>
  16.  
  17. #define MAX_INTERNAL_LINE_SEGS    1000
  18. #define MAX_STYLES              200
  19. #define CUSTOM_STYLE_OFFSET    10
  20.  
  21. /* Round x up                                                    */
  22. #define ROUND(x) x - (long)x > 0.5 ? x + 1 : x
  23.  
  24. /* Custom line style structures                                    */
  25. typedef struct lineSegStruct {
  26.  
  27.     POINTL     point1,
  28.          point2;
  29.  
  30. } LINESEG, *PLINESEG;
  31.  
  32. typedef struct styleStruct {
  33.  
  34.     USHORT     usSegWidth;
  35.     USHORT     usNumSegs;
  36.     PLINESEG segments;
  37.  
  38. } STYLE, *PSTYLE;
  39.  
  40. /* Global line style data                                        */
  41. STYLE        styleList[MAX_STYLES];
  42.  
  43. LONG        glCurrLineStyle;
  44.  
  45. POINTL        lineOut[MAX_INTERNAL_LINE_SEGS];
  46.  
  47. /* Loads a line style from the supplied resource file            */
  48. /* Returns line assigned style number                    */
  49.  
  50. /* Resource format:                                                */
  51. /* RCDATA Resource_Id {                                            */
  52. /*    NumSegs, StyleWidth, Seg1.x1, Seg1.y1, Seg1.x2, Seg1.y2,    */
  53. /*                     Seg2.x1, Seg2.y1, Seg2.x2, Seg2.y2, ...    */
  54. /* }                                                            */
  55.  
  56. LONG GpiLoadLineStyle(HMODULE resource, LONG resourceID)
  57. {
  58. ULONG    currStyle, i, j;
  59. PSHORT    resourceData;
  60.  
  61. static    BOOL firstLoad = TRUE;
  62.  
  63.     /* Initialize styleList on first call only            */
  64.     if (firstLoad) {
  65.         memset(styleList, 0, sizeof(styleList));
  66.         firstLoad = FALSE;
  67.     }
  68.  
  69.     /* Locate a free style offset                    */
  70.     for (currStyle = 0 ; currStyle < MAX_STYLES ; currStyle++)
  71.         if (!(styleList[currStyle].usNumSegs)) break;
  72.  
  73.     if (currStyle == MAX_STYLES) return 0L;
  74.  
  75.     /* Load the resource                        */
  76.     DosGetResource(resource, RT_RCDATA, resourceID, (PPVOID)&resourceData);
  77.  
  78.     /* Set usNumSegs, allocate usNumSegs LINESEG's            */
  79.     styleList[currStyle].usNumSegs = resourceData[0];
  80.     styleList[currStyle].segments  = (PLINESEG)malloc(*resourceData * sizeof(LINESEG));
  81.  
  82.     /* Copy the style width                        */
  83.     styleList[currStyle].usSegWidth = resourceData[1];
  84.  
  85.     /* Copy the style segment points                */
  86.     for (j = 0, i = 2 ; j < resourceData[0] ; j++) {
  87.         styleList[currStyle].segments[j].point1.x = resourceData[i++];
  88.         styleList[currStyle].segments[j].point1.y = resourceData[i++];
  89.         styleList[currStyle].segments[j].point2.x = resourceData[i++];
  90.         styleList[currStyle].segments[j].point2.y = resourceData[i++];
  91.     }
  92.  
  93.     /* Free the resource                        */
  94.     DosFreeResource(resourceData);
  95.  
  96.     /* Return the assigned style number                */
  97.     return currStyle + CUSTOM_STYLE_OFFSET;
  98. }
  99.  
  100. /* Frees the data associated with a custom line style so that             */
  101. /* the style number may be re-used.                    */
  102.  
  103. /* Returns FALSE on failure                        */
  104. BOOL GpiFreeLineStyle(LONG lStyle)
  105. {
  106.     /* Predefined style returns FALSE                */
  107.     if (lStyle < CUSTOM_STYLE_OFFSET) return FALSE;
  108.  
  109.     /* Free the style data                        */
  110.     lStyle -= CUSTOM_STYLE_OFFSET;
  111.     styleList[lStyle].usNumSegs     = 0;
  112.     styleList[lStyle].usSegWidth     = 0;
  113.     free(styleList[lStyle].segments);
  114.  
  115.     /* return OK                             */
  116.     return TRUE;
  117. }
  118.  
  119. /* Replacement for GpiSetLineType()                    */
  120. /* Sets line type.  Does not perform management of different        */
  121. /* styles between separate PS's except for default predefined            */
  122. /* line styles...                            */
  123.  
  124. /* Returns FALSE on falure                        */
  125. BOOL nphSetLineType(HPS hps, LONG lStyle)
  126. {
  127. ULONG i;
  128.  
  129.     // Set global glCurrLineStyle variable
  130.     glCurrLineStyle = lStyle;
  131.  
  132.     /* Determine if requested line style is GPI or custom        */
  133.     if (lStyle < CUSTOM_STYLE_OFFSET)
  134.         return GpiSetLineType(hps, lStyle);
  135.  
  136.     /* Set GPI line style to solid                    */
  137.     return GpiSetLineType(hps, LINETYPE_SOLID);
  138.  
  139. }
  140.  
  141. /* Replacement for GpiLine().  Checks current line style, then            */
  142. /* plots accordingly.  Predefined line styles are routed to             */
  143. /* normal GpiLine().                            */
  144.  
  145. /* Returns correlation/error code from GpiLine(),             */
  146. /* GpiPolyLineDisjoint()                        */
  147. LONG nphLine(HPS hps, PPOINTL pEndPoint)
  148. {
  149. POINTL     startPoint;
  150.  
  151. LONG    startX,
  152.     startY,
  153.     lStyle,
  154.     opp, adj,
  155.     currSegLength,
  156.     j, k, l;
  157.  
  158. double  sinSegAngle,
  159.     cosSegAngle;
  160.  
  161.     /* Check to see if the current line style is GPI or custom    */
  162.     /* If GPI, draw the line segment normally            */
  163.     if (glCurrLineStyle < CUSTOM_STYLE_OFFSET)
  164.         return GpiLine(hps, pEndPoint);
  165.     else
  166.         lStyle = glCurrLineStyle - CUSTOM_STYLE_OFFSET;
  167.  
  168.     /* Determine the current position within the ps         */
  169.     if (!(GpiQueryCurrentPosition(hps, &startPoint)))
  170.         return FALSE;
  171.  
  172.     /* Determine opp/adj sides to virtual triangle            */
  173.     opp = pEndPoint->y - startPoint.y;
  174.     adj = pEndPoint->x - startPoint.x;
  175.  
  176.     /* Calculate output line segment length in units        */
  177.     /* Use an integer sqrt() function here for speed....        */
  178.     currSegLength = (LONG)sqrt((double)((opp * opp) + (adj * adj)));
  179.     if (!currSegLength) return 0L;
  180.  
  181.     /* Calculate sin/cos of the angle set by the output line    */
  182.     sinSegAngle = (double)(double)opp / (double)currSegLength;
  183.     cosSegAngle = (double)(double)adj / (double)currSegLength;
  184.  
  185.     /* Loop through line style sub-segments                */
  186.     for (j = 0, l = 0 ; j < (currSegLength / styleList[lStyle].usSegWidth) - 1 ; j++) {
  187.  
  188.         /* Calculate current segment starting position      */
  189.         startX = (j * styleList[lStyle].usSegWidth * cosSegAngle) + startPoint.x;
  190.         startY = (j * styleList[lStyle].usSegWidth * sinSegAngle) + startPoint.y;
  191.  
  192.         /* Loop through current sub-segment points to translate    */
  193.         /* and rotate to correct position along output path     */
  194.         for (k = 0 ; k < styleList[lStyle].usNumSegs ; k++) {
  195.  
  196.             lineOut[l].x   = ROUND( ((styleList[lStyle].segments[k].point1.x * cosSegAngle - \
  197.                                       styleList[lStyle].segments[k].point1.y * sinSegAngle) + startX));
  198.  
  199.             lineOut[l++].y = ROUND( ((styleList[lStyle].segments[k].point1.x * sinSegAngle + \
  200.                                       styleList[lStyle].segments[k].point1.y * cosSegAngle) + startY));
  201.  
  202.  
  203.             lineOut[l].x   = ROUND( ((styleList[lStyle].segments[k].point2.x * cosSegAngle - \
  204.                                       styleList[lStyle].segments[k].point2.y * sinSegAngle) + startX));
  205.  
  206.             lineOut[l++].y = ROUND( ((styleList[lStyle].segments[k].point2.x * sinSegAngle + \
  207.                                       styleList[lStyle].segments[k].point2.y * cosSegAngle) + startY));
  208.         }
  209.     }
  210.  
  211.     /* Add a straight trailer to end of output line segment        */
  212.     lineOut[l].x   = (j * styleList[lStyle].usSegWidth * cosSegAngle) + startPoint.x;
  213.     lineOut[l++].y = (j * styleList[lStyle].usSegWidth * sinSegAngle) + startPoint.y;
  214.     lineOut[l].x   = pEndPoint->x;
  215.     lineOut[l++].y = pEndPoint->y;
  216.  
  217.     /* Plot the line with GpiPolyLineDisjoint()            */
  218.     return GpiPolyLineDisjoint(hps, l, lineOut);
  219.  
  220.     /* If driver incorrectly processes GpiPolyLineDisjoint(),    */
  221.     /* revert to GpiMove() -> GpiLine()...                         */
  222. /*    for (j = 0 ; j < l ; j++) {
  223.         GpiMove(hps, &lineOut[j]);
  224.         GpiLine(hps, &lineOut[++j]);
  225.     }
  226. */
  227. }
  228.