/******************************Module*Header*******************************\ * Module Name: rleblt.c * * Blt from RLE format bitmap to VGA. * * Copyright (c) 1992-1995 Microsoft Corporation \**************************************************************************/ #include "driver.h" #include "bitblt.h" typedef struct _RLEINFO { PBYTE pjTrg; PBYTE pjSrc; PBYTE pjSrcEnd; PRECTL prclClip; PULONG pulXlate; LONG xBegin; ULONG lNextScan; // Offset to the next scan line - DDB Only. ULONG lNextPlane; // Offset to the next plane - DDB Only. PRECTL prclTrg; DWORD Format; PDEVSURF pdsurfTrg; }RLEINFO, *PRLEINFO; VOID vRle8ToVga(PRLEINFO); VOID vRle4ToVga(PRLEINFO); BOOL DrvIntersectRect(PRECTL, PRECTL, PRECTL); typedef VOID (*PFN_RleToVga)(PRLEINFO); /******************************Public*Routine******************************\ * BOOL bRleBlt(*psoTrg, *psoSrc, *pco, *pxlo, *prclTrg, *pptlSrc) * * Blt from RLE format bitmap to VGA. * \**************************************************************************/ BOOL bRleBlt ( SURFOBJ *psoTrg, // Target surface SURFOBJ *psoSrc, // Source surface CLIPOBJ *pco, // Clip through this XLATEOBJ *pxlo, // Color translation RECTL *prclTrg, // Target offset and extent POINTL *pptlSrc // Source offset ) { BOOL bMore; // Clip continuation flag ULONG ircl; // Clip enumeration rectangle index RECT_ENUM bben; // Clip enumerator PFN_RleToVga pfnRleToVga; // Pointer to either Rle8ToVga or Rle4ToVga PDEVSURF pdsurf; RECTL rclTrg; PDEV *ppdevTrg; RLEINFO rleInfo; PRECTL prcl; // Pointer to the current cliprect PRECTL prclNext; // Pointer to the next cliprect PBYTE pjTrgTmp; // For saving fields in rleInfo. PBYTE pjSrcTmp; LONG lTrgBottomTmp; LONG xBeginTmp; ULONG aulTriv[16]; // In case a null pxlo is passed in int x; // Get the target surface information. This is guaranteed to be a device // surface or a device format bitmap. pdsurf = (PDEVSURF) psoTrg->dhsurf; ppdevTrg = pdsurf->ppdev; // Get the source surface information. Common to the screen and DFB's rleInfo.pjSrc = psoSrc->pvBits; rleInfo.pjSrcEnd = (PBYTE)(psoSrc->pvBits) + (psoSrc->cjBits); // Determine if color translation is required. If so, then get the color // translation vector. if (!pxlo) { for (x = 0; x < 16; x++) aulTriv[x] = x; rleInfo.pulXlate = &aulTriv[0]; } else { rleInfo.pulXlate = pxlo->pulXlate; } // Enlarge the destination rectangle to include area that would have to be // drawn if ptlSrc is (0, 0). rclTrg.left = prclTrg->left - pptlSrc->x; rclTrg.top = prclTrg->top; rclTrg.right = prclTrg->right; rclTrg.bottom = prclTrg->top + psoSrc->sizlBitmap.cy - pptlSrc->y; rleInfo.prclTrg = &rclTrg; rleInfo.xBegin = rclTrg.left; // Calculate our starting address in the bitmap & get our blt function // First (bottom) dest scan, *exclusive* // Offset within bitmap of first (bottom) dest scan, *inclusive* rleInfo.pjTrg = (PBYTE) ((rclTrg.bottom - 1) * pdsurf->lNextScan); rleInfo.pdsurfTrg = pdsurf; if (psoSrc->iBitmapFormat == BMF_8RLE) pfnRleToVga = vRle8ToVga; else pfnRleToVga = vRle4ToVga; // Everything is ready. Let's go draw on the VGA. Shooby Doobie Doo. Whee. switch(pco->iDComplexity) { case DC_TRIVIAL: rleInfo.prclClip = prclTrg; pfnRleToVga(&rleInfo); break; case DC_RECT: rleInfo.prclClip = &pco->rclBounds; pfnRleToVga(&rleInfo); break; case DC_COMPLEX: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTUP, ENUM_RECT_LIMIT); do { // Fill n slots with (n - 1) rectangles. bMore = CLIPOBJ_bEnum(pco,(ULONG) (sizeof(bben) - sizeof(RECT)), (PVOID) &bben); // Force save and restore rleInfo for the last rect. bben.arcl[bben.c].bottom = bben.arcl[bben.c - 1].bottom; for (ircl = 0; ircl < bben.c; ircl++) { prcl = &bben.arcl[ircl]; // If the clipping rect is above the target rect, don't // enumerate any more clipprect. Since the direction of // enumeration is bottom up, nothing is visible in new cliprect. if (prcl->bottom <= rleInfo.prclTrg->top) { break; bMore = FALSE; } // We check for NULL or inverted rectanges because we may get them. if ((prcl->top < prcl->bottom) && (prcl->left < prcl->right)) { rleInfo.prclClip = prcl; prclNext = &bben.arcl[ircl + 1]; // Pass the same rleInfo for next cliprect if the next // cliprect is on the same scan as the current cliprect if (prcl->bottom == prclNext->bottom) { // save rleInfo. pjTrgTmp = rleInfo.pjTrg; pjSrcTmp = rleInfo.pjSrc; lTrgBottomTmp = rleInfo.prclTrg->bottom; xBeginTmp = rleInfo.xBegin; pfnRleToVga(&rleInfo); // restore rleinfo rleInfo.pjTrg = pjTrgTmp; rleInfo.pjSrc = pjSrcTmp; rleInfo.prclTrg->bottom = lTrgBottomTmp; rleInfo.xBegin = xBeginTmp; } else { pfnRleToVga(&rleInfo); } } } } while(bMore); //DbgBreakPoint(); break; default: RIP("ERROR bRleBlt invalid clip complexity\n"); return(FALSE); } return(TRUE); }