svtools/source/filter/jpeg/jpeg.cxx | 36 ++++- svx/inc/svx/svdundo.hxx | 8 - svx/source/svdraw/svdograf.cxx | 40 +++++ svx/source/svdraw/svdundo.cxx | 41 +++++- vcl/source/gdi/pngread.cxx | 241 +++++++++++++++++++++++++++++------- 5 files changed, 308 insertions(+), 58 deletions(-)
New commits: commit f18ad6132d79540431bf04f090a7472e21a23e49 Author: Armin Le Grand <a...@apache.org> Date: Thu Sep 5 13:01:45 2013 +0000 i122985 Various speedups for graphic object swapping to enhance user experience diff --git a/svtools/source/filter/jpeg/jpeg.cxx b/svtools/source/filter/jpeg/jpeg.cxx index d544e064..62b9f7a 100644 --- a/svtools/source/filter/jpeg/jpeg.cxx +++ b/svtools/source/filter/jpeg/jpeg.cxx @@ -474,14 +474,38 @@ void JPEGReader::FillBitmap() for( long nY = 0L; nY < nHeight; nY++ ) { - pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth; + // #122985# Added fast-lane implementations using CopyScanline with direct supported mem formats + static bool bCheckOwnReader(true); - for( long nX = 0L; nX < nWidth; nX++ ) + if(bCheckOwnReader) + { + // #122985# Trying to copy the RGB data from jpeg import to make things faster. Unfortunately + // it has no GBR format, so RGB three-byte groups need to be 'flipped' to GBR first, + // then CopyScanline can use a memcpy to do the data transport. CopyScanline can also + // do the needed conversion from BMP_FORMAT_24BIT_TC_RGB (and it works well), but this + // is not faster that the old loop below using SetPixel. + sal_uInt8* aSource((sal_uInt8*)pBuffer + nY * nAlignedWidth); + sal_uInt8* aEnd(aSource + (nWidth * 3)); + + for(sal_uInt8* aTmp(aSource); aTmp < aEnd; aTmp += 3) + { + ::std::swap(*aTmp, *(aTmp + 2)); + } + + pAcc->CopyScanline(nY, aSource, BMP_FORMAT_24BIT_TC_BGR, nWidth * 3); + } + else { - aColor.SetRed( *pTmp++ ); - aColor.SetGreen( *pTmp++ ); - aColor.SetBlue( *pTmp++ ); - pAcc->SetPixel( nY, nX, aColor ); + // old version: WritePixel + pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth; + + for( long nX = 0L; nX < nWidth; nX++ ) + { + aColor.SetRed( *pTmp++ ); + aColor.SetGreen( *pTmp++ ); + aColor.SetBlue( *pTmp++ ); + pAcc->SetPixel( nY, nX, aColor ); + } } } } diff --git a/svx/inc/svx/svdundo.hxx b/svx/inc/svx/svdundo.hxx index c804456..cc6ddc3 100644 --- a/svx/inc/svx/svdundo.hxx +++ b/svx/inc/svx/svdundo.hxx @@ -335,10 +335,12 @@ public: class SVX_DLLPUBLIC SdrUndoDelObj : public SdrUndoRemoveObj { +private: + void TryToFlushGraphicContent(); + public: - SdrUndoDelObj(SdrObject& rNewObj, FASTBOOL bOrdNumDirect=sal_False) - : SdrUndoRemoveObj(rNewObj,bOrdNumDirect) { SetOwner(sal_True); } - virtual ~SdrUndoDelObj() {} + SdrUndoDelObj(SdrObject& rNewObj, FASTBOOL bOrdNumDirect=sal_False); + virtual ~SdrUndoDelObj(); virtual void Undo(); virtual void Redo(); diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index 2328272..81daa7a 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -69,6 +69,7 @@ #include <vos/mutex.hxx> #include <drawinglayer/processor2d/objectinfoextractor2d.hxx> #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> +#include <unotools/cacheoptions.hxx> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::io; @@ -80,6 +81,37 @@ using namespace ::com::sun::star::io; #define GRAFSTREAMPOS_INVALID 0xffffffff #define SWAPGRAPHIC_TIMEOUT 5000 +// #122985# it is not correct to se the swap-timeout to a hard-coded 5000ms as it was before. +// Added code and experimented what to do as a good compromize, see description +sal_uInt32 getCacheTimeInMs() +{ + static bool bSetAtAll(true); + + if(bSetAtAll) + { + static bool bSetToPreferenceTime(true); + + if(bSetToPreferenceTime) + { + const SvtCacheOptions aCacheOptions; + const sal_Int32 nSeconds(aCacheOptions.GetGraphicManagerObjectReleaseTime()); + + // the default is 10 minutes. The minimum is one minute, thus 60 seconds. When the minimum + // should match to the former hard-coded 5 seconds, we have a divisor of 12 to use. For the + // default of 10 minutes this would mean 50 seconds. Compared to before this is ten times + // more (would allow better navigation by switching through pages) and is controllable + // by the user by setting the tools/options/memory/Remove_from_memory_after setting. Seems + // to be a good compromize to me. + return nSeconds * 1000 / 12; + } + else + { + return SWAPGRAPHIC_TIMEOUT; + } + } + + return 0; +} // ------------------ // - SdrGraphicLink - @@ -375,7 +407,7 @@ SdrGrafObj::SdrGrafObj() { pGraphic = new GraphicObject; mpReplacementGraphic = 0; - pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() ); onGraphicChanged(); // #i118485# Shear allowed and possible now @@ -402,7 +434,7 @@ SdrGrafObj::SdrGrafObj(const Graphic& rGrf, const Rectangle& rRect) { pGraphic = new GraphicObject( rGrf ); mpReplacementGraphic = 0; - pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() ); onGraphicChanged(); // #i118485# Shear allowed and possible now @@ -429,7 +461,7 @@ SdrGrafObj::SdrGrafObj( const Graphic& rGrf ) { pGraphic = new GraphicObject( rGrf ); mpReplacementGraphic = 0; - pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() ); onGraphicChanged(); // #i118485# Shear allowed and possible now @@ -463,7 +495,7 @@ void SdrGrafObj::SetGraphicObject( const GraphicObject& rGrfObj ) *pGraphic = rGrfObj; delete mpReplacementGraphic; mpReplacementGraphic = 0; - pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), SWAPGRAPHIC_TIMEOUT ); + pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() ); pGraphic->SetUserData(); mbIsPreview = sal_False; SetChanged(); diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx index 8cfe431..f5ec0e9 100644 --- a/svx/source/svdraw/svdundo.cxx +++ b/svx/source/svdraw/svdundo.cxx @@ -42,8 +42,9 @@ #include <svx/svdocapt.hxx> #include <svl/whiter.hxx> #include <svx/e3dsceneupdater.hxx> - -#include "svx/svdviter.hxx" +#include <svx/svdviter.hxx> +#include <svx/svdograf.hxx> +#include <svx/sdr/contact/viewcontactofgraphic.hxx> //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -882,6 +883,38 @@ void SdrUndoInsertObj::Redo() //////////////////////////////////////////////////////////////////////////////////////////////////// +void SdrUndoDelObj::TryToFlushGraphicContent() +{ + SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj); + + if(pSdrGrafObj) + { + sdr::contact::ViewContactOfGraphic* pVC = dynamic_cast< sdr::contact::ViewContactOfGraphic* >(&pSdrGrafObj->GetViewContact()); + + if(pVC) + { + pVC->flushViewObjectContacts(); + pVC->flushGraphicObjects(); + } + + pSdrGrafObj->ForceSwapOut(); + } +} + +SdrUndoDelObj::SdrUndoDelObj(SdrObject& rNewObj, FASTBOOL bOrdNumDirect) +: SdrUndoRemoveObj(rNewObj,bOrdNumDirect) +{ + SetOwner(sal_True); + + // #122985# if graphic object is deleted (but goes to undo) flush it's graphic content + // since it is potentially no longer needed + TryToFlushGraphicContent(); +} + +SdrUndoDelObj::~SdrUndoDelObj() +{ +} + void SdrUndoDelObj::Undo() { SdrUndoRemoveObj::Undo(); @@ -894,6 +927,10 @@ void SdrUndoDelObj::Redo() SdrUndoRemoveObj::Redo(); DBG_ASSERT(!IsOwner(),"RedoDeleteObj: pObj gehoert bereits der UndoAction"); SetOwner(sal_True); + + // #122985# if graphic object is deleted (but goes to undo) flush it's graphic content + // since it is potentially no longer needed + TryToFlushGraphicContent(); } XubString SdrUndoDelObj::GetComment() const diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx index 3e798b5..62a424c 100644 --- a/vcl/source/gdi/pngread.cxx +++ b/vcl/source/gdi/pngread.cxx @@ -151,6 +151,15 @@ private: sal_Bool mbpHYs; // sal_True if pysical size of pixel available sal_Bool mbIgnoreGammaChunk; +#ifdef DBG_UTIL + // do some checks in debug mode + sal_uInt32 mnAllocSizeScanline; + sal_uInt32 mnAllocSizeScanlineAlpha; +#endif + // the temporary Scanline (and alpha) for direct scanline copy to Bitmap + sal_uInt8* mpScanline; + sal_uInt8* mpScanlineAlpha; + bool ReadNextChunk(); void ReadRemainingChunks(); void SkipRemainingChunks(); @@ -204,7 +213,13 @@ PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream ) mbIDAT( sal_False ), mbGamma ( sal_False ), mbpHYs ( sal_False ), - mbIgnoreGammaChunk ( sal_False ) + mbIgnoreGammaChunk ( sal_False ), +#ifdef DBG_UTIL + mnAllocSizeScanline(0), + mnAllocSizeScanlineAlpha(0), +#endif + mpScanline(0), + mpScanlineAlpha(0) { // prepare the PNG data stream mnOrigStreamMode = mrPNGStream.GetNumberFormatInt(); @@ -250,6 +265,9 @@ PNGReaderImpl::~PNGReaderImpl() delete[] mpInflateInBuf; delete[] mpScanPrior; delete mpZCodec; + + delete[] mpScanline; + delete[] mpScanlineAlpha; } // ------------------------------------------------------------------------ @@ -1358,42 +1376,123 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) } else // no palette => truecolor { - if( mbAlphaChannel ) // has RGB + alpha - { // BMP_FORMAT_32BIT_TC_RGBA + // #122985# Added fast-lane implementations using CopyScanline with direct supported mem formats + static bool bCkeckDirectScanline(true); + + if( mbAlphaChannel ) + { + // has RGB + alpha if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample { - if ( mpColorTable != mpDefaultColorTable ) + // BMP_FORMAT_32BIT_TC_RGBA + // only use DirectScanline when we have no preview shifting stuff and accesses to content and alpha + const bool bDoDirectScanline( + bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc && mpMaskAcc); + const bool bCustomColorTable(mpColorTable != mpDefaultColorTable); + + if(bDoDirectScanline) { - for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 ) - ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ], - mpColorTable[ pTmp[ 1 ] ], - mpColorTable[ pTmp[ 2 ] ] ), pTmp[ 3 ] ); + // allocate scanlines on demand, reused for next line + if(!mpScanline) + { +#ifdef DBG_UTIL + mnAllocSizeScanline = maOrigSize.Width() * 3; +#endif + mpScanline = new sal_uInt8[maOrigSize.Width() * 3]; + } + + if(!mpScanlineAlpha) + { +#ifdef DBG_UTIL + mnAllocSizeScanlineAlpha = maOrigSize.Width(); +#endif + mpScanlineAlpha = new sal_uInt8[maOrigSize.Width()]; + } + } + + if(bDoDirectScanline) + { + OSL_ENSURE(mpScanline, "No Scanline allocated (!)"); + OSL_ENSURE(mpScanlineAlpha, "No ScanlineAlpha allocated (!)"); + OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)"); + OSL_ENSURE(mnAllocSizeScanlineAlpha >= maOrigSize.Width(), "Allocated ScanlineAlpha too small (!)"); + sal_uInt8* pScanline(mpScanline); + sal_uInt8* pScanlineAlpha(mpScanlineAlpha); + + for(sal_uInt32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 4) + { + // prepare content line as BGR by reordering when copying + // do not forget to invert alpha (source is alpha, target is opacity) + if(bCustomColorTable) + { + *pScanline++ = mpColorTable[pTmp[2]]; + *pScanline++ = mpColorTable[pTmp[1]]; + *pScanline++ = mpColorTable[pTmp[0]]; + *pScanlineAlpha++ = ~pTmp[3]; + } + else + { + *pScanline++ = pTmp[2]; + *pScanline++ = pTmp[1]; + *pScanline++ = pTmp[0]; + *pScanlineAlpha++ = ~pTmp[3]; + } + } + + // copy scanlines directly to bitmaps for content and alpha; use the formats which + // are able to copy directly to BitmapBuffer + mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3); + mpMaskAcc->CopyScanline(nY, mpScanlineAlpha, BMP_FORMAT_8BIT_PAL, maOrigSize.Width()); } else { -// if ( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible -// { -// int nLineBytes = 4 * maOrigSize.Width(); -// mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_32BIT_TC_RGBA, nLineBytes ); -// pTmp += nLineBytes; -// } -// else + for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 ) { - for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 ) - ImplSetAlphaPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ), pTmp[3] ); + if(bCustomColorTable) + { + ImplSetAlphaPixel( + nY, + nX, + BitmapColor( + mpColorTable[ pTmp[ 0 ] ], + mpColorTable[ pTmp[ 1 ] ], + mpColorTable[ pTmp[ 2 ] ]), + pTmp[ 3 ]); + } + else + { + ImplSetAlphaPixel( + nY, + nX, + BitmapColor( + pTmp[0], + pTmp[1], + pTmp[2]), + pTmp[3]); + } } } } else - { // BMP_FORMAT_64BIT_TC_RGBA + { + // BMP_FORMAT_64BIT_TC_RGBA for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 8 ) - ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ], - mpColorTable[ pTmp[ 2 ] ], - mpColorTable[ pTmp[ 4 ] ] ), pTmp[6] ); + { + ImplSetAlphaPixel( + nY, + nX, + BitmapColor( + mpColorTable[ pTmp[ 0 ] ], + mpColorTable[ pTmp[ 2 ] ], + mpColorTable[ pTmp[ 4 ] ]), + pTmp[6]); + } } } else if( mbTransparent ) // has RGB + transparency - { // BMP_FORMAT_24BIT_TC_RGB + { + // BMP_FORMAT_24BIT_TC_RGB + // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample { for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 ) @@ -1402,7 +1501,7 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) sal_uInt8 nGreen = pTmp[ 1 ]; sal_uInt8 nBlue = pTmp[ 2 ]; sal_Bool bTransparent = ( ( nRed == mnTransRed ) - && ( nGreen == mnTransGreen ) + && ( nGreen == mnTransGreen ) && ( nBlue == mnTransBlue ) ); ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ], @@ -1411,7 +1510,8 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) } } else - { // BMP_FORMAT_48BIT_TC_RGB + { + // BMP_FORMAT_48BIT_TC_RGB for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 ) { sal_uInt8 nRed = pTmp[ 0 ]; @@ -1428,37 +1528,92 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) } } else // has RGB but neither alpha nor transparency - { // BMP_FORMAT_24BIT_TC_RGB + { + // BMP_FORMAT_24BIT_TC_RGB + // only use DirectScanline when we have no preview shifting stuff and access to content + const bool bDoDirectScanline( + bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc); + const bool bCustomColorTable(mpColorTable != mpDefaultColorTable); + + if(bDoDirectScanline && !mpScanline) + { + // allocate scanlines on demand, reused for next line +#ifdef DBG_UTIL + mnAllocSizeScanline = maOrigSize.Width() * 3; +#endif + mpScanline = new sal_uInt8[maOrigSize.Width() * 3]; + } + if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample { - if ( mpColorTable != mpDefaultColorTable ) + if(bDoDirectScanline) { - for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 ) - ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ], - mpColorTable[ pTmp[ 1 ] ], - mpColorTable[ pTmp[ 2 ] ] ) ); + OSL_ENSURE(mpScanline, "No Scanline allocated (!)"); + OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)"); + sal_uInt8* pScanline(mpScanline); + + for(sal_uInt32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 3) + { + // prepare content line as BGR by reordering when copying + if(bCustomColorTable) + { + *pScanline++ = mpColorTable[pTmp[2]]; + *pScanline++ = mpColorTable[pTmp[1]]; + *pScanline++ = mpColorTable[pTmp[0]]; + } + else + { + *pScanline++ = pTmp[2]; + *pScanline++ = pTmp[1]; + *pScanline++ = pTmp[0]; + } + } + + // copy scanline directly to bitmap for content; use the format which is able to + // copy directly to BitmapBuffer + mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3); } else { - if( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible - { - int nLineBytes = maOrigSize.Width() * 3; - mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_24BIT_TC_RGB, nLineBytes ); - pTmp += nLineBytes; - } - else + for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 ) { - for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 ) - ImplSetPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ) ); + if(bCustomColorTable) + { + ImplSetPixel( + nY, + nX, + BitmapColor( + mpColorTable[ pTmp[ 0 ] ], + mpColorTable[ pTmp[ 1 ] ], + mpColorTable[ pTmp[ 2 ] ])); + } + else + { + ImplSetPixel( + nY, + nX, + BitmapColor( + pTmp[0], + pTmp[1], + pTmp[2])); + } } } } else - { // BMP_FORMAT_48BIT_TC_RGB + { + // BMP_FORMAT_48BIT_TC_RGB + // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 ) - ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ], - mpColorTable[ pTmp[ 2 ] ], - mpColorTable[ pTmp[ 4 ] ] ) ); + { + ImplSetPixel( + nY, + nX, + BitmapColor( + mpColorTable[ pTmp[ 0 ] ], + mpColorTable[ pTmp[ 2 ] ], + mpColorTable[ pTmp[ 4 ] ])); + } } } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits