Annotation of mstools/samples/sdktools/imagedit/workwp.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  *                                                                         *
                      3:  *  MODULE      : WorkWP.c                                                 *
                      4:  *                                                                         *
                      5:  *  DESCRIPTION : Functions controlling the workspace window.              *
                      6:  *                                                                         *
                      7:  *  HISTORY     : 6/21/89 LR                                               *
                      8:  *                                                                         *
                      9:  ***************************************************************************/
                     10: 
                     11: #include "imagedit.h"
                     12: 
                     13: #include <stdlib.h>
                     14: 
                     15: 
                     16: /*
                     17:  * This structure is used in conjunction with DeltaGenInit() and DeltaGen().
                     18:  */
                     19: typedef struct _DELTAGEN { /* dg */
                     20:     BOOL fSwap;
                     21:     INT xf;
                     22:     INT yf;
                     23:     INT dx;
                     24:     INT dy;
                     25:     INT d;
                     26:     INT incx;
                     27:     INT incy;
                     28:     INT inc1;
                     29:     INT inc2;
                     30: } DELTAGEN;
                     31: typedef DELTAGEN *PDELTAGEN;
                     32: 
                     33: 
                     34: STATICFN VOID NEAR WorkPaint(HWND hwnd);
                     35: STATICFN VOID WorkButtonDown(HWND hwnd, UINT msg, PPOINT ppt);
                     36: STATICFN VOID WorkButtonMouseMove(HWND hwnd, UINT msg, PPOINT ppt);
                     37: STATICFN VOID WorkButtonUp(HWND hwnd, UINT msg, PPOINT ppt);
                     38: STATICFN VOID NEAR SnapPointToGrid(PPOINT ppt);
                     39: STATICFN VOID DrawToPoint(HWND hwnd, PPOINT ppt, BOOL fBrush);
                     40: STATICFN BOOL NEAR DeltaGenInit(PDELTAGEN pdg, INT x0, INT y0,
                     41:     INT xf, INT yf, PINT px, PINT py);
                     42: STATICFN BOOL NEAR DeltaGen(PDELTAGEN pdg, PINT px, PINT py);
                     43: STATICFN VOID DrawPoint(HWND hwnd, PPOINT ppt, BOOL fBrush);
                     44: STATICFN VOID NEAR RubberBandLine(BOOL fFirstTime);
                     45: STATICFN VOID NEAR RectDPDraw(HWND hwnd);
                     46: STATICFN VOID NEAR RubberBandRect(BOOL fFirstTime);
                     47: STATICFN VOID NEAR CircleDPDraw(HWND hwnd);
                     48: STATICFN VOID NEAR RubberBandCircle(BOOL fFirstTime);
                     49: STATICFN VOID NEAR MarkHotSpotPosition(INT x, INT y);
                     50: STATICFN VOID NEAR StartRubberBanding(HWND hwnd);
                     51: STATICFN VOID NEAR EndRubberBanding(HWND hwnd);
                     52: 
                     53: 
                     54: static BOOL fDrawing = FALSE;           // TRUE if mouse button is down.
                     55: static BOOL fLeftButtonDown;            // TRUE if left button was pressed.
                     56: static POINT ptStart;                   // Saves the starting point.
                     57: static POINT ptEnd;                     // Saves the ending point.
                     58: static POINT ptPrev;                    // Saves the previous point.
                     59: static HDC hdcRubberBand;               // DC used during rubber banding.
                     60: static BOOL fRubberBanding = FALSE;     // Tracking is in progress.
                     61: 
                     62: 
                     63: 
                     64: /****************************************************************************
                     65:  * WorkWndProc
                     66:  *                                                                          *
                     67:  * purpose: Processes basic create and size and paint messages for the      *
                     68:  *          workspace window.
                     69:  *                                                                          *
                     70:  ****************************************************************************/
                     71: 
                     72: WINDOWPROC WorkWndProc(
                     73:     HWND hwnd,
                     74:     UINT msg,
                     75:     WPARAM wParam,
                     76:     LPARAM lParam)
                     77: {
                     78:     LPCREATESTRUCT cs;
                     79:     POINT pt;
                     80: 
                     81:     switch (msg) {
                     82:         case WM_CREATE:
                     83:             /* set up image variables */
                     84:             cs = (LPCREATESTRUCT)lParam;
                     85:             gcxWorkSpace = cs->cx;
                     86:             gcyWorkSpace = cs->cy;
                     87:             break;
                     88: 
                     89:         case WM_SIZE:
                     90:             gcxWorkSpace = LOWORD(lParam);
                     91:             gcyWorkSpace = HIWORD(lParam);
                     92: 
                     93:             break;
                     94: 
                     95:         case WM_PAINT:
                     96:             WorkPaint(hwnd);
                     97:             break;
                     98: 
                     99:         case WM_MOUSEMOVE:
                    100:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
                    101:             WorkButtonMouseMove(hwnd, msg, &pt);
                    102:             break;
                    103: 
                    104:         case WM_RBUTTONDOWN:
                    105:         case WM_LBUTTONDOWN:
                    106:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
                    107:             WorkButtonDown(hwnd, msg, &pt);
                    108:             break;
                    109: 
                    110:         case WM_LBUTTONUP:
                    111:         case WM_RBUTTONUP:
                    112:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
                    113:             WorkButtonUp(hwnd, msg, &pt);
                    114:             break;
                    115: 
                    116:         case WM_KEYDOWN:
                    117:             switch (wParam) {
                    118:                 case VK_ESCAPE:
                    119:                     if (fDrawing) {
                    120:                         if (fRubberBanding) {
                    121:                             EndRubberBanding(hwnd);
                    122:                             WorkUpdate();
                    123:                         }
                    124: 
                    125:                         PropBarClearSize();
                    126:                         ReleaseCapture();
                    127:                         fDrawing = FALSE;
                    128:                     }
                    129: 
                    130:                     break;
                    131:             }
                    132: 
                    133:             break;
                    134: 
                    135:         default:
                    136:             return DefWindowProc(hwnd, msg, wParam, lParam);
                    137:     }
                    138: 
                    139:     return 0;
                    140: }
                    141: 
                    142: 
                    143: 
                    144: /****************************************************************************
                    145: * WorkPaint
                    146: *
                    147: * Handles WM_PAINT for the workspace window.
                    148: *
                    149: * History:
                    150: *
                    151: ****************************************************************************/
                    152: 
                    153: STATICFN VOID NEAR WorkPaint(    HWND hwnd)
                    154: {
                    155:     register INT i;
                    156:     PAINTSTRUCT ps;
                    157:     HCURSOR hcurOld;
                    158:     HDC hdcTemp;
                    159:     HBITMAP hbmTemp;
                    160: 
                    161:     hcurOld = SetCursor(hcurWait);
                    162:     BeginPaint(hwnd, &ps);
                    163: 
                    164:     /*
                    165:      * Do they want a grid and is there enough room to show the lines?
                    166:      */
                    167:     if (gfGrid && gZoomFactor > 1) {
                    168:         /*
                    169:          * Stretch the bits onto a temporary DC.
                    170:          */
                    171:         hdcTemp = CreateCompatibleDC(ghdcImage);
                    172:         hbmTemp = CreateCompatibleBitmap(ghdcImage,
                    173:                 gcxWorkSpace, gcyWorkSpace);
                    174:         SelectObject(hdcTemp, hbmTemp);
                    175:         StretchBlt(hdcTemp, 0, 0, gcxWorkSpace, gcyWorkSpace,
                    176:                 ghdcImage, 0, 0, gcxImage, gcyImage, SRCCOPY);
                    177: 
                    178:         /*
                    179:          * Draw the grid lines on the temp DC.
                    180:          */
                    181:         for (i = gZoomFactor - 1; i < gcxWorkSpace; i += gZoomFactor)
                    182:             PatBlt(hdcTemp, i, 0, 1, gcyWorkSpace, BLACKNESS);
                    183:         for (i = gZoomFactor - 1; i < gcyWorkSpace; i += gZoomFactor)
                    184:             PatBlt(hdcTemp, 0, i, gcxWorkSpace, 1, BLACKNESS);
                    185: 
                    186:         /*
                    187:          * Copy the bits to the screen.
                    188:          */
                    189:         BitBlt(ps.hdc, 0, 0, gcxWorkSpace, gcyWorkSpace,
                    190:                 hdcTemp, 0, 0, SRCCOPY);
                    191: 
                    192:         DeleteDC(hdcTemp);
                    193:         DeleteObject(hbmTemp);
                    194:     }
                    195:     else {
                    196:         /*
                    197:          * No grid.  Just stretch the image to the screen.
                    198:          */
                    199:         StretchBlt(ps.hdc, 0, 0, gcxWorkSpace, gcyWorkSpace,
                    200:                 ghdcImage, 0, 0, gcxImage, gcyImage, SRCCOPY);
                    201:     }
                    202: 
                    203:     EndPaint(hwnd, &ps);
                    204:     SetCursor(hcurOld);
                    205: }
                    206: 
                    207: 
                    208: 
                    209: /****************************************************************************
                    210: * WorkUpdate
                    211: *
                    212: * This function updates the workspace window.
                    213: *
                    214: * History:
                    215: *
                    216: ****************************************************************************/
                    217: 
                    218: VOID WorkUpdate(VOID)
                    219: {
                    220:     /*
                    221:      * Invalidate the workspace window.  Because the image will be
                    222:      * be blt'ed onto it, we do not need to force the background to
                    223:      * be cleared first.
                    224:      */
                    225:     InvalidateRect(ghwndWork, NULL, FALSE);
                    226: }
                    227: 
                    228: 
                    229: 
                    230: /****************************************************************************
                    231: * WorkReset
                    232: *
                    233: * This function reset the workspace window.  It should be called
                    234: * any time that a new image is loaded (because the size could
                    235: * change) or the size of the main window changes (because the
                    236: * workspace window needs to be resized to fit).
                    237: *
                    238: * History:
                    239: *
                    240: ****************************************************************************/
                    241: 
                    242: VOID WorkReset(VOID)
                    243: {
                    244:     RECT rcClient;
                    245:     INT cx;
                    246:     INT cy;
                    247:     INT xScale;
                    248:     INT yScale;
                    249:     INT cxBorder;
                    250:     INT cyBorder;
                    251: 
                    252:     cxBorder = GetSystemMetrics(SM_CXBORDER);
                    253:     cyBorder = GetSystemMetrics(SM_CYBORDER);
                    254: 
                    255:     if (!gcxImage || !gcyImage) {
                    256:         gZoomFactor = 1;
                    257:     }
                    258:     else {
                    259:         GetClientRect(ghwndMain, &rcClient);
                    260:         cx = rcClient.right - (2 * PALETTEMARGIN) - (2 * cxBorder);
                    261:         cy = rcClient.bottom - (2 * PALETTEMARGIN) - (2 * cyBorder) -
                    262:                 gcyPropBar;
                    263: 
                    264:         xScale = cx / gcxImage;
                    265:         yScale = cy / gcyImage;
                    266: 
                    267:         if (xScale > 0 && yScale > 0)
                    268:             gZoomFactor = min(xScale, yScale);
                    269:         else
                    270:             gZoomFactor = 1;
                    271:     }
                    272: 
                    273:     SetWindowPos(ghwndWork, NULL,
                    274:             PALETTEMARGIN, PALETTEMARGIN + gcyPropBar,
                    275:             (gZoomFactor * gcxImage) + (2 * cxBorder),
                    276:             (gZoomFactor * gcyImage) + (2 * cyBorder),
                    277:             SWP_NOACTIVATE | SWP_NOZORDER);
                    278:     WorkUpdate();
                    279: }
                    280: 
                    281: 
                    282: 
                    283: /************************************************************************
                    284: * WorkButtonDown
                    285: *
                    286: *
                    287: *
                    288: * Arguments:
                    289: *
                    290: * History:
                    291: *
                    292: ************************************************************************/
                    293: 
                    294: STATICFN VOID WorkButtonDown(
                    295:     HWND hwnd,
                    296:     UINT msg,
                    297:     PPOINT ppt)
                    298: {
                    299:     /*
                    300:      * If the other button is already down, just ignore this one.
                    301:      */
                    302:     if (fDrawing)
                    303:         return;
                    304: 
                    305:     SetFocus(hwnd);
                    306:     fLeftButtonDown = (msg == WM_LBUTTONDOWN) ? TRUE : FALSE;
                    307: 
                    308:     SnapPointToGrid(ppt);
                    309:     ptStart = ptPrev = ptEnd = *ppt;
                    310: 
                    311:     if (fLeftButtonDown) {
                    312:         ghbrDraw = ghbrLeft;
                    313:         ghbrDrawSolid = ghbrLeftSolid;
                    314:         gfDrawMode = gfModeLeft;
                    315:         ghpenDraw = ghpenLeft;
                    316:     }
                    317:     else {
                    318:         ghbrDraw = ghbrRight;
                    319:         ghbrDrawSolid = ghbrRightSolid;
                    320:         gfDrawMode = gfModeRight;
                    321:         ghpenDraw = ghpenRight;
                    322:     }
                    323: 
                    324:     /*
                    325:      * If this tool draws on the down-click, update the undo
                    326:      * buffer now.
                    327:      */
                    328:     if (gaTools[gCurTool].fDrawOnDown)
                    329:         ImageUpdateUndo();
                    330: 
                    331:     SetCapture(ghwndWork);
                    332:     fDrawing = TRUE;
                    333: 
                    334:     (*gpfnDrawProc)(hwnd, msg, *ppt);
                    335: 
                    336:     PropBarSetSize(ptStart, ptEnd);
                    337: }
                    338: 
                    339: 
                    340: 
                    341: /************************************************************************
                    342: * WorkButtonMouseMove
                    343: *
                    344: *
                    345: *
                    346: * Arguments:
                    347: *
                    348: * History:
                    349: *
                    350: ************************************************************************/
                    351: 
                    352: STATICFN VOID WorkButtonMouseMove(
                    353:     HWND hwnd,
                    354:     UINT msg,
                    355:     PPOINT ppt)
                    356: {
                    357:     static POINT ptNZLast;  // Saves the last point (non-zoomed).
                    358:     POINT ptNZ;
                    359: 
                    360:     SetCursor(gaTools[gCurTool].hcur);
                    361: 
                    362:     SnapPointToGrid(ppt);
                    363: 
                    364:     /*
                    365:      * Calculate the point as it would be on the actual image
                    366:      * (non-zoomed).
                    367:      */
                    368:     ptNZ.x = ppt->x / gZoomFactor;
                    369:     ptNZ.y = ppt->y / gZoomFactor;
                    370: 
                    371:     /*
                    372:      * Only call the drawing proc if the point changed enough to
                    373:      * jump over a zoomed pixels width (it jumped a grid square).
                    374:      * This prevents calling the DrawProc for a mouse move of
                    375:      * a single pixel (unless the zoom factor is 1, of course).
                    376:      */
                    377:     if (ptNZLast.x != ptNZ.x || ptNZLast.y != ptNZ.y) {
                    378:         ptEnd = *ppt;
                    379:         (*gpfnDrawProc)(hwnd, msg, *ppt);
                    380:         ptPrev = ptEnd;
                    381: 
                    382:         PropBarSetPos(ptNZ.x, ptNZ.y);
                    383: 
                    384:         if (fDrawing)
                    385:             PropBarSetSize(ptStart, ptEnd);
                    386: 
                    387:         ptNZLast = ptNZ;
                    388:     }
                    389: }
                    390: 
                    391: 
                    392: 
                    393: /************************************************************************
                    394: * WorkButtonUp
                    395: *
                    396: *
                    397: *
                    398: * Arguments:
                    399: *
                    400: * History:
                    401: *
                    402: ************************************************************************/
                    403: 
                    404: STATICFN VOID WorkButtonUp(
                    405:     HWND hwnd,
                    406:     UINT msg,
                    407:     PPOINT ppt)
                    408: {
                    409:     /*
                    410:      * Pass this on to the draw procs, but only if we are still drawing.
                    411:      * The drawing could have been cancelled by the Escape key, in
                    412:      * which case we just ignore the button up message.
                    413:      */
                    414:     if (fDrawing) {
                    415:         SnapPointToGrid(ppt);
                    416: 
                    417:         /*
                    418:          * If this tool draws on the up-click, update the undo
                    419:          * buffer now.
                    420:          */
                    421:         if (gaTools[gCurTool].fDrawOnUp)
                    422:             ImageUpdateUndo();
                    423: 
                    424:         (*gpfnDrawProc)(hwnd, msg, *ppt);
                    425: 
                    426:         ReleaseCapture();
                    427:         fDrawing = FALSE;
                    428:     }
                    429: }
                    430: 
                    431: 
                    432: 
                    433: /******************************************************************************
                    434:  * SnapPointToGrid
                    435:  *
                    436:  * PURPOSE : Snap the current mouse coordinate to the nearest grid intersection.
                    437:  *
                    438:  * PARAMS  : PPOINT ppt : current mouse coordinates
                    439:  *
                    440:  *****************************************************************************/
                    441: 
                    442: STATICFN VOID NEAR SnapPointToGrid(
                    443:     PPOINT ppt)
                    444: {
                    445:     /*
                    446:      * Scale the point down (this gridizes it at the same time).
                    447:      */
                    448:     ppt->x = ppt->x / gZoomFactor;
                    449:     ppt->y = ppt->y / gZoomFactor;
                    450: 
                    451:     /*
                    452:      * Limit the point to within the image.
                    453:      */
                    454:     if (ppt->x < 0)
                    455:         ppt->x = 0;
                    456: 
                    457:     if (ppt->y < 0)
                    458:         ppt->y = 0;
                    459: 
                    460:     if (ppt->x >= gcxImage)
                    461:         ppt->x = gcxImage - 1;
                    462: 
                    463:     if (ppt->y >= gcyImage)
                    464:         ppt->y = gcyImage - 1;
                    465: 
                    466:     /*
                    467:      * Finally, scale it back up to the workspace window size.
                    468:      */
                    469:     ppt->x *= gZoomFactor;
                    470:     ppt->y *= gZoomFactor;
                    471: }
                    472: 
                    473: 
                    474: 
                    475: /************************************************************************
                    476: * PencilDP
                    477: *
                    478: *
                    479: *
                    480: * Arguments:
                    481: *
                    482: * History:
                    483: *
                    484: ************************************************************************/
                    485: 
                    486: VOID PencilDP(
                    487:     HWND hwnd,
                    488:     UINT msg,
                    489:     POINT ptNew)
                    490: {
                    491:     switch (msg) {
                    492:         case WM_LBUTTONDOWN:
                    493:         case WM_RBUTTONDOWN:
                    494:             DrawPoint(hwnd, &ptNew, FALSE);
                    495:             break;
                    496: 
                    497:         case WM_MOUSEMOVE:
                    498:             if (fDrawing)
                    499:                 DrawToPoint(hwnd, &ptNew, FALSE);
                    500: 
                    501:             break;
                    502:     }
                    503: }
                    504: 
                    505: 
                    506: 
                    507: /************************************************************************
                    508: * BrushDP
                    509: *
                    510: *
                    511: *
                    512: * Arguments:
                    513: *
                    514: * History:
                    515: *
                    516: ************************************************************************/
                    517: 
                    518: VOID BrushDP(
                    519:     HWND hwnd,
                    520:     UINT msg,
                    521:     POINT ptNew)
                    522: {
                    523:     switch (msg) {
                    524:         case WM_LBUTTONDOWN:
                    525:         case WM_RBUTTONDOWN:
                    526:             DrawPoint(hwnd, &ptNew, TRUE);
                    527:             break;
                    528: 
                    529:         case WM_MOUSEMOVE:
                    530:             if (fDrawing)
                    531:                 DrawToPoint(hwnd, &ptNew, TRUE);
                    532: 
                    533:             break;
                    534:     }
                    535: }
                    536: 
                    537: 
                    538: 
                    539: /************************************************************************
                    540: * DrawToPoint
                    541: *
                    542: * This function draws from the previous point to the given point.
                    543: * This includes all points between.
                    544: *
                    545: * The global ptPrev must have been initialized prior to the  first time
                    546: * this function is called during a drawing operation.
                    547: *
                    548: * Arguments:
                    549: *
                    550: * History:
                    551: *
                    552: ************************************************************************/
                    553: 
                    554: STATICFN VOID DrawToPoint(
                    555:     HWND hwnd,
                    556:     PPOINT ppt,
                    557:     BOOL fBrush)
                    558: {
                    559:     DELTAGEN dg;
                    560:     BOOL fContinue;
                    561:     POINT pt;
                    562:     INT x;
                    563:     INT y;
                    564: 
                    565:     x = ppt->x / gZoomFactor;
                    566:     y = ppt->y / gZoomFactor;
                    567:     DeltaGenInit(&dg, ptPrev.x / gZoomFactor, ptPrev.y / gZoomFactor,
                    568:             ppt->x / gZoomFactor, ppt->y / gZoomFactor, &x, &y);
                    569:     do {
                    570:         pt.x = x * gZoomFactor;
                    571:         pt.y = y * gZoomFactor;
                    572:         DrawPoint(hwnd, &pt, fBrush);
                    573:         fContinue = DeltaGen(&dg, &x, &y);
                    574:     } while (fContinue);
                    575: }
                    576: 
                    577: 
                    578: 
                    579: /***************************** Public  Function ****************************\
                    580: * DeltaGenInit
                    581: *
                    582: * This routine initializes the pdg, px and py in preparation for using
                    583: * DeltaGen().  Returns fContinue.
                    584: *
                    585: * Algorithm derived from BRESENHAM line algorighm on p. 435 of Fund. of
                    586: * interactive computer graphics, Foley/VanDam, addison-wesley 1983.
                    587: *
                    588: * History:
                    589: *       3/7/89  sanfords        created
                    590: \***************************************************************************/
                    591: 
                    592: STATICFN BOOL NEAR DeltaGenInit(
                    593:     PDELTAGEN pdg,
                    594:     INT x0,
                    595:     INT y0,
                    596:     INT xf,
                    597:     INT yf,
                    598:     PINT px,
                    599:     PINT py)
                    600: {
                    601:     INT nT;
                    602: 
                    603:     pdg->xf = xf;
                    604:     pdg->yf = yf;
                    605: 
                    606:     if (x0 == xf && y0 == yf)
                    607:         return FALSE;
                    608: 
                    609:     if (xf >= x0)
                    610:         pdg->incx = 1;
                    611:     else
                    612:         pdg->incx = -1;
                    613: 
                    614:     if (yf >= y0)        pdg->incy = 1;
                    615:     else
                    616:         pdg->incy = -1;
                    617: 
                    618:     pdg->dx = (xf - x0) * pdg->incx;
                    619:     pdg->dy = (yf - y0) * pdg->incy;
                    620: 
                    621:     if (pdg->dy > pdg->dx) {
                    622:         nT = pdg->dy;
                    623:         pdg->dy = pdg->dx;
                    624:         pdg->dx = nT;
                    625:         nT = pdg->incx;
                    626:         pdg->incx = pdg->incy;
                    627:         pdg->incy = nT;
                    628:         pdg->fSwap = TRUE;
                    629:     }
                    630:     else {
                    631:         pdg->fSwap = FALSE;
                    632:     }
                    633: 
                    634:     pdg->inc1 = pdg->dy * 2;
                    635:     pdg->inc2 = (pdg->dy - pdg->dx) * 2;
                    636:     pdg->d = pdg->inc1 - pdg->dx;
                    637: 
                    638:     pdg->xf = xf;
                    639:     pdg->yf = yf;
                    640: 
                    641:     *px = x0;
                    642:     *py = y0;
                    643: 
                    644:     return TRUE;
                    645: }
                    646: 
                    647: 
                    648: 
                    649: /***************************** Public  Function ****************************\
                    650: * DeltaGen
                    651: *
                    652: * This routine generates the next coordinates for px,py assuming that this
                    653: * point is proceeding linearly from x0,y0 to xf, yf.  It returns FALSE only
                    654: * if *px == xf and *py == yf on entry.  (ie returns fContinue)  pdg should
                    655: * have been previously set by DeltaGenInit().
                    656: *
                    657: * Algorithm derived from BRESENHAM line algorighm on p. 435 of Fund. of
                    658: * interactive computer graphics, Foley/VanDam, addison-wesley 1983.
                    659: *
                    660: * History:
                    661: *       3/7/89  sanfords        created
                    662: \***************************************************************************/
                    663: 
                    664: STATICFN BOOL NEAR DeltaGen(
                    665:     PDELTAGEN pdg,
                    666:     PINT px,
                    667:     PINT py)
                    668: {
                    669:     PINT pnT;
                    670: 
                    671:     if ((*px == pdg->xf) && (*py == pdg->yf))
                    672:         return FALSE;
                    673: 
                    674:     if (pdg->fSwap) {
                    675:         pnT = px;
                    676:         px = py;
                    677:         py = pnT;
                    678:     }
                    679: 
                    680:     *px += pdg->incx;
                    681:     if (pdg->d < 0) {
                    682:         pdg->d += pdg->inc1;
                    683:     }
                    684:     else {
                    685:         *py += pdg->incy;
                    686:         pdg->d += pdg->inc2;
                    687:     }
                    688: 
                    689:     return TRUE;
                    690: }
                    691: 
                    692: 
                    693: 
                    694: /************************************************************************
                    695: * DrawPoint
                    696: *
                    697: * This function is called to draw a point on the image.  It is used
                    698: * by the Pencil and Brush tools.
                    699: *
                    700: * Arguments:
                    701: *
                    702: * History:
                    703: *
                    704: ************************************************************************/
                    705: 
                    706: STATICFN VOID DrawPoint(    HWND hwnd,
                    707:     PPOINT ppt,
                    708:     BOOL fBrush)
                    709: {
                    710:     HDC hDC;
                    711:     HBRUSH hbrOld;
                    712:     INT wx;
                    713:     INT wy;
                    714:     INT iStartY;
                    715:     INT wStep;
                    716:     INT i;
                    717:     INT j;
                    718:     INT nBrushSize;
                    719: 
                    720:     if (ppt->x < 0 || ppt->y < 0)
                    721:         return;
                    722: 
                    723:     hDC = GetDC(hwnd);
                    724: 
                    725:     /*
                    726:      * If this is a point from the brush tool, use the current
                    727:      * brush width.  Otherwise, draw a single pixel point.
                    728:      */
                    729:     if (fBrush)
                    730:         nBrushSize = gnBrushSize;
                    731:     else
                    732:         nBrushSize = 1;
                    733: 
                    734:     /*     * Determine some starting factors, then draw the point in
                    735:      * the workspace window.
                    736:      */
                    737:     hbrOld = SelectObject(hDC, ghbrDrawSolid);
                    738:     wy = iStartY = ppt->y - (ppt->y % gZoomFactor)
                    739:             -(nBrushSize / 2) * gZoomFactor;
                    740:     wx = ppt->x - (ppt->x % gZoomFactor)
                    741:             -(nBrushSize / 2) * gZoomFactor;
                    742:     wStep = gZoomFactor;
                    743: 
                    744:     if (gfGrid && gZoomFactor > 1)
                    745:         wStep -= 1;
                    746: 
                    747:     for (i = 0; i < nBrushSize; i++, wx += gZoomFactor) {
                    748:         wy = iStartY;
                    749:         for (j = 0; j < nBrushSize; j++, wy += gZoomFactor)
                    750:             PatBlt(hDC, wx, wy, wStep, wStep, PATCOPY);
                    751:     }
                    752: 
                    753:     SelectObject(hDC, hbrOld);
                    754:     ReleaseDC(hwnd, hDC);
                    755: 
                    756:     /*
                    757:      * Set the point in the bitmap directly as an optimization.
                    758:      */
                    759:     wx = ppt->x / gZoomFactor;
                    760:     wy = ppt->y / gZoomFactor;
                    761:     if (wx < gcxImage && wy < gcyImage) {
                    762:         hbrOld = SelectObject(ghdcImage, ghbrDrawSolid);
                    763:         PatBlt(ghdcImage, wx - nBrushSize / 2, wy - nBrushSize / 2,
                    764:                 nBrushSize, nBrushSize, PATCOPY);
                    765: 
                    766:         if (giType != FT_BITMAP) {
                    767:             /*
                    768:              * If in color mode, set the mask bits black.  Otherwise make
                    769:              * them white.
                    770:              */
                    771:             PatBlt(ghdcANDMask, wx - nBrushSize / 2, wy - nBrushSize / 2,
                    772:                     nBrushSize, nBrushSize,
                    773:                     (gfDrawMode == MODE_COLOR) ? BLACKNESS : WHITENESS);
                    774:         }
                    775: 
                    776:         SelectObject(ghdcImage, hbrOld);
                    777: 
                    778:         /*
                    779:          * Draw the point in the view window directly as an optimization.
                    780:          */
                    781:         if (ghwndView)
                    782:             ViewSetPixel(wx, wy, nBrushSize);
                    783:     }
                    784: 
                    785:     /*
                    786:      * Mark the image as changed.
                    787:      */
                    788:     fImageDirty = TRUE;
                    789: }
                    790: 
                    791: 
                    792: 
                    793: /************************************************************************
                    794: * PickDP
                    795: *
                    796: * Drawing proc that selects a rectangular portion of the image.
                    797: * It updates the global picking rectangle.
                    798: *
                    799: * Arguments:
                    800: *
                    801: * History:
                    802: *
                    803: ************************************************************************/
                    804: 
                    805: VOID PickDP(
                    806:     HWND hwnd,
                    807:     UINT msg,
                    808:     POINT ptNew)
                    809: {
                    810:     POINT ptTL;         // Top-Left point.
                    811:     POINT ptBR;         // Bottom-Right point
                    812: 
                    813:     switch (msg) {
                    814:         case WM_LBUTTONDOWN:
                    815:         case WM_RBUTTONDOWN:
                    816:             /* erase any previous ghost rectangle */
                    817:             WorkUpdate();
                    818:             UpdateWindow(ghwndWork);
                    819: 
                    820:             /*
                    821:              * Initialize the pick rectangle to cover the entire screen.
                    822:              */
                    823:             PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
                    824: 
                    825:             StartRubberBanding(hwnd);
                    826:             RubberBandRect(TRUE);
                    827:             break;
                    828: 
                    829:         case WM_MOUSEMOVE:
                    830:             if (fRubberBanding)
                    831:                 RubberBandRect(FALSE);
                    832: 
                    833:             break;
                    834: 
                    835:         case WM_LBUTTONUP:
                    836:         case WM_RBUTTONUP:
                    837:             EndRubberBanding(hwnd);
                    838: 
                    839:             /*
                    840:              * Flip the points (if needed) and scale down.
                    841:              */
                    842:             ptTL = ptStart;
                    843:             ptBR = ptEnd;
                    844:             NormalizePoints(&ptTL, &ptBR);
                    845:             ptTL.x /= gZoomFactor;
                    846:             ptTL.y /= gZoomFactor;
                    847:             ptBR.x /= gZoomFactor;
                    848:             ptBR.y /= gZoomFactor;
                    849: 
                    850:             PickSetRect(ptTL.x, ptTL.y, ptBR.x, ptBR.y);
                    851: 
                    852:             break;
                    853:     }
                    854: }
                    855: 
                    856: 
                    857: 
                    858: /******************************************************************************
                    859:  * VOID LineDP(hwnd, msg, ptNew)
                    860:  *
                    861:  * PURPOSE: Draw a straight line according to tracking line.
                    862:  *
                    863:  * PARAMS : HWND   hwnd : handle to dest. DC
                    864:  *          unsigned msg  : Upper left corner of rect;
                    865:  *          POINT  ptNew   : end pt. of line
                    866:  *
                    867:  * SIDE EFFECTS: may change bits in image DC
                    868:  *
                    869:  *****************************************************************************/
                    870: 
                    871: VOID LineDP(
                    872:     HWND hwnd,
                    873:     UINT msg,
                    874:     POINT ptNew)
                    875: {
                    876:     INT sx;
                    877:     INT sy;
                    878:     INT ex;
                    879:     INT ey;
                    880:     HPEN hpen;
                    881:     HPEN hpenOld;
                    882:     HBRUSH hbrOld;
                    883: 
                    884:     switch (msg) {
                    885:         case WM_RBUTTONDOWN:
                    886:         case WM_LBUTTONDOWN:
                    887:             StartRubberBanding(hwnd);
                    888:             RubberBandLine(TRUE);
                    889:             break;
                    890: 
                    891:         case WM_MOUSEMOVE:
                    892:             if (fRubberBanding)
                    893:                 RubberBandLine(FALSE);
                    894: 
                    895:             break;
                    896: 
                    897:         case WM_LBUTTONUP:
                    898:         case WM_RBUTTONUP:
                    899:             EndRubberBanding(hwnd);
                    900: 
                    901:             /* transform selected coordinates to those of actual image */
                    902:             sx = ptStart.x / gZoomFactor;
                    903:             sy = ptStart.y / gZoomFactor;
                    904:             ex = ptEnd.x / gZoomFactor;
                    905:             ey = ptEnd.y / gZoomFactor;
                    906: 
                    907:             hpenOld = SelectObject(ghdcImage, ghpenDraw);
                    908:             MoveToEx(ghdcImage, sx, sy, NULL);
                    909:             LineTo(ghdcImage, ex, ey);
                    910:             SelectObject(ghdcImage, hpenOld);
                    911: 
                    912:             if (giType != FT_BITMAP) {
                    913:                 /* for icons and cursors draw the line on the AND DC (memory)
                    914:                  * in black (if in color mode) or white (otherwise)
                    915:                  */
                    916:                 hpen = CreatePen(PS_INSIDEFRAME, 1,
                    917:                         (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
                    918:                 hpenOld = SelectObject(ghdcANDMask, hpen);
                    919:                 hbrOld = SelectObject(ghdcANDMask, GetStockObject(NULL_BRUSH));
                    920:                 MoveToEx(ghdcANDMask, sx, sy, NULL);
                    921:                 LineTo(ghdcANDMask, ex, ey);
                    922:                 SelectObject(ghdcANDMask, hbrOld);
                    923:                 SelectObject(ghdcANDMask, hpenOld);
                    924:                 DeleteObject(hpen);
                    925:             }
                    926: 
                    927:             /*
                    928:              * Because the LineTo function does not draw the ending
                    929:              * point, we must do it manually here.
                    930:              */
                    931:             DrawPoint(hwnd, &ptEnd, FALSE);
                    932: 
                    933:             fImageDirty = TRUE;
                    934: 
                    935:             ViewUpdate();
                    936: 
                    937:             break;
                    938:     }
                    939: }
                    940: 
                    941: 
                    942: 
                    943: /************************************************************************
                    944: * RubberBandLine
                    945: *
                    946: * This function erases the old line and draws the new tracking line
                    947: * when using the "Line" tool.
                    948: *
                    949: * Arguments:
                    950: *   BOOL fFirstTime - TRUE if starting to track the line (it doesn't
                    951: *                     need to erase the old line).
                    952: *
                    953: * History:
                    954: *
                    955: ************************************************************************/
                    956: 
                    957: STATICFN VOID NEAR RubberBandLine(
                    958:     BOOL fFirstTime)
                    959: {
                    960:     INT nOffset;
                    961: 
                    962:     /*
                    963:      * Set the raster-op to invert.
                    964:      */
                    965:     SetROP2(hdcRubberBand, R2_NOT);
                    966: 
                    967:     /*
                    968:      * If we are magnifying the image at all, the line needs to be
                    969:      * slightly offset so that it will be draw exactly in between
                    970:      * the grid lines.
                    971:      */
                    972:     if (gZoomFactor > 1)
                    973:         nOffset = -1;
                    974:     else
                    975:         nOffset = 0;
                    976: 
                    977:     if (!fFirstTime) {
                    978:         /*
                    979:          * Erase the old line.
                    980:          */
                    981:         
                    982: MoveToEx(hdcRubberBand, ptStart.x + (gZoomFactor / 2) + nOffset, ptStart.y + (gZoomFactor / 2) + nOffset, NULL);
                    983:         LineTo(hdcRubberBand, ptPrev.x + (gZoomFactor / 2) + nOffset,
                    984:                 ptPrev.y + (gZoomFactor / 2) + nOffset);
                    985:     }
                    986: 
                    987:     /*
                    988:      * Draw the new one.
                    989:      */
                    990:     
                    991: MoveToEx(hdcRubberBand, ptStart.x + (gZoomFactor / 2) + nOffset, ptStart.y + (gZoomFactor / 2) + nOffset, NULL);
                    992:     LineTo(hdcRubberBand, ptEnd.x + (gZoomFactor / 2) + nOffset,
                    993:             ptEnd.y + (gZoomFactor / 2) + nOffset);
                    994: }
                    995: 
                    996: 
                    997: 
                    998: /******************************************************************************
                    999:  * VOID RectDP(hwnd, msg, ptNew)
                   1000:  *
                   1001:  * PURPOSE: Draw a rectangle (filled/hollow) in the area specified
                   1002:  *
                   1003:  * PARAMS : HWND   hwnd : handle to dest. DC
                   1004:  *          WORD   msg  :
                   1005:  *          POINT  ptNew   : end pt. of line
                   1006:  *
                   1007:  * SIDE EFFECTS: may change bits in image DC
                   1008:  *
                   1009:  *****************************************************************************/
                   1010: 
                   1011: VOID RectDP(
                   1012:     HWND hwnd,
                   1013:     UINT msg,
                   1014:     POINT ptNew)
                   1015: {
                   1016:     switch (msg) {
                   1017:         case WM_RBUTTONDOWN:
                   1018:         case WM_LBUTTONDOWN:
                   1019:             StartRubberBanding(hwnd);
                   1020:             RubberBandRect(TRUE);
                   1021:             break;
                   1022: 
                   1023:         case WM_MOUSEMOVE:
                   1024:             if (fRubberBanding)
                   1025:                 RubberBandRect(FALSE);
                   1026: 
                   1027:             break;
                   1028: 
                   1029:         case WM_LBUTTONUP:
                   1030:         case WM_RBUTTONUP:
                   1031:             RectDPDraw(hwnd);
                   1032:             break;
                   1033:     }
                   1034: }
                   1035: 
                   1036: 
                   1037: 
                   1038: /************************************************************************
                   1039: * RectDPDraw
                   1040: *
                   1041: * Does the final drawing of a rectangle when using the Rectangle tool.
                   1042: *
                   1043: * Arguments:
                   1044: *   HWND hwnd - Window handle to the workspace.
                   1045: *
                   1046: * History:
                   1047: *
                   1048: ************************************************************************/
                   1049: 
                   1050: STATICFN VOID NEAR RectDPDraw(
                   1051:     HWND hwnd)
                   1052: {
                   1053:     POINT ptTL;         // Top-Left point.
                   1054:     POINT ptBR;         // Bottom-Right point
                   1055:     HBRUSH hbr;
                   1056:     HBRUSH hbrOld;
                   1057:     HPEN hpen;
                   1058:     HPEN hpenOld;
                   1059:     INT nOutset;
                   1060: 
                   1061:     EndRubberBanding(hwnd);
                   1062: 
                   1063:     /*
                   1064:      * Flip the points (if needed) and scale down.
                   1065:      */
                   1066:     ptTL = ptStart;
                   1067:     ptBR = ptEnd;
                   1068:     NormalizePoints(&ptTL, &ptBR);
                   1069:     ptTL.x /= gZoomFactor;
                   1070:     ptTL.y /= gZoomFactor;
                   1071:     ptBR.x /= gZoomFactor;
                   1072:     ptBR.y /= gZoomFactor;
                   1073: 
                   1074:     if (gCurTool == TOOL_RECT) {
                   1075:         hpen = ghpenDraw;
                   1076:         hbr = GetStockObject(NULL_BRUSH);
                   1077:         nOutset = 1;
                   1078:     }
                   1079:     else {
                   1080:         hpen = GetStockObject(NULL_PEN);
                   1081:         hbr = ghbrDraw;
                   1082:         nOutset = 2;
                   1083:     }
                   1084: 
                   1085:     hpenOld = SelectObject(ghdcImage, hpen);
                   1086:     hbrOld = SelectObject(ghdcImage, hbr);
                   1087:     Rectangle(ghdcImage, ptTL.x, ptTL.y,
                   1088:             ptBR.x + nOutset, ptBR.y + nOutset);
                   1089:     SelectObject(ghdcImage, hpenOld);
                   1090:     SelectObject(ghdcImage, hbrOld);
                   1091: 
                   1092:     if (giType != FT_BITMAP) {
                   1093:         /* for icons and cursors draw the shape on the AND DC (memory)
                   1094:          * in black (if in color mode) or white (otherwise)
                   1095:          */
                   1096:         if (gCurTool == TOOL_RECT) {
                   1097:             hpen = CreatePen(PS_INSIDEFRAME, 1,
                   1098:                     (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
                   1099:             hbr = GetStockObject(NULL_BRUSH);
                   1100:         }
                   1101:         else {
                   1102:             hpen = GetStockObject(NULL_PEN);
                   1103:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
                   1104:                     BLACK_BRUSH : WHITE_BRUSH);
                   1105:         }
                   1106: 
                   1107:         hpenOld = SelectObject(ghdcANDMask, hpen);
                   1108:         hbrOld = SelectObject(ghdcANDMask, hbr);
                   1109:         Rectangle(ghdcANDMask, ptTL.x, ptTL.y,
                   1110:                 ptBR.x + nOutset, ptBR.y + nOutset);
                   1111:         SelectObject(ghdcANDMask, hpenOld);
                   1112:         SelectObject(ghdcANDMask, hbrOld);
                   1113: 
                   1114:         if (gCurTool == TOOL_RECT)
                   1115:             DeleteObject(hpen);
                   1116:     }
                   1117: 
                   1118:     fImageDirty = TRUE;
                   1119: 
                   1120:     ViewUpdate();
                   1121: }
                   1122: 
                   1123: 
                   1124: 
                   1125: /******************************************************************************
                   1126:  * VOID PASCAL RubberBandRect()
                   1127:  *
                   1128:  * PURPOSE: Draw rubberbanding rect.
                   1129:  *
                   1130:  * PARAMS : HANDLE hDst : handle to dest. DC
                   1131:  *
                   1132:  *****************************************************************************/
                   1133: 
                   1134: STATICFN VOID NEAR RubberBandRect(
                   1135:     BOOL fFirstTime)
                   1136: {
                   1137:     POINT ptTL;         // Top-Left point.
                   1138:     POINT ptBR;         // Bottom-Right point
                   1139: 
                   1140:     /*
                   1141:      * Set the raster-op to invert.
                   1142:      */
                   1143:     SetROP2(hdcRubberBand, R2_NOT);
                   1144: 
                   1145:     if (!fFirstTime) {
                   1146:         /*
                   1147:          * Erase the old rectangle.
                   1148:          */
                   1149:         ptTL = ptStart;
                   1150:         ptBR = ptPrev;
                   1151:         NormalizePoints(&ptTL, &ptBR);
                   1152:         Rectangle(hdcRubberBand, ptTL.x, ptTL.y,
                   1153:                 ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
                   1154:     }
                   1155: 
                   1156: 
                   1157:     /*
                   1158:      * Draw the new one.
                   1159:      */
                   1160:     ptTL = ptStart;
                   1161:     ptBR = ptEnd;
                   1162:     NormalizePoints(&ptTL, &ptBR);
                   1163:     Rectangle(hdcRubberBand, ptTL.x, ptTL.y,
                   1164:             ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
                   1165: }
                   1166: 
                   1167: 
                   1168: 
                   1169: /******************************************************************************
                   1170:  * VOID CircleDP(hwnd, msg, ptNew)
                   1171:  *
                   1172:  * PURPOSE: Draw an ellipse (filled/hollow) in the area specified.
                   1173:  *
                   1174:  * PARAMS : HWND   hwnd : handle to dest. DC
                   1175:  *          unsigned msg  : Upper left corner of rect;
                   1176:  *          POINT  ptNew   : end pt. of line
                   1177:  *
                   1178:  * SIDE EFFECTS: may change bits in image DC
                   1179:  *
                   1180:  *****************************************************************************/
                   1181: 
                   1182: VOID CircleDP(
                   1183:     HWND hwnd,
                   1184:     UINT msg,
                   1185:     POINT ptNew)
                   1186: {
                   1187:     switch (msg) {
                   1188:         case WM_RBUTTONDOWN:
                   1189:         case WM_LBUTTONDOWN:
                   1190:             StartRubberBanding(hwnd);
                   1191:             RubberBandCircle(TRUE);
                   1192:             break;
                   1193: 
                   1194:         case WM_MOUSEMOVE:
                   1195:             if (fRubberBanding)
                   1196:                 RubberBandCircle(FALSE);
                   1197: 
                   1198:             break;
                   1199: 
                   1200:         case WM_LBUTTONUP:
                   1201:         case WM_RBUTTONUP:
                   1202:             CircleDPDraw(hwnd);
                   1203:             break;
                   1204:     }
                   1205: }
                   1206: 
                   1207: 
                   1208: 
                   1209: /************************************************************************
                   1210: * CircleDPDraw
                   1211: *
                   1212: * Does the final drawing of an ellipse when using the Ellipse tool.
                   1213: *
                   1214: * Arguments:
                   1215: *   HWND hwnd - Window handle to the workspace.
                   1216: *
                   1217: * History:
                   1218: *
                   1219: ************************************************************************/
                   1220: 
                   1221: STATICFN VOID NEAR CircleDPDraw(
                   1222:     HWND hwnd)
                   1223: {
                   1224:     POINT ptTL;         // Top-Left point.
                   1225:     POINT ptBR;         // Bottom-Right point
                   1226:     HBRUSH hbr;
                   1227:     HBRUSH hbrOld;
                   1228:     HPEN hpen;
                   1229:     HPEN hpenOld;
                   1230:     INT nOutset;
                   1231: 
                   1232:     EndRubberBanding(hwnd);
                   1233: 
                   1234:     /*
                   1235:      * Flip the points (if needed) and scale down.
                   1236:      */
                   1237:     ptTL = ptStart;
                   1238:     ptBR = ptEnd;
                   1239:     NormalizePoints(&ptTL, &ptBR);
                   1240:     ptTL.x /= gZoomFactor;
                   1241:     ptTL.y /= gZoomFactor;
                   1242:     ptBR.x /= gZoomFactor;
                   1243:     ptBR.y /= gZoomFactor;
                   1244: 
                   1245: #ifdef WIN16
                   1246:     /*
                   1247:      * The win 3.x code does not properly draw an ellipse if it
                   1248:      * has a NULL pen selected in (to not draw the border).  For
                   1249:      * this platform, we must select in the drawing pen.  This is
                   1250:      * not necessary for NT (we can use a NULL pen to avoid
                   1251:      * drawing the solid border).
                   1252:      */
                   1253: 
                   1254:     if (gCurTool == TOOL_CIRCLE)
                   1255:         hbr = GetStockObject(NULL_BRUSH);
                   1256:     else
                   1257:         hbr = ghbrDraw;
                   1258: 
                   1259:     hpenOld = SelectObject(ghdcImage, ghpenDraw);
                   1260:     hbrOld = SelectObject(ghdcImage, hbr);
                   1261:     Ellipse(ghdcImage, ptTL.x, ptTL.y, ptBR.x + 1, ptBR.y + 1);
                   1262:     SelectObject(ghdcImage, hbrOld);
                   1263:     SelectObject(ghdcImage, hpenOld);
                   1264: 
                   1265:     if (giType != FT_BITMAP) {
                   1266:         /* for icons and cursors draw the shape on the AND DC (memory)
                   1267:          * in black (if in color mode) or white (otherwise)
                   1268:          */
                   1269:         hpen = CreatePen(PS_INSIDEFRAME, 1,
                   1270:                 (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
                   1271: 
                   1272:         if (gCurTool == TOOL_CIRCLE)
                   1273:             hbr = GetStockObject(NULL_BRUSH);
                   1274:         else
                   1275:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
                   1276:                     BLACK_BRUSH : WHITE_BRUSH);
                   1277: 
                   1278:         hpenOld = SelectObject(ghdcANDMask, hpen);
                   1279:         hbrOld = SelectObject(ghdcANDMask, hbr);
                   1280:         Ellipse(ghdcANDMask, ptTL.x, ptTL.y, ptBR.x + 1, ptBR.y + 1);
                   1281:         SelectObject(ghdcANDMask, hpenOld);
                   1282:         SelectObject(ghdcANDMask, hbrOld);
                   1283:         DeleteObject(hpen);
                   1284:     }
                   1285: 
                   1286: #else
                   1287: 
                   1288:     if (gCurTool == TOOL_CIRCLE) {
                   1289:         hpen = ghpenDraw;
                   1290:         hbr = GetStockObject(NULL_BRUSH);
                   1291:         nOutset = 1;
                   1292:     }
                   1293:     else {
                   1294:         hpen = GetStockObject(NULL_PEN);
                   1295:         hbr = ghbrDraw;
                   1296:         nOutset = 2;
                   1297:     }
                   1298: 
                   1299:     hpenOld = SelectObject(ghdcImage, hpen);
                   1300:     hbrOld = SelectObject(ghdcImage, hbr);
                   1301:     Ellipse(ghdcImage, ptTL.x, ptTL.y, ptBR.x + nOutset, ptBR.y + nOutset);
                   1302:     SelectObject(ghdcImage, hpenOld);
                   1303:     SelectObject(ghdcImage, hbrOld);
                   1304: 
                   1305:     if (giType != FT_BITMAP) {
                   1306:         /* for icons and cursors draw the shape on the AND DC (memory)
                   1307:          * in black (if in color mode) or white (otherwise)
                   1308:          */
                   1309:         if (gCurTool == TOOL_CIRCLE) {
                   1310:             hpen = CreatePen(PS_INSIDEFRAME, 1,
                   1311:                     (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
                   1312:             hbr = GetStockObject(NULL_BRUSH);
                   1313:         }
                   1314:         else {
                   1315:             hpen = GetStockObject(NULL_PEN);
                   1316:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
                   1317:                     BLACK_BRUSH : WHITE_BRUSH);
                   1318:         }
                   1319: 
                   1320:         hpenOld = SelectObject(ghdcANDMask, hpen);
                   1321:         hbrOld = SelectObject(ghdcANDMask, hbr);
                   1322:         Ellipse(ghdcANDMask, ptTL.x, ptTL.y, ptBR.x + nOutset, ptBR.y + nOutset);
                   1323:         SelectObject(ghdcANDMask, hpenOld);
                   1324:         SelectObject(ghdcANDMask, hbrOld);
                   1325: 
                   1326:         if (gCurTool == TOOL_CIRCLE)
                   1327:             DeleteObject(hpen);
                   1328:     }
                   1329: 
                   1330: #endif
                   1331: 
                   1332:     fImageDirty = TRUE;
                   1333: 
                   1334:     ViewUpdate();
                   1335: }
                   1336: 
                   1337: 
                   1338: 
                   1339: /******************************************************************************
                   1340:  * VOID PASCAL RubberBandCircle()
                   1341:  *
                   1342:  * PURPOSE: Draw rubberbanding circle
                   1343:  *
                   1344:  *
                   1345:  *****************************************************************************/
                   1346: 
                   1347: STATICFN VOID NEAR RubberBandCircle(
                   1348:     BOOL fFirstTime)
                   1349: {
                   1350:     POINT ptTL;         // Top-Left point.
                   1351:     POINT ptBR;         // Bottom-Right point
                   1352: 
                   1353:     /*
                   1354:      * Set the raster-op to invert.
                   1355:      */
                   1356:     SetROP2(hdcRubberBand, R2_NOT);
                   1357: 
                   1358:     if (!fFirstTime) {
                   1359:         /*
                   1360:          * Erase the old circle.
                   1361:          */
                   1362:         ptTL = ptStart;
                   1363:         ptBR = ptPrev;
                   1364:         NormalizePoints(&ptTL, &ptBR);
                   1365:         Ellipse(hdcRubberBand, ptTL.x, ptTL.y,
                   1366:                 ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
                   1367:     }
                   1368: 
                   1369: 
                   1370:     /*
                   1371:      * Draw the new one.
                   1372:      */
                   1373:     ptTL = ptStart;
                   1374:     ptBR = ptEnd;
                   1375:     NormalizePoints(&ptTL, &ptBR);
                   1376:     Ellipse(hdcRubberBand, ptTL.x, ptTL.y,
                   1377:             ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
                   1378: }
                   1379: 
                   1380: 
                   1381: 
                   1382: /************************************************************************
                   1383: * FloodDP
                   1384: *
                   1385: *
                   1386: *
                   1387: * Arguments:
                   1388: *
                   1389: * History:
                   1390: *
                   1391: ************************************************************************/
                   1392: 
                   1393: VOID FloodDP(
                   1394:     HWND hwnd,
                   1395:     UINT msg,
                   1396:     POINT ptNew)
                   1397: {
                   1398:     HDC dc;
                   1399:     HDC bwdc;
                   1400:     HBRUSH hbrOld;
                   1401:     HBITMAP bwbit;
                   1402:     HCURSOR hcurSave;
                   1403: 
                   1404:     switch (msg) {
                   1405:         case WM_RBUTTONDOWN:
                   1406:         case WM_LBUTTONDOWN:
                   1407:             hcurSave = SetCursor(hcurWait);
                   1408: 
                   1409:             dc = GetDC(hwnd);
                   1410:             /* create temporary DC */
                   1411:             bwdc = CreateCompatibleDC(dc);
                   1412: 
                   1413:             /* create temporary monochrome bitmap */
                   1414:             if (!(bwbit = CreateBitmap(gcxImage, gcyImage, 1, 1, NULL))) {
                   1415:                 DeleteDC(bwdc);
                   1416:                 ReleaseDC(hwnd, dc);
                   1417:                 Message(MSG_OUTOFMEMORY);
                   1418:                 return;
                   1419:             }
                   1420:             SelectObject(bwdc, bwbit);
                   1421: 
                   1422:             /*  Set background color of image DC to desired floodfill color.*/
                   1423:             SetBkColor(ghdcImage,
                   1424:                     GetPixel(ghdcImage, (ptNew.x / gZoomFactor),
                   1425:                     (ptNew.y / gZoomFactor)));
                   1426: 
                   1427:             /******* OPERATION 0 ******/
                   1428:             /* First create a monochrome mask of the image after setting background
                   1429:              * color to the floodfill color. This will make the region to be
                   1430:              * flooded white(background), and it's boundary black (foreground) in the
                   1431:              * mask.
                   1432:              */
                   1433:             BitBlt(bwdc, 0, 0, gcxImage, gcyImage, ghdcImage, 0, 0, SRCCOPY);
                   1434: 
                   1435:             /******* OPERATION 1 ******/
                   1436:             /* floodfill selected region in mask (which is white bounded by black)
                   1437:              * with black.
                   1438:              */
                   1439:             SelectObject(bwdc, GetStockObject(BLACK_BRUSH));
                   1440:             ExtFloodFill(bwdc, ptNew.x / gZoomFactor,
                   1441:                     ptNew.y / gZoomFactor, RGB_BLACK, FLOODFILLBORDER);
                   1442: 
                   1443:             /******* OPERATION 2 ******/
                   1444:             /* Now XOR the original image on the mask , inverting the
                   1445:              * flood-filled pixels on mask (black --> white).
                   1446:              */
                   1447:             BitBlt(bwdc, 0, 0, gcxImage, gcyImage, ghdcImage, 0, 0, SRCINVERT);
                   1448: 
                   1449:             /* the AND mask needs to be updated only if in screen or inverse mode */
                   1450:             if ((giType == FT_CURSOR) || (giType == FT_ICON)) {
                   1451:                 if (gfDrawMode == MODE_COLOR) {
                   1452:                     SetBkColor(ghdcANDMask, RGB(0, 0, 0));
                   1453:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
                   1454:                             0, 0, ROP_DSna);
                   1455:                     SelectObject(ghdcANDMask, GetStockObject(BLACK_BRUSH));
                   1456:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
                   1457:                             0, 0, ROP_DSPao);
                   1458:                 }
                   1459:                 else {
                   1460:                     SetBkColor(ghdcANDMask, RGB(0xff, 0xff, 0xff));                    BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
                   1461:                             0, 0, ROP_DSna);
                   1462:                     SelectObject(ghdcANDMask, GetStockObject(WHITE_BRUSH));
                   1463:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
                   1464:                             0, 0, ROP_DSPao);
                   1465:                 }
                   1466:             }
                   1467: 
                   1468:             SetBkColor(ghdcImage, RGB_WHITE);
                   1469:             /****** OPERATION 3 ******/
                   1470:             /* The following operation turns the flooded area on-screen black,
                   1471:              * on the image, preserving the rest of the it.
                   1472:              */
                   1473:             BitBlt(ghdcImage, 0, 0, gcxImage, gcyImage, bwdc, 0, 0, ROP_DSna);
                   1474: 
                   1475:             /****** OPERATION 4 ******/
                   1476:             /* Rop_DSPao ANDs the pattern (current brush which is the floodfill
                   1477:              * color) on the source making flooded area (which was white as a
                   1478:              * result of operation 2 ) the current brush color, and keeps the rest
                   1479:              * of the source black. The source is then ORed into the original image
                   1480:              * (whose flooded area is black as a result of operation 3) to get
                   1481:              * the desired end result.
                   1482:              */
                   1483:             hbrOld = SelectObject(ghdcImage, ghbrDraw);
                   1484:             BitBlt(ghdcImage, 0, 0, gcxImage, gcyImage, bwdc, 0, 0, ROP_DSPao);
                   1485:             SelectObject(ghdcImage, hbrOld);
                   1486: 
                   1487:             /* clean up */
                   1488:             DeleteDC(bwdc);
                   1489:             DeleteObject(bwbit);
                   1490:             ReleaseDC(hwnd, dc);
                   1491: 
                   1492:             /*
                   1493:              * Mark the image as changed.
                   1494:              */
                   1495:             fImageDirty = TRUE;
                   1496: 
                   1497:             ViewUpdate();
                   1498: 
                   1499:             SetCursor(hcurSave);
                   1500: 
                   1501:             break;
                   1502:     }
                   1503: }
                   1504: 
                   1505: 
                   1506: 
                   1507: /******************************************************************************
                   1508:  * VOID HotSpotDP(hwnd, msg, ptNew)
                   1509:  *
                   1510:  * PURPOSE: Sets the hotspot.
                   1511:  *
                   1512:  * PARAMS : HWND   hwnd : handle to dest. DC
                   1513:  *          WORD   msg  :
                   1514:  *          POINT  ptNew   : end pt.
                   1515:  *
                   1516:  *****************************************************************************/
                   1517: 
                   1518: VOID HotSpotDP(
                   1519:     HWND hwnd,
                   1520:     UINT msg,
                   1521:     POINT ptNew)
                   1522: {
                   1523:     switch (msg) {
                   1524:         case WM_LBUTTONDOWN:
                   1525:             PropBarSetHotSpot(ptNew.x / gZoomFactor, ptNew.y / gZoomFactor);
                   1526:             break;
                   1527: 
                   1528:         case WM_MOUSEMOVE:
                   1529:             if (fDrawing && fLeftButtonDown)
                   1530:                 PropBarSetHotSpot(ptNew.x / gZoomFactor,
                   1531:                         ptNew.y / gZoomFactor);
                   1532: 
                   1533:             break;
                   1534: 
                   1535:         case WM_LBUTTONUP:
                   1536:             MarkHotSpotPosition(ptNew.x / gZoomFactor, ptNew.y / gZoomFactor);
                   1537:             break;
                   1538:     }
                   1539: }
                   1540: 
                   1541: 
                   1542: 
                   1543: /************************************************************************
                   1544: * MarkHotSpotPosition
                   1545: *
                   1546: * Updates the hotspot location in the currently selected cursor image.
                   1547: *
                   1548: * Arguments:
                   1549: *
                   1550: * History:
                   1551: *
                   1552: ************************************************************************/
                   1553: 
                   1554: STATICFN VOID NEAR MarkHotSpotPosition(
                   1555:     INT x,
                   1556:     INT y)
                   1557: {
                   1558:     gpImageCur->iHotspotX = x;
                   1559:     gpImageCur->iHotspotY = y;
                   1560:     PropBarSetHotSpot(x, y);
                   1561: 
                   1562:     /*
                   1563:      * Mark the image as changed.
                   1564:      */
                   1565:     fImageDirty = TRUE;
                   1566: }
                   1567: 
                   1568: 
                   1569: 
                   1570: /******************************************************************************
                   1571:  * NormalizePoints
                   1572:  *
                   1573:  * PURPOSE : interchange start and end pts
                   1574:  *           if start point is > end point.
                   1575:  *
                   1576:  *****************************************************************************/
                   1577: 
                   1578: VOID NormalizePoints(
                   1579:     PPOINT pptStart,
                   1580:     PPOINT pptEnd)
                   1581: {
                   1582:     INT n;
                   1583: 
                   1584:     if (pptStart->x > pptEnd->x) {
                   1585:         n = pptEnd->x;
                   1586:         pptEnd->x = pptStart->x;
                   1587:         pptStart->x = n;
                   1588:     }
                   1589: 
                   1590:     if (pptStart->y > pptEnd->y) {
                   1591:         n = pptEnd->y;
                   1592:         pptEnd->y = pptStart->y;
                   1593:         pptStart->y = n;
                   1594:     }
                   1595: }
                   1596: 
                   1597: 
                   1598: 
                   1599: /******************************************************************************
                   1600:  * HDC PASCAL StartRubberBanding(hwnd)
                   1601:  *
                   1602:  * PURPOSE: Sets up rubberbanding for all tools.
                   1603:  *
                   1604:  * PARAMS : HANDLE hDst : handle to box DC
                   1605:  *
                   1606:  * RETURNS :handle to destination display context
                   1607:  *
                   1608:  * SIDE EFFECTS: alters a few global flags for tracking
                   1609:  *
                   1610:  *****************************************************************************/
                   1611: 
                   1612: STATICFN VOID NEAR StartRubberBanding(
                   1613:     HWND hwnd)
                   1614: {
                   1615:     hdcRubberBand = GetDC(hwnd);
                   1616: 
                   1617:     /*
                   1618:      * Select a white pen, and a null brush (prevents drawing the
                   1619:      * interior of rectangles and ellipses).
                   1620:      */
                   1621:     SelectObject(hdcRubberBand, GetStockObject(WHITE_PEN));
                   1622:     SelectObject(hdcRubberBand, GetStockObject(NULL_BRUSH));
                   1623: 
                   1624:     fRubberBanding = TRUE;
                   1625: }
                   1626: 
                   1627: 
                   1628: 
                   1629: /******************************************************************************
                   1630:  * VOID PASCAL EndRubberBanding()
                   1631:  *
                   1632:  * PURPOSE: Stops rubberbanding rect. and cleans up
                   1633:  *
                   1634:  *****************************************************************************/
                   1635: 
                   1636: STATICFN VOID NEAR EndRubberBanding(
                   1637:     HWND hwnd)
                   1638: {
                   1639:     ReleaseDC(hwnd, hdcRubberBand);
                   1640:     fRubberBanding = FALSE;
                   1641: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.