diff options
author | Armin Le Grand (Collabora) <armin.le.grand@me.com> | 2020-02-21 16:58:17 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-02-24 13:10:29 +0100 |
commit | ef6f94e93bbe55a26b67b55b2aecda67d406ab85 (patch) | |
tree | 271d344f997e520ecf406a5b102edaf059542d1d /sw | |
parent | 59edfb81f05da304b49609a239961607db6f6900 (diff) |
tdf#130768 speedup huge pixel graphics Cairo
For more information/documentation please
refer to the bugzilla task
Fixed a crash in CppunitTest_desktop_lib which
led to a missing test of mpGraphics in
OutputDevice::DrawTransformedBitmapEx. Other
public methods test that and one of the goals
of the cange was to use that method more often,
so this may have never been detected before
Change-Id: I10e57bd05db0c8cf868ff98d63f5af3d116a3015
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89230
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89252
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/core/doc/notxtfrm.cxx | 198 | ||||
-rw-r--r-- | sw/source/core/inc/frmtool.hxx | 6 | ||||
-rw-r--r-- | sw/source/core/inc/notxtfrm.hxx | 6 |
3 files changed, 198 insertions, 12 deletions
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 04e556277738..f2b148361994 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -82,6 +82,14 @@ #include <drawinglayer/primitive2d/maskprimitive2d.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> +// MM02 needed for VOC mechanism and getting the OC - may be moved to an own file +#include <svx/sdrpagewindow.hxx> +#include <svx/svdpagv.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> + using namespace com::sun::star; static bool GetRealURL( const SwGrfNode& rNd, OUString& rText ) @@ -148,7 +156,9 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText, SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib ) : SwContentFrame( pNode, pSib ), // RotateFlyFrame3 - mpTransformableSwFrame() + mpTransformableSwFrame(), + // MM02 + mpViewContact() { mnFrameType = SwFrameType::NoTxt; } @@ -925,6 +935,7 @@ static bool paintUsingPrimitivesHelper( return false; } +// MM02 original using falölback to VOC and primitive-based version void paintGraphicUsingPrimitivesHelper( vcl::RenderContext & rOutputDevice, GraphicObject const& rGrfObj, @@ -936,12 +947,24 @@ void paintGraphicUsingPrimitivesHelper( // -> the primitive renderer will create the needed pdf export data // -> if bitmap content, it will be cached system-dependent drawinglayer::primitive2d::Primitive2DContainer aContent(1); - aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D( rGraphicTransform, rGrfObj, rGraphicAttr); + // MM02 use primitive-based version for visualization + paintGraphicUsingPrimitivesHelper( + rOutputDevice, + aContent, + rGraphicTransform); +} + +// MM02 new VOC and primitive-based version +void paintGraphicUsingPrimitivesHelper( + vcl::RenderContext & rOutputDevice, + drawinglayer::primitive2d::Primitive2DContainer& rContent, + const basegfx::B2DHomMatrix& rGraphicTransform) +{ // RotateFlyFrame3: If ClipRegion is set at OutputDevice, we // need to use that. Usually the renderer would be a VCL-based // PrimitiveRenderer, but there are system-specific shortcuts that @@ -1008,9 +1031,12 @@ void paintGraphicUsingPrimitivesHelper( aTarget.append(aClip); } - aContent[0] = new drawinglayer::primitive2d::MaskPrimitive2D( - aTarget, - aContent); + drawinglayer::primitive2d::MaskPrimitive2D* pNew( + new drawinglayer::primitive2d::MaskPrimitive2D( + aTarget, + rContent)); + rContent.resize(1); + rContent[0] = pNew; } } @@ -1019,11 +1045,111 @@ void paintGraphicUsingPrimitivesHelper( paintUsingPrimitivesHelper( rOutputDevice, - aContent, + rContent, aTargetRange, aTargetRange); } +// DrawContact section +namespace { // anonymous namespace +class ViewObjectContactOfSwNoTextFrame : public sdr::contact::ViewObjectContact +{ +protected: + virtual drawinglayer::primitive2d::Primitive2DContainer createPrimitive2DSequence( + const sdr::contact::DisplayInfo& rDisplayInfo) const override; + +public: + ViewObjectContactOfSwNoTextFrame( + sdr::contact::ObjectContact& rObjectContact, + sdr::contact::ViewContact& rViewContact); +}; + +class ViewContactOfSwNoTextFrame : public sdr::contact::ViewContact +{ +private: + // owner + const SwNoTextFrame& mrSwNoTextFrame; + +protected: + // Create an Object-Specific ViewObjectContact, set ViewContact and + // ObjectContact. Always needs to return something. + virtual sdr::contact::ViewObjectContact& CreateObjectSpecificViewObjectContact( + sdr::contact::ObjectContact& rObjectContact) override; + +public: + // read-access to owner + const SwNoTextFrame& getSwNoTextFrame() const { return mrSwNoTextFrame; } + + // basic constructor, used from SwNoTextFrame. + explicit ViewContactOfSwNoTextFrame(const SwNoTextFrame& rSwNoTextFrame); +}; + +drawinglayer::primitive2d::Primitive2DContainer ViewObjectContactOfSwNoTextFrame::createPrimitive2DSequence( + const sdr::contact::DisplayInfo& /*rDisplayInfo*/) const +{ + // MM02 get all the parameters formally used in paintGraphicUsingPrimitivesHelper + ViewContactOfSwNoTextFrame& rVCOfNTF(static_cast<ViewContactOfSwNoTextFrame&>(GetViewContact())); + const SwNoTextFrame& rSwNoTextFrame(rVCOfNTF.getSwNoTextFrame()); + SwNoTextNode& rNoTNd(const_cast<SwNoTextNode&>(*static_cast<const SwNoTextNode*>(rSwNoTextFrame.GetNode()))); + SwGrfNode* pGrfNd(rNoTNd.GetGrfNode()); + + if(nullptr != pGrfNd) + { + const bool bPrn(GetObjectContact().isOutputToPrinter() || GetObjectContact().isOutputToRecordingMetaFile()); + const GraphicObject& rGrfObj(pGrfNd->GetGrfObj(bPrn)); + GraphicAttr aGraphicAttr; + pGrfNd->GetGraphicAttr(aGraphicAttr, &rSwNoTextFrame); + const basegfx::B2DHomMatrix aGraphicTransform(rSwNoTextFrame.getFrameAreaTransformation()); + + // MM02 this is the right place in the VOC-Mechanism to create + // the primitives for visualization - these will be automatically + // buffered and reused + drawinglayer::primitive2d::Primitive2DContainer aContent(1); + aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D( + aGraphicTransform, + rGrfObj, + aGraphicAttr); + + return aContent; + } + + return drawinglayer::primitive2d::Primitive2DContainer(); +} + +ViewObjectContactOfSwNoTextFrame::ViewObjectContactOfSwNoTextFrame( + sdr::contact::ObjectContact& rObjectContact, + sdr::contact::ViewContact& rViewContact) +: sdr::contact::ViewObjectContact(rObjectContact, rViewContact) +{ +} + +sdr::contact::ViewObjectContact& ViewContactOfSwNoTextFrame::CreateObjectSpecificViewObjectContact( + sdr::contact::ObjectContact& rObjectContact) +{ + sdr::contact::ViewObjectContact* pRetval = new ViewObjectContactOfSwNoTextFrame(rObjectContact, *this); + return *pRetval; +} + +ViewContactOfSwNoTextFrame::ViewContactOfSwNoTextFrame( + const SwNoTextFrame& rSwNoTextFrame +) +: sdr::contact::ViewContact(), + mrSwNoTextFrame(rSwNoTextFrame) +{ +} +} // end of anonymous namespace + +sdr::contact::ViewContact& SwNoTextFrame::GetViewContact() const +{ + if(!mpViewContact) + { + const_cast< SwNoTextFrame* >(this)->mpViewContact = + std::make_unique<ViewContactOfSwNoTextFrame>(*this); + } + + return *mpViewContact; +} + /** Paint the graphic. We require either a QuickDraw-Bitmap or a graphic here. If we do not have @@ -1149,13 +1275,61 @@ void SwNoTextFrame::PaintPicture( vcl::RenderContext* pOut, const SwRect &rGrfAr } else { - const basegfx::B2DHomMatrix aGraphicTransform(getFrameAreaTransformation()); + // MM02 To allow system-dependent buffering of the involved + // bitmaps it is necessary to re-use the involved primitives + // and their already executed decomposition (also for + // performance reasons). This is usually done in DrawingLayer + // by using the VOC-Mechanism (see descriptions elsewhere). + // To get that here, make the involved SwNoTextFrame (this) + // a sdr::contact::ViewContact supplier by supporing + // a GetViewContact() - call. For ObjectContact we can use + // the already exising ObjectContact from the involved + // DrawingLayer. For tis, the helper classes + // ViewObjectContactOfSwNoTextFrame + // ViewContactOfSwNoTextFrame + // are created which support the VOC-mechanism in it's minimal + // form. This allows automatic and view-dependent (multiple edit + // windows, print, etc.) re-use of the created primitives. + // Also: Will be very useful when completely changing the Writer + // repaint to VOC and Primitives, too. + static const char* pDisableMM02Goodies(getenv("SAL_DISABLE_MM02_GOODIES")); + static bool bUseViewObjectContactMechanism(nullptr == pDisableMM02Goodies); + + if(bUseViewObjectContactMechanism) + { + // MM02 use VOC-mechanism and buffer primitives + SwViewShellImp* pImp(pShell->Imp()); + SdrPageView* pPageView(nullptr != pImp ? pImp->GetPageView() : nullptr); + SdrPageWindow* pPageWindow(nullptr != pPageView ? pPageView->FindPageWindow(*pShell->GetOut()) : nullptr); - paintGraphicUsingPrimitivesHelper( - *pOut, - rGrfObj, - aGrfAttr, - aGraphicTransform); + if(nullptr != pPageWindow) + { + sdr::contact::ObjectContact& rOC(pPageWindow->GetObjectContact()); + sdr::contact::ViewContact& rVC(GetViewContact()); + sdr::contact::ViewObjectContact& rVOC(rVC.GetViewObjectContact(rOC)); + sdr::contact::DisplayInfo aDisplayInfo; + + drawinglayer::primitive2d::Primitive2DContainer aPrimitives(rVOC.getPrimitive2DSequence(aDisplayInfo)); + const basegfx::B2DHomMatrix aGraphicTransform(getFrameAreaTransformation()); + + paintGraphicUsingPrimitivesHelper( + *pOut, + aPrimitives, + aGraphicTransform); + } + } + else + { + // MM02 fallback to direct paint with primitive-recreation + // which will block reusage of system-dependent bitmap data + const basegfx::B2DHomMatrix aGraphicTransform(getFrameAreaTransformation()); + + paintGraphicUsingPrimitivesHelper( + *pOut, + rGrfObj, + aGrfAttr, + aGraphicTransform); + } } } else diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx index 5ffcd20083f7..54c1c9231e28 100644 --- a/sw/source/core/inc/frmtool.hxx +++ b/sw/source/core/inc/frmtool.hxx @@ -97,6 +97,12 @@ void paintGraphicUsingPrimitivesHelper( GraphicAttr const& rGraphicAttr, const basegfx::B2DHomMatrix& rGraphicTransform); +// MM02 new VOC and primitive-based version +void paintGraphicUsingPrimitivesHelper( + vcl::RenderContext & rOutputDevice, + drawinglayer::primitive2d::Primitive2DContainer& rContent, + const basegfx::B2DHomMatrix& rGraphicTransform); + // method to align rectangle. // Created declaration here to avoid <extern> declarations void SwAlignRect( SwRect &rRect, const SwViewShell *pSh, const vcl::RenderContext* pRenderContext ); diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx index fad416c27d8f..6c168041d244 100644 --- a/sw/source/core/inc/notxtfrm.hxx +++ b/sw/source/core/inc/notxtfrm.hxx @@ -20,6 +20,8 @@ #define INCLUDED_SW_SOURCE_CORE_INC_NOTXTFRM_HXX #include "cntfrm.hxx" +// MM02 +#include <svx/sdr/contact/viewcontact.hxx> class SwNoTextNode; class OutputDevice; @@ -49,6 +51,10 @@ private: void ClearCache(); + // MM02 + std::unique_ptr<sdr::contact::ViewContact> mpViewContact; + sdr::contact::ViewContact& GetViewContact() const; + protected: virtual void MakeAll(vcl::RenderContext* pRenderContext) override; virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override; |