home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / pm / bmpsamp / misc.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  33KB  |  867 lines

  1. /******************************************************************************
  2. *
  3. *  File Name   : MISC.C
  4. *
  5. *  Description : miscellaneous Jigsaw functions
  6. *
  7. *  Entry Points:
  8. *                CreateBitmapHdcHps()
  9. *                SegListUpdate()
  10. *                SetDVTransform()
  11. *                SetRect()
  12. *                SegListGet()
  13. *                DrawPiece()
  14. *                DoDraw()
  15. *                CalcBounds()
  16. *                CalcTransform()
  17. *                Redraw()
  18. *                Correlate()
  19. *                MarkIsland()
  20. *
  21. *  Copyright (C) 1992 IBM Corporation
  22. *
  23. *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  24. *      sample code created by IBM Corporation. This sample code is not
  25. *      part of any standard or IBM product and is provided to you solely
  26. *      for  the purpose of assisting you in the development of your
  27. *      applications.  The code is provided "AS IS", without
  28. *      warranty of any kind.  IBM shall not be liable for any damages
  29. *      arising out of your use of the sample code, even if they have been
  30. *      advised of the possibility of such damages.                                                    *
  31. *
  32. ******************************************************************************/
  33.  
  34. #include "jigsaw.h"
  35. #include "globals.h"
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39.  
  40. /******************************************************************************/
  41. /*                                                                            */
  42. /* Create a memory DC and an associated PS.                                   */
  43. /*                                                                            */
  44. /******************************************************************************/
  45. BOOL CreateBitmapHdcHps( phdc, phps)
  46. PHDC phdc;
  47. PHPS phps;
  48. {
  49.   SIZEL    sizl;
  50.   HDC      hdc;
  51.   HPS      hps;
  52.  
  53.   hdc = DevOpenDC( habMain, OD_MEMORY, "*", 3L, (PDEVOPENDATA)&dop, NULLHANDLE);
  54.   if( !hdc)
  55.     return( FALSE);
  56.  
  57.   sizl.cx = sizl.cy = 1L;
  58.   if ((hps = GpiCreatePS( habMain
  59.                         , hdc
  60.                         , &sizl
  61.                         , PU_PELS | GPIA_ASSOC | GPIT_MICRO )) == GPI_ERROR)
  62.              DispError(habMain,hwndClient);
  63.   if( !hps)
  64.     return( FALSE);
  65.  
  66.   *phdc = hdc;
  67.   *phps = hps;
  68.   return( TRUE);
  69. }
  70.  
  71. /*****************************************************************************/
  72. /*                                                                            */
  73. /* Add (at head or tail) or delete a specified segment list member.           */
  74. /*                                                                            */
  75. /******************************************************************************/
  76. PSEGLIST SegListUpdate(USHORT usOperation,PSEGLIST pslUpdate)
  77. {
  78.   PSEGLIST psl;
  79.  
  80.   switch( usOperation)
  81.   {
  82.     case ADD_HEAD_SEG:
  83.       if( pslHead == NULL)
  84.       {
  85.         DosAllocMem((PPVOID)&pslHead,(ULONG)sizeof(SEGLIST),(ULONG)PAG_READ | PAG_WRITE | PAG_COMMIT);
  86.         if( pslHead == NULL)
  87.           return( NULL);
  88.         *pslHead = *pslUpdate;
  89.         pslHead->pslPrev = NULL;
  90.         pslHead->pslNext = NULL;
  91.         pslTail = pslHead;
  92.       } else
  93.       {
  94.         DosAllocMem((PPVOID)&psl,(ULONG)sizeof(SEGLIST),(ULONG)PAG_READ | PAG_WRITE | PAG_COMMIT);
  95.         if( psl == NULL)
  96.           return( NULL);
  97.         *psl = *pslUpdate;
  98.         pslHead->pslPrev = psl;
  99.         psl->pslNext = pslHead;
  100.         psl->pslPrev = NULL;
  101.         pslHead = psl;
  102.       }
  103.       return( pslHead);
  104.       break;
  105.  
  106.     case ADD_TAIL_SEG:
  107.       if( pslTail == NULL)
  108.       {
  109.         DosAllocMem((PPVOID)&pslHead,(ULONG)sizeof(SEGLIST),(ULONG)PAG_READ | PAG_WRITE |
  110.                 PAG_COMMIT);
  111.         if( pslHead == NULL)
  112.           return( NULL);
  113.         *pslHead = *pslUpdate;
  114.         pslHead->pslPrev = NULL;
  115.         pslHead->pslNext = NULL;
  116.         pslTail = pslHead;
  117.       } else
  118.       {
  119.         DosAllocMem((PPVOID)&psl,(ULONG)sizeof(SEGLIST),(ULONG)PAG_READ | PAG_WRITE |
  120.                 PAG_COMMIT);
  121.         if( psl == NULL)
  122.           return( NULL);
  123.         *psl = *pslUpdate;
  124.         pslTail->pslNext = psl;
  125.         psl->pslPrev = pslTail;
  126.         psl->pslNext = NULL;
  127.         pslTail = psl;
  128.       }
  129.       return( pslTail);
  130.       break;
  131.  
  132.     case MAKE_TAIL_SEG:
  133.       if( pslUpdate == pslTail)
  134.         return( pslTail);
  135.       if( pslUpdate == pslHead)
  136.       {
  137.         pslHead = pslHead->pslNext;
  138.         pslHead->pslPrev = NULL;
  139.       } else
  140.       {
  141.         pslUpdate->pslPrev->pslNext = pslUpdate->pslNext;
  142.         pslUpdate->pslNext->pslPrev = pslUpdate->pslPrev;
  143.       }
  144.       pslTail->pslNext = pslUpdate;
  145.       pslUpdate->pslPrev = pslTail;
  146.       pslTail = pslUpdate;
  147.       pslTail->pslNext = NULL;
  148.       return( pslTail);
  149.       break;
  150.  
  151.     case MAKE_HEAD_SEG:
  152.       if( pslUpdate == pslHead)
  153.         return( pslHead);
  154.       if( pslUpdate == pslTail)
  155.       {
  156.         pslTail = pslTail->pslPrev;
  157.         pslTail->pslNext = NULL;
  158.       } else
  159.       {
  160.         pslUpdate->pslPrev->pslNext = pslUpdate->pslNext;
  161.         pslUpdate->pslNext->pslPrev = pslUpdate->pslPrev;
  162.       }
  163.       pslHead->pslPrev = pslUpdate;
  164.       pslUpdate->pslNext = pslHead;
  165.       pslHead = pslUpdate;
  166.       pslHead->pslPrev = NULL;
  167.       return( pslHead);
  168.       break;
  169.  
  170.     case DEL_SEG:
  171.       for( psl = pslHead; psl != NULL; psl = psl->pslNext)
  172.       {
  173.         if( psl->lSegId == pslUpdate->lSegId)
  174.         {
  175.           if( psl == pslHead)
  176.           {
  177.             pslHead = psl->pslNext;
  178.             if( pslHead == NULL)
  179.               pslTail = NULL;
  180.             else
  181.               pslHead->pslPrev = NULL;
  182.           }else if( psl == pslTail)
  183.           {
  184.             pslTail = psl->pslPrev;
  185.             pslTail->pslNext = NULL;
  186.           } else
  187.           {
  188.             (psl->pslPrev)->pslNext = psl->pslNext;
  189.             (psl->pslNext)->pslPrev = psl->pslPrev;
  190.           }
  191.           DosFreeMem( psl);
  192.           return( psl);
  193.           break;
  194.         }
  195.       }
  196.       return( NULL);
  197.       break;
  198.  
  199.     default:
  200.       return( NULL);
  201.   }
  202. }
  203.  
  204. /******************************************************************************/
  205. /*                                                                            */
  206. /* set the default viewing transform                                          */
  207. /*                                                                            */
  208. /******************************************************************************/
  209. VOID SetDVTransform( fx11, fx12, fx21, fx22, l31, l32, lType)
  210. FIXED fx11;
  211. FIXED fx12;
  212. FIXED fx21;
  213. FIXED fx22;
  214. FIXED l31;
  215. FIXED l32;
  216. FIXED lType;
  217. {
  218.   MATRIXLF  matlf;
  219.  
  220.   matlf.fxM11 = fx11;
  221.   matlf.fxM12 = fx12;
  222.   matlf.lM13  = 0L;
  223.   matlf.fxM21 = fx21;
  224.   matlf.fxM22 = fx22;
  225.   matlf.lM23  = 0L;
  226.   matlf.lM31  = l31;
  227.   matlf.lM32  = l32;
  228.   matlf.lM33  = 1L;
  229.   if (GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, lType) == GPI_ERROR)
  230.       DispError(habMain,hwndClient);
  231. }
  232.  
  233. /******************************************************************************/
  234. /*                                                                            */
  235. /* Determine the bounding rect of a segment.                                  */
  236. /*                                                                            */
  237. /* Use special knowledge that the only non-identity part of the segment       */
  238. /* transform is the translation part.                                         */
  239. /******************************************************************************/
  240. VOID SetRect( psl)
  241. PSEGLIST psl;
  242. {
  243.   psl->rclCurrent         = psl->rclBitBlt;      /* world space bounding rect */
  244.   psl->rclCurrent.xLeft   += psl->ptlModelXlate.x;
  245.   psl->rclCurrent.yBottom += psl->ptlModelXlate.y;
  246.   psl->rclCurrent.xRight  += psl->ptlModelXlate.x;
  247.   psl->rclCurrent.yTop    += psl->ptlModelXlate.y;
  248. }
  249.  
  250. /******************************************************************************/
  251. /*                                                                            */
  252. /* Return a pointer to a segment list member, based on segment id.            */
  253. /*                                                                            */
  254. /******************************************************************************/
  255. PSEGLIST SegListGet( lSeg)
  256. LONG lSeg;
  257. {
  258.   PSEGLIST  psl;
  259.  
  260.   for( psl = pslHead; psl != NULL; psl = psl->pslNext)
  261.     if( psl->lSegId == lSeg)
  262.       return( psl);
  263.   return( NULL);
  264. }
  265.  
  266.  
  267. /******************************************************************************
  268. *
  269. *  Name        : DrawPiece
  270. *
  271. *  Description : Draw one piece.
  272. *
  273. *  Concepts    :
  274. *
  275. *  API's       :
  276. *
  277. *  Parameters  : HPS      hps
  278. *                PSEGLIST psl
  279. *                BOOL     fFill
  280. *
  281. *  Return      : VOID
  282. *
  283. ******************************************************************************/
  284.  
  285. VOID DrawPiece(HPS hps, PSEGLIST psl, BOOL fFill)
  286. {
  287.    POINTL  aptl[4];
  288.    APIRET  rc;
  289.  
  290.    if(psl->fVisible)                          /* don't bother if not visible */
  291.    {
  292.       /*
  293.        *  Setup source and target points based on model transform of this peice
  294.        */
  295.  
  296.       aptl[2].x = aptl[2].y = 0L;                      /* source: lower left */
  297.       aptl[3] = psl->aptlBitBlt[3];                   /* source: upper right */
  298.  
  299.                                                                /* target:    */
  300.       aptl[0].x = psl->rclBitBlt.xLeft + psl->ptlModelXlate.x; /* lower left */
  301.       aptl[0].y = psl->rclBitBlt.yBottom + psl->ptlModelXlate.y;
  302.  
  303.       rc =
  304.       GpiConvert(hpsClient, CVTC_MODEL, CVTC_DEVICE, 1L, aptl);
  305.  
  306.       if (rc == GPI_ERROR)
  307.          DispError(habMain,hwndClient);
  308.  
  309.       aptl[1].x = aptl[0].x + aptl[3].x;              /* target: upper right */
  310.       aptl[1].y = aptl[0].y + aptl[3].y;           /* (equal to source size) */
  311.  
  312.       /*
  313.        *  Punch a hole
  314.        */
  315.  
  316.       rc =
  317.       GpiBitBlt(
  318.          hps,                            /* target presentation-space handle */
  319.          psl->hpsHole,                   /* source presentation-space handle */
  320.          4L,                             /* number of points in array        */
  321.          aptl,                           /* address of array                 */
  322.          ROP_SRCAND,                     /* mixing method                    */
  323.          BBO_IGNORE);                    /* line/column-compression flag     */
  324.  
  325.       if (rc == GPI_ERROR)
  326.          DispError(habMain,hwndClient);
  327.  
  328.       if (fFill)
  329.       {
  330.          /*
  331.           *  Fill the hole
  332.           */
  333.          rc =
  334.          GpiBitBlt(
  335.             hps,                         /* target presentation-space handle */
  336.             psl->hpsFill,                /* source presentation-space handle */
  337.             4L,                          /* number of points in array        */
  338.             aptl,                        /* address of array                 */
  339.             ROP_SRCPAINT,                /* mixing method                    */
  340.             BBO_IGNORE);                 /* line/column-compression flag     */
  341.  
  342.          if (rc == GPI_ERROR)
  343.             DispError(habMain,hwndClient);
  344.  
  345.       }   /* end if (fFill) */
  346.  
  347.    }   /* end if(psl->fVisible) */
  348.  
  349. }   /* end DrawPiece() */
  350.  
  351. /******************************************************************************/
  352. /*                                                                            */
  353. /* Draw the picture, using the passed region for clipping.                    */
  354. /* Intersect the bounding box used for the clip region with the client rect.  */
  355. /* Test each segment to see if its bounding box intersects the bounding box   */
  356. /* of the clipping region.  Draw only if there is an intersection.            */
  357. /*                                                                            */
  358. /******************************************************************************/
  359. BOOL DoDraw(HPS hps,HRGN hrgn,BOOL fPaint)
  360. {
  361.   HRGN      hrgnOld;
  362.   RECTL     rcl, rclRegion, rclDst, rclClient;
  363.   PSEGLIST  psl;
  364.   ULONG     ulPostCt;
  365.  
  366.   if( fPaint && !fFirstLoad)
  367.   {
  368.     if (GpiSetColor( hps, CLR_BACKGROUND) == GPI_ERROR)
  369.         DispError(habMain,hwndClient);
  370.     if (GpiPaintRegion( hps, hrgn) == GPI_ERROR)             /* erase region */
  371.         DispError(habMain,hwndClient);
  372.   }
  373.  
  374.   if (GpiQueryRegionBox( hps, hrgn, &rclRegion) == RGN_ERROR)
  375.       DispError(habMain,hwndClient);
  376.  
  377.   WinQueryWindowRect( hwndClient, &rclClient);
  378.  
  379.   if( !WinIntersectRect( habAsync, &rclRegion, &rclRegion, &rclClient))
  380.     return( FALSE);                                  /* not in client window */
  381.  
  382.   if (GpiSetClipRegion( hps, hrgn, &hrgnOld) == RGN_ERROR) /* make the clip region */
  383.       DispError(habMain,hwndClient);
  384.  
  385.   for( psl = pslHead; psl != NULL; psl = psl->pslNext)    /* scan all pieces */
  386.   {
  387.     /**************************************************************************/
  388.     /* get the piece bounding box in device coordinates                       */
  389.     /**************************************************************************/
  390.     rcl = psl->rclCurrent;
  391.     if (GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 2L, (PPOINTL)&rcl) == GPI_ERROR)
  392.         DispError(habMain,hwndClient);
  393.     rcl.xRight++;
  394.     rcl.yTop++;
  395.  
  396.     /**************************************************************************/
  397.     /* if the piece might be visible, and drawing allowed, draw the piece     */
  398.     /**************************************************************************/
  399.  
  400.     if( WinIntersectRect( habAsync, &rclDst, &rcl, &rclRegion))
  401.        {
  402.        DosQueryEventSem( hevDrawOn, &ulPostCt);          /* drawing enabled? */
  403.          if( ulPostCt)                                                /* yes */
  404.            DrawPiece( hps, psl, TRUE);
  405.          else
  406.            break;                   /* drawing is disabled; don't draw piece */
  407.        }
  408.   }
  409.  
  410.   if (GpiSetClipRegion( hps, NULLHANDLE, &hrgnOld) == RGN_ERROR)
  411.       DispError(habMain,hwndClient);
  412.  
  413.   DosQueryEventSem( hevDrawOn, &ulPostCt);
  414.   if( ulPostCt)                                        /* drawing is enabled */
  415.     if (GpiSetRegion( hpsClient, hrgnInvalid, 0L, NULL) == RGN_ERROR)
  416.         DispError(habMain,hwndClient);
  417.  
  418.   return( TRUE);
  419.  
  420. }   /* end DoDraw() */
  421.  
  422. /******************************************************************************/
  423. /*                                                                            */
  424. /* get bounding rect of whole picture in model coordinates                    */
  425. /*                                                                            */
  426. /******************************************************************************/
  427. VOID CalcBounds(VOID)
  428. {
  429.   PSEGLIST  psl;
  430.   RECTL     rclOld;
  431.   ULONG     ulPostKillDraw, ulPostCt;
  432.  
  433.   if( !pslHead)
  434.     return;
  435.   rclBounds = rclOld = pslHead->rclCurrent;
  436.  
  437.   /*
  438.    * get start killdraw post count
  439.    */
  440.   DosQueryEventSem(hevKillDraw, &ulPostKillDraw);
  441.  
  442.   for( psl = pslHead->pslNext; psl != NULL; psl = psl->pslNext) {
  443.     DosQueryEventSem(hevKillDraw, &ulPostCt);
  444.     if (ulPostKillDraw != ulPostCt) {
  445.         rclBounds = rclOld;
  446.         return;
  447.         }
  448.     WinUnionRect(habAsync, &rclBounds, &rclBounds, &(psl->rclCurrent));
  449.     }
  450. }
  451.  
  452. /******************************************************************************/
  453. /*                                                                            */
  454. /* Calculate and set the default viewing transform based on zoom and scroll   */
  455. /*                                                                            */
  456. /******************************************************************************/
  457. VOID CalcTransform( hwnd)
  458. HWND hwnd;
  459. {
  460.   RECTL     rclClient;
  461.   POINTL    ptlCenter, ptlTrans, ptlScale, aptl[4], ptlOrg, aptlSides[12];
  462.   PSEGLIST  psl;
  463.   LONG      l;
  464.   MATRIXLF  matlf;
  465.   ULONG     ulPostCt, ulPostKillDraw;
  466.  
  467.  
  468.   /*
  469.    * get start killdraw post count
  470.    */
  471.   DosQueryEventSem(hevKillDraw, &ulPostKillDraw);
  472.  
  473.  
  474.   /****************************************************************************/
  475.   /* from bounding rect of picture get center of picture                      */
  476.   /****************************************************************************/
  477.   ptlCenter.x = (rclBounds.xLeft   + rclBounds.xRight) / 2;
  478.   ptlCenter.y = (rclBounds.yBottom + rclBounds.yTop  ) / 2;
  479.  
  480.   /****************************************************************************/
  481.   /* translate center of picture to origin                                    */
  482.   /****************************************************************************/
  483.   SetDVTransform( (FIXED)UNITY
  484.                 , (FIXED)0
  485.                 , (FIXED)0
  486.                 , (FIXED)UNITY
  487.                 , -ptlCenter.x
  488.                 , -ptlCenter.y
  489.                 , TRANSFORM_REPLACE);
  490.  
  491.   /****************************************************************************/
  492.   /* scale down to 1:1 of bitmap in file                                      */
  493.   /****************************************************************************/
  494.   if (pbmp2BitmapFile->cbFix  == sizeof(BITMAPINFOHEADER))
  495.       {
  496.       ptlScale.x = UNITY * ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cx
  497.               / (ptlTopRight.x - ptlBotLeft.x);
  498.       ptlScale.y = UNITY * ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cy
  499.               / (ptlTopRight.y - ptlBotLeft.y);
  500.       }
  501.   else
  502.       {
  503.       ptlScale.x = UNITY * pbmp2BitmapFile->cx
  504.               / (ptlTopRight.x - ptlBotLeft.x);
  505.       ptlScale.y = UNITY * pbmp2BitmapFile->cy
  506.               / (ptlTopRight.y - ptlBotLeft.y);
  507.       }
  508.  
  509.   /****************************************************************************/
  510.   /* add in zoom scale                                                        */
  511.   /****************************************************************************/
  512.   ptlScale.x += ptlScale.x * lScale / (ZOOM_MAX + 1);
  513.   ptlScale.y += ptlScale.y * lScale / (ZOOM_MAX + 1);
  514.  
  515.   SetDVTransform( (FIXED)ptlScale.x
  516.                 , (FIXED)0
  517.                 , (FIXED)0
  518.                 , (FIXED)ptlScale.y
  519.                 , 0L
  520.                 , 0L
  521.                 , TRANSFORM_ADD);
  522.  
  523.   /****************************************************************************/
  524.   /* translate center of picture to center of client window                   */
  525.   /****************************************************************************/
  526.   WinQueryWindowRect( hwnd, &rclClient);
  527.   ptlTrans.x = (rclClient.xRight - rclClient.xLeft)   / 2;
  528.   ptlTrans.y = (rclClient.yTop   - rclClient.yBottom) / 2;
  529.  
  530.   /****************************************************************************/
  531.   /* add in horizontal and vertical scrolling factors                         */
  532.   /****************************************************************************/
  533.   ptlTrans.x -= ptsScrollPos.x - ptsHalfScrollMax.x;
  534.   ptlTrans.y += ptsScrollPos.y - ptsHalfScrollMax.y;
  535.   SetDVTransform( (FIXED)UNITY
  536.                 , (FIXED)0
  537.                 , (FIXED)0
  538.                 , (FIXED)UNITY
  539.                 , ptlTrans.x
  540.                 , ptlTrans.y
  541.                 , TRANSFORM_ADD);
  542.  
  543.   if (GpiQueryDefaultViewMatrix( hpsClient, 9L, &matlf) == GPI_ERROR)
  544.       DispError(habMain,hwndClient);
  545.   if (GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, TRANSFORM_REPLACE) == GPI_ERROR)
  546.       DispError(habMain,hwndClient);
  547.  
  548.   /****************************************************************************/
  549.   /* create bitmaps for pieces                                                */
  550.   /****************************************************************************/
  551.  
  552.   ptlOffset = ptlBotLeft;                  /* BottomLeft corner in dev coord  */
  553.   if (GpiConvert( hpsClient, CVTC_WORLD, CVTC_DEVICE, 1L, &ptlOffset) == GPI_ERROR)
  554.       DispError(habMain,hwndClient);
  555.   if( (ptlScale.x != ptlScaleRef.x) || (ptlScale.y != ptlScaleRef.y))
  556.   {
  557.     ptlScaleRef = ptlScale;
  558.  
  559.     /**************************************************************************/
  560.     /* create a shadow bitmap of the original, sized to current output size   */
  561.     /**************************************************************************/
  562.     aptl[0] = ptlBotLeft;                  /* current output rect, dev coord  */
  563.     aptl[1] = ptlTopRight;
  564.     if (GpiConvert( hpsClient, CVTC_WORLD, CVTC_DEVICE, 2L, aptl) == GPI_ERROR)
  565.         DispError(habMain,hwndClient);
  566.     aptl[0].x -= ptlOffset.x;              /* put bottom left at (0,0)        */
  567.     aptl[0].y -= ptlOffset.y;
  568.     aptl[1].x -= ptlOffset.x;
  569.     aptl[1].y -= ptlOffset.y;
  570. #ifdef fred
  571.     aptl[1].x -= ptlOffset.x - 1;          /* correct for coordinate convert  */
  572.     aptl[1].y -= ptlOffset.y - 1;
  573. #endif
  574.     aptl[2].x = 0L;
  575.     aptl[2].y = 0L;
  576.   if (pbmp2BitmapFile->cbFix  == sizeof(BITMAPINFOHEADER))
  577.      {
  578.     aptl[3].x = ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cx;  /*bitmap dimensions   */
  579.     aptl[3].y = ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cy;
  580.      }
  581.   else
  582.      {
  583.     aptl[3].x = pbmp2BitmapFile->cx;        /* bitmap dimensions               */
  584.     aptl[3].y = pbmp2BitmapFile->cy;
  585.      }
  586.     if (GpiSetBitmap( hpsBitmapSize, hbmBitmapSize) == (HBITMAP)BMB_ERROR)
  587.         DispError(habMain,hwndClient);
  588.     if (GpiBitBlt( hpsBitmapSize               /* copy the bitmap                 */
  589.                  , hpsBitmapFile
  590.                  , 4L
  591.                  , aptl
  592.                  , ROP_SRCCOPY
  593.                  , BBO_IGNORE) == GPI_ERROR)
  594.         DispError(habMain,hwndClient);
  595.  
  596.     for( psl = pslHead; psl != NULL; psl = psl->pslNext)
  597.     {
  598.       DosQueryEventSem( hevTerminate, &ulPostCt);
  599.       if( ulPostCt) /* exit if quit   */
  600.         break;
  601.  
  602.       DosQueryEventSem( hevKillDraw, &ulPostCt);
  603.       if( ulPostCt != ulPostKillDraw) {
  604.         break;
  605.         }
  606.  
  607.       aptl[0].x = psl->rclBitBlt.xLeft;     /* bounding rect in world space   */
  608.       aptl[0].y = psl->rclBitBlt.yBottom;
  609.       aptl[1].x = psl->rclBitBlt.xRight;
  610.       aptl[1].y = psl->rclBitBlt.yTop;
  611.       aptl[2] = aptl[0];
  612.       aptl[3] = aptl[1];
  613.       if (GpiConvert( hpsClient, CVTC_WORLD, CVTC_DEVICE, 2L, &aptl[2]) == GPI_ERROR)
  614.           DispError(habMain,hwndClient);
  615.       ptlOrg = aptl[2];
  616.       aptl[3].x -= ptlOrg.x - 1;            /* bitmap rect of piece           */
  617.       aptl[3].y -= ptlOrg.y - 1;
  618.       aptl[2].x = 0L;
  619.       aptl[2].y = 0L;
  620.       psl->aptlBitBlt[0] = aptl[0];
  621.       psl->aptlBitBlt[1] = aptl[1];
  622.       psl->aptlBitBlt[2] = aptl[2];
  623.       psl->aptlBitBlt[3] = aptl[3];
  624.  
  625.       /************************************************************************/
  626.       /* compute the piece control points                                     */
  627.       /************************************************************************/
  628.       for ( l = 0; l < 12; l++)
  629.         aptlSides[l] = psl->aptlSides[l];
  630.       if (GpiConvert( hpsClient, CVTC_WORLD, CVTC_DEVICE, 12L, aptlSides) == GPI_ERROR)
  631.           DispError(habMain,hwndClient);
  632.       for ( l = 0; l < 12; l++)
  633.       {
  634.         aptlSides[l].x -= ptlOrg.x;
  635.         aptlSides[l].y -= ptlOrg.y;
  636.       }
  637.  
  638.       /************************************************************************/
  639.       /* prepare the mask to punch a hole in the output bitmap                */
  640.       /************************************************************************/
  641.       if (GpiSetClipPath( psl->hpsHole, 0L, SCP_RESET)== GPI_ERROR)/* no clip path          */
  642.           DispError(habMain,hwndClient);
  643.       if (GpiBitBlt( psl->hpsHole                        /* fill with 1's         */
  644.                    , NULLHANDLE
  645.                    , 2L
  646.                    , &psl->aptlBitBlt[2]
  647.                    , ROP_ONE
  648.                    , BBO_IGNORE) == GPI_ERROR)
  649.           DispError(habMain,hwndClient);
  650.  
  651.       if (GpiBeginPath( psl->hpsHole, 1L) == GPI_ERROR)  /* define a clip path    */
  652.           DispError(habMain,hwndClient);
  653.       if (GpiMove( psl->hpsHole, &aptlSides[11]) == GPI_ERROR)
  654.           DispError(habMain,hwndClient);
  655.       if (GpiPolySpline( psl->hpsHole, 12L, aptlSides) == GPI_ERROR)
  656.           DispError(habMain,hwndClient);
  657.       if (GpiEndPath( psl->hpsHole) == GPI_ERROR)
  658.           DispError(habMain,hwndClient);
  659.       if (GpiSetClipPath( psl->hpsHole, 1L, SCP_AND) == GPI_ERROR)
  660.           DispError(habMain,hwndClient);
  661.       if (GpiBitBlt( psl->hpsHole                        /* fill with 0's         */
  662.                    , NULLHANDLE
  663.                    , 2L
  664.                    , &psl->aptlBitBlt[2]
  665.                    , ROP_ZERO
  666.                    , BBO_IGNORE) == GPI_ERROR)
  667.           DispError(habMain,hwndClient);
  668.       if (GpiSetClipPath( psl->hpsHole, 0L, SCP_RESET) == GPI_ERROR)  /* clear the clip path   */
  669.           DispError(habMain,hwndClient);
  670.  
  671.       /************************************************************************/
  672.       /* prepare the mask to fill the hole in the output bitmap               */
  673.       /************************************************************************/
  674.       aptl[0] = psl->aptlBitBlt[2];
  675.       aptl[1] = psl->aptlBitBlt[3];
  676.       aptl[2] = aptl[0];
  677.       if (GpiBitBlt( psl->hpsFill                        /* make inverse of hole  */
  678.                    , psl->hpsHole
  679.                    , 3L
  680.                    , aptl
  681.                    , ROP_NOTSRCCOPY
  682.                    , BBO_IGNORE) == GPI_ERROR)
  683.           DispError(habMain,hwndClient);
  684.  
  685.       aptl[0] = psl->aptlBitBlt[2];
  686.       aptl[1] = psl->aptlBitBlt[3];
  687.       aptl[2].x = ptlOrg.x - ptlOffset.x;            /* pick the right part   */
  688.       aptl[2].y = ptlOrg.y - ptlOffset.y;            /* of the sized bitmap   */
  689.       if (GpiBitBlt( psl->hpsFill                        /* fill with data        */
  690.                    , hpsBitmapSize
  691.                    , 3L
  692.                    , aptl
  693.                    , ROP_SRCAND
  694.                    , BBO_IGNORE) == GPI_ERROR)
  695.           DispError(habMain,hwndClient);
  696.       if (GpiSetClipPath( psl->hpsFill, 0L, SCP_RESET) == GPI_ERROR)  /* clear the clip path   */
  697.           DispError(habMain,hwndClient);
  698.       if (GpiSetColor( psl->hpsFill, CLR_RED) == GPI_ERROR)/* draw the outline      */
  699.           DispError(habMain,hwndClient);
  700.       if (GpiMove( psl->hpsFill, &aptlSides[11]) == GPI_ERROR)
  701.           DispError(habMain,hwndClient);
  702.       if (GpiPolySpline( psl->hpsFill, 12L, aptlSides) == GPI_ERROR)
  703.           DispError(habMain,hwndClient);
  704.       DrawPiece( hpsClient, psl, TRUE);
  705.     }
  706.   }
  707. }
  708.  
  709. /******************************************************************************/
  710. /*                                                                            */
  711. /* Redraw the entire client window.                                           */
  712. /*                                                                            */
  713. /******************************************************************************/
  714. VOID Redraw(VOID)
  715. {
  716.   RECTL   rclInvalid;
  717.   HRGN    hrgnUpdt;
  718.   POINTL  aptlUpdtNew[3];
  719.  
  720.   WinQueryWindowRect( hwndClient, &rclInvalid);
  721.   hrgnUpdt = GpiCreateRegion( hpsBitmapBuff, 1L, &rclInvalid);
  722.   DoDraw( hpsBitmapBuff, hrgnUpdt, TRUE);
  723.   if (GpiDestroyRegion( hpsBitmapBuff, hrgnUpdt) == GPI_ERROR)
  724.      DispError(habMain,hwndClient);
  725.   aptlUpdtNew[0].x = rclInvalid.xLeft;
  726.   aptlUpdtNew[0].y = rclInvalid.yBottom;
  727.   aptlUpdtNew[1].x = rclInvalid.xRight;
  728.   aptlUpdtNew[1].y = rclInvalid.yTop;
  729.   ROUND_DOWN_MOD( aptlUpdtNew[0].x, lByteAlignX);         /* round down       */
  730.   ROUND_DOWN_MOD( aptlUpdtNew[0].y, lByteAlignY);         /* round down       */
  731.   ROUND_UP_MOD(   aptlUpdtNew[1].x, lByteAlignX);         /* round up         */
  732.   ROUND_UP_MOD(   aptlUpdtNew[1].y, lByteAlignY);         /* round up         */
  733.   aptlUpdtNew[2] = aptlUpdtNew[0];
  734.  
  735.   if (!fFirstLoad)
  736.   {
  737.      if (GpiBitBlt( hpsClient
  738.                   , hpsBitmapBuff
  739.                   , 3L
  740.                   , aptlUpdtNew
  741.                   , ROP_SRCCOPY
  742.                   , BBO_IGNORE ) == GPI_ERROR)
  743.          DispError(habMain,hwndClient);
  744.   }   /* end if (!fFirstLoad) */
  745. }
  746.  
  747. /******************************************************************************
  748. *
  749. *  Name        : CorrelatePPOINTL
  750. *
  751. *  Description : perform bitmap-based correlation
  752. *
  753. *  Concepts    :
  754. *
  755. *  API's       :
  756. *
  757. *  Parameters  : PPOINTL pptl
  758. *
  759. *  Return      : PSEGLIST
  760. *
  761. ******************************************************************************/
  762.  
  763. PSEGLIST Correlate(PPOINTL pptl)
  764. {
  765.    PSEGLIST  psl;
  766.    POINTL    aptl[2];
  767.    LONG      lColor;
  768.    RECTL     rcl;
  769.    APIRET    rc;                                    /* return code from APIs */
  770.  
  771.  
  772.    aptl[0] = aptl[1] = *pptl;                     /* target lower-left point */
  773.  
  774.    aptl[1].x++;                           /* target bitmap upper-right point */
  775.    aptl[1].y++;
  776.  
  777.    /*
  778.     *  Set all hpsBitmapSave pels to 1.  We're doing this so we can draw
  779.     *  the correlated segment (if any) overtop of it.  Then, if the color
  780.     *  didn't change, we know that we hit a clipped part of the segment
  781.     *  (piece).
  782.     */
  783.    rc =
  784.    GpiBitBlt(
  785.       hpsBitmapSave,                     /* target presentation-space handle */
  786.       NULLHANDLE,                        /* source presentation-space handle */
  787.       2L,                                /* number of points in array        */
  788.       aptl,                              /* address of array                 */
  789.       ROP_ONE,                           /* mixing method                    */
  790.       BBO_IGNORE);                       /* line/column-compression flag     */
  791.  
  792.    if (rc  == GPI_ERROR)
  793.       DispError(habMain,hwndClient);
  794.  
  795.    /*
  796.     *  Retrieve color attribute for correlation point
  797.     */
  798.  
  799.    lColor =                                               /* should return 0 */
  800.    GpiQueryPel(hpsBitmapSave, pptl);
  801.  
  802.    if (lColor == GPI_ALTERROR)
  803.       DispError(habMain,hwndClient);
  804.  
  805.    /*
  806.     *  Do a manual correlation by determining if the correlation point
  807.     *  intersects the region occupied be each segment (piece).
  808.     */
  809.  
  810.    for( psl = pslTail; psl != NULL; psl = psl->pslPrev)
  811.    {
  812.       /*
  813.        *  get device coordinates for current segment (peice) bounding box
  814.        */
  815.  
  816.       rcl = psl->rclCurrent;
  817.       rc =
  818.       GpiConvert(
  819.          hpsClient,             /* presentation-space handle                 */
  820.          CVTC_MODEL,            /* source coordinate space                   */
  821.          CVTC_DEVICE,           /* target coordinate space                   */
  822.          2L,                    /* number of coordinate pairs in structure   */
  823.          (PPOINTL)&rcl);        /* address of structure for coordinate pairs */
  824.  
  825.       if (rc == GPI_ERROR)
  826.          DispError(habMain,hwndClient);
  827.  
  828.       rcl.xRight++;
  829.       rcl.yTop++;
  830.  
  831.       /*
  832.        *  Does the point fall inside this segment's (peice's) bounding box?
  833.        *  If so, did the color of the pel change when we drew the piece?  If
  834.        *  so, we selected a point inside this piece (segment) which isn't
  835.        *  clipped.  Return it.
  836.        */
  837.  
  838.       if (WinPtInRect(habAsync, &rcl, pptl))
  839.       {
  840.           DrawPiece( hpsBitmapSave, psl, FALSE);      /* draw clipped bitmap */
  841.           if(GpiQueryPel( hpsBitmapSave, pptl) != lColor)   /* color change? */
  842.              break;                                             /* got a hit */
  843.       }
  844.    }   /* end for(all segments in our linked list) */
  845.  
  846.    return( psl);
  847.  
  848. }   /* end Correlate() */
  849.  
  850. /******************************************************************************/
  851. /*                                                                            */
  852. /* mark a whole island                                                        */
  853. /*                                                                            */
  854. /******************************************************************************/
  855. VOID MarkIsland(PSEGLIST pslMark,BOOL fMark)
  856. {
  857.   PSEGLIST  psl;
  858.   BOOL      fFirst;
  859.  
  860.   for( psl = pslMark, fFirst = TRUE
  861.      ; (psl != pslMark) || fFirst
  862.      ; psl = psl->pslNextIsland, fFirst = FALSE )
  863.       psl->fIslandMark = fMark;               /* mark as island member        */
  864. }
  865.  
  866. /********************************  END MISC.C  *******************************/
  867.