зеркало из https://github.com/mozilla/gecko-dev.git
bug=102321 Speed up the background tiling r=kmcclusky sr=attinasi
This commit is contained in:
Родитель
df2c867541
Коммит
50b46f9fc1
|
@ -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);
|
||||||
|
|
||||||
PRInt32
|
validX = 0;
|
||||||
destScaledWidth = PR_MAX(int(mBHead->biWidth*scale), 1),
|
validY = 0;
|
||||||
destScaledHeight = PR_MAX(int(mBHead->biHeight*scale), 1);
|
validWidth = mBHead->biWidth;
|
||||||
|
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
|
|
||||||
useSlow = PR_TRUE;
|
|
||||||
} else {
|
|
||||||
// CASE 4 -- THE PLATFORM IS ON NT AND BOTH THE WIDTH AND HEIGHT ARE LARGE.
|
|
||||||
// -- THIS IS AN ODD CASE.. SEEMS PATBLT WITH LARGER BRUSHES HAS A DIFFICULT TIME
|
|
||||||
// -- AND THE TIMES ARE SLOWER.
|
|
||||||
useSlow = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
for (y=aY0;y<aY1;y+=srcRect.height) {
|
||||||
|
for (x=aX0;x<aX1;x+=srcRect.width) {
|
||||||
|
destRect.x = x;
|
||||||
if(useSlow){
|
destRect.y = y;
|
||||||
for(y=aY0;y<aY1;y+=imageScaledHeight){
|
::BitBlt(theHDC,x,y,width,height,maskDC,0,0,SRCAND);
|
||||||
for(x=aX0;x<aX1;x+=imageScaledWidth){
|
::BitBlt(theHDC,x,y,width,height,offDC,0,0,SRCPAINT);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
::SelectObject(maskDC,oldMaskBits);
|
||||||
return(PR_TRUE);
|
::DeleteObject(maskBits);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче