static void MyAddDirtyRect (MIOWinInfoPtr pmInfoPtr, MYRECT pmRect) { MYRECTLIST *myDirtyRect, *myLastDirtyRect, *myNewRect; MYRECT myWindowRect; myWindowRect.left = 0; myWindowRect.top = 0; myWindowRect.right = pmInfoPtr -> width - 1; myWindowRect.bottom = pmInfoPtr -> height - 1; if (!MIO_RectanglesSetIntersect (&pmRect, &myWindowRect)) { return; } myDirtyRect = pmInfoPtr -> dirtyRectHead; while (myDirtyRect != NULL) { if (MIO_RectanglesIntersect (&myDirtyRect -> rect, &pmRect)) { // There is an intersection. Replace the new rectangle with // a union of the two and remove this rectangle from the // dirty list. Then start at the beginniong MIO_RectanglesUnion (&pmRect, &myDirtyRect -> rect); if (pmInfoPtr -> dirtyRectHead == myDirtyRect) { pmInfoPtr -> dirtyRectHead = myDirtyRect -> next; } else { myLastDirtyRect -> next = myDirtyRect -> next; } free (myDirtyRect); myLastDirtyRect = myDirtyRect; myDirtyRect = pmInfoPtr -> dirtyRectHead; } else { myLastDirtyRect = myDirtyRect; myDirtyRect = myDirtyRect -> next; } } // Add the new rect to the beginning of the list myNewRect = (MYRECTLIST *) malloc (sizeof (MYRECTLIST)); myNewRect -> rect = pmRect; myNewRect -> next = pmInfoPtr -> dirtyRectHead; pmInfoPtr -> dirtyRectHead = myNewRect; } // MyAddDirtyRect
void MDIOSprite_UpdateWindow (MIOWinInfoPtr pmInfoPtr, BOOL pmCopyToOffscreen) { MYRECTLIST *myDirtyRect, *myNextDirtyRect; MYRECT myRect; SpriteInfo *mySpritePtr; BOOL mySpriteNotDrawn, myBackgroundNotDrawn; int myWidth, myHeight; //int gdiRes, userRes, gdiRes1, userRes1; //gdiRes = GetGuiResources (GetCurrentProcess(), GR_GDIOBJECTS); //userRes = GetGuiResources (GetCurrentProcess(), GR_USEROBJECTS); myDirtyRect = pmInfoPtr -> dirtyRectHead; // Set up the window. // TW // Now, if there are no items that are behind the offscreen window (i.e. // all sprites have positive height), then simply do a copy of the // offscreen window. However, if there are, then we start by filling // the entire area with the transparent colour of the offscreen window, // then drawing the non-postive height sprites in MERGE mode, then drawing // the offscreen window in MERGE mode, then drawing the rest of the // sprites in MERGE mode. while (myDirtyRect != NULL) { myRect = myDirtyRect -> rect; // Convert from Turing coordinates to Windows coordinates myWidth = myRect.right - myRect.left; myHeight = myRect.bottom - myRect.top; // Now draw each sprite mySpritePtr = (SpriteInfo *) (pmInfoPtr -> spriteQueueHead); mySpriteNotDrawn = TRUE; myBackgroundNotDrawn = TRUE; while (mySpritePtr != NULL) { // If the sprite is not visible or does not intersect with the // dirty rectangle, ignore it. if ((!mySpritePtr -> visible) || !MIO_RectanglesIntersect (&myDirtyRect -> rect, &mySpritePtr -> spriteRect)) { // Sprite not visible or doesn't intersect, don't draw it! mySpritePtr = mySpritePtr -> next; continue; } // If we haven't drawn a sprite before we either have to draw the // offscreen window (if the first sprite's height is positive, // or just fill the sprite space with the transparent colour). if (mySpriteNotDrawn) { if (mySpritePtr -> spriteHeight >= 0) { // The lowest sprite is above the background. Draw the // background using COPY BitBlt (pmInfoPtr -> spriteDeviceContext, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> offscreenDeviceContext, myRect.left, myRect.top, SRCCOPY); myBackgroundNotDrawn = FALSE; } else { // Fill the background with the offscreen window's // transparent color HPEN myNewPen, myOldPen; HBRUSH myNewBrush, myOldBrush; COLORREF myTransparentColour; myTransparentColour = (COLORREF) MIORGB_ConvertColour ( pmInfoPtr -> transparentColour); myNewPen = CreatePen (PS_SOLID, 1, myTransparentColour); myNewBrush = CreateSolidBrush (myTransparentColour); myOldPen = SelectPen (pmInfoPtr -> spriteDeviceContext, myNewPen); myOldBrush = SelectBrush (pmInfoPtr -> spriteDeviceContext, myNewBrush); Rectangle (pmInfoPtr -> spriteDeviceContext, myRect.left, myRect.top, myRect.right + 1, myRect.bottom + 1); SelectBrush (pmInfoPtr -> spriteDeviceContext, myOldBrush); DeleteBrush (myNewBrush); SelectPen (pmInfoPtr -> spriteDeviceContext, myOldPen); DeletePen (myNewPen); } mySpriteNotDrawn = FALSE; } else { // If we haven't drawn the background before, and this sprite // is above the background (height >= 0), then its time to // draw the background in MERGE mode if (myBackgroundNotDrawn && (mySpritePtr -> spriteHeight >= 0)) { MDIOPic_SpriteDraw (pmInfoPtr, NULL, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> transparentColour); myBackgroundNotDrawn = FALSE; } } // Draw Sprite MDIOPic_SpriteDraw (pmInfoPtr, mySpritePtr -> picMDPicInfo, mySpritePtr -> x, mySpritePtr -> y, mySpritePtr -> picWidth, mySpritePtr -> picHeight, mySpritePtr -> picTransparentColour); mySpritePtr = mySpritePtr -> next; } // If we still haven't drawn the background after having drawn all the // sprites, then it is time to draw the background. If we've drawn // any sprites above, then the background has already been drawn, and // we draw in MERGE mode. If we haven't drawn a sprite, then we draw // the background in copy mode. if (myBackgroundNotDrawn) { if (mySpriteNotDrawn) { BitBlt (pmInfoPtr -> spriteDeviceContext, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> offscreenDeviceContext, myRect.left, myRect.top, SRCCOPY); } else { MDIOPic_SpriteDraw (pmInfoPtr, NULL, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> transparentColour); } myBackgroundNotDrawn = FALSE; } // Finally, draw the completed sprite surface to the on-screen window. BitBlt (pmInfoPtr -> deviceContext, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> spriteDeviceContext, myRect.left, myRect.top, SRCCOPY); // Okay, if pmCopyToOffscreen is true, then copy all of this to the // offscreen bitmap as well. This is used when Turing is finished and // the sprites are about to be deallocated. if (pmCopyToOffscreen) { BitBlt (pmInfoPtr -> offscreenDeviceContext, myRect.left, myRect.top, myWidth, myHeight, pmInfoPtr -> spriteDeviceContext, myRect.left, myRect.top, SRCCOPY); } // Free the current dirty rect and get the next dirty rectangle. myNextDirtyRect = myDirtyRect -> next; free (myDirtyRect); myDirtyRect = myNextDirtyRect; } // while pmInfoPtr -> dirtyRectHead = NULL; //gdiRes1 = GetGuiResources (GetCurrentProcess(), GR_GDIOBJECTS); //userRes1 = GetGuiResources (GetCurrentProcess(), GR_USEROBJECTS); } // MDIOSprite_UpdateWindow