diff options
-rw-r--r-- | include/svx/svdundo.hxx | 6 | ||||
-rw-r--r-- | svx/source/svdraw/svdograf.cxx | 43 | ||||
-rw-r--r-- | svx/source/svdraw/svdundo.cxx | 37 | ||||
-rw-r--r-- | vcl/source/filter/jpeg/JpegReader.cxx | 36 | ||||
-rw-r--r-- | vcl/source/gdi/pngread.cxx | 241 |
5 files changed, 306 insertions, 57 deletions
diff --git a/include/svx/svdundo.hxx b/include/svx/svdundo.hxx index d3a8a8321e59..a3766b735b82 100644 --- a/include/svx/svdundo.hxx +++ b/include/svx/svdundo.hxx @@ -299,9 +299,11 @@ public: class SVX_DLLPUBLIC SdrUndoDelObj : public SdrUndoRemoveObj { +private: + void TryToFlushGraphicContent(); + public: - SdrUndoDelObj(SdrObject& rNewObj, bool bOrdNumDirect = false) - : SdrUndoRemoveObj(rNewObj,bOrdNumDirect) { SetOwner(sal_True); } + SdrUndoDelObj(SdrObject& rNewObj, bool bOrdNumDirect = false); virtual void Undo(); virtual void Redo(); diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index 277833fdabc6..6adf75b55244 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -60,6 +60,7 @@ #include <osl/thread.hxx> #include <drawinglayer/processor2d/objectinfoextractor2d.hxx> #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx> +#include <officecfg/Office/Common.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -67,6 +68,40 @@ using namespace ::com::sun::star::io; #define SWAPGRAPHIC_TIMEOUT 5000 +// #i122985# it is not correct to set 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 sal_uInt32 nSeconds = + officecfg::Office::Common::Cache::GraphicManager::ObjectReleaseTime::get( + comphelper::getProcessComponentContext()); + + + // 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; +} + const Graphic ImpLoadLinkedGraphic( const OUString aFileName, const OUString aFilterName ) { Graphic aGraphic; @@ -333,7 +368,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 @@ -357,7 +392,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 @@ -381,7 +416,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 @@ -410,7 +445,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 = false; SetChanged(); diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx index fcdf5f09546d..caf3ba46e1bd 100644 --- a/svx/source/svdraw/svdundo.cxx +++ b/svx/source/svdraw/svdundo.cxx @@ -38,8 +38,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> //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -887,6 +888,34 @@ 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, bool bOrdNumDirect) +: SdrUndoRemoveObj(rNewObj,bOrdNumDirect) +{ + SetOwner(true); + + // #i122985# if graphic object is deleted (but goes to undo) flush it's graphic content + // since it is potentially no longer needed + TryToFlushGraphicContent(); +} + void SdrUndoDelObj::Undo() { SdrUndoRemoveObj::Undo(); @@ -899,6 +928,10 @@ void SdrUndoDelObj::Redo() SdrUndoRemoveObj::Redo(); DBG_ASSERT(!IsOwner(),"RedoDeleteObj: pObj already belongs to UndoAction"); SetOwner(sal_True); + + // #i122985# if graphic object is deleted (but goes to undo) flush it's graphic content + // since it is potentially no longer needed + TryToFlushGraphicContent(); } OUString SdrUndoDelObj::GetComment() const diff --git a/vcl/source/filter/jpeg/JpegReader.cxx b/vcl/source/filter/jpeg/JpegReader.cxx index 8b87aa6d9f20..a79f5ca12a02 100644 --- a/vcl/source/filter/jpeg/JpegReader.cxx +++ b/vcl/source/filter/jpeg/JpegReader.cxx @@ -354,14 +354,38 @@ void JPEGReader::FillBitmap() for( long nY = 0L; nY < nHeight; nY++ ) { - pTmp = (sal_uInt8*) mpBuffer + nY * nAlignedWidth; + // #i122985# Added fast-lane implementations using CopyScanline with direct supported mem formats + static bool bCheckOwnReader(true); - for( long nX = 0L; nX < nWidth; nX++ ) + if(bCheckOwnReader) + { + // #i122985# 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*)mpBuffer + nY * nAlignedWidth); + sal_uInt8* aEnd(aSource + (nWidth * 3)); + + for(sal_uInt8* aTmp(aSource); aTmp < aEnd; aTmp += 3) + { + ::std::swap(*aTmp, *(aTmp + 2)); + } + + mpAcc->CopyScanline(nY, aSource, BMP_FORMAT_24BIT_TC_BGR, nWidth * 3); + } + else { - aColor.SetRed( *pTmp++ ); - aColor.SetGreen( *pTmp++ ); - aColor.SetBlue( *pTmp++ ); - mpAcc->SetPixel( nY, nX, aColor ); + // old version: WritePixel + pTmp = (sal_uInt8*) mpBuffer + nY * nAlignedWidth; + + for( long nX = 0L; nX < nWidth; nX++ ) + { + aColor.SetRed( *pTmp++ ); + aColor.SetGreen( *pTmp++ ); + aColor.SetBlue( *pTmp++ ); + mpAcc->SetPixel( nY, nX, aColor ); + } } } } diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx index 71fb345326d1..f8b4e9561c3e 100644 --- a/vcl/source/gdi/pngread.cxx +++ b/vcl/source/gdi/pngread.cxx @@ -123,6 +123,15 @@ private: bool mbpHYs; // true if pysical size of pixel available 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(); @@ -178,7 +187,13 @@ PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream ) mbIDAT( false ), mbGamma ( false ), mbpHYs ( false ), - mbIgnoreGammaChunk ( false ) + mbIgnoreGammaChunk ( false ), +#ifdef DBG_UTIL + mnAllocSizeScanline(0), + mnAllocSizeScanlineAlpha(0), +#endif + mpScanline(0), + mpScanlineAlpha(0) { // prepare the PNG data stream mnOrigStreamMode = mrPNGStream.GetNumberFormatInt(); @@ -222,6 +237,9 @@ PNGReaderImpl::~PNGReaderImpl() delete[] mpInflateInBuf; delete[] mpScanPrior; delete mpZCodec; + + delete[] mpScanline; + delete[] mpScanlineAlpha; } bool PNGReaderImpl::ReadNextChunk() @@ -1290,42 +1308,123 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) } else // no palette => truecolor { - if( mbAlphaChannel ) // has RGB + alpha - { // BMP_FORMAT_32BIT_TC_RGBA + // #i122985# 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 ) @@ -1334,7 +1433,7 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd ) sal_uInt8 nGreen = pTmp[ 1 ]; sal_uInt8 nBlue = pTmp[ 2 ]; bool bTransparent = ( ( nRed == mnTransRed ) - && ( nGreen == mnTransGreen ) + && ( nGreen == mnTransGreen ) && ( nBlue == mnTransBlue ) ); ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ], @@ -1343,7 +1442,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 ]; @@ -1360,37 +1460,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 ] ])); + } } } } |