diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx index 2cc7ae3762e5..299f883f8c5c 100644 --- a/svtools/source/graphic/grfmgr2.cxx +++ b/svtools/source/graphic/grfmgr2.cxx @@ -46,6 +46,7 @@ #define WATERMARK_LUM_OFFSET 50 #define WATERMARK_CON_OFFSET -70 +#define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<20L)+nFrac*((long)(cVal1)-(cVal0)))>>20L)) // ------------------ // - GraphicManager - @@ -264,172 +265,659 @@ sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, return bRet; } -sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOutputDevice, - const Point& rPoint, const Size& rSize, - const BitmapEx& rBitmapEx, const GraphicAttr& rAttributes, - const sal_uLong nFlags, BitmapEx* pResultBitmapEx ) +sal_Bool ImplCreateRotatedScaled( const BitmapEx& rBmpEx, const GraphicAttr& rAttributes, + sal_uInt16 nRot10, const Size& rUnrotatedSzPix, + long nStartX, long nEndX, long nStartY, long nEndY, + BitmapEx& rOutBmpEx ) { - bool bRet = false; + const long aUnrotatedWidth = rUnrotatedSzPix.Width(); + const long aUnrotatedHeight = rUnrotatedSzPix.Height(); + const long aBitmapWidth = rBmpEx.GetSizePixel().Width(); + const long aBitmapHeight = rBmpEx.GetSizePixel().Height(); - Point aUnrotatedPointInPixels( pOutputDevice->LogicToPixel( rPoint ) ); - Size aUnrotatedSizeInPixels( pOutputDevice->LogicToPixel( rSize ) ); + long nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY, nTmp; + double fTmp; - if( aUnrotatedSizeInPixels.Width() <= 0 || aUnrotatedSizeInPixels.Height() <= 0) - return false; + bool bHMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0; + bool bVMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0; - Point aOutPointInPixels; - Size aOutSizeInPixels; - BitmapEx aBitmapEx( rBitmapEx ); - int nRotation = rAttributes.GetRotation() % 3600; + long* pMapIX = new long[ aUnrotatedWidth ]; + long* pMapFX = new long[ aUnrotatedWidth ]; + long* pMapIY = new long[ aUnrotatedHeight ]; + long* pMapFY = new long[ aUnrotatedHeight ]; - if( nRotation != 0 ) + const double fScaleX = ( aUnrotatedWidth - 1 ) / (double) ( aBitmapWidth - 1 ); + const double fScaleY = ( aUnrotatedHeight - 1 ) / (double) ( aBitmapHeight - 1 ); + + const double fRevScaleX = 1.0 / fScaleX; + const double fRevScaleY = 1.0 / fScaleY; + + int x,y; + + // create horizontal mapping table + for( x = 0, nTmpX = aBitmapWidth - 1L, nTmp = aBitmapWidth - 2L; x < aUnrotatedWidth; x++ ) { - Polygon aPoly( Rectangle( rPoint, rSize ) ); - aPoly.Rotate( rPoint, nRotation ); - const Rectangle aRotationBoundRect( aPoly.GetBoundRect() ); - aOutPointInPixels = pOutputDevice->LogicToPixel( aRotationBoundRect.TopLeft() ); - aOutSizeInPixels = pOutputDevice->LogicToPixel( aRotationBoundRect.GetSize() ); - } - else - { - aOutPointInPixels = aUnrotatedPointInPixels; - aOutSizeInPixels = aUnrotatedSizeInPixels; + fTmp = x * fRevScaleX; + + if( bHMirr ) + fTmp = nTmpX - fTmp; + + pMapIX[ x ] = MinMax( fTmp, 0, nTmp ); + pMapFX[ x ] = (long) ( ( fTmp - pMapIX[ x ] ) * 1048576.0 ); } - Point aOutPoint; - Size aOutSize; - - const Size& rBitmapSizePixels = rBitmapEx.GetSizePixel(); - Rectangle aCropRectangle(0, 0, 0, 0); - - bool isHorizontalMirrored = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0; - bool isVerticalMirrored = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0; - - // calculate output sizes - if( true || !pResultBitmapEx ) + // create vertical mapping table + for( y = 0, nTmpY = aBitmapHeight - 1L, nTmp = aBitmapHeight - 2L; y < aUnrotatedHeight; y++ ) { - Rectangle aBitmapRectangle( aOutPointInPixels, aOutSizeInPixels ); - Rectangle aOutRect( Point(), pOutputDevice->GetOutputSizePixel() ); + fTmp = y * fRevScaleY; - if( pOutputDevice->GetOutDevType() == OUTDEV_WINDOW ) + if( bVMirr ) + fTmp = nTmpY - fTmp; + + pMapIY[ y ] = MinMax( fTmp, 0, nTmp ); + pMapFY[ y ] = (long) ( ( fTmp - pMapIY[ y ] ) * 1048576.0 ); + } + + + Bitmap aBmp( rBmpEx.GetBitmap() ); + Bitmap aOutBmp; + BitmapReadAccess* pReadAccess = aBmp.AcquireReadAccess(); + BitmapWriteAccess* pWriteAccess; + + const double fCosAngle = cos( nRot10 * F_PI1800 ); + const double fSinAngle = sin( nRot10 * F_PI1800 ); + const long aTargetWidth = nEndX - nStartX + 1L; + const long aTargetHeight = nEndY - nStartY + 1L; + long* pCosX = new long[ aTargetWidth ]; + long* pSinX = new long[ aTargetWidth ]; + long* pCosY = new long[ aTargetHeight ]; + long* pSinY = new long[ aTargetHeight ]; + long nUnRotX, nUnRotY, nSinY, nCosY; + sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; + bool bRet = false; + + Polygon aPoly( Rectangle( Point(), rUnrotatedSzPix ) ); + aPoly.Rotate( Point(), nRot10 ); + Rectangle aNewBound( aPoly.GetBoundRect() ); + + bool scaleByAveraging = fScaleX < 0.6 || fScaleY < 0.6; + + // create horizontal mapping table + for( x = 0, nTmpX = aNewBound.Left() + nStartX; x < aTargetWidth; x++ ) + { + pCosX[ x ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) ); + pSinX[ x ] = FRound( fSinAngle * fTmp ); + } + + // create vertical mapping table + for( y = 0, nTmpY = aNewBound.Top() + nStartY; y < aTargetHeight; y++ ) + { + pCosY[ y ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) ); + pSinY[ y ] = FRound( fSinAngle * fTmp ); + } + + if( pReadAccess ) + { + aOutBmp = Bitmap( Size( aTargetWidth, aTargetHeight ), 24 ); + pWriteAccess = aOutBmp.AcquireWriteAccess(); + + if( pWriteAccess ) { - const Region aPaintRegion( ( (Window*) pOutputDevice )->GetPaintRegion() ); + BitmapColor aColRes; - if( !aPaintRegion.IsNull() ) - aOutRect.Intersection( pOutputDevice->LogicToPixel( aPaintRegion.GetBoundRect() ) ); - } - aOutRect.Intersection( aBitmapRectangle ); + if ( !scaleByAveraging ) + { + if( pReadAccess->HasPalette() ) + { + for( y = 0; y < aTargetHeight; y++ ) + { + nSinY = pSinY[ y ]; + nCosY = pCosY[ y ]; - if( !aOutRect.IsEmpty() ) - { - aOutPoint = pOutputDevice->PixelToLogic( aOutRect.TopLeft() ); - aOutSize = pOutputDevice->PixelToLogic( aOutRect.GetSize() ); + for( x = 0; x < aTargetWidth; x++ ) + { + nUnRotX = ( pCosX[ x ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ x ] + nCosY ) >> 8; - aCropRectangle = Rectangle( - aOutRect.Left() - aBitmapRectangle.Left(), - aOutRect.Top() - aBitmapRectangle.Top(), - aOutRect.Right() - aBitmapRectangle.Left(), - aOutRect.Bottom() - aBitmapRectangle.Top() ); - } - } - else - { - aOutPoint = pOutputDevice->PixelToLogic( aOutPointInPixels ); - aOutSize = pOutputDevice->PixelToLogic( aOutSizeInPixels ); + if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) && + ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; - aCropRectangle = Rectangle( - 0, 0, - aOutSizeInPixels.Width() - 1, - aOutSizeInPixels.Height() - 1 ); - } + const BitmapColor& rCol0 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, nTmpX ) ); + const BitmapColor& rCol1 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, ++nTmpX ) ); + cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX ); + cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX ); + cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX ); + const BitmapColor& rCol3 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( ++nTmpY, nTmpX ) ); + const BitmapColor& rCol2 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, --nTmpX ) ); + cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX ); + cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX ); + cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX ); - if( aCropRectangle.GetWidth() <= 0 && aCropRectangle.GetHeight() <= 0 ) - return false; + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWriteAccess->SetPixel( y, x, aColRes ); + } + } + } + } + else + { + BitmapColor aCol0, aCol1; - // do transformation - if( !isHorizontalMirrored && - !isVerticalMirrored && - !nRotation && - aOutSizeInPixels == rBitmapSizePixels) - { - // simple copy thorugh - aOutPoint = pOutputDevice->PixelToLogic( aOutPointInPixels ); - aOutSize = pOutputDevice->PixelToLogic( aOutSizeInPixels ); - bRet = true; - } - else - { - // mirror the image - this should not impact the picture dimenstions - if( isHorizontalMirrored || isVerticalMirrored ) - bRet = aBitmapEx.Mirror( rAttributes.GetMirrorFlags() ); + for( y = 0; y < aTargetHeight; y++ ) + { + nSinY = pSinY[ y ]; + nCosY = pCosY[ y ]; - // prepare rotation if needed - if (nRotation != 0) - { - Polygon aPoly( Rectangle( Point(), aUnrotatedSizeInPixels) ); - aPoly.Rotate( Point(), nRotation ); - Rectangle aNewBound( aPoly.GetBoundRect() ); + for( x = 0; x < aTargetWidth; x++ ) + { + nUnRotX = ( pCosX[ x ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ x ] + nCosY ) >> 8; - aCropRectangle = Rectangle ( - aCropRectangle.Left() + aNewBound.Left(), - aCropRectangle.Top() + aNewBound.Top(), - aCropRectangle.Right() + aNewBound.Left(), - aCropRectangle.Bottom() + aNewBound.Top() ); + if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) && + ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + aCol0 = pReadAccess->GetPixel( nTmpY, nTmpX ); + aCol1 = pReadAccess->GetPixel( nTmpY, ++nTmpX ); + cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aCol1 = pReadAccess->GetPixel( ++nTmpY, nTmpX ); + aCol0 = pReadAccess->GetPixel( nTmpY, --nTmpX ); + cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX ); + cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX ); + cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX ); + + aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) ); + aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) ); + aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) ); + pWriteAccess->SetPixel( y, x, aColRes ); + } + } + } + } + } + else + { + double aSumRed, aSumGreen, aSumBlue, aCount; + BitmapColor aColor; + BitmapColor aResultColor; + + for( y = 0; y < aTargetHeight; y++ ) + { + nSinY = pSinY[ y ]; + nCosY = pCosY[ y ]; + + for( x = 0; x < aTargetWidth; x++ ) + { + double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0; + double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0; + + if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) && + ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) ) + { + double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5; + double dYEnd = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5; + + int yStart = MinMax( dYStart, 0, aBitmapHeight - 1); + int yEnd = MinMax( dYEnd, 0, aBitmapHeight - 1); + + double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5; + double dXEnd = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5; + + int xStart = MinMax( dXStart, 0, aBitmapWidth - 1); + int xEnd = MinMax( dXEnd, 0, aBitmapWidth - 1); + + aSumRed = aSumGreen = aSumBlue = 0.0; + aCount = 0; + + for (int yIn = yStart; yIn <= yEnd; yIn++) + { + for (int xIn = xStart; xIn <= xEnd; xIn++) + { + aColor = pReadAccess->GetPixel( yIn, xIn ); + + if( pReadAccess->HasPalette() ) + aColor = pReadAccess->GetPaletteColor( aColor ); + + aSumRed += aColor.GetRed(); + aSumGreen += aColor.GetGreen(); + aSumBlue += aColor.GetBlue(); + + aCount++; + } + } + + aResultColor.SetRed( MinMax( aSumRed / aCount, 0, 255) ); + aResultColor.SetGreen( MinMax( aSumGreen / aCount, 0, 255) ); + aResultColor.SetBlue( MinMax( aSumBlue / aCount, 0, 255) ); + + pWriteAccess->SetPixel( y, x, aResultColor ); + } + } + } + } + + aOutBmp.ReleaseAccess( pWriteAccess ); + bRet = true; } - // calculate scaling factors - double fScaleX = aUnrotatedSizeInPixels.Width() / (double) rBitmapSizePixels.Width(); - double fScaleY = aUnrotatedSizeInPixels.Height() / (double) rBitmapSizePixels.Height(); + aBmp.ReleaseAccess( pReadAccess ); + } - if( nFlags & GRFMGR_DRAW_SMOOTHSCALE ) + // mask processing + if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 0 && nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) ) + { + bRet = false; + + if( rBmpEx.IsAlpha() ) { - bRet = aBitmapEx.ScaleCropRotate( fScaleX, fScaleY, aCropRectangle, nRotation, COL_TRANSPARENT ); + AlphaMask aAlpha( rBmpEx.GetAlpha() ); + AlphaMask aOutAlpha; + + pReadAccess = aAlpha.AcquireReadAccess(); + + if( pReadAccess ) + { + aOutAlpha = AlphaMask( Size( aTargetWidth, aTargetHeight ) ); + pWriteAccess = aOutAlpha.AcquireWriteAccess(); + + if( pWriteAccess ) + { + if( pReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL && + pWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) + { + if ( !scaleByAveraging ) + { + Scanline pLine0, pLine1, pLineW; + + for( nY = 0; nY < aTargetHeight; nY++ ) + { + nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; + pLineW = pWriteAccess->GetScanline( nY ); + + for( nX = 0; nX < aTargetWidth; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) && + ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) ) + { + nTmpX = pMapIX[ nUnRotX ], nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + pLine0 = pReadAccess->GetScanline( nTmpY++ ); + pLine1 = pReadAccess->GetScanline( nTmpY ); + + const long nAlpha0 = pLine0[ nTmpX ]; + const long nAlpha2 = pLine1[ nTmpX++ ]; + const long nAlpha1 = pLine0[ nTmpX ]; + const long nAlpha3 = pLine1[ nTmpX ]; + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); + + *pLineW++ = MAP( n0, n1, nTmpFY ); + } + else + *pLineW++ = 255; + } + } + } + else + { + const BitmapColor aTrans( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) ); + BitmapColor aResultColor( 0 ); + double aSum, aCount; + + for( y = 0; y < aTargetHeight; y++ ) + { + nSinY = pSinY[ y ]; + nCosY = pCosY[ y ]; + + for( x = 0; x < aTargetWidth; x++ ) + { + + double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0; + double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0; + + if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) && + ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) ) + { + double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5; + double dYEnd = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5; + + int yStart = MinMax( dYStart, 0, aBitmapHeight - 1); + int yEnd = MinMax( dYEnd, 0, aBitmapHeight - 1); + + double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5; + double dXEnd = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5; + + int xStart = MinMax( dXStart, 0, aBitmapWidth - 1); + int xEnd = MinMax( dXEnd, 0, aBitmapWidth - 1); + + aSum = 0.0; + aCount = 0; + + for (int yIn = yStart; yIn <= yEnd; yIn++) + { + for (int xIn = xStart; xIn <= xEnd; xIn++) + { + aSum += pReadAccess->GetPixel( yIn, xIn ).GetIndex(); + aCount++; + } + } + aResultColor.SetIndex( MinMax( aSum / aCount, 0, 255) ); + pWriteAccess->SetPixel( y, x, aResultColor ); + } + else + { + pWriteAccess->SetPixel( y, x, aTrans ); + } + } + } + } + } + else + { + const BitmapColor aTrans( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) ); + BitmapColor aAlphaVal( 0 ); + + for( nY = 0; nY < aTargetHeight; nY++ ) + { + nSinY = pSinY[ nY ], nCosY = pCosY[ nY ]; + + for( nX = 0; nX < aTargetWidth; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) && + ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) ) + { + nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ]; + nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ]; + + const long nAlpha0 = pReadAccess->GetPixel( nTmpY, nTmpX ).GetIndex(); + const long nAlpha1 = pReadAccess->GetPixel( nTmpY, ++nTmpX ).GetIndex(); + const long nAlpha3 = pReadAccess->GetPixel( ++nTmpY, nTmpX ).GetIndex(); + const long nAlpha2 = pReadAccess->GetPixel( nTmpY, --nTmpX ).GetIndex(); + const long n0 = MAP( nAlpha0, nAlpha1, nTmpFX ); + const long n1 = MAP( nAlpha2, nAlpha3, nTmpFX ); + + aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) ); + pWriteAccess->SetPixel( nY, nX, aAlphaVal ); + } + else + pWriteAccess->SetPixel( nY, nX, aTrans ); + } + } + } + + aOutAlpha.ReleaseAccess( pWriteAccess ); + bRet = sal_True; + } + + aAlpha.ReleaseAccess( pReadAccess ); + } + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha ); } else { - aCropRectangle = Rectangle ( - aCropRectangle.Left() / fScaleX, - aCropRectangle.Top() / fScaleY, - aCropRectangle.Right() / fScaleX, - aCropRectangle.Bottom() / fScaleY ); + Bitmap aOutMsk( Size( aTargetWidth, aTargetHeight ), 1 ); + pWriteAccess = aOutMsk.AcquireWriteAccess(); - bRet = aBitmapEx.Crop( aCropRectangle ); - if ( bRet ) - bRet = aBitmapEx.Scale( fScaleX, fScaleY ); + if( pWriteAccess ) + { + Bitmap aMsk( rBmpEx.GetMask() ); + const BitmapColor aB( pWriteAccess->GetBestMatchingColor( Color( COL_BLACK ) ) ); + const BitmapColor aW( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) ); + BitmapReadAccess* pMAcc = NULL; + + if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != NULL ) ) + { + long* pMapLX = new long[ aUnrotatedWidth ]; + long* pMapLY = new long[ aUnrotatedHeight ]; + BitmapColor aTestB; + + if( pMAcc ) + aTestB = pMAcc->GetBestMatchingColor( Color( COL_BLACK ) ); + + // create new horizontal mapping table + for( nX = 0UL; nX < aUnrotatedWidth; nX++ ) + pMapLX[ nX ] = FRound( (double) pMapIX[ nX ] + pMapFX[ nX ] / 1048576. ); + + // create new vertical mapping table + for( nY = 0UL; nY < aUnrotatedHeight; nY++ ) + pMapLY[ nY ] = FRound( (double) pMapIY[ nY ] + pMapFY[ nY ] / 1048576. ); + + // do mask rotation + for( nY = 0; nY < aTargetHeight; nY++ ) + { + nSinY = pSinY[ nY ]; + nCosY = pCosY[ nY ]; + + for( nX = 0; nX < aTargetWidth; nX++ ) + { + nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8; + nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8; + + if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) && + ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) ) + { + if( pMAcc ) + { + if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB ) + pWriteAccess->SetPixel( nY, nX, aB ); + else + pWriteAccess->SetPixel( nY, nX, aW ); + } + else + pWriteAccess->SetPixel( nY, nX, aB ); + } + else + pWriteAccess->SetPixel( nY, nX, aW ); + } + } + + delete[] pMapLX; + delete[] pMapLY; + + if( pMAcc ) + aMsk.ReleaseAccess( pMAcc ); + + bRet = sal_True; + } + + aOutMsk.ReleaseAccess( pWriteAccess ); + } + + if( bRet ) + rOutBmpEx = BitmapEx( aOutBmp, aOutMsk ); } + + if( !bRet ) + rOutBmpEx = aOutBmp; + } + else + rOutBmpEx = aOutBmp; + + delete[] pSinX; + delete[] pCosX; + delete[] pSinY; + delete[] pCosY; + + delete[] pMapIX; + delete[] pMapFX; + delete[] pMapIY; + delete[] pMapFY; + + return bRet; +} + +sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOutputDevice, + const Point& rPoint, const Size& rSize, + const BitmapEx& rBitmapEx, const GraphicAttr& rAttributes, + const sal_uLong /*nFlags*/, BitmapEx* pBmpEx ) +{ + sal_uInt16 nRot10 = rAttributes.GetRotation() % 3600; + + Point aOutputPointPix; + Size aOutputSizePix; + Point aUnrotatedPointPix( pOutputDevice->LogicToPixel( rPoint ) ); + Size aUnrotatedSizePix( pOutputDevice->LogicToPixel( rSize ) ); + + bool bRet = false; + + if( nRot10 ) + { + Polygon aPoly( Rectangle( rPoint, rSize ) ); + aPoly.Rotate( rPoint, nRot10 ); + const Rectangle aRotBoundRect( aPoly.GetBoundRect() ); + aOutputPointPix = pOutputDevice->LogicToPixel( aRotBoundRect.TopLeft() ); + aOutputSizePix = pOutputDevice->LogicToPixel( aRotBoundRect.GetSize() ); + } + else + { + aOutputPointPix = aUnrotatedPointPix; + aOutputSizePix = aUnrotatedSizePix; } - if( bRet ) + if( aUnrotatedSizePix.Width() && aUnrotatedSizePix.Height() ) { - // attribute adjustment if neccessary - if( rAttributes.IsSpecialDrawMode() - || rAttributes.IsAdjusted() - || rAttributes.IsTransparent() ) + BitmapEx aBmpEx( rBitmapEx ); + BitmapEx aOutBmpEx; + Point aOutPoint; + Size aOutSize; + const Size& rBmpSzPix = rBitmapEx.GetSizePixel(); + const long nW = rBmpSzPix.Width(); + const long nH = rBmpSzPix.Height(); + long nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1; + bool bHMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0; + bool bVMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0; + + // calculate output sizes + if( !pBmpEx ) { - ImplAdjust( aBitmapEx, rAttributes, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY ); + Point aPt; + Rectangle aOutRect( aPt, pOutputDevice->GetOutputSizePixel() ); + Rectangle aBmpRect( aOutputPointPix, aOutputSizePix ); + + if( pOutputDevice->GetOutDevType() == OUTDEV_WINDOW ) + { + const Region aPaintRgn( ( (Window*) pOutputDevice )->GetPaintRegion() ); + if( !aPaintRgn.IsNull() ) + aOutRect.Intersection( pOutputDevice->LogicToPixel( aPaintRgn.GetBoundRect() ) ); + } + + aOutRect.Intersection( aBmpRect ); + + if( !aOutRect.IsEmpty() ) + { + aOutPoint = pOutputDevice->PixelToLogic( aOutRect.TopLeft() ); + aOutSize = pOutputDevice->PixelToLogic( aOutRect.GetSize() ); + nStartX = aOutRect.Left() - aBmpRect.Left(); + nStartY = aOutRect.Top() - aBmpRect.Top(); + nEndX = aOutRect.Right() - aBmpRect.Left(); + nEndY = aOutRect.Bottom() - aBmpRect.Top(); + } + else + { + nStartX = -1L; // invalid + } + } + else + { + aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix ); + aOutSize = pOutputDevice->PixelToLogic( aOutputSizePix ); + nStartX = nStartY = 0; + nEndX = aOutputSizePix.Width() - 1L; + nEndY = aOutputSizePix.Height() - 1L; } - // OutDev adjustment if neccessary - if( pOutputDevice->GetOutDevType() != OUTDEV_PRINTER - && pOutputDevice->GetBitCount() <= 8 - && aBitmapEx.GetBitCount() >= 8 ) + // do transformation + if( nStartX >= 0L ) { - aBitmapEx.Dither( BMP_DITHER_MATRIX ); - } - } + const bool bSimple = ( 1 == nW || 1 == nH ); - // create output - if( bRet ) - { - if( pResultBitmapEx ) + if( nRot10 ) + { + if( bSimple ) + { + bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSizePix ); + + if( bRet ) + aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT ); + } + else + { + bRet = ImplCreateRotatedScaled( aBmpEx, rAttributes, + nRot10, aUnrotatedSizePix, + nStartX, nEndX, nStartY, nEndY, + aOutBmpEx ); + } + } + else + { + if( !bHMirr && !bVMirr && aOutputSizePix == rBmpSzPix ) + { + aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix ); + aOutSize = pOutputDevice->PixelToLogic( aOutputSizePix ); + aOutBmpEx = aBmpEx; + bRet = true; + } + else + { + if( bSimple ) + { + bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) ); + } + else + { + bRet = ImplCreateRotatedScaled( aBmpEx, rAttributes, + nRot10, aUnrotatedSizePix, + nStartX, nEndX, nStartY, nEndY, + aOutBmpEx ); + } + } + } + + if( bRet ) + { + // Attribute adjustment if neccessary + if( rAttributes.IsSpecialDrawMode() || rAttributes.IsAdjusted() || rAttributes.IsTransparent() ) + ImplAdjust( aOutBmpEx, rAttributes, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY ); + + // OutDev adjustment if neccessary + if( pOutputDevice->GetOutDevType() != OUTDEV_PRINTER && pOutputDevice->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 ) + aOutBmpEx.Dither( BMP_DITHER_MATRIX ); + } + } + + // Create output + if( bRet ) { - if( !rAttributes.IsTransparent() && !aBitmapEx.IsAlpha() ) - aBitmapEx = BitmapEx( aBitmapEx.GetBitmap().CreateDisplayBitmap( pOutputDevice ), aBitmapEx.GetMask() ); + if( !pBmpEx ) + pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, aOutBmpEx ); + else + { + if( !rAttributes.IsTransparent() && !aOutBmpEx.IsAlpha() ) + aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOutputDevice ), aOutBmpEx.GetMask() ); - *pResultBitmapEx = aBitmapEx; + pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, *pBmpEx = aOutBmpEx ); + } } - pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, aBitmapEx); } return bRet; diff --git a/vcl/inc/vcl/bitmap.hxx b/vcl/inc/vcl/bitmap.hxx index e1e489f06faf..b73f2075a959 100644 --- a/vcl/inc/vcl/bitmap.hxx +++ b/vcl/inc/vcl/bitmap.hxx @@ -415,12 +415,12 @@ public: double* pBlurVector, double*& pWeights, int*& pPixels, int*& pCount ); public: - Bitmap(); - Bitmap( const Bitmap& rBitmap ); - Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal = NULL ); - Bitmap( const ResId& rResId ); - Bitmap( SalBitmap* pSalBitmap ); - ~Bitmap(); + Bitmap(); + Bitmap( const Bitmap& rBitmap ); + Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal = NULL ); + Bitmap( const ResId& rResId ); + Bitmap( SalBitmap* pSalBitmap ); + ~Bitmap(); Bitmap& operator=( const Bitmap& rBitmap ); inline sal_Bool operator!() const; @@ -448,7 +448,6 @@ public: */ void SetSourceSizePixel( const Size& ); - sal_uInt16 GetBitCount() const; inline sal_uLong GetColorCount() const; inline sal_uLong GetSizeBytes() const; @@ -650,11 +649,6 @@ public: */ sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_DEFAULT ); - /** Scale, crop and rotate the bitmap */ - sal_Bool ScaleCropRotate( - const double& rScaleX, const double& rScaleY, const Rectangle& rRectPixel, long nAngle10, - const Color& rFillColor, sal_uLong nScaleFlag = BMP_SCALE_DEFAULT ); - /** Rotate bitmap by the specified angle @param nAngle10 diff --git a/vcl/inc/vcl/bitmapex.hxx b/vcl/inc/vcl/bitmapex.hxx index 437c70a794a8..2c29d68eeb07 100644 --- a/vcl/inc/vcl/bitmapex.hxx +++ b/vcl/inc/vcl/bitmapex.hxx @@ -268,11 +268,6 @@ public: */ sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_DEFAULT ); - /** Scale, crop and rotate the bitmap */ - sal_Bool ScaleCropRotate( - const double& rScaleX, const double& rScaleY, const Rectangle& rRectPixel, long nAngle10, - const Color& rFillColor, sal_uLong nScaleFlag = BMP_SCALE_DEFAULT ); - /** Rotate bitmap by the specified angle @param nAngle10 diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx index a4900c6df6f2..13b6d13ff55c 100644 --- a/vcl/source/gdi/bitmap3.cxx +++ b/vcl/source/gdi/bitmap3.cxx @@ -2313,237 +2313,4 @@ bool Bitmap::ImplConvolutionPass(Bitmap& aNewBitmap, const int nNewSize, BitmapR return true; } -sal_Bool Bitmap::ScaleCropRotate( - const double& rScaleX, const double& rScaleY, const Rectangle& rRectPixel, long nAngle10, - const Color& rFillColor, sal_uLong /* nScaleFlag */ ) -{ - bool bRet; - - if ( rScaleX < 0.6 || rScaleY < 0.6 ) - { - bRet = ImplTransformAveraging( rScaleX, rScaleY, rRectPixel, nAngle10, rFillColor); - } - else - { - bRet = ImplTransformBilinearFiltering( rScaleX, rScaleY, rRectPixel, nAngle10, rFillColor); - } - - return bRet; -} - -// Scaling algorithm best for shrinking below factor 0.5 where algorithms with limited sampling range show bad results (bilinear, bicubic). -// The algoritm determines the sampling range for one pixel and calculates the average of samples which is the resulting pixel. -bool Bitmap::ImplTransformAveraging( const double& rScaleX, const double& rScaleY, const Rectangle& rRotatedRectangle, const long nAngle10, const Color& rFillColor ) -{ - const Size aSizePix( GetSizePixel() ); - - const int nStartX = rRotatedRectangle.Left(); - const int nStartY = rRotatedRectangle.Top(); - const int nEndX = rRotatedRectangle.Right(); - const int nEndY = rRotatedRectangle.Bottom(); - - const int nTargetWidth = rRotatedRectangle.GetWidth(); - const int nTargetHeight = rRotatedRectangle.GetHeight(); - - const int nOriginWidth = aSizePix.Width(); - const int nOriginHeight = aSizePix.Height(); - - const int nScaledWidth = FRound( nOriginWidth * rScaleX ); - const int nScaledHeight = FRound( nOriginHeight * rScaleY ); - - const double aReverseScaleX = 1.0 / rScaleX; - const double aReverseScaleY = 1.0 / rScaleY; - - const double fCosAngle = cos( nAngle10 * F_PI1800 ); - const double fSinAngle = sin( nAngle10 * F_PI1800 ); - - if( nTargetWidth <= 1L || nTargetHeight <= 1L ) - return false; - - BitmapColor aColor, aResultColor; - - Bitmap aOutBmp( Size( nTargetWidth, nTargetHeight ), 24 ); - - BitmapReadAccess* pReadAccess = AcquireReadAccess(); - BitmapWriteAccess* pWriteAccess = aOutBmp.AcquireWriteAccess(); - - if( !pReadAccess || !pWriteAccess ) - return false; - - const BitmapColor aFillColor( pWriteAccess->GetBestMatchingColor( rFillColor ) ); - - int x, y, xOut, yOut; - int aCount; - double aSumRed, aSumGreen, aSumBlue; - - for( y = nStartY, yOut = 0; y <= nEndY; y++, yOut++ ) - { - for( x = nStartX, xOut = 0; x <= nEndX; x++, xOut++ ) - { - double unrotatedX = fCosAngle * x - fSinAngle * y; - double unrotatedY = fSinAngle * x + fCosAngle * y; - - if ( unrotatedX < 0 - || unrotatedX > nScaledWidth - || unrotatedY < 0 - || unrotatedY > nScaledHeight) - { - pWriteAccess->SetPixel( yOut, xOut, aFillColor ); - } - else - { - double dYStart = ((unrotatedY + 0.5) * aReverseScaleY) - 0.5; - double dYEnd = ((unrotatedY + 1.5) * aReverseScaleY) - 0.5; - - int yStart = MinMax( dYStart, 0, nOriginHeight - 1); - int yEnd = MinMax( dYEnd, 0, nOriginHeight - 1); - - double dXStart = ((unrotatedX + 0.5) * aReverseScaleX) - 0.5; - double dXEnd = ((unrotatedX + 1.5) * aReverseScaleX) - 0.5; - - int xStart = MinMax( dXStart, 0, nOriginWidth - 1); - int xEnd = MinMax( dXEnd, 0, nOriginWidth - 1); - - aSumRed = aSumGreen = aSumBlue = 0.0; - aCount = 0; - - for (int yIn = yStart; yIn <= yEnd; yIn++) - { - for (int xIn = xStart; xIn <= xEnd; xIn++) - { - aColor = pReadAccess->GetPixel( yIn, xIn ); - - if( pReadAccess->HasPalette() ) - aColor = pReadAccess->GetPaletteColor( aColor ); - - aSumRed += aColor.GetRed(); - aSumGreen += aColor.GetGreen(); - aSumBlue += aColor.GetBlue(); - - aCount++; - } - } - - aResultColor.SetRed( MinMax( aSumRed / aCount, 0, 255) ); - aResultColor.SetGreen( MinMax( aSumGreen / aCount, 0, 255) ); - aResultColor.SetBlue( MinMax( aSumBlue / aCount, 0, 255) ); - - pWriteAccess->SetPixel( yOut, xOut, aResultColor ); - } - } - } - - ReleaseAccess( pReadAccess ); - aOutBmp.ReleaseAccess( pWriteAccess ); - ImplAssignWithSize( aOutBmp ); - - return true; -} - -// Bilinear filtering used for shrinking and enlarging the source bitmap. Filtering is also used for rotation. -// Filtering shows bad results at shrinking for a factor less than 0.5 because of limited sampling. -bool Bitmap::ImplTransformBilinearFiltering( const double& rScaleX, const double& rScaleY, const Rectangle& rRotatedRectangle, const long nAngle10, const Color& rFillColor ) -{ - const int nOriginWidth = GetSizePixel().Width(); - const int nOriginHeight = GetSizePixel().Height(); - - const int nScaledWidth = FRound( nOriginWidth * rScaleX ); - const int nScaledHeight = FRound( nOriginHeight * rScaleY ); - - const int nTargetWidth = rRotatedRectangle.GetWidth(); - const int nTargetHeight = rRotatedRectangle.GetHeight(); - - const int nStartX = rRotatedRectangle.Left(); - const int nEndX = rRotatedRectangle.Right(); - const int nStartY = rRotatedRectangle.Top(); - const int nEndY = rRotatedRectangle.Bottom(); - - const double fCosAngle = cos( nAngle10 * F_PI1800 ); - const double fSinAngle = sin( nAngle10 * F_PI1800 ); - - Bitmap aOutBmp( Size( nTargetWidth, nTargetHeight ), 24 ); - - BitmapReadAccess* pReadAccess = AcquireReadAccess(); - BitmapWriteAccess* pWriteAccess = aOutBmp.AcquireWriteAccess(); - - if( !pReadAccess || !pWriteAccess ) - return false; - - const BitmapColor aFillColor( pWriteAccess->GetBestMatchingColor( rFillColor ) ); - - double aReverseScaleX = 1.0 / rScaleX; - double aReverseScaleY = 1.0 / rScaleY; - - BitmapColor aColor00, aColor01, aColor10, aColor11, aResultColor; - - int x, y, xOut, yOut; - - for( y = nStartY, yOut = 0; y <= nEndY; y++, yOut++ ) - { - for( x = nStartX, xOut = 0; x <= nEndX; x++, xOut++ ) - { - double unrotatedX = fCosAngle * x - fSinAngle * y; - double unrotatedY = fSinAngle * x + fCosAngle * y; - - if ( unrotatedX < 0 - || unrotatedX >= nScaledWidth - || unrotatedY < 0 - || unrotatedY >= nScaledHeight) - { - pWriteAccess->SetPixel( yOut, xOut, aFillColor ); - } - else - { - double sy0 = ((unrotatedY + 0.5) * aReverseScaleY) - 0.5; - - int y0 = MinMax( floor( sy0 ), 0, nOriginHeight - 1); - int y1 = MinMax( y0 + 1, 0, nOriginHeight - 1); - - double sx0 = ((unrotatedX + 0.5) * aReverseScaleX) - 0.5; - int x0 = MinMax( floor( sx0 ), 0, nOriginWidth - 1); - int x1 = MinMax( x0 + 1, 0, nOriginWidth - 1); - - aColor00 = pReadAccess->GetPixel( y0, x0 ); - aColor01 = pReadAccess->GetPixel( y1, x0 ); - aColor10 = pReadAccess->GetPixel( y0, x1 ); - aColor11 = pReadAccess->GetPixel( y1, x1 ); - - if( pReadAccess->HasPalette() ) - { - aColor00 = pReadAccess->GetPaletteColor( aColor00 ); - aColor01 = pReadAccess->GetPaletteColor( aColor01 ); - aColor10 = pReadAccess->GetPaletteColor( aColor10 ); - aColor11 = pReadAccess->GetPaletteColor( aColor11 ); - } - - double fx0 = sx0 - x0; - double fy0 = sy0 - y0; - double fx1 = 1.0 - fx0; - double fy1 = 1.0 - fy0; - - double w00 = fx1 * fy1; - double w01 = fx1 * fy0; - double w10 = fx0 * fy1; - double w11 = fx0 * fy0; - - double red = aColor00.GetRed() * w00 + aColor10.GetRed() * w10 + aColor01.GetRed() * w01 + aColor11.GetRed() * w11; - double green = aColor00.GetGreen() * w00 + aColor10.GetGreen() * w10 + aColor01.GetGreen() * w01 + aColor11.GetGreen() * w11; - double blue = aColor00.GetBlue() * w00 + aColor10.GetBlue() * w10 + aColor01.GetBlue() * w01 + aColor11.GetBlue() * w11; - - aResultColor.SetRed( MinMax(red, 0, 255) ); - aResultColor.SetGreen( MinMax(green, 0, 255) ); - aResultColor.SetBlue( MinMax(blue, 0, 255) ); - - pWriteAccess->SetPixel( yOut, xOut, aResultColor ); - } - } - } - - ReleaseAccess( pReadAccess ); - aOutBmp.ReleaseAccess( pWriteAccess ); - ImplAssignWithSize( aOutBmp ); - - return true; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index 5851b743dcfa..06eec646a000 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -389,62 +389,6 @@ sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) return bRet; } -sal_Bool BitmapEx::ScaleCropRotate( - const double& rScaleX, const double& rScaleY, const Rectangle& rRectPixel, - long nAngle10, const Color& rFillColor, sal_uLong nScaleFlag ) -{ - bool bReturn = false; - - if( !!aBitmap ) - { - // If fill color is transpatent - const bool bTransparentRotation = Color( COL_TRANSPARENT ) == rFillColor; - - // If angle is 0, 90, 180 or 270 degreees, then we don't need to create an alpha bitmap. - const bool bRightAngleRotation = (nAngle10 == 0 || nAngle10 == 900 || nAngle10 == 1800 || nAngle10 == 2700); - - if( !bRightAngleRotation && bTransparentRotation ) - { - if( eTransparent == TRANSPARENT_COLOR ) - { - bReturn = aBitmap.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, aTransparentColor, nScaleFlag ); - } - else if( eTransparent == TRANSPARENT_NONE ) - { - bReturn = aBitmap.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, COL_BLACK, nScaleFlag ); - if ( bReturn ) - { - aMask = Bitmap( aBitmapSize, 1 ); - aMask.Erase( COL_BLACK ); - aMask.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, COL_WHITE, nScaleFlag ); - eTransparent = TRANSPARENT_BITMAP; - } - } else { - bReturn = aBitmap.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, COL_BLACK, nScaleFlag ); - if( bReturn && !!aMask ) - { - aMask.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, COL_WHITE, nScaleFlag ); - aMask.Convert( BMP_CONVERSION_8BIT_GREYS ); - } - } - } - else - { - bReturn = aBitmap.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, rFillColor, nScaleFlag ); - if( eTransparent == TRANSPARENT_BITMAP && !!aMask ) - { - bReturn = aMask.ScaleCropRotate( rScaleX, rScaleY, rRectPixel, nAngle10, COL_WHITE, nScaleFlag ); - aMask.Convert( BMP_CONVERSION_8BIT_GREYS ); - } - } - } - - if ( bReturn ) - aBitmapSize = aBitmap.GetSizePixel(); - - return bReturn; -} - sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor ) { sal_Bool bRet = sal_False;