📄 dib.c
字号:
xsrc.left = 0; xsrc.right = sdesc.dwWidth; } else { memset(&xsrc,0,sizeof(xsrc)); } } /* First check for the validity of source / destination rectangles. This was verified using a test application + by MSDN. */ if ((src != NULL) && ((xsrc.bottom > sdesc.dwHeight) || (xsrc.bottom < 0) || (xsrc.top > sdesc.dwHeight) || (xsrc.top < 0) || (xsrc.left > sdesc.dwWidth) || (xsrc.left < 0) || (xsrc.right > sdesc.dwWidth) || (xsrc.right < 0) || (xsrc.right < xsrc.left) || (xsrc.bottom < xsrc.top))) { WARN("Application gave us bad source rectangle for Blt.\n"); return DDERR_INVALIDRECT; } /* For the Destination rect, it can be out of bounds on the condition that a clipper is set for the given surface. */ if ((This->clipper == NULL) && ((xdst.bottom > ddesc.dwHeight) || (xdst.bottom < 0) || (xdst.top > ddesc.dwHeight) || (xdst.top < 0) || (xdst.left > ddesc.dwWidth) || (xdst.left < 0) || (xdst.right > ddesc.dwWidth) || (xdst.right < 0) || (xdst.right < xdst.left) || (xdst.bottom < xdst.top))) { WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); return DDERR_INVALIDRECT; } /* Now handle negative values in the rectangles. Warning: only supported for now in the 'simple' cases (ie not in any stretching / rotation cases). First, the case where nothing is to be done. */ if (((xdst.bottom <= 0) || (xdst.right <= 0) || (xdst.top >= (int) ddesc.dwHeight) || (xdst.left >= (int) ddesc.dwWidth)) || ((src != NULL) && ((xsrc.bottom <= 0) || (xsrc.right <= 0) || (xsrc.top >= (int) sdesc.dwHeight) || (xsrc.left >= (int) sdesc.dwWidth)))) { TRACE("Nothing to be done !\n"); goto release; } /* The easy case : the source-less blits.... */ if (src == NULL) { RECT full_rect; RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */ full_rect.left = 0; full_rect.top = 0; full_rect.right = ddesc.dwWidth; full_rect.bottom = ddesc.dwHeight; IntersectRect(&temp_rect, &full_rect, &xdst); xdst = temp_rect; } else { /* Only handle clipping on the destination rectangle */ int clip_horiz = (xdst.left < 0) || (xdst.right > (int) ddesc.dwWidth ); int clip_vert = (xdst.top < 0) || (xdst.bottom > (int) ddesc.dwHeight); if (clip_vert || clip_horiz) { /* Now check if this is a special case or not... */ if ((((xdst.bottom - xdst.top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || (((xdst.right - xdst.left) != (xsrc.right - xsrc.left)) && clip_horiz) || (dwFlags & DDBLT_DDFX)) { WARN("Out of screen rectangle in special case. Not handled right now.\n"); goto release; } if (clip_horiz) { if (xdst.left < 0) { xsrc.left -= xdst.left; xdst.left = 0; } if (xdst.right > ddesc.dwWidth) { xsrc.right -= (xdst.right - (int) ddesc.dwWidth); xdst.right = (int) ddesc.dwWidth; } } if (clip_vert) { if (xdst.top < 0) { xsrc.top -= xdst.top; xdst.top = 0; } if (xdst.bottom > ddesc.dwHeight) { xsrc.bottom -= (xdst.bottom - (int) ddesc.dwHeight); xdst.bottom = (int) ddesc.dwHeight; } } /* And check if after clipping something is still to be done... */ if ((xdst.bottom <= 0) || (xdst.right <= 0) || (xdst.top >= (int) ddesc.dwHeight) || (xdst.left >= (int) ddesc.dwWidth) || (xsrc.bottom <= 0) || (xsrc.right <= 0) || (xsrc.top >= (int) sdesc.dwHeight) || (xsrc.left >= (int) sdesc.dwWidth)) { TRACE("Nothing to be done after clipping !\n"); goto release; } } } bpp = GET_BPP(ddesc); srcheight = xsrc.bottom - xsrc.top; srcwidth = xsrc.right - xsrc.left; dstheight = xdst.bottom - xdst.top; dstwidth = xdst.right - xdst.left; width = (xdst.right - xdst.left) * bpp; assert(width <= ddesc.u1.lPitch); dbuf = (BYTE*)ddesc.lpSurface+(xdst.top*ddesc.u1.lPitch)+(xdst.left*bpp); if (dwFlags & (DDBLT_WAIT|DDBLT_ASYNC)) { static BOOL displayed = FALSE; if (!displayed) { FIXME("dwFlags DDBLT_WAIT and/or DDBLT_ASYNC: can't handle right now.\n"); displayed = TRUE; } dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC); } /* First, all the 'source-less' blits */ if (dwFlags & DDBLT_COLORFILL) { ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, ddesc.u1.lPitch, lpbltfx->u5.dwFillColor); dwFlags &= ~DDBLT_COLORFILL; } if (dwFlags & DDBLT_DEPTHFILL) FIXME("DDBLT_DEPTHFILL needs to be implemented!\n"); if (dwFlags & DDBLT_ROP) { /* Catch some degenerate cases here */ switch(lpbltfx->dwROP) { case BLACKNESS: ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,0); break; case 0xAA0029: /* No-op */ break; case WHITENESS: ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,~0); break; case SRCCOPY: /* well, we do that below ? */ break; default: FIXME("Unsupported raster op: %08lx Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u5.lpDDSPattern); goto error; } dwFlags &= ~DDBLT_ROP; } if (dwFlags & DDBLT_DDROPS) { FIXME("\tDdraw Raster Ops: %08lx Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern); } /* Now the 'with source' blits */ if (src) { LPBYTE sbase; int sx, xinc, sy, yinc; if (!dstwidth || !dstheight) /* hmm... stupid program ? */ goto release; sbase = (BYTE*)sdesc.lpSurface+(xsrc.top*sdesc.u1.lPitch)+xsrc.left*bpp; xinc = (srcwidth << 16) / dstwidth; yinc = (srcheight << 16) / dstheight; if (!dwFlags) { /* No effects, we can cheat here */ if (dstwidth == srcwidth) { if (dstheight == srcheight) { /* No stretching in either direction. This needs to be as * fast as possible */ sbuf = sbase; /* check for overlapping surfaces */ if (src != iface || xdst.top < xsrc.top || xdst.right <= xsrc.left || xsrc.right <= xdst.left) { /* no overlap, or dst above src, so copy from top downwards */ for (y = 0; y < dstheight; y++) { memcpy(dbuf, sbuf, width); sbuf += sdesc.u1.lPitch; dbuf += ddesc.u1.lPitch; } } else if (xdst.top > xsrc.top) /* copy from bottom upwards */ { sbuf += (sdesc.u1.lPitch*dstheight); dbuf += (ddesc.u1.lPitch*dstheight); for (y = 0; y < dstheight; y++) { sbuf -= sdesc.u1.lPitch; dbuf -= ddesc.u1.lPitch; memcpy(dbuf, sbuf, width); } } else /* src and dst overlapping on the same line, use memmove */ { for (y = 0; y < dstheight; y++) { memmove(dbuf, sbuf, width); sbuf += sdesc.u1.lPitch; dbuf += ddesc.u1.lPitch; } } } else { /* Stretching in Y direction only */ for (y = sy = 0; y < dstheight; y++, sy += yinc) { sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch; memcpy(dbuf, sbuf, width); dbuf += ddesc.u1.lPitch; } } } else { /* Stretching in X direction */ int last_sy = -1; for (y = sy = 0; y < dstheight; y++, sy += yinc) { sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch; if ((sy >> 16) == (last_sy >> 16)) { /* this sourcerow is the same as last sourcerow - * copy already stretched row */ memcpy(dbuf, dbuf - ddesc.u1.lPitch, width); } else {#define STRETCH_ROW(type) { \ type *s = (type *) sbuf, *d = (type *) dbuf; \ for (x = sx = 0; x < dstwidth; x++, sx += xinc) \ d[x] = s[sx >> 16]; \ break; } switch(bpp) { case 1: STRETCH_ROW(BYTE) case 2: STRETCH_ROW(WORD) case 4: STRETCH_ROW(DWORD) case 3: { LPBYTE s,d = dbuf; for (x = sx = 0; x < dstwidth; x++, sx+= xinc) { DWORD pixel; s = sbuf+3*(sx>>16); pixel = s[0]|(s[1]<<8)|(s[2]<<16); d[0] = (pixel )&0xff; d[1] = (pixel>> 8)&0xff; d[2] = (pixel>>16)&0xff; d+=3; } break; } default: FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8); ret = DDERR_UNSUPPORTED; goto error; }#undef STRETCH_ROW } dbuf += ddesc.u1.lPitch; last_sy = sy; } } } else { LONG dstyinc = ddesc.u1.lPitch, dstxinc = bpp; DWORD keylow = 0, keyhigh = 0; if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE)) { if (dwFlags & DDBLT_KEYSRC) { keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue; keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue; } else if (dwFlags & DDBLT_KEYDEST){ keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue; keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue; } else if (dwFlags & DDBLT_KEYSRCOVERRIDE) { keylow = lpbltfx->ddckSrcColorkey.dwColorSpaceLowValue; keyhigh = lpbltfx->ddckSrcColorkey.dwColorSpaceHighValue; } else { keylow = lpbltfx->ddckDestColorkey.dwColorSpaceLowValue; keyhigh = lpbltfx->ddckDestColorkey.dwColorSpaceHighValue; } dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE); } if (dwFlags & DDBLT_DDFX) { LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp; LONG tmpxy; dTopLeft = dbuf; dTopRight = dbuf+((dstwidth-1)*bpp); dBottomLeft = dTopLeft+((dstheight-1)*ddesc.u1.lPitch); dBottomRight = dBottomLeft+((dstwidth-1)*bpp); if (lpbltfx->dwDDFX & DDBLTFX_ARITHSTRETCHY){ /* I don't think we need to do anything about this flag */ WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_ARITHSTRETCHY\n"); } if (lpbltfx->dwDDFX & DDBLTFX_MIRRORLEFTRIGHT) { tmp = dTopRight; dTopRight = dTopLeft; dTopLeft = tmp; tmp = dBottomRight; dBottomRight = dBottomLeft; dBottomLeft = tmp; dstxinc = dstxinc *-1; } if (lpbltfx->dwDDFX & DDBLTFX_MIRRORUPDOWN) { tmp = dTopLeft; dTopLeft = dBottomLeft; dBottomLeft = tmp; tmp = dTopRight; dTopRight = dBottomRight; dBottomRight = tmp; dstyinc = dstyinc *-1; } if (lpbltfx->dwDDFX & DDBLTFX_NOTEARING) { /* I don't think we need to do anything about this flag */ WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_NOTEARING\n"); } if (lpbltfx->dwDDFX & DDBLTFX_ROTATE180) { tmp = dBottomRight; dBottomRight = dTopLeft; dTopLeft = tmp; tmp = dBottomLeft; dBottomLeft = dTopRight; dTopRight = tmp; dstxinc = dstxinc * -1; dstyinc = dstyinc * -1; } if (lpbltfx->dwDDFX & DDBLTFX_ROTATE270) { tmp = dTopLeft; dTopLeft = dBottomLeft; dBottomLeft = dBottomRight; dBottomRight = dTopRight; dTopRight = tmp; tmpxy = dstxinc; dstxinc = dstyinc; dstyinc = tmpxy; dstxinc = dstxinc * -1; } if (lpbltfx->dwDDFX & DDBLTFX_ROTATE90) { tmp = dTopLeft; dTopLeft = dTopRight; dTopRight = dBottomRight; dBottomRight = dBottomLeft; dBottomLeft = tmp; tmpxy = dstxinc; dstxinc = dstyinc; dstyinc = tmpxy; dstyinc = dstyinc * -1; } if (lpbltfx->dwDDFX & DDBLTFX_ZBUFFERBASEDEST) { /* I don't think we need to do anything about this flag */ WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_ZBUFFERBASEDEST\n"); } dbuf = dTopLeft; dwFlags &= ~(DDBLT_DDFX); }#define COPY_COLORKEY_FX(type) { \ type *s = (type *) sbuf, *d = (type *) dbuf, *dx, tmp; \ for (y = sy = 0; y < dstheight; y++, sy += yinc) { \ (LPBYTE)s = sbase + (sy >> 16) * sdesc.u1.lPitch; \ (LPBYTE)dx = d; \ for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \ tmp = s[sx >> 16]; \ if (tmp < keylow || tmp > keyhigh) dx[0] = tmp; \ (LPBYTE)dx += dstxinc; \ } \ (LPBYTE)d += dstyinc; \ } \ break; } switch (bpp) { case 1: COPY_COLORKEY_FX(BYTE) case 2: COPY_COLORKEY_FX(WORD) case 4: COPY_COLORKEY_FX(DWORD) case 3: {LPBYTE s,d = dbuf, dx; for (y = sy = 0; y < dstheight; y++, sy += yinc) { sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch; dx = d; for (x = sx = 0; x < dstwidth; x++, sx+= xinc) { DWORD pixel; s = sbuf+3*(sx>>16); pixel = s[0]|(s[1]<<8)|(s[2]<<16); if (pixel < keylow || pixel > keyhigh){ dx[0] = (pixel )&0xff; dx[1] = (pixel>> 8)&0xff; dx[2] = (pixel>>16)&0xff; } dx+= dstxinc; } d += dstyinc; } break;} default: FIXME("%s color-keyed blit not implemented for bpp %d!\n", (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8); ret = DDERR_UNSUPPORTED; goto error;#undef COPY_COLORKEY_FX } } }error: if (dwFlags && FIXME_ON(ddraw)) { FIXME("\tUnsupported flags: "); DDRAW_dump_DDBLT(dwFlags); }release: IDirectDrawSurface7_Unlock(iface,NULL); if (src) IDirectDrawSurface7_Unlock(src,NULL); return DD_OK;}/* BltBatch: generic, unimplemented */HRESULT WINAPIDIB_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dstx, DWORD dsty, LPDIRECTDRAWSURFACE7 src, LPRECT rsrc, DWORD trans){ ICOM_THIS(IDirectDrawSurfaceImpl,iface); int bpp, w, h, x, y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -