1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: GDI EngCopyBits Function 5 * FILE: win32ss/gdi/eng/copybits.c 6 * PROGRAMERS: Jason Filby 7 * Doug Lyons 8 */ 9 10 #include <win32k.h> 11 12 #define NDEBUG 13 #include <debug.h> 14 15 /* 16 * @implemented 17 */ 18 BOOL APIENTRY 19 EngCopyBits( 20 _In_ SURFOBJ *psoDest, 21 _In_ SURFOBJ *psoSource, 22 _In_opt_ CLIPOBJ *Clip, 23 _In_opt_ XLATEOBJ *ColorTranslation, 24 _In_ RECTL *DestRect, 25 _In_ POINTL *SourcePoint) 26 { 27 BOOL ret; 28 BYTE clippingType; 29 RECT_ENUM RectEnum; 30 BOOL EnumMore; 31 BLTINFO BltInfo; 32 SURFACE *psurfDest; 33 SURFACE *psurfSource; 34 RECTL rclDest = *DestRect; 35 POINTL ptlSrc = *SourcePoint; 36 LONG lTmp; 37 BOOL bTopToBottom; 38 39 DPRINT("Entering EngCopyBits with SourcePoint (%d,%d) and DestRect (%d,%d)-(%d,%d).\n", 40 SourcePoint->x, SourcePoint->y, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); 41 42 DPRINT("psoSource cx/cy is %d/%d and psoDest cx/cy is %d/%d.\n", 43 psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy); 44 45 /* Retrieve Top Down/flip here and then make Well-Ordered again */ 46 if (DestRect->top > DestRect->bottom) 47 { 48 bTopToBottom = TRUE; 49 lTmp = DestRect->top; 50 DestRect->top = DestRect->bottom; 51 DestRect->bottom = lTmp; 52 rclDest = *DestRect; 53 } 54 else 55 { 56 bTopToBottom = FALSE; 57 } 58 59 DPRINT("bTopToBottom is '%d'.\n", bTopToBottom); 60 61 ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL); 62 63 psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); 64 psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); 65 66 /* Clip dest rect against source surface size / source point */ 67 if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left) 68 rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x; 69 if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top) 70 rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y; 71 72 /* Clip dest rect against target surface size */ 73 if (rclDest.right > psoDest->sizlBitmap.cx) 74 rclDest.right = psoDest->sizlBitmap.cx; 75 if (rclDest.bottom > psoDest->sizlBitmap.cy) 76 rclDest.bottom = psoDest->sizlBitmap.cy; 77 if (RECTL_bIsEmptyRect(&rclDest)) return TRUE; 78 DestRect = &rclDest; 79 80 // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead, 81 // mark the copy block function to be DrvCopyBits instead of the 82 // GDI's copy bit function so as to remove clipping from the 83 // driver's responsibility 84 85 // If one of the surfaces isn't managed by the GDI 86 if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP)) 87 { 88 // Destination surface is device managed 89 if (psoDest->iType!=STYPE_BITMAP) 90 { 91 /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ 92 if (psurfDest->flags & HOOK_COPYBITS) 93 { 94 ret = GDIDEVFUNCS(psoDest).CopyBits( 95 psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); 96 97 goto cleanup; 98 } 99 } 100 101 // Source surface is device managed 102 if (psoSource->iType!=STYPE_BITMAP) 103 { 104 /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ 105 if (psurfSource->flags & HOOK_COPYBITS) 106 { 107 ret = GDIDEVFUNCS(psoSource).CopyBits( 108 psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); 109 110 goto cleanup; 111 } 112 } 113 114 // If CopyBits wasn't hooked, BitBlt must be 115 ret = IntEngBitBlt(psoDest, psoSource, 116 NULL, Clip, ColorTranslation, DestRect, SourcePoint, 117 NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); 118 119 goto cleanup; 120 } 121 122 // Determine clipping type 123 if (!Clip) 124 { 125 clippingType = DC_TRIVIAL; 126 } 127 else 128 { 129 clippingType = Clip->iDComplexity; 130 } 131 132 BltInfo.DestSurface = psoDest; 133 BltInfo.SourceSurface = psoSource; 134 BltInfo.PatternSurface = NULL; 135 BltInfo.XlateSourceToDest = ColorTranslation; 136 BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY); 137 138 switch (clippingType) 139 { 140 case DC_TRIVIAL: 141 DPRINT("DC_TRIVIAL.\n"); 142 BltInfo.DestRect = *DestRect; 143 BltInfo.SourcePoint = *SourcePoint; 144 145 /* Now we set the Dest Rect top and bottom based on Top Down/flip */ 146 if (bTopToBottom) 147 { 148 lTmp = BltInfo.DestRect.top; 149 BltInfo.DestRect.top = BltInfo.DestRect.bottom; 150 BltInfo.DestRect.bottom = lTmp; 151 } 152 153 ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); 154 break; 155 156 case DC_RECT: 157 DPRINT("DC_RECT.\n"); 158 // Clip the blt to the clip rectangle 159 RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds); 160 161 BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; 162 BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; 163 164 /* Now we set the Dest Rect top and bottom based on Top Down/flip */ 165 if (bTopToBottom) 166 { 167 lTmp = BltInfo.DestRect.top; 168 BltInfo.DestRect.top = BltInfo.DestRect.bottom; 169 BltInfo.DestRect.bottom = lTmp; 170 } 171 172 ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); 173 break; 174 175 case DC_COMPLEX: 176 DPRINT("DC_COMPLEX.\n"); 177 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0); 178 179 do 180 { 181 EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 182 183 if (RectEnum.c > 0) 184 { 185 RECTL* prclEnd = &RectEnum.arcl[RectEnum.c]; 186 RECTL* prcl = &RectEnum.arcl[0]; 187 188 do 189 { 190 RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect); 191 192 BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; 193 BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; 194 195 /* Now we set the Dest Rect top and bottom based on Top Down/flip */ 196 if (bTopToBottom) 197 { 198 lTmp = BltInfo.DestRect.top; 199 BltInfo.DestRect.top = BltInfo.DestRect.bottom; 200 BltInfo.DestRect.bottom = lTmp; 201 } 202 203 if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo)) 204 { 205 ret = FALSE; 206 goto cleanup; 207 } 208 209 prcl++; 210 211 } while (prcl < prclEnd); 212 } 213 214 } while (EnumMore); 215 ret = TRUE; 216 break; 217 218 default: 219 ASSERT(FALSE); 220 ret = FALSE; 221 break; 222 } 223 224 cleanup: 225 return ret; 226 } 227 228 BOOL APIENTRY 229 IntEngCopyBits( 230 SURFOBJ *psoDest, 231 SURFOBJ *psoSource, 232 CLIPOBJ *pco, 233 XLATEOBJ *pxlo, 234 RECTL *prclDest, 235 POINTL *ptlSource) 236 { 237 return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource); 238 } 239 240 241 /* EOF */ 242