include/svtools/grfmgr.hxx | 22 ++++++++++ svtools/source/graphic/grfmgr.cxx | 50 +++++++++++++++++++----- svtools/source/graphic/grfmgr2.cxx | 75 ++++++++++++++++++++++++++++++++++++- sw/source/core/doc/notxtfrm.cxx | 57 +++++++++++++++++++++++++--- sw/source/core/inc/frmtool.hxx | 4 - sw/source/core/layout/paintfrm.cxx | 2 vcl/win/source/gdi/salbmp.cxx | 54 +++++++++++++++----------- 7 files changed, 220 insertions(+), 44 deletions(-)
New commits: commit 8930030323f269a9b3c6bd6a09fc723e09211caa Author: Armin Le Grand <a...@apache.org> Date: Thu Jul 3 13:58:29 2014 +0000 Resolves: #i125171# support lossless embedding of linked jpegs... in writer for PDF export (cherry picked from commit 131669af7168020750b726e4e6d1568975f73886) Conflicts: sw/source/core/doc/notxtfrm.cxx Add missing includes to fix build break (cherry picked from commit 662b23eb1f1b7c178a7a5507864c647a390fae34) Conflicts: sw/source/core/doc/notxtfrm.cxx 1e2c208ac91c8e666e4f3f6f89cd917736cdc44d Change-Id: Ie560fa05964b79240fbd97825be74b0543c97aba diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 0f98c9c..c6bae4a 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -75,6 +75,8 @@ #include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/processor2d/processor2dtools.hxx> #include <txtfly.hxx> +#include <vcl/graphicfilter.hxx> +#include <vcl/pdfextoutdevdata.hxx> using namespace com::sun::star; @@ -754,7 +756,7 @@ bool paintUsingPrimitivesHelper( } void paintGraphicUsingPrimitivesHelper(OutputDevice & rOutputDevice, - Graphic const& rGraphic, GraphicAttr const& rGraphicAttr, + GraphicObject const& rGrfObj, GraphicAttr const& rGraphicAttr, SwRect const& rAlignedGrfArea) { // unify using GraphicPrimitive2D @@ -768,12 +770,55 @@ void paintGraphicUsingPrimitivesHelper(OutputDevice & rOutputDevice, basegfx::tools::createScaleTranslateB2DHomMatrix( aTargetRange.getRange(), aTargetRange.getMinimum())); + drawinglayer::primitive2d::Primitive2DSequence aContent(1); + bool bDone(false); + + // #i125171# The mechanism to get lossless jpegs into pdf is based on having the original + // file data (not the bitmap data) at the Graphic in the GfxLink (which has *nothing* to + // do with the graphic being linked). This works well for DrawingLayer GraphicObjects (linked + // and unlinked) but fails for linked Writer GraphicObjects. These have the URL in the + // GraphicObject, but no GfxLink with the original file data when it's a linked graphic. + // Since this blows up PDF size by a factor of 10 (the graphics get embedded as pixel maps + // then) it is okay to add this workarund: In the needed case, load the graphic in a way to + // get the GfxLink in the needed form and use that Graphic temporarily. Do this only when + // - we have PDF export + // - the GraphicObject is linked + // - the Graphic has no GfxLink + // - LosslessCompression is activated + // - it's indeed a jpeg graphic (could be checked by the url ending, but is more reliable to check later) + // In all other cases (normal repaint, print, etc...) use the available Graphic with the + // already loaded pixel graphic as before this change. + if (rOutputDevice.GetExtOutDevData() && rGrfObj.HasLink() && !rGrfObj.GetGraphic().IsLink()) + { + const vcl::PDFExtOutDevData* pPDFExt = dynamic_cast< const vcl::PDFExtOutDevData* >(rOutputDevice.GetExtOutDevData()); + + if (pPDFExt && pPDFExt->GetIsLosslessCompression()) + { + Graphic aTempGraphic; + INetURLObject aURL(rGrfObj.GetLink()); - aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D( - aTargetTransform, - rGraphic, - rGraphicAttr); + if (GRFILTER_OK == GraphicFilter::GetGraphicFilter().ImportGraphic(aTempGraphic, aURL)) + { + if(aTempGraphic.IsLink() && GFX_LINK_TYPE_NATIVE_JPG == aTempGraphic.GetLink().GetType()) + { + aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D( + aTargetTransform, + aTempGraphic, + rGraphicAttr); + bDone = true; + } + } + } + } + + if(!bDone) + { + aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D( + aTargetTransform, + rGrfObj.GetGraphic(), + rGraphicAttr); + } paintUsingPrimitivesHelper( rOutputDevice, @@ -905,7 +950,7 @@ void SwNoTxtFrm::PaintPicture( OutputDevice* pOut, const SwRect &rGrfArea ) cons else { paintGraphicUsingPrimitivesHelper(*pOut, - rGrfObj.GetGraphic(), aGrfAttr, aAlignedGrfArea); + rGrfObj, aGrfAttr, aAlignedGrfArea); } } else diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx index 1372efb..1fdaee5 100644 --- a/sw/source/core/inc/frmtool.hxx +++ b/sw/source/core/inc/frmtool.hxx @@ -40,7 +40,7 @@ class XFillGradientItem; class SdrMarkList; class SwNodeIndex; class OutputDevice; -class Graphic; +class GraphicObject; class GraphicAttr; class SwPageDesc; class SwFrmFmts; @@ -72,7 +72,7 @@ bool DrawFillAttributes( void paintGraphicUsingPrimitivesHelper( OutputDevice & rOutputDevice, - Graphic const& rGraphic, GraphicAttr const& rGraphicAttr, + GraphicObject const& rGraphicObj, GraphicAttr const& rGraphicAttr, SwRect const& rAlignedGrfArea); // method to align rectangle. diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 162c7a9..f3aad5f 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -1817,7 +1817,7 @@ static void lcl_DrawGraphic( const SvxBrushItem& rBrush, OutputDevice *pOut, if (pGrf->GetGraphic().getSvgData().get()) { // fdo#68927 - SVGs are rasterized badly by DrawWithPDFHandling paintGraphicUsingPrimitivesHelper(*pOut, - pGrf->GetGraphic(), pGrf->GetAttr(), aAlignedGrfRect); + *pGrf, pGrf->GetAttr(), aAlignedGrfRect); } else { commit 60de576a295682002c59b90b1429da25bcd854ea Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jul 15 12:58:17 2014 +0100 use same swap stategy on all platforms Change-Id: I565dfd9233088feae69de6261d1081fc51f10806 diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx index d5731d8..3db6161 100644 --- a/svtools/source/graphic/grfmgr2.cxx +++ b/svtools/source/graphic/grfmgr2.cxx @@ -189,60 +189,56 @@ namespace void GraphicManager::ImplCheckSizeOfSwappedInGraphics() { - // only necessary for 32bit systems - if(SAL_TYPES_SIZEOFPOINTER <= 4) + // get the currently used memory footprint of all swapped in bitmap graphics + // of this graphic manager. Remember candidates in a vector. The size in bytes is + // already available, thus this loop is not expensive to execute + sal_uLong nUsedSize(0); + GraphicObject* pObj = 0; + std::vector< GraphicObject* > aCandidates; + + for (size_t i = 0, n = maObjList.size(); i < n; ++i) { - // get the currently used memory footprint of all swapped in bitmap graphics - // of this graphic manager. Remember candidates in a vector. The size in bytes is - // already available, thus this loop is not expensive to execute - sal_uLong nUsedSize(0); - GraphicObject* pObj = 0; - std::vector< GraphicObject* > aCandidates; - - for (size_t i = 0, n = maObjList.size(); i < n; ++i) + pObj = maObjList[i]; + if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes()) { - pObj = maObjList[i]; - if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes()) - { - aCandidates.push_back(pObj); - nUsedSize += pObj->GetSizeBytes(); - } + aCandidates.push_back(pObj); + nUsedSize += pObj->GetSizeBytes(); } + } + + // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted + // to 20MB) and add a decent multiplicator (experimented to find one). Limit to + // a useful maximum for 32Bit address space - // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted - // to 20MB) and add a decent multiplicator (expecrimented to find one). Limit to - // a useful maximum for 32Bit address space + // default is 20MB, so allow 200MB initially + static sal_uLong aMultiplicator(10); - // default is 20MB, so allow 200MB initially - static sal_uLong aMultiplicator(10); + // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start + // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for + // app activity is needed + static sal_uLong aMaxSize32Bit(500 * 1024 * 1024); - // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start - // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for - // app activity is needed - static sal_uLong aMaxSize32Bit(500 * 1024 * 1024); + // calc max allowed cache size + const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit)); - // calc max allowed cache size - const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit)); + if(nUsedSize >= nMaxCacheSize && !aCandidates.empty()) + { + // if we use more currently, sort by last DataChangeTimeStamp + // sort by DataChangeTimeStamp so that the oldest get removed first + ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp()); - if(nUsedSize >= nMaxCacheSize && !aCandidates.empty()) + for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++) { - // if we use more currently, sort by last DataChangeTimeStamp - // sort by DataChangeTimeStamp so that the oldest get removed first - ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp()); + // swap out until we have no more or the goal to use less than nMaxCacheSize + // is reached + pObj = aCandidates[a]; + const sal_uLong nSizeBytes(pObj->GetSizeBytes()); - for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++) + // do not swap out when we have less than 16KB data objects + if(nSizeBytes >= (16 * 1024)) { - // swap out until we have no more or the goal to use less than nMaxCacheSize - // is reached - pObj = aCandidates[a]; - const sal_uLong nSizeBytes(pObj->GetSizeBytes()); - - // do not swap out when we have less than 16KB data objects - if(nSizeBytes >= (16 * 1024)) - { - pObj->FireSwapOutRequest(); - nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0; - } + pObj->FireSwapOutRequest(); + nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0; } } } commit 0ca0202a0994c0b7c99c366fd5cafd8a655df203 Author: Armin Le Grand <a...@apache.org> Date: Thu Jun 19 16:49:26 2014 +0000 Resolves: #i125111# limit mem footprint for GraphicObjects... in 32Bit environments Conflicts: svtools/inc/svtools/grfmgr.hxx svtools/source/graphic/grfmgr.cxx svtools/source/graphic/grfmgr2.cxx sw/source/core/doc/notxtfrm.cxx sw/source/core/graphic/ndgrf.cxx "commit 62b0eaf37c08dd27244e77b8bc90c691b000ebd6 Related: fdo#50697 reset the cache timeout on GetGraphic so the graphic gets swapped out Xms after the last use and not Xms after initial creation regardless of if it got used a moment earlier." corrected place for stl sort function for linux (cherry picked from commit a48414a396f7de4e00510e82e3744c097ce3d5d6) Conflicts: svtools/source/graphic/grfmgr2.cxx Change-Id: I79158b7d42629f8dec2bc5565540701bcd3ef6f4 6f21c7fd4d2681446fc1a6d9607366a1e69165a1 diff --git a/include/svtools/grfmgr.hxx b/include/svtools/grfmgr.hxx index 251ee6d..4ef7e10 100644 --- a/include/svtools/grfmgr.hxx +++ b/include/svtools/grfmgr.hxx @@ -175,6 +175,10 @@ private: Timer* mpSwapOutTimer; GrfSimpleCacheObj* mpSimpleCache; sal_uLong mnAnimationLoopCount; + + // a unique increasing ID to be able to say which data change is older + sal_uLong mnDataChangeTimeStamp; + bool mbAutoSwapped : 1; bool mbTransparent : 1; bool mbAnimated : 1; @@ -299,8 +303,12 @@ private: DECL_LINK( ImplAutoSwapOutHdl, void* ); - void SVT_DLLPRIVATE ResetCacheTimeOut(); + // restart SwapOut timer; this is like touching in a cache to reset to the full timeout value + void SVT_DLLPRIVATE restartSwapOutTimer() const; + // Handle evtl. needed AfterDataChanges, needs to be called when new + // graphic data is swapped in/added to the GraphicManager + void SVT_DLLPRIVATE ImplAfterDataChange(); protected: virtual void GraphicManagerDestroyed(); @@ -506,6 +514,9 @@ public: double fTopCrop, double fRightCrop, double fBottomCrop) const; + + // read access + sal_uLong GetDataChangeTimeStamp() const { return mnDataChangeTimeStamp; } }; typedef ::std::vector< GraphicObject* > GraphicObjectList_impl; @@ -597,12 +608,21 @@ private: OString SVT_DLLPRIVATE ImplGetUniqueID( const GraphicObject& rObj ) const; + // This method allows to check memory footprint for all currently swapped in GraphicObjects on this GraphicManager + // which are based on Bitmaps. This is needed on 32Bit systems and only does something on those systems. The problem + // to solve is that normally the SwapOut is timer-driven, but even with short timer settings there are situations + // where this does not trigger - or in other words: A maximum limitation for GraphicManagers was not in place before. + // For 32Bit systems this leads to situations where graphics will be missing. This method will actively swap out + // the longest swapped in graphics until a maximum memory boundary (derived from user settings in tools/options/memory) + // is no longer exceeded + void SVT_DLLPRIVATE ImplCheckSizeOfSwappedInGraphics(); public: GraphicManager( sal_uLong nCacheSize = 10000000UL, sal_uLong nMaxObjCacheSize = 2400000UL ); ~GraphicManager(); void SetMaxCacheSize( sal_uLong nNewCacheSize ); + sal_uLong GetMaxCacheSize() const; void SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx index 408081e..1402ea7 100644 --- a/svtools/source/graphic/grfmgr.cxx +++ b/svtools/source/graphic/grfmgr.cxx @@ -59,6 +59,19 @@ struct GrfSimpleCacheObj TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream ); +// unique increasing ID for being able to detect the GraphicObject with the +// oldest last data changes +static sal_uLong aIncrementingTimeOfLastDataChange = 1; + +void GraphicObject::ImplAfterDataChange() +{ + // set unique timestamp ID of last data change + mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; + + // check memory footprint of all GraphicObjects managed and evtl. take action + GetGraphicManager().ImplCheckSizeOfSwappedInGraphics(); +} + GraphicObject::GraphicObject( const GraphicManager* pMgr ) : maLink (), maUserData () @@ -130,6 +143,9 @@ void GraphicObject::ImplConstruct() mbAutoSwapped = false; mbIsInSwapIn = false; mbIsInSwapOut = false; + + // Init with a unique, increasing ID + mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++; } void GraphicObject::ImplAssignGraphicData() @@ -243,6 +259,9 @@ void GraphicObject::ImplAutoSwapIn() if( !mbAutoSwapped && mpMgr ) mpMgr->ImplGraphicObjectWasSwappedIn( *this ); } + + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); } } @@ -744,15 +763,6 @@ void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData ) mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData ); } -void GraphicObject::ResetCacheTimeOut() -{ - if (mpSwapOutTimer) - { - mpSwapOutTimer->Stop(); - mpSwapOutTimer->Start(); - } -} - const Graphic& GraphicObject::GetGraphic() const { GraphicObject *pThis = const_cast<GraphicObject*>(this); @@ -763,7 +773,7 @@ const Graphic& GraphicObject::GetGraphic() const //fdo#50697 If we've been asked to provide the graphic, then reset //the cache timeout to start from now and not remain at the //time of creation - pThis->ResetCacheTimeOut(); + pThis->restartSwapOutTimer(); return maGraphic; } @@ -785,6 +795,9 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pC if( mpSwapOutTimer ) mpSwapOutTimer->Start(); + + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); } void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink ) @@ -1101,7 +1114,9 @@ bool GraphicObject::SwapIn() bRet = true; } else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) ) + { bRet = true; + } else { bRet = maGraphic.SwapIn(); @@ -1111,8 +1126,13 @@ bool GraphicObject::SwapIn() } if( bRet ) + { ImplAssignGraphicData(); + // Handle evtl. needed AfterDataChanges + ImplAfterDataChange(); + } + return bRet; } @@ -1297,4 +1317,14 @@ basegfx::B2DVector GraphicObject::calculateCropScaling( return basegfx::B2DVector(fFactorX,fFactorY); } +// restart SwapOut timer +void GraphicObject::restartSwapOutTimer() const +{ + if( mpSwapOutTimer && mpSwapOutTimer->IsActive() ) + { + mpSwapOutTimer->Stop(); + mpSwapOutTimer->Start(); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx index 117a4d0..d5731d8 100644 --- a/svtools/source/graphic/grfmgr2.cxx +++ b/svtools/source/graphic/grfmgr2.cxx @@ -64,6 +64,11 @@ void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize ) mpCache->SetMaxDisplayCacheSize( nNewCacheSize ); } +sal_uLong GraphicManager::GetMaxCacheSize() const +{ + return mpCache->GetMaxDisplayCacheSize(); +} + void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, bool bDestroyGreaterCached ) { mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached ); @@ -171,9 +176,81 @@ OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const return mpCache->GetUniqueID( rObj ); } +namespace +{ + struct simpleSortByDataChangeTimeStamp + { + bool operator() (GraphicObject* p1, GraphicObject* p2) const + { + return p1->GetDataChangeTimeStamp() < p2->GetDataChangeTimeStamp(); + } + }; +} // end of anonymous namespace + +void GraphicManager::ImplCheckSizeOfSwappedInGraphics() +{ + // only necessary for 32bit systems + if(SAL_TYPES_SIZEOFPOINTER <= 4) + { + // get the currently used memory footprint of all swapped in bitmap graphics + // of this graphic manager. Remember candidates in a vector. The size in bytes is + // already available, thus this loop is not expensive to execute + sal_uLong nUsedSize(0); + GraphicObject* pObj = 0; + std::vector< GraphicObject* > aCandidates; + + for (size_t i = 0, n = maObjList.size(); i < n; ++i) + { + pObj = maObjList[i]; + if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes()) + { + aCandidates.push_back(pObj); + nUsedSize += pObj->GetSizeBytes(); + } + } + + // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted + // to 20MB) and add a decent multiplicator (expecrimented to find one). Limit to + // a useful maximum for 32Bit address space + + // default is 20MB, so allow 200MB initially + static sal_uLong aMultiplicator(10); + + // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start + // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for + // app activity is needed + static sal_uLong aMaxSize32Bit(500 * 1024 * 1024); + + // calc max allowed cache size + const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit)); + + if(nUsedSize >= nMaxCacheSize && !aCandidates.empty()) + { + // if we use more currently, sort by last DataChangeTimeStamp + // sort by DataChangeTimeStamp so that the oldest get removed first + ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp()); + + for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++) + { + // swap out until we have no more or the goal to use less than nMaxCacheSize + // is reached + pObj = aCandidates[a]; + const sal_uLong nSizeBytes(pObj->GetSizeBytes()); + + // do not swap out when we have less than 16KB data objects + if(nSizeBytes >= (16 * 1024)) + { + pObj->FireSwapOutRequest(); + nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0; + } + } + } + } +} + bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute ) { - return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) ); + return mpCache->FillSwappedGraphicObject(rObj, rSubstitute); } void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj ) diff --git a/vcl/win/source/gdi/salbmp.cxx b/vcl/win/source/gdi/salbmp.cxx index 445839e..2bccbd7 100644 --- a/vcl/win/source/gdi/salbmp.cxx +++ b/vcl/win/source/gdi/salbmp.cxx @@ -453,35 +453,43 @@ Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlph if(pRetval) { - sal_uInt8* pSrcRGB(pRGB->mpBits); - sal_uInt8* pSrcA(pA->mpBits); - const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); - const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); - const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); - const Gdiplus::Rect aAllRect(0, 0, nW, nH); - Gdiplus::BitmapData aGdiPlusBitmapData; - pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData); - - // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and - // A from alpha, so inner loop is needed (who invented BitmapEx..?) - for(sal_uInt32 y(0); y < nH; y++) + if ( pRetval->GetLastStatus() == Gdiplus::Ok ) // 2nd place to secure with new Gdiplus::Bitmap { - const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); - sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride); + sal_uInt8* pSrcRGB(pRGB->mpBits); + sal_uInt8* pSrcA(pA->mpBits); + const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); + const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); + const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); + const Gdiplus::Rect aAllRect(0, 0, nW, nH); + Gdiplus::BitmapData aGdiPlusBitmapData; + pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData); - for(sal_uInt32 x(0); x < nW; x++) + // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and + // A from alpha, so inner loop is needed (who invented BitmapEx..?) + for(sal_uInt32 y(0); y < nH; y++) { - *targetPixels++ = *pSrcRGB++; - *targetPixels++ = *pSrcRGB++; - *targetPixels++ = *pSrcRGB++; - *targetPixels++ = 0xff - *pSrcA++; + const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); + sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride); + + for(sal_uInt32 x(0); x < nW; x++) + { + *targetPixels++ = *pSrcRGB++; + *targetPixels++ = *pSrcRGB++; + *targetPixels++ = *pSrcRGB++; + *targetPixels++ = 0xff - *pSrcA++; + } + + pSrcRGB += nExtraRGB; + pSrcA += nExtraA; } - pSrcRGB += nExtraRGB; - pSrcA += nExtraA; + pRetval->UnlockBits(&aGdiPlusBitmapData); + } + else + { + delete pRetval; + pRetval = NULL; } - - pRetval->UnlockBits(&aGdiPlusBitmapData); } }
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits