diff --git a/mozilla/gfx/src/nsIBlender.h b/mozilla/gfx/src/nsIBlender.h index 5a552c24f24..66914af734c 100644 --- a/mozilla/gfx/src/nsIBlender.h +++ b/mozilla/gfx/src/nsIBlender.h @@ -62,8 +62,7 @@ public: * @param aSrcOpacity 0.0f -> 1.0f opacity value of source area. 1.0f indicates * complete opacity. */ - virtual void Blend(nsDrawingSurface aSrc, - PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, + virtual nsresult Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea) = 0; /** diff --git a/mozilla/gfx/src/windows/nsBlenderWin.cpp b/mozilla/gfx/src/windows/nsBlenderWin.cpp index e7b4a7094c6..e6efd6a29fc 100644 --- a/mozilla/gfx/src/windows/nsBlenderWin.cpp +++ b/mozilla/gfx/src/windows/nsBlenderWin.cpp @@ -119,10 +119,11 @@ nsBlenderWin::CleanUp() //------------------------------------------------------------ -void -nsBlenderWin::Blend(nsDrawingSurface aSrc,PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, +nsresult +nsBlenderWin::Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, nsDrawingSurface aDst, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea) { +nsresult result = NS_ERROR_FAILURE; HDC dstdc,tb1; HBITMAP dstbits; nsPoint srcloc,maskloc; @@ -146,7 +147,7 @@ nsColorMap *colormap; oldsize = mSaveLS*mSaveNumLines; // allocate some memory - mSaveLS = CalcBytesSpan(numbytes,mDstInfo.bmBitsPixel); + mSaveLS = numbytes; mSaveNumLines = numlines; size = mSaveLS * numlines; mSaveNumBytes = numbytes; @@ -171,13 +172,14 @@ nsColorMap *colormap; { if(mask) { - numbytes/=3; // since the mask is only 8 bits, this routine wants number of pixels this->Do24BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,nsHighQual,aSaveBlendArea); + result = NS_OK; } else { level = (PRInt32)(aSrcOpacity*100); this->Do24Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,nsHighQual,aSaveBlendArea); + result = NS_OK; } } else @@ -186,11 +188,24 @@ nsColorMap *colormap; if(mask) { this->Do8BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,nsHighQual,aSaveBlendArea); + result = NS_OK; } else { level = (PRInt32)(aSrcOpacity*100); this->Do8Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,colormap,nsHighQual,aSaveBlendArea); + result = NS_OK; + } + } + else + { + if ((mSrcInfo.bmBitsPixel==16) && (mDstInfo.bmBitsPixel==16)) + { + if(!mask) + { + this->Do16Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,nsHighQual,aSaveBlendArea); + result = NS_OK; + } } } @@ -201,6 +216,7 @@ nsColorMap *colormap; ::DeleteObject(tb1); } +return result; } //------------------------------------------------------------ @@ -340,14 +356,21 @@ nsBlenderWin :: BuildDIB(LPBITMAPINFOHEADER *aBHead,unsigned char **aBits,PRInt { PRInt32 numpalletcolors,imagesize,spanbytes; PRUint8 *colortable; +DWORD bicomp; switch (aDepth) { case 8: numpalletcolors = 256; + bicomp = BI_RGB; + break; + case 16: + numpalletcolors = 0; + bicomp = BI_RGB; break; case 24: numpalletcolors = 0; + bicomp = BI_RGB; break; default: numpalletcolors = -1; @@ -363,7 +386,7 @@ PRUint8 *colortable; (*aBHead)->biHeight = aHeight; (*aBHead)->biPlanes = 1; (*aBHead)->biBitCount = (unsigned short) aDepth; - (*aBHead)->biCompression = BI_RGB; + (*aBHead)->biCompression = bicomp; (*aBHead)->biSizeImage = 0; // not compressed, so we dont need this to be set (*aBHead)->biXPelsPerMeter = 0; (*aBHead)->biYPelsPerMeter = 0; @@ -539,6 +562,109 @@ PRUint8 *saveptr,*sv2; //------------------------------------------------------------ +#define RED16(x) ((x)&0x7C00)>>7 +#define GREEN16(x) ((x)&0x3E0)>>2 +#define BLUE16(x) ((x)&0x1F)<<3 + + +// This routine can not be fast enough +void +nsBlenderWin::Do16Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea) +{ +PRUint16 *d1,*d2,*s1,*s2; +PRUint32 val1,val2,red,green,blue; +PRInt32 x,y,numlines,xinc,yinc; +PRUint16 *saveptr,*sv2; +PRInt16 dspan,sspan,span,savesp; + + // since we are using 16 bit pointers, the num bytes need to be cut by 2 + saveptr = (PRUint16*)mSaveBytes; + aBlendVal = (aBlendVal*255)/100; + val2 = aBlendVal; + val1 = 255-val2; + + // now go thru the image and blend (remember, its bottom upwards) + s1 = (PRUint16*)aSImage; + d1 = (PRUint16*)aDImage; + dspan = aDLSpan/2; + sspan = aSLSpan/2; + span = aNumbytes/2; + savesp = mSaveLS/2; + numlines = aNumlines; + xinc = 1; + yinc = 1; + + if(aSaveBlendArea) + { + for(y = 0; y < aNumlines; y++) + { + s2 = s1; + d2 = d1; + sv2 = saveptr; + + for(x=0;x>8; + if(red>255) + red = 255; + + green = ((PRUint32)(GREEN16(*d2))*val1+(PRUint32)(GREEN16(*s2)*val2))>>8; + if(green>255) + green = 255; + + blue = ((PRUint32)(BLUE16(*d2))*val1+(PRUint32)(BLUE16(*s2)*val2))>>8; + if(blue>255) + blue = 255; + + + *sv2 = *d2; + *d2 = ((red&0xF8)<<7) | ((green&0xF8)<<2) | (blue&0xF8)>>3; + sv2++; + d2++; + s2++; + } + + + s1 += sspan; + d1 += dspan; + saveptr += savesp; + } + } + else + { + for(y = 0; y < aNumlines; y++) + { + s2 = s1; + d2 = d1; + + for(x = 0; x < aNumbytes; x++) + { + red = RED16(*d2)*val1+RED16(*s2)*val2; + if(red>255) + red = 255; + + green = GREEN16(*d2)*val1+GREEN16(*s2)*val2; + if(green>255) + green = 255; + + blue = BLUE16(*d2)*val1+BLUE16(*s2)*val2; + if(blue>255) + blue = 255; + + *d2 = ((red&0xf8)<<7) | ((green&0xf8)<<2) | ((blue&0xf8)>>3); + d2++; + s2++; + } + + s1 += aSLSpan; + d1 += aDLSpan; + } + } + +} + +//------------------------------------------------------------ + // This routine can not be fast enough void nsBlenderWin::Do8BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea) diff --git a/mozilla/gfx/src/windows/nsBlenderWin.h b/mozilla/gfx/src/windows/nsBlenderWin.h index 4732060e2a3..2b0721f6af1 100644 --- a/mozilla/gfx/src/windows/nsBlenderWin.h +++ b/mozilla/gfx/src/windows/nsBlenderWin.h @@ -40,9 +40,8 @@ public: virtual nsresult Init(nsDrawingSurface aSrc,nsDrawingSurface aDst); virtual void CleanUp(); - virtual void Blend(nsDrawingSurface aSrc, - PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, - nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea); + virtual nsresult Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight, + nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea); nsDrawingSurface GetSrcDS() {return(mSrcDC);} nsDrawingSurface GetDstDS() {return(mDstDC);} @@ -105,10 +104,27 @@ public: * @param aBlendQuality The quality of this blend, this is for tweening if neccesary * @param aSaveBlendArea informs routine if the area affected area will be save first */ + void Do24Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage, PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea); + /** + * Blend two 16 bit image arrays using a passed in blend value + * @param aNumlines Number of lines to blend + * @param aNumberBytes Number of bytes per line to blend + * @param aSImage Pointer to beginning of the source bytes + * @param aDImage Pointer to beginning of the destination bytes + * @param aMImage Pointer to beginning of the mask bytes + * @param aSLSpan number of bytes per line for the source bytes + * @param aDLSpan number of bytes per line for the destination bytes + * @param aMLSpan number of bytes per line for the Mask bytes + * @param aBlendQuality The quality of this blend, this is for tweening if neccesary + * @param aSaveBlendArea informs routine if the area affected area will be save first + */ + void Do16Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage, + PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea); + /** * Blend two 8 bit image arrays using an 8 bit alpha mask * @param aNumlines Number of lines to blend diff --git a/mozilla/gfx/tests/btest/BitTest.cpp b/mozilla/gfx/tests/btest/BitTest.cpp index 2a14c4ae8df..5e4f3315973 100644 --- a/mozilla/gfx/tests/btest/BitTest.cpp +++ b/mozilla/gfx/tests/btest/BitTest.cpp @@ -72,7 +72,7 @@ static PRBool gCanBlend = PR_FALSE; static HBITMAP gDobits,gSobits,gSrcbits,gDestbits; static HDC gDestdc,gSrcdc,gScreendc; -extern void Compositetest(nsIBlender *aBlender,nsIImage *aImage, +extern nsresult Compositetest(nsIBlender *aBlender,nsIImage *aImage, PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth,PRInt32 aHeight, PRInt32 aDX,PRInt32 aDY, float aBlendAmount,PRBool aBuff); @@ -88,6 +88,9 @@ extern nsresult BuildDIB(LPBITMAPINFOHEADER *aBHead,unsigned char **aBits,PRInt extern PRInt32 CalcBytesSpan(PRUint32 aWidth,PRUint32 aBitsPixel); +#define RED16(x) ((x)&0x7C00)>>7 +#define GREEN16(x) ((x)&0x3E0)>>2 +#define BLUE16(x) ((x)&0x1F)<<3 //------------------------------------------------------------ @@ -288,9 +291,7 @@ nsresult rv; rv = NSRepository::CreateInstance(kBlenderCID, nsnull, kBlenderIID, (void **)&gImageblender); gImageblender->Init(gSrcdc,gDestdc); - } - } //------------------------------------------------------------ @@ -315,6 +316,7 @@ void Restore(nsIBlender *aBlender,nsIImage *aImage) { PRUint8 *thebytes,*curbyte,*srcbytes,*cursourcebytes; +PRUint16 *cur16; PRInt32 w,h,ls,x,y,numbytes,sls; HDC dstdc; HBITMAP srcbits,tb1; @@ -343,22 +345,45 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext(); w = aImage->GetWidth(); ls = aImage->GetLineStride(); sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel); - for(y=0;yDrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight()); + //drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight()); } //------------------------------------------------------------ @@ -366,6 +391,7 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext(); void InterActiveBlend(nsIBlender *aBlender,nsIImage *aImage) { +nsresult result; float blendamount; nsString str; PRInt32 numerror,i,height,width; @@ -392,27 +418,35 @@ MSG msg; width = gBlendImage->GetWidth(); height = gBlendImage->GetHeight(); - Compositetest(aBlender,aImage,cpos.x,cpos.y,width,height,0,0,blendamount,PR_TRUE); - Restore(aBlender,aImage); + result = Compositetest(aBlender,aImage,cpos.x,cpos.y,width,height,0,0,blendamount,PR_TRUE); - if(GetMessage(&msg,NULL,0,0)) + if(result == NS_OK) { - TranslateMessage(&msg); - DispatchMessage(&msg); + Restore(aBlender,aImage); + + if(GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } + else + break; } } } //------------------------------------------------------------ -void +nsresult Compositetest(nsIBlender *aBlender,nsIImage *aImage, PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth,PRInt32 aHeight, PRInt32 aDX, PRInt32 aDY, float aBlendAmount,PRBool aBuff) { +nsresult result = NS_ERROR_FAILURE; PRUint8 *thebytes,*curbyte,*srcbytes,*cursourcebytes; +PRUint16 *cur16; PRInt32 w,h,ls,x,y,numbytes,sls; HDC srcdc,dstdc; HBITMAP srcbits,tb1; @@ -424,42 +458,71 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext(); srcdc = aBlender->GetSrcDS(); dstdc = aBlender->GetDstDS(); - aBlender->Blend(srcdc,aSX,aSY,aWidth,aHeight,dstdc,0, 0,aBlendAmount,aBuff); + result = aBlender->Blend(aSX,aSY,aWidth,aHeight,dstdc,0, 0,aBlendAmount,aBuff); - // this takes the Destination DC and copies the information into aImage - tb1 = CreateCompatibleBitmap(dstdc,3,3); - srcbits = ::SelectObject(dstdc, tb1); - numbytes = ::GetObject(srcbits,sizeof(BITMAP),&srcinfo); - // put into a DIB - BuildDIB(&srcbinfo,&srcbytes,srcinfo.bmWidth,srcinfo.bmHeight,srcinfo.bmBitsPixel); - numbytes = ::GetDIBits(dstdc,srcbits,0,srcinfo.bmHeight,srcbytes,(LPBITMAPINFO)srcbinfo,DIB_RGB_COLORS); - - ::SelectObject(dstdc,srcbits); - DeleteObject(tb1); - - - // copy the information back into the source - thebytes = aImage->GetBits(); - h = aImage->GetHeight(); - w = aImage->GetWidth(); - ls = aImage->GetLineStride(); - sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel); - for(y=0;yGetBits(); + h = aImage->GetHeight(); + w = aImage->GetWidth(); + ls = aImage->GetLineStride(); + sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel); + + + // put the bitmap back into the image + if(srcinfo.bmBitsPixel==24) { - *curbyte = *cursourcebytes; - curbyte++; - cursourcebytes++; + for(y=0;yDrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight()); + drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight()); + } + return(result); } //------------------------------------------------------------ @@ -1091,6 +1154,7 @@ PRUint8 *colortable; case 8: numpalletcolors = 256; break; + case 16: case 24: numpalletcolors = 0; break;