b=98252, r=kmcclusk, sr=attinasi. Added support for fast alpha tiling.

This commit is contained in:
dcone%netscape.com 2002-01-09 15:02:00 +00:00
Родитель fb72d889c4
Коммит 303d368fed
1 изменённых файлов: 102 добавлений и 29 удалений

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

@ -517,7 +517,7 @@ nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
(LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCAND); (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCAND);
rop = SRCPAINT; rop = SRCPAINT;
} }
} }
} }
@ -603,6 +603,10 @@ nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
return NS_OK; return NS_OK;
} }
/** ---------------------------------------------------
* This is a helper routine to do the blending for the DrawComposited method
* @update 1/04/02 dwc
*/
void nsImageWin::DrawComposited24(unsigned char *aBits, int aX, int aY, int aWidth, int aHeight) void nsImageWin::DrawComposited24(unsigned char *aBits, int aX, int aY, int aWidth, int aHeight)
{ {
PRInt32 targetRowBytes = ((aWidth * 3) + 3) & ~3; PRInt32 targetRowBytes = ((aWidth * 3) + 3) & ~3;
@ -622,7 +626,8 @@ void nsImageWin::DrawComposited24(unsigned char *aBits, int aX, int aY, int aWid
} }
/** --------------------------------------------------- /** ---------------------------------------------------
* Do alpha blending by hand * Blend the image into a 24 bit buffer.. using an 8 bit alpha mask
* @update 1/04/02 dwc
*/ */
void nsImageWin::DrawComposited(HDC TheHDC, int aDX, int aDY, int aDWidth, int aDHeight, void nsImageWin::DrawComposited(HDC TheHDC, int aDX, int aDY, int aDWidth, int aDHeight,
int aSX, int aSY, int aSWidth, int aSHeight) int aSX, int aSY, int aSWidth, int aSHeight)
@ -634,14 +639,14 @@ void nsImageWin::DrawComposited(HDC TheHDC, int aDX, int aDY, int aDWidth, int a
(LPVOID *)&screenBits, NULL, 0); (LPVOID *)&screenBits, NULL, 0);
HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap); HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap);
/* Copy from the screen */ /* Copy from the HDC */
::StretchBlt(memDC, 0, 0, aSWidth, aSHeight, ::StretchBlt(memDC, 0, 0, aSWidth, aSHeight,
TheHDC, aDX, aDY, aDWidth, aDHeight, SRCCOPY); TheHDC, aDX, aDY, aDWidth, aDHeight, SRCCOPY);
/* Do composite */ /* Do composite */
DrawComposited24(screenBits, aSX, aSY, aSWidth, aSHeight); DrawComposited24(screenBits, aSX, aSY, aSWidth, aSHeight);
/* Copy back to the screen */ /* Copy back to the HDC */
::StretchBlt(TheHDC, aDX, aDY, aDWidth, aDHeight, ::StretchBlt(TheHDC, aDX, aDY, aDWidth, aDHeight,
memDC, 0, 0, aSWidth, aSHeight, SRCCOPY); memDC, 0, 0, aSWidth, aSHeight, SRCCOPY);
@ -679,10 +684,8 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
PRInt32 PRInt32
destinationX = 0, destScaledWidth = (int) (mBHead->biWidth*scale),
destinationY = 0, destScaledHeight = (int) (mBHead->biHeight*scale);
destinationWidth = mBHead->biWidth*scale,
destinationHeight = mBHead->biHeight*scale;
PRInt32 PRInt32
validX = 0, validX = 0,
@ -695,22 +698,20 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
// has been validated. // has been validated.
if (mDecodedY2 < mBHead->biHeight) { if (mDecodedY2 < mBHead->biHeight) {
validHeight = mDecodedY2 - mDecodedY1; validHeight = mDecodedY2 - mDecodedY1;
destinationHeight = validHeight*scale; destScaledHeight = (int)(validHeight*scale);
} }
if (mDecodedX2 < mBHead->biWidth) { if (mDecodedX2 < mBHead->biWidth) {
validWidth = mDecodedX2 - mDecodedX1; validWidth = mDecodedX2 - mDecodedX1;
destinationHeight = validWidth*scale; destScaledHeight = (int)(validWidth*scale);
} }
if (mDecodedY1 > 0) { if (mDecodedY1 > 0) {
validHeight -= mDecodedY1; validHeight -= mDecodedY1;
destinationY -= mDecodedY1*scale; destScaledHeight = (int)(validHeight*scale);
destinationHeight = validHeight*scale;
validY = mDecodedY1; validY = mDecodedY1;
} }
if (mDecodedX1 > 0) { if (mDecodedX1 > 0) {
validWidth -= mDecodedX1; validWidth -= mDecodedX1;
destinationX -= mDecodedX1*scale; destScaledHeight = (int)(validWidth*scale);
destinationHeight = validWidth*scale;
validX = mDecodedX1; validX = mDecodedX1;
} }
@ -723,12 +724,13 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
// 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 aWidth = mBHead->biWidth*scale; nscoord imageScaledWidth = (int)(mBHead->biWidth*scale);
nscoord aHeight = mBHead->biHeight*scale; nscoord imageScaledHeight = (int)(mBHead->biHeight*scale);
nscoord tileWidth = aTileRect.width; nscoord tileWidth = aTileRect.width;
nscoord tileHeight = aTileRect.height; nscoord tileHeight = aTileRect.height;
PRBool tryAgain = PR_FALSE;
nsRect destRect,srcRect,tvrect; nsRect destRect,srcRect,tvrect;
HDC TheHDC,offDC,maskDC; HDC TheHDC,offDC,maskDC;
PRInt32 x,y,width,height,canRaster,TileBufferWidth,TileBufferHeight; PRInt32 x,y,width,height,canRaster,TileBufferWidth,TileBufferHeight;
@ -740,17 +742,88 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
tvrect.SetRect(0,0,aX1-aX0,aY1-aY0); 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
* draw the alpha and the bitmap to an offscreen buffer.. for the blend.. first
*/
// get the current HDC to draw to..
((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
if (NULL == TheHDC){
return (PR_FALSE);
}
// create a buffer for the blend
HDC memDC = CreateCompatibleDC(TheHDC);
unsigned char *screenBits;
width = aX1-aX0;
height = aY1-aY0;
ALPHA24BITMAPINFO bmi(width, height);
HBITMAP tmpBitmap = ::CreateDIBSection(memDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, (LPVOID *)&screenBits, NULL, 0);
HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap);
if(0 == tmpBitmap){
::DeleteObject(memDC);
tryAgain = PR_TRUE;
} else {
// Copy from the HDC to the memory DC
::StretchBlt(memDC, 0, 0, width, height,TheHDC, 0, 0, width, height, SRCCOPY);
PRInt32 targetRowBytes = ((width * 3) + 3) & ~3;
unsigned char *targetRow,*imageRow,*alphaRow;
PRInt32 temp1,temp2,imageScaledHeightPlus,imageScaledWidthPlus;
imageScaledHeightPlus = imageScaledHeight + aSYOffset;
imageScaledWidthPlus = imageScaledWidth + aSXOffset;
temp1 = mRowBytes + 3 * aSXOffset;
temp2 = mARowBytes + aSXOffset;
for (int y = 0,byw=aSYOffset; y < height; y++,byw++) {
if(byw >= imageScaledHeightPlus){
byw = aSYOffset;
}
targetRow = screenBits + y * targetRowBytes;
imageRow = mImageBits + byw * temp1;
alphaRow = mAlphaBits + byw * temp2;
for (int x=0,bxw=aSXOffset;x<width;x++,targetRow+=3,imageRow+=3,bxw++, alphaRow++) {
if(bxw>=imageScaledWidthPlus){
bxw = aSXOffset;
imageRow = mImageBits + byw * mRowBytes + ((3*bxw)%mRowBytes);
alphaRow = mAlphaBits + byw * mARowBytes + (bxw%mRowBytes);
}
unsigned alpha = *alphaRow;
MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], targetRow[2], imageRow[2], alpha);
}
}
// Copy back to the HDC
::StretchBlt(TheHDC, 0, 0, width, height,memDC, 0, 0, width, height, SRCCOPY);
::SelectObject(memDC, oldBitmap);
::DeleteObject(tmpBitmap);
::DeleteObject(memDC);
return(PR_TRUE);
}
}
// we have to use the old way.. for 256 color mode and printing.. slow, but will always work. // we have to use the old way.. for 256 color mode and printing.. slow, but will always work.
if ((mAlphaDepth>1) || (canRaster==DT_RASPRINTER) || (256==mNumPaletteColors) if ((mAlphaDepth>8) || ((mAlphaDepth==8)&&tryAgain) || (canRaster==DT_RASPRINTER) || (256==mNumPaletteColors)
|| (aWidth>MAX_BUFFER_WIDTH) || (aHeight>MAX_BUFFER_HEIGHT)){ || (imageScaledWidth>MAX_BUFFER_WIDTH) || (imageScaledHeight>MAX_BUFFER_HEIGHT)){
for(y=aY0;y<aY1;y+=aHeight){ for(y=aY0;y<aY1;y+=imageScaledHeight){
for(x=aX0;x<aX1;x+=aWidth){ for(x=aX0;x<aX1;x+=imageScaledWidth){
Draw(aContext, aSurface, Draw(aContext, aSurface,
0, 0, PR_MIN(validWidth, aX1-x), PR_MIN(validHeight, aY1-y), 0, 0, PR_MIN(validWidth, aX1-x), PR_MIN(validHeight, aY1-y),
x, y, PR_MIN(destinationWidth, aX1-x), PR_MIN(destinationHeight, aY1-y)); x, y, PR_MIN(destScaledWidth, aX1-x), PR_MIN(destScaledHeight, aY1-y));
} }
} }
return(PR_TRUE); return(PR_TRUE);
} else if(mAlphaDepth == 8 ){
} }
// create a larger tile from the smaller one // create a larger tile from the smaller one
@ -810,17 +883,17 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
// get the mask into our new tiled mask // get the mask into our new tiled mask
MONOBITMAPINFO bmi(mAlphaWidth,mAlphaHeight); MONOBITMAPINFO bmi(mAlphaWidth,mAlphaHeight);
::StretchDIBits(maskDC, 0, 0, aWidth, aHeight,0, 0, ::StretchDIBits(maskDC, 0, 0, imageScaledWidth, imageScaledHeight,0, 0,
mAlphaWidth, mAlphaHeight, mAlphaBits,(LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCCOPY); mAlphaWidth, mAlphaHeight, mAlphaBits,(LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCCOPY);
::BitBlt(maskDC,0,0,aWidth,aHeight,maskDC,0,0,SRCCOPY); ::BitBlt(maskDC,0,0,imageScaledWidth,imageScaledHeight,maskDC,0,0,SRCCOPY);
srcRect.SetRect(0,0,aWidth,aHeight); srcRect.SetRect(0,0,imageScaledWidth,imageScaledHeight);
BuildTile(maskDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY); BuildTile(maskDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY);
} }
// put the initial tile of background image into the offscreen // put the initial tile of background image into the offscreen
if (!IsOptimized() || nsnull==mHBitmap){ if (!IsOptimized() || nsnull==mHBitmap){
::StretchDIBits(offDC, 0, 0, aWidth, aHeight,0, 0, aWidth, aHeight, mImageBits, ::StretchDIBits(offDC, 0, 0, imageScaledWidth, imageScaledHeight,0, 0, imageScaledWidth, imageScaledHeight, mImageBits,
(LPBITMAPINFO)mBHead, 256 == mNumPaletteColors ? DIB_PAL_COLORS:DIB_RGB_COLORS, (LPBITMAPINFO)mBHead, 256 == mNumPaletteColors ? DIB_PAL_COLORS:DIB_RGB_COLORS,
SRCCOPY); SRCCOPY);
}else{ }else{
@ -828,11 +901,11 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext,
HBITMAP oldBits; HBITMAP oldBits;
oldBits = (HBITMAP)::SelectObject(TheHDC, mHBitmap); oldBits = (HBITMAP)::SelectObject(TheHDC, mHBitmap);
::BitBlt(offDC,0,0,aWidth,aHeight,TheHDC,0,0,SRCCOPY); ::BitBlt(offDC,0,0,imageScaledWidth,imageScaledHeight,TheHDC,0,0,SRCCOPY);
::SelectObject(TheHDC, oldBits); ::SelectObject(TheHDC, oldBits);
} }
srcRect.SetRect(0,0,aWidth,aHeight); srcRect.SetRect(0,0,imageScaledWidth,imageScaledHeight);
BuildTile(offDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY); BuildTile(offDC,srcRect,TileBufferWidth/2,TileBufferHeight/2,SRCCOPY);
// now duplicate our tile into the background // now duplicate our tile into the background
@ -1304,8 +1377,8 @@ nsImageWin::GetBits()
#ifdef USE_IMG2 #ifdef USE_IMG2
NS_IMETHODIMP nsImageWin::DrawToImage(nsIImage* aDstImage, nscoord aDX, nscoord aDY, nscoord aDWidth, nscoord aDHeight) NS_IMETHODIMP nsImageWin::DrawToImage(nsIImage* aDstImage, nscoord aDX, nscoord aDY, nscoord aDWidth, nscoord aDHeight)
{ {
PRInt32 canRaster,srcy; PRInt32 srcy;
HBITMAP oldSrcBits, oldDstBits; HBITMAP oldDstBits;
DWORD rop; DWORD rop;
PRInt32 origDHeight = aDHeight; PRInt32 origDHeight = aDHeight;
PRInt32 origDWidth = aDWidth; PRInt32 origDWidth = aDWidth;