summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <quikee@gmail.com>2012-06-25 21:07:06 +0200
committerTomaž Vajngerl <quikee@gmail.com>2012-06-25 21:24:47 +0200
commit764525b39c78bfad1f6fc44a8517a565547f67cf (patch)
treeae00865af2be96114df9729ceda96e84d3ea3e5f
parent16e73f6d728d7fe40c4a87ee7e29caf649090407 (diff)
use only Bitmap scaling and fixes to scaling
"grfmgr" uses its own scaling functions instead of the scaling functions available on Bitmap object. The step to use the Bitmap::Scale for most scenarios was already made, now the "grfmgr" functions are not used anymore. In addition this commit fixes croping the bitmap with large zoom levels. Change-Id: Ib27029d2cdf4684146befc131e3c72656dfa407c
-rw-r--r--svtools/source/graphic/grfmgr2.cxx315
1 files changed, 123 insertions, 192 deletions
diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 33192b596595..fa01654ea0bd 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -265,228 +265,159 @@ sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt,
return bRet;
}
-// -----------------------------------------------------------------------------
-
-sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
- const Point& rPt, const Size& rSz,
- const BitmapEx& rBmpEx, const GraphicAttr& rAttr,
+sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOutputDevice,
+ const Point& rPoint, const Size& rSize,
+ const BitmapEx& rBitmapEx, const GraphicAttr& rAttr,
const sal_uLong nFlags, BitmapEx* pBmpEx )
{
- sal_uInt16 nRot10 = rAttr.GetRotation() % 3600;
- Point aOutPtPix;
- Size aOutSzPix;
- Size aUnrotatedSzPix( pOut->LogicToPixel( rSz ) );
- sal_Bool bRet = sal_False;
+ bool bRet = false;
+ Point aOutPointInPixels;
+ Size aOutSizeInPixels;
+ int nRotation = rAttr.GetRotation() % 3600;
+ Size aUnrotatedSizeInPixels( pOutputDevice->LogicToPixel( rSize ) );
- if( nRot10 )
- {
- Polygon aPoly( Rectangle( rPt, rSz ) );
+ BitmapEx aBitmapEx( rBitmapEx );
- aPoly.Rotate( rPt, nRot10 );
- const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
- aOutPtPix = pOut->LogicToPixel( aRotBoundRect.TopLeft() );
- aOutSzPix = pOut->LogicToPixel( aRotBoundRect.GetSize() );
+ if( !aUnrotatedSizeInPixels.Width() || !aUnrotatedSizeInPixels.Height() )
+ return false;
+
+ if( nRotation )
+ {
+ Polygon aRotationPolygon( Rectangle( rPoint, rSize ) );
+ aRotationPolygon.Rotate( rPoint, nRotation );
+ const Rectangle aRotationBoundRectangle( aRotationPolygon.GetBoundRect() );
+ aOutPointInPixels = pOutputDevice->LogicToPixel( aRotationBoundRectangle.TopLeft() );
+ aOutSizeInPixels = pOutputDevice->LogicToPixel( aRotationBoundRectangle.GetSize() );
+
+ // rotate the image before further processing
+ aBitmapEx.Rotate( nRotation, COL_TRANSPARENT );
}
else
{
- aOutPtPix = pOut->LogicToPixel( rPt );
- aOutSzPix = aUnrotatedSzPix;
+ aOutPointInPixels = pOutputDevice->LogicToPixel( rPoint );
+ aOutSizeInPixels = aUnrotatedSizeInPixels;
}
- if( aUnrotatedSzPix.Width() && aUnrotatedSzPix.Height() )
+ Point aOutPoint;
+ Size aOutSize;
+ const Size& rBitmapSizePixels = rBitmapEx.GetSizePixel();
+ long nStartX, nStartY, nEndX, nEndY;
+ bool isHorizontalMirrored = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
+ bool isVerticalMirrored = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
+
+ Rectangle aBmpRect( aOutPointInPixels, aOutSizeInPixels );
+
+ // calculate output sizes
+ if( !pBmpEx )
{
- BitmapEx aBmpEx( rBmpEx );
- BitmapEx aOutBmpEx;
- Point aOutPt;
- Size aOutSz;
- const Size rBmpSzPix = rBmpEx.GetSizePixel();
- const long nW = rBmpSzPix.Width();
- const long nH = rBmpSzPix.Height();
- const long nNewW = aUnrotatedSzPix.Width();
- const long nNewH = aUnrotatedSzPix.Height();
- double fTmp;
- long* pMapIX = new long[ nNewW ];
- long* pMapFX = new long[ nNewW ];
- long* pMapIY = new long[ nNewH ];
- long* pMapFY = new long[ nNewH ];
- long nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1;
- long nX, nY, nTmp, nTmpX, nTmpY;
- sal_Bool bHMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
- sal_Bool bVMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
+ Point aPoint;
+ Rectangle aOutRect( aPoint, pOutputDevice->GetOutputSizePixel() );
- if( !( nFlags & GRFMGR_DRAW_SMOOTHSCALE ))
+ if( pOutputDevice->GetOutDevType() == OUTDEV_WINDOW )
{
- // #98290# Use a different mapping for non-interpolating mode, to avoid missing rows/columns
- const double fRevScaleX = ( nNewW > 1L ) ? ( (double) nW / nNewW ) : 0.0;
- const double fRevScaleY = ( nNewH > 1L ) ? ( (double) nH / nNewH ) : 0.0;
-
- // create horizontal mapping table
- for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ )
+ const Region aPaintRgn( ( (Window*) pOutputDevice )->GetPaintRegion() );
+ if( !aPaintRgn.IsNull() )
{
- fTmp = nX * fRevScaleX;
-
- if( bHMirr )
- fTmp = nTmpX - fTmp;
-
- // #98290# Do not use round to zero, otherwise last column will be missing
- pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp );
- pMapFX[ nX ] = fTmp >= nTmp+1 ? 1048576 : 0;
- }
-
- // create vertical mapping table
- for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ )
- {
- fTmp = nY * fRevScaleY;
-
- if( bVMirr )
- fTmp = nTmpY - fTmp;
-
- // #98290# Do not use round to zero, otherwise last row will be missing
- pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp );
- pMapFY[ nY ] = fTmp >= nTmp+1 ? 1048576 : 0;
+ aOutRect.Intersection( pOutputDevice->LogicToPixel( aPaintRgn.GetBoundRect() ) );
}
}
+ aOutRect.Intersection( aBmpRect );
- // calculate output sizes
- if( !pBmpEx )
+ if( !aOutRect.IsEmpty() )
{
- Point aPt;
- Rectangle aOutRect( aPt, pOut->GetOutputSizePixel() );
- Rectangle aBmpRect( aOutPtPix, aOutSzPix );
+ 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( aOutPointInPixels );
+ aOutSize = pOutputDevice->PixelToLogic( aOutSizeInPixels );
+ nStartX = nStartY = 0;
+ nEndX = aOutSizeInPixels.Width() - 1L;
+ nEndY = aOutSizeInPixels.Height() - 1L;
+ }
- if( pOut->GetOutDevType() == OUTDEV_WINDOW )
- {
- const Region aPaintRgn( ( (Window*) pOut )->GetPaintRegion() );
- if( !aPaintRgn.IsNull() )
- aOutRect.Intersection( pOut->LogicToPixel( aPaintRgn.GetBoundRect() ) );
- }
- aOutRect.Intersection( aBmpRect );
+ if( nStartX < 0L )
+ return false;
- if( !aOutRect.IsEmpty() )
- {
- aOutPt = pOut->PixelToLogic( aOutRect.TopLeft() );
- aOutSz = pOut->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
- {
- aOutPt = pOut->PixelToLogic( aOutPtPix );
- aOutSz = pOut->PixelToLogic( aOutSzPix );
- nStartX = nStartY = 0;
- nEndX = aOutSzPix.Width() - 1L;
- nEndY = aOutSzPix.Height() - 1L;
- }
+ // do transformation
- // do transformation
- if( nStartX >= 0L )
- {
- const sal_Bool bSimple = ( 1 == nW || 1 == nH );
+ // #105229# Don't scale if output size equals bitmap size
+ // #107226# Copy through only if we're not mirroring
+ if( !isHorizontalMirrored &&
+ !isVerticalMirrored &&
+ aOutSizeInPixels == rBitmapSizePixels &&
+ !nRotation)
+ {
+ // #107226# Use original dimensions when just copying through
+ aOutPoint = pOutputDevice->PixelToLogic( aOutPointInPixels );
+ aOutSize = pOutputDevice->PixelToLogic( aOutSizeInPixels );
+ bRet = true;
+ }
+ else
+ {
+ // calculate scaling factors
+ double fScaleX = aBmpRect.GetWidth() / (double) aBitmapEx.GetSizePixel().Width();
+ double fScaleY = aBmpRect.GetHeight() / (double) aBitmapEx.GetSizePixel().Height();
- if( nRot10 )
- {
- if( bSimple )
- {
- bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSzPix );
+ // calculate crop regions on original non-scaled bitmap
+ long nOriginalStartX = nStartX / fScaleX;
+ long nOriginalEndX = nEndX / fScaleX;
+ long nOriginalStartY = nStartY / fScaleY;
+ long nOriginalEndY = nEndY / fScaleY;
- if( bRet )
- bRet = aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
- }
- else if( nFlags & GRFMGR_DRAW_SMOOTHSCALE )
- {
- // Scale using Bitmap::Scale() rather than this algorithm, as that one provides
- // better quality, while being somewhat slower (the result should be cached though).
- aOutBmpEx = aBmpEx;
- bRet = true;
- if( bHMirr || bVMirr )
- bRet = aOutBmpEx.Mirror(( bHMirr ? BMP_MIRROR_HORZ : BMP_MIRROR_NONE )
- | ( bVMirr ? BMP_MIRROR_VERT : BMP_MIRROR_NONE ));
- if( bRet )
- bRet = aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
- if( bRet ) // scale as last (rotating would destroy the smooth scaling)
- bRet = aOutBmpEx.Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ));
- }
- else
- {
- bRet = ImplCreateRotatedScaled( aBmpEx,
- nRot10, aOutSzPix, aUnrotatedSzPix,
- pMapIX, pMapFX, pMapIY, pMapFY, nStartX, nEndX, nStartY, nEndY,
- aOutBmpEx );
- }
- }
- else
- {
- // #105229# Don't scale if output size equals bitmap size
- // #107226# Copy through only if we're not mirroring
- if( !bHMirr && !bVMirr && aOutSzPix == rBmpSzPix )
- {
- // #107226# Use original dimensions when just copying through
- aOutPt = pOut->PixelToLogic( aOutPtPix );
- aOutSz = pOut->PixelToLogic( aOutSzPix );
- aOutBmpEx = aBmpEx;
- bRet = sal_True;
- }
- else
- {
- if( bSimple )
- bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) );
- else if( nFlags & GRFMGR_DRAW_SMOOTHSCALE )
- {
- // Scale using Bitmap::Scale() rather than this algorithm, as that one provides
- // better quality, while being somewhat slower (the result should be cached though).
- aOutBmpEx = aBmpEx;
- bRet = aOutBmpEx.Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ));
- if( bRet && ( bHMirr || bVMirr ))
- bRet = aOutBmpEx.Mirror(( bHMirr ? BMP_MIRROR_HORZ : BMP_MIRROR_NONE )
- | ( bVMirr ? BMP_MIRROR_VERT : BMP_MIRROR_NONE ));
- }
- else
- {
- bRet = ImplCreateScaled( aBmpEx,
- pMapIX, pMapFX, pMapIY, pMapFY,
- nStartX, nEndX, nStartY, nEndY,
- aOutBmpEx );
- }
- }
- }
+ Size aScaleSize( nEndX - nStartX + 1, nEndY - nStartY + 1 );
- if( bRet )
- {
- // attribute adjustment if neccessary
- if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsTransparent() )
- ImplAdjust( aOutBmpEx, rAttr, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY );
+ // crop the bitmap, so we deal with a smaller bitmap
+ // todo: join crop and scale step into one step on Bitmap to decrease processing
+ bRet = aBitmapEx.Crop( Rectangle( nOriginalStartX, nOriginalStartY, nOriginalEndX, nOriginalEndY ) );
- // OutDev adjustment if neccessary
- if( pOut->GetOutDevType() != OUTDEV_PRINTER && pOut->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 )
- aOutBmpEx.Dither( BMP_DITHER_MATRIX );
- }
- }
+ // mirror the image - this should not impact the picture dimenstions
+ if( isHorizontalMirrored || isVerticalMirrored )
+ bRet = aBitmapEx.Mirror( rAttr.GetMirrorFlags() );
+
+ // depending on the flags, scale the image to the desired proportions
+ // use FAST scale if no smooth scale is desired
+ if( !( nFlags & GRFMGR_DRAW_SMOOTHSCALE ))
+ bRet = aBitmapEx.Scale( aScaleSize, BMP_SCALE_FAST );
+ else
+ bRet = aBitmapEx.Scale( aScaleSize );
+ }
- // delete lookup tables
- delete[] pMapIX;
- delete[] pMapFX;
- delete[] pMapIY;
- delete[] pMapFY;
+ if( bRet )
+ {
+ // attribute adjustment if neccessary
+ if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsTransparent() )
+ ImplAdjust( aBitmapEx, rAttr, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY );
+
+ // OutDev adjustment if neccessary
+ if( pOutputDevice->GetOutDevType() != OUTDEV_PRINTER &&
+ pOutputDevice->GetBitCount() <= 8 &&
+ aBitmapEx.GetBitCount() >= 8 )
+ {
+ aBitmapEx.Dither( BMP_DITHER_MATRIX );
+ }
+ }
- // create output
- if( bRet )
+ // create output
+ if( bRet )
+ {
+ if( pBmpEx )
{
- if( !pBmpEx )
- pOut->DrawBitmapEx( aOutPt, aOutSz, aOutBmpEx );
- else
- {
- if( !rAttr.IsTransparent() && !aOutBmpEx.IsAlpha() )
- aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOut ), aOutBmpEx.GetMask() );
+ if( !rAttr.IsTransparent() && !aBitmapEx.IsAlpha() )
+ aBitmapEx = BitmapEx( aBitmapEx.GetBitmap().CreateDisplayBitmap( pOutputDevice ), aBitmapEx.GetMask() );
- pOut->DrawBitmapEx( aOutPt, aOutSz, *pBmpEx = aOutBmpEx );
- }
+ *pBmpEx = aBitmapEx;
}
+ pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, aBitmapEx);
}
return bRet;