bug=102321 Speed up the background tiling r=kmcclusky sr=attinasi

This commit is contained in:
dcone%netscape.com 2002-04-23 23:48:56 +00:00
Родитель df2c867541
Коммит 50b46f9fc1
2 изменённых файлов: 215 добавлений и 308 удалений

Просмотреть файл

@ -40,9 +40,6 @@
#include "nsImageWin.h" #include "nsImageWin.h"
#include "nsRenderingContextWin.h" #include "nsRenderingContextWin.h"
#define MAX_BUFFER_WIDTH 128
#define MAX_BUFFER_HEIGHT 128
static nsresult BuildDIB(LPBITMAPINFOHEADER *aBHead,PRInt32 aWidth,PRInt32 aHeight,PRInt32 aDepth,PRInt8 *aNumBitPix); static nsresult BuildDIB(LPBITMAPINFOHEADER *aBHead,PRInt32 aWidth,PRInt32 aHeight,PRInt32 aDepth,PRInt8 *aNumBitPix);
@ -661,118 +658,118 @@ NS_IMETHODIMP nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface
NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext, NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
nsDrawingSurface aSurface, nsDrawingSurface aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset, PRInt32 aSXOffset, PRInt32 aSYOffset,
const nsRect &aTileRect) const nsRect &aDestRect)
{ {
float scale; float scale;
unsigned char *targetRow,*imageRow,*alphaRow;
PRBool result;
PRInt32 numTiles,x0,y0,x1,y1,destScaledWidth,destScaledHeight;
PRInt32 validWidth,validHeight,validX,validY,targetRowBytes;
PRInt32 temp1,temp2,ScaledTileHeight_Offset,ScaledTileWidth_Offset;
PRInt32 x,y,width,height,canRaster;
nsCOMPtr<nsIDeviceContext> theDeviceContext;
HDC theHDC;
nsRect destRect,srcRect;
nscoord ScaledTileWidth,ScaledTileHeight;
{ aContext.GetDeviceContext(*getter_AddRefs(theDeviceContext));
nsCOMPtr<nsIDeviceContext> theDeviceContext; theDeviceContext->GetCanonicalPixelScale(scale);
aContext.GetDeviceContext(*getter_AddRefs(theDeviceContext));
theDeviceContext->GetCanonicalPixelScale(scale); destScaledWidth = PR_MAX(PRInt32(mBHead->biWidth*scale), 1);
} destScaledHeight = PR_MAX(PRInt32(mBHead->biHeight*scale), 1);
validX = 0;
PRInt32 validY = 0;
destScaledWidth = PR_MAX(int(mBHead->biWidth*scale), 1), validWidth = mBHead->biWidth;
destScaledHeight = PR_MAX(int(mBHead->biHeight*scale), 1); validHeight = mBHead->biHeight;
PRInt32
validX = 0,
validY = 0,
validWidth = mBHead->biWidth,
validHeight = mBHead->biHeight;
// limit the image rectangle to the size of the image data which // limit the image rectangle to the size of the image data which
// has been validated. // has been validated.
if (mDecodedY2 < mBHead->biHeight) { if (mDecodedY2 < mBHead->biHeight) {
validHeight = mDecodedY2 - mDecodedY1; validHeight = mDecodedY2 - mDecodedY1;
destScaledHeight = PR_MAX(int(validHeight*scale), 1); destScaledHeight = PR_MAX(PRInt32(validHeight*scale), 1);
} }
if (mDecodedX2 < mBHead->biWidth) { if (mDecodedX2 < mBHead->biWidth) {
validWidth = mDecodedX2 - mDecodedX1; validWidth = mDecodedX2 - mDecodedX1;
destScaledWidth = PR_MAX(int(validWidth*scale), 1); destScaledWidth = PR_MAX(PRInt32(validWidth*scale), 1);
} }
if (mDecodedY1 > 0) { if (mDecodedY1 > 0) {
validHeight -= mDecodedY1; validHeight -= mDecodedY1;
destScaledHeight = PR_MAX(int(validHeight*scale), 1); destScaledHeight = PR_MAX(PRInt32(validHeight*scale), 1);
validY = mDecodedY1; validY = mDecodedY1;
} }
if (mDecodedX1 > 0) { if (mDecodedX1 > 0) {
validWidth -= mDecodedX1; validWidth -= mDecodedX1;
destScaledWidth = PR_MAX(int(validWidth*scale), 1); destScaledWidth = PR_MAX(PRInt32(validWidth*scale), 1);
validX = mDecodedX1; validX = mDecodedX1;
} }
// put the width and hieght into the devices coordinates // put the width and hieght into the devices coordinates
PRInt32 aY0 = aTileRect.y - aSYOffset, // put the DestRect into absolute coordintes of the device
aX0 = aTileRect.x - aSXOffset,
aY1 = aTileRect.y + aTileRect.height, y0 = aDestRect.y - aSYOffset;
aX1 = aTileRect.x + aTileRect.width; x0 = aDestRect.x - aSXOffset;
y1 = aDestRect.y + aDestRect.height;
x1 = aDestRect.x + aDestRect.width;
// this is the width and height of the image in pixels // this is the width and height of the image in pixels
// we need to map this to the pixel height of the device // we need to map this to the pixel height of the device
nscoord imageScaledWidth = PR_MAX(int(mBHead->biWidth*scale), 1); ScaledTileWidth = PR_MAX(PRInt32(mBHead->biWidth*scale), 1);
nscoord imageScaledHeight = PR_MAX(int(mBHead->biHeight*scale), 1); ScaledTileHeight = PR_MAX(PRInt32(mBHead->biHeight*scale), 1);
nscoord tileWidth = aTileRect.width;
nscoord tileHeight = aTileRect.height;
PRBool tryAgain = PR_FALSE;
nsRect destRect,srcRect,tvrect;
HDC TheHDC,offDC,maskDC;
PRInt32 x,y,width,height,canRaster,TileBufferWidth,TileBufferHeight;
HBITMAP maskBits,tileBits,oldBits,oldMaskBits;
// The slower tiling will need to be used for the following cases:
// 1.) Printers 2.) When in 256 color mode 3.) when the tile is larger than the buffer
tvrect.SetRect(0,0,aX1-aX0,aY1-aY0);
((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster); ((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster);
if( mAlphaDepth == 8){ // do alpha depth equal to 8 here.. this needs some special attention
if(!mImageBits){
if ( mAlphaDepth == 8) {
unsigned char *screenBits=nsnull;
HDC memDC=nsnull;
HBITMAP tmpBitmap=nsnull,oldBitmap;
unsigned char alpha;
if (!mImageBits) {
ConvertDDBtoDIB(); ConvertDDBtoDIB();
} }
/**
* do alpha depth equal to 8 here.. this needs some special attention
* draw the alpha and the bitmap to an offscreen buffer.. for the blend.. first // draw the alpha and the bitmap to an offscreen buffer.. for the blend.. first
*/ ((nsDrawingSurfaceWin *)aSurface)->GetDC(&theHDC);
// get the current HDC to draw to.. if (theHDC) {
((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
if (NULL == TheHDC){
return (PR_FALSE);
}
// create a buffer for the blend // create a buffer for the blend
HDC memDC = CreateCompatibleDC(TheHDC); memDC = CreateCompatibleDC(theHDC);
unsigned char *screenBits; width = x1-x0;
width = aX1-aX0; height = y1-y0;
height = aY1-aY0;
ALPHA24BITMAPINFO bmi(width, height); ALPHA24BITMAPINFO bmi(width, height);
HBITMAP tmpBitmap = ::CreateDIBSection(memDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, (LPVOID *)&screenBits, NULL, 0); tmpBitmap = ::CreateDIBSection(memDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, (LPVOID *)&screenBits, NULL, 0);
HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap); oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap);
if(0 == tmpBitmap){ }
::DeleteObject(memDC);
tryAgain = PR_TRUE; if (!tmpBitmap) {
if (memDC) {
::DeleteObject(memDC);
}
// this failed..and will fall into the slow blitting code
NS_WARNING("The Creation of the tmpBitmap failed \n");
} else { } else {
// Copy from the HDC to the memory DC // Copy from the HDC to the memory DC
::StretchBlt(memDC, 0, 0, width, height,TheHDC, 0, 0, width, height, SRCCOPY); ::StretchBlt(memDC, 0, 0, width, height,theHDC, 0, 0, width, height, SRCCOPY);
PRInt32 targetRowBytes = ((width * 3) + 3) & ~3; targetRowBytes = ((width * 3) + 3) & ~3;
unsigned char *targetRow,*imageRow,*alphaRow; ScaledTileHeight_Offset = ScaledTileHeight + aSYOffset;
PRInt32 temp1,temp2,imageScaledHeightPlus,imageScaledWidthPlus; ScaledTileWidth_Offset = ScaledTileWidth + aSXOffset;
imageScaledHeightPlus = imageScaledHeight + aSYOffset;
imageScaledWidthPlus = imageScaledWidth + aSXOffset;
temp1 = mRowBytes + 3 * aSXOffset; temp1 = mRowBytes + 3 * aSXOffset;
temp2 = mARowBytes + aSXOffset; temp2 = mARowBytes + aSXOffset;
for (int y = 0,byw=aSYOffset; y < height; y++,byw++) { for (int y = 0,byw=aSYOffset; y < height; y++,byw++) {
if(byw >= imageScaledHeightPlus){ if (byw >= ScaledTileHeight_Offset) {
byw = aSYOffset; byw = aSYOffset;
} }
targetRow = screenBits + y * targetRowBytes; targetRow = screenBits + y * targetRowBytes;
@ -780,12 +777,12 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
alphaRow = mAlphaBits + byw * temp2; alphaRow = mAlphaBits + byw * temp2;
for (int x=0,bxw=aSXOffset;x<width;x++,targetRow+=3,imageRow+=3,bxw++, alphaRow++) { for (int x=0,bxw=aSXOffset;x<width;x++,targetRow+=3,imageRow+=3,bxw++, alphaRow++) {
if(bxw>=imageScaledWidthPlus){ if (bxw>=ScaledTileWidth_Offset) {
bxw = aSXOffset; bxw = aSXOffset;
imageRow = mImageBits + byw * mRowBytes + ((3*bxw)%mRowBytes); imageRow = mImageBits + byw * mRowBytes + ((3*bxw)%mRowBytes);
alphaRow = mAlphaBits + byw * mARowBytes + (bxw%mRowBytes); alphaRow = mAlphaBits + byw * mARowBytes + (bxw%mRowBytes);
} }
unsigned alpha = *alphaRow; alpha = *alphaRow;
MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha); MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha); MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha);
@ -794,255 +791,158 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
} }
// Copy back to the HDC // Copy back to the HDC
::StretchBlt(TheHDC, 0, 0, width, height,memDC, 0, 0, width, height, SRCCOPY); ::StretchBlt(theHDC, 0, 0, width, height,memDC, 0, 0, width, height, SRCCOPY);
::SelectObject(memDC, oldBitmap); ::SelectObject(memDC, oldBitmap);
::DeleteObject(tmpBitmap); ::DeleteObject(tmpBitmap);
::DeleteObject(memDC); ::DeleteObject(memDC);
return(PR_TRUE); return(NS_OK);
} }
} }
numTiles = (aDestRect.width*aDestRect.height)/(ScaledTileWidth*ScaledTileHeight);
// figure out which case to use for tiling // if alpha is less than 8,not printing, and not 8 bit palette image then we can do
PRBool useSlow = PR_FALSE; // a progressive tile and the tile is at least 4 times smaller than the area to update
if ( (mAlphaDepth < 8) && (canRaster!=DT_RASPRINTER) && (256!=mNumPaletteColors) &&
(numTiles > 3) ) {
result = ProgressiveDoubleBlit(aSurface,aDestRect.width, aDestRect.height,
ScaledTileWidth,ScaledTileHeight, x0,y0,x1,y1);
if (result ) {
return(NS_OK);
}
}
if ((mAlphaDepth>8) || ((mAlphaDepth==8)&&tryAgain) || (canRaster==DT_RASPRINTER) // if we got to this point.. everything else failed.. and the slow blit backstop
|| (256==mNumPaletteColors)){ // will finish this tiling
// CASE 1 -- ALPHA DEPTH IS TO HIGH OR WE ARE PRINTING OR ALPHA ALGORITHM FROM ABOVE FAILED for (y=y0;y<y1;y+=ScaledTileHeight) {
useSlow = PR_TRUE; for (x=x0;x<x1;x+=ScaledTileWidth) {
} else if ( (imageScaledWidth>MAX_BUFFER_WIDTH) || (imageScaledHeight>MAX_BUFFER_HEIGHT)) { Draw(aContext, aSurface,
if(PR_TRUE != gIsWinNT){ 0, 0, PR_MIN(validWidth, x1-x), PR_MIN(validHeight, y1-y),
// CASE 2 -- THE PLATFORM IS NOT ON NT AND CAN NOT USE A PATBLT x, y, PR_MIN(destScaledWidth, x1-x), PR_MIN(destScaledHeight, y1-y));
useSlow = PR_TRUE; }
}
return(NS_OK);
}
/** ---------------------------------------------------
* See documentation in nsImageWin.h
* @update 4/16/02 dwc
*/
PRBool
nsImageWin::ProgressiveDoubleBlit(nsDrawingSurface aSurface,
PRInt32 aDestBufferWidth, PRInt32 aDestBufferHeight,
PRInt32 aScaledTileWidth,PRInt32 aScaledTileHeight,
PRInt32 aX0,PRInt32 aY0,
PRInt32 aX1,PRInt32 aY1)
{
PRInt32 x,y,width,height;
nsRect destRect,srcRect;
HDC theHDC,offDC,maskDC;
HBITMAP maskBits,tileBits,oldBits,oldMaskBits;
// create a larger tile from the smaller one
((nsDrawingSurfaceWin *)aSurface)->GetDC(&theHDC);
if (NULL == theHDC) {
return (PR_FALSE);
}
// so we will create a screen compatible bitmap and then install this into the offscreen DC
offDC = ::CreateCompatibleDC(theHDC);
if (NULL ==offDC) {
return (PR_FALSE);
}
tileBits = ::CreateCompatibleBitmap(theHDC, aDestBufferWidth,aDestBufferHeight);
if (NULL == tileBits) {
::DeleteObject(offDC);
return (PR_FALSE);
}
oldBits =(HBITMAP) ::SelectObject(offDC,tileBits);
if (1==mAlphaDepth) {
// larger tile for mask
maskDC = ::CreateCompatibleDC(theHDC);
if (NULL ==maskDC){
::SelectObject(offDC,oldBits);
::DeleteObject(tileBits);
::DeleteObject(offDC);
return (PR_FALSE);
}
maskBits = ::CreateCompatibleBitmap(theHDC, aDestBufferWidth, aDestBufferHeight);
if (NULL ==maskBits) {
::SelectObject(offDC,oldBits);
::DeleteObject(tileBits);
::DeleteObject(offDC);
::DeleteObject(maskDC);
return (PR_FALSE);
}
oldMaskBits = (HBITMAP)::SelectObject(maskDC,maskBits);
// get the mask into our new tiled mask
MONOBITMAPINFO bmi(mAlphaWidth,mAlphaHeight);
::StretchDIBits(maskDC, 0, 0, aScaledTileWidth, aScaledTileHeight,0, 0,
mAlphaWidth, mAlphaHeight, mAlphaBits,(LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCCOPY);
::BitBlt(maskDC,0,0,aScaledTileWidth,aScaledTileHeight,maskDC,0,0,SRCCOPY);
srcRect.SetRect(0,0,aScaledTileWidth,aScaledTileHeight);
BuildTile(maskDC,srcRect,aDestBufferWidth/2,aDestBufferHeight/2,SRCCOPY);
}
// put the initial tile of background image into the offscreen
if (!IsOptimized() || nsnull==mHBitmap) {
::StretchDIBits(offDC, 0, 0, aScaledTileWidth, aScaledTileHeight,0, 0, aScaledTileWidth, aScaledTileHeight, mImageBits,
(LPBITMAPINFO)mBHead, 256 == mNumPaletteColors ? DIB_PAL_COLORS:DIB_RGB_COLORS,
SRCCOPY);
} else { } else {
if( (imageScaledWidth < MAX_BUFFER_WIDTH) || (imageScaledHeight < MAX_BUFFER_HEIGHT) ) { // need to select install this bitmap into this DC first
// CASE 3 -- THE PLATFORM IS ON NT AND WE HAVE ONE LARGE AND ONE SMALL WIDTH AND HEIGHT HBITMAP oldBits;
if (PatBltTile(aContext,aSurface,aX0,aY0,aX1,aY1)) { oldBits = (HBITMAP)::SelectObject(theHDC, mHBitmap);
return(PR_TRUE); ::BitBlt(offDC,0,0,aScaledTileWidth,aScaledTileHeight,theHDC,0,0,SRCCOPY);
::SelectObject(theHDC, oldBits);
}
srcRect.SetRect(0,0,aScaledTileWidth,aScaledTileHeight);
BuildTile(offDC,srcRect,aDestBufferWidth/2,aDestBufferHeight/2,SRCCOPY);
// now duplicate our tile into the background
destRect = srcRect;
width = destRect.width;
height = destRect.height;
if (1!=mAlphaDepth) {
for (y=aY0;y<aY1;y+=srcRect.height) {
for (x=aX0;x<aX1;x+=srcRect.width) {
destRect.x = x;
destRect.y = y;
::BitBlt(theHDC,x,y,width,height,offDC,0,0,SRCCOPY);
} }
// If PatBltTile returns PR_FALSE then we must drop through to the slow tiling }
// code because either the width or height of the tiling buffer has been exceeded } else {
useSlow = PR_TRUE; for (y=aY0;y<aY1;y+=srcRect.height) {
} else { for (x=aX0;x<aX1;x+=srcRect.width) {
// CASE 4 -- THE PLATFORM IS ON NT AND BOTH THE WIDTH AND HEIGHT ARE LARGE. destRect.x = x;
// -- THIS IS AN ODD CASE.. SEEMS PATBLT WITH LARGER BRUSHES HAS A DIFFICULT TIME destRect.y = y;
// -- AND THE TIMES ARE SLOWER. ::BitBlt(theHDC,x,y,width,height,maskDC,0,0,SRCAND);
useSlow = PR_TRUE; ::BitBlt(theHDC,x,y,width,height,offDC,0,0,SRCPAINT);
} }
} }
} ::SelectObject(maskDC,oldMaskBits);
::DeleteObject(maskBits);
if(useSlow){
for(y=aY0;y<aY1;y+=imageScaledHeight){
for(x=aX0;x<aX1;x+=imageScaledWidth){
Draw(aContext, aSurface,
0, 0, PR_MIN(validWidth, aX1-x), PR_MIN(validHeight, aY1-y),
x, y, PR_MIN(destScaledWidth, aX1-x), PR_MIN(destScaledHeight, aY1-y));
}
}
return(PR_TRUE);
}
// create a larger tile from the smaller one
((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
if (NULL == TheHDC){
return (PR_FALSE);
}
// IF WE MADE IT THIS FAR.. A PROGRESSIVE DOUBLING ALGORITHM WILL BE USED TO TILE
// so we will create a screen compatible bitmap and then install this into the offscreen DC
tvrect.SetRect(0,0,aX1-aX0,aY1-aY0);
offDC = ::CreateCompatibleDC(TheHDC);
if (NULL ==offDC){
return (PR_FALSE);
}
if (tileWidth < tvrect.width){
TileBufferWidth = MAX_BUFFER_WIDTH;
} else {
TileBufferWidth = tileWidth;
}
if (tileHeight < tvrect.height){
TileBufferHeight = MAX_BUFFER_HEIGHT;
} else {
TileBufferHeight = tileHeight;
}
tileBits = ::CreateCompatibleBitmap(TheHDC, TileBufferWidth,TileBufferHeight);
if (NULL == tileBits){
::DeleteObject(offDC);
return (PR_FALSE);
}
oldBits =(HBITMAP) ::SelectObject(offDC,tileBits);
if (1==mAlphaDepth) {
// larger tile for mask
maskDC = ::CreateCompatibleDC(TheHDC);
if (NULL ==maskDC){
::SelectObject(offDC,oldBits);
::DeleteObject(tileBits);
::DeleteObject(offDC);
return (PR_FALSE);
}
maskBits = ::CreateCompatibleBitmap(TheHDC, TileBufferWidth, TileBufferHeight);
if (NULL ==maskBits){
::SelectObject(offDC,oldBits);
::DeleteObject(tileBits);
::DeleteObject(offDC);
::DeleteObject(maskDC); ::DeleteObject(maskDC);
return (PR_FALSE);
} }
oldMaskBits = (HBITMAP)::SelectObject(maskDC,maskBits);
// get the mask into our new tiled mask
MONOBITMAPINFO bmi(mAlphaWidth,mAlphaHeight);
::StretchDIBits(maskDC, 0, 0, imageScaledWidth, imageScaledHeight,0, 0,
mAlphaWidth, mAlphaHeight, mAlphaBits,(LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCCOPY);
::BitBlt(maskDC,0,0,imageScaledWidth,imageScaledHeight,maskDC,0,0,SRCCOPY);
srcRect.SetRect(0,0,imageScaledWidth,imageScaledHeight);
BuildTile(maskDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY);
}
// put the initial tile of background image into the offscreen
if (!IsOptimized() || nsnull==mHBitmap){
::StretchDIBits(offDC, 0, 0, imageScaledWidth, imageScaledHeight,0, 0, imageScaledWidth, imageScaledHeight, mImageBits,
(LPBITMAPINFO)mBHead, 256 == mNumPaletteColors ? DIB_PAL_COLORS:DIB_RGB_COLORS,
SRCCOPY);
}else{
// need to select install this bitmap into this DC first
HBITMAP oldBits;
oldBits = (HBITMAP)::SelectObject(TheHDC, mHBitmap);
::BitBlt(offDC,0,0,imageScaledWidth,imageScaledHeight,TheHDC,0,0,SRCCOPY);
::SelectObject(TheHDC, oldBits);
}
srcRect.SetRect(0,0,imageScaledWidth,imageScaledHeight);
BuildTile(offDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY);
// now duplicate our tile into the background
destRect = srcRect;
width = destRect.width;
height = destRect.height;
if (1!=mAlphaDepth) {
for(y=aY0;y<aY1;y+=srcRect.height){
for(x=aX0;x<aX1;x+=srcRect.width){
destRect.x = x;
destRect.y = y;
::BitBlt(TheHDC,x,y,width,height,offDC,0,0,SRCCOPY);
}
}
} else {
for(y=aY0;y<aY1;y+=srcRect.height){
for(x=aX0;x<aX1;x+=srcRect.width){
destRect.x = x;
destRect.y = y;
::BitBlt(TheHDC,x,y,width,height,maskDC,0,0,SRCAND);
::BitBlt(TheHDC,x,y,width,height,offDC,0,0,SRCPAINT);
}
}
::SelectObject(maskDC,oldMaskBits);
::DeleteObject(maskBits);
::DeleteObject(maskDC);
}
::SelectObject(offDC,oldBits); ::SelectObject(offDC,oldBits);
::DeleteObject(tileBits); ::DeleteObject(tileBits);
::DeleteObject(offDC); ::DeleteObject(offDC);
return NS_OK; return(PR_TRUE);
} }
/** ---------------------------------------------------
* See documentation in nsIRenderingContext.h
* @update 3/16/00 dwc
*/
PRBool
nsImageWin :: PatBltTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
nscoord aX0,nscoord aY0,nscoord aX1,nscoord aY1)
{
HDC TheHDC;
HBRUSH hBrush,oldBrush;
BOOL success,problem=FALSE;
DWORD rop;
HBITMAP theBits;
POINT originalPoint;
if (PR_TRUE != gIsWinNT) {
// Windows 98 can not have a brush smaller than 8x8. There is also a know bug
// that crashes windows 98
// (http://support.microsoft.com/default.aspx?scid=kb;EN-US;q235618)
// if you have the wrong driver installed.. and the patBlt
// for some reason.. really hits this problem..
// Windows 95 seems to have other requirements that may have to do with a power
// of 2 size requirement based on some comments in other bugs.
// I will have 98 and 95 fail this test because of all the problems those OS's cause
// Win 2k, NT and XP all tested and seem to work fine with PatBlt.
return PR_FALSE;
}
if (PR_FALSE==mCanOptimize) {
return (PR_FALSE);
}
if (nsnull==mHBitmap) {
CreateDDB(aSurface);
}
((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
if (NULL == TheHDC){
return (PR_FALSE);
}
// default copy mode
rop = PATCOPY;
// we have to reset the origin here..
::SetBrushOrgEx(TheHDC,aX0,aY0,&originalPoint);
// if there is an alpha layer, lay down the mask first
if (1==mAlphaDepth){
((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
theBits = ::CreateBitmap(mAlphaWidth,mAlphaHeight,1,1,NULL);
MONOBITMAPINFO bmi(mAlphaWidth, mAlphaHeight);
SetDIBits(TheHDC,theBits,0,mAlphaHeight,mAlphaBits,(LPBITMAPINFO)&bmi,DIB_RGB_COLORS);
hBrush = CreatePatternBrush(theBits);
oldBrush = (HBRUSH)SelectObject(TheHDC,hBrush);
success = PatBlt( TheHDC, aX0,aY0,aX1-aX0,aY1-aY0,0xA000C9);
SelectObject(TheHDC,oldBrush);
DeleteObject(hBrush);
DeleteObject(theBits);
rop = 0xFA0089;
}
// do a pattern blit
if (mHBitmap == NULL) {
problem = TRUE;
}
hBrush = CreatePatternBrush(mHBitmap);
oldBrush = (HBRUSH)SelectObject(TheHDC,hBrush);
success = PatBlt( TheHDC, aX0,aY0,aX1-aX0,aY1-aY0,rop);
SelectObject(TheHDC,oldBrush);
DeleteObject(hBrush);
::SetBrushOrgEx(TheHDC,originalPoint.x,originalPoint.y,NULL);
return (PR_TRUE);
}
ALPHABLENDPROC nsImageWin::gAlphaBlend = NULL; ALPHABLENDPROC nsImageWin::gAlphaBlend = NULL;

Просмотреть файл

@ -126,17 +126,24 @@ public:
const nsRect &aTileRect); const nsRect &aTileRect);
/** /**
* Draw a tiled version of the bitmap, but use the windows specific highly optimized PatBlt * Progressivly double the bitmap size as we blit.. very fast way to tile
* @update - dwc 3/30/00 * @update - dwc 4/160/02
* @param aSurface the surface to blit to * @param aSurface the surface to blit to
* @param aX The destination horizontal location * @param aDestBufferWidth Width of buffer
* @param aY The destination vertical location * @param aDestBufferHeight Height of buffer
* @param aScaledTileWidth Width of tile
* @param aScaledTileHeight Height of tile
* @param aX0,aY0,aX1,aY1 Coordinates of screen to blit to
* @return if TRUE, no errors * @return if TRUE, no errors
*/ */
PRBool PatBltTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface,nscoord aX0,nscoord aY0,nscoord aX1,nscoord aY1);
PRBool ProgressiveDoubleBlit(nsDrawingSurface aSurface,
PRInt32 aDestBufferWidth, PRInt32 aDestBufferHeight,
PRInt32 aScaledTileWidth,PRInt32 aScaledTileHeight,
PRInt32 aX0,PRInt32 aY0,
PRInt32 aX1,PRInt32 aY1);
/** /**
* Return the header size of the Device Independent Bitmap(DIB). * Return the header size of the Device Independent Bitmap(DIB).
* @return size of header in bytes * @return size of header in bytes
*/ */