sw/source/core/draw/dflyobj.cxx | 8 - sw/source/core/frmedt/fefly1.cxx | 2 sw/source/core/inc/flyfrms.hxx | 7 - sw/source/core/layout/fly.cxx | 219 +++++++++++++++++++++----------------- sw/source/core/layout/flylay.cxx | 42 +++++++ sw/source/core/layout/frmtool.cxx | 20 ++- sw/source/core/text/txtfly.cxx | 17 ++ 7 files changed, 206 insertions(+), 109 deletions(-)
New commits: commit 255147eae820b26a8522814711066a1d883a7106 Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Thu Nov 16 18:47:29 2017 +0100 RotateFlyFrame3: add support for AutoContour For transformed FlyFrames with no Border and no Padding it would be nice to immediately start using AutoContour, added first implementation to do so Change-Id: I9f82d6ff3be8e1b8fb39b33836935b32879f405c diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx index a4466f1f9085..2dd8cffbf300 100644 --- a/sw/source/core/draw/dflyobj.cxx +++ b/sw/source/core/draw/dflyobj.cxx @@ -632,9 +632,9 @@ void SwVirtFlyDrawObj::NbcSetLogicRect(const tools::Rectangle& ) // SwVirtFlyDrawObj::Move() and Resize() void SwVirtFlyDrawObj::NbcMove(const Size& rSiz) { - if(GetFlyFrame()->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()) + if(GetFlyFrame()->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame()) { - // When we have a change and are in transformed state (e.g. rotation used), + // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used), // we need to fall back to the un-transformed state to keep the old code below // working properly. Restore FrameArea and use aOutRect from old FrameArea. TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); @@ -825,7 +825,7 @@ void SwVirtFlyDrawObj::NbcCrop(const basegfx::B2DPoint& rRef, double fxFact, dou const bool bIsTransformableSwFrame( GetFlyFrame()->IsFlyFreeFrame() && - static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()); + static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame()); if(bIsTransformableSwFrame) { @@ -977,7 +977,7 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const Fraction& xFact, const const bool bUseRightEdge((bVertX && !bVertL2RX ) || bRTL); const bool bIsTransformableSwFrame( GetFlyFrame()->IsFlyFreeFrame() && - static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()); + static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame()); if(bIsTransformableSwFrame) { diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx index 105689dbf848..ece412fde57c 100644 --- a/sw/source/core/frmedt/fefly1.cxx +++ b/sw/source/core/frmedt/fefly1.cxx @@ -369,7 +369,7 @@ void SwFEShell::SetFlyPos( const Point& rAbsPos ) // Anchor and new RelPos will be calculated and set by the Fly if ( pFly->IsFlyAtContentFrame() ) { - if(pFly->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(pFly)->isTransformableSwFrame()) + if(pFly->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(pFly)->isTransformableSwFrame()) { // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used), // we need to correct the absolute position (rAbsPos) which was created in diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index eaae5b89059d..1bde38f6784b 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -37,10 +37,10 @@ private: // #i34753# - flag for at-page anchored Writer fly frames // to prevent a positioning - call of method <MakeObjPos()> -, if Writer // fly frame is already clipped during its format by the object formatter. - bool mbNoMakePos; + bool mbNoMakePos : 1; // #i37068# - flag to prevent move in method <CheckClip(..)> - bool mbNoMoveOnCheckClip; + bool mbNoMoveOnCheckClip : 1; SwRect maUnclippedFrame; @@ -134,6 +134,9 @@ public: TransformableSwFrame* getTransformableSwFrame() { return mpTransformableSwFrame.get(); } const TransformableSwFrame* getTransformableSwFrame() const { return mpTransformableSwFrame.get(); } + // RotateFlyFrame3 - Support for AutoContour + bool supportsAutoContour() const; + // RotateFlyFrame3 - Support for Transformations virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index 5163fbb3f3c4..4e7639411062 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -2303,8 +2303,18 @@ void SwFlyFrame::NotifyDrawObj() pObj->SetRectsDirty(); pObj->SetChanged(); pObj->BroadcastObjectChange(); + if ( GetFormat()->GetSurround().IsContour() ) + { + ClrContourCache( pObj ); + } + else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame* >(this)->supportsAutoContour()) + { + // RotateFlyFrame3: Also need to clear when changes happen + // Caution: isTransformableSwFrame is already reset when resetting rotation, so + // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation ClrContourCache( pObj ); + } } Size SwFlyFrame::CalcRel( const SwFormatFrameSize &rSz ) const @@ -2435,120 +2445,135 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon& rContour, bool bRet = false; const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame()); - if(bIsCandidate && GetFormat()->GetSurround().IsContour()) + if(bIsCandidate) { - SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwContentFrame*>(Lower())->GetNode())); - // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic> - // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic - // node and method is called for paint. - const GraphicObject* pGrfObj = nullptr; - bool bGrfObjCreated = false; - const SwGrfNode* pGrfNd = pNd->GetGrfNode(); - if ( pGrfNd && _bForPaint ) - { - pGrfObj = &(pGrfNd->GetGrfObj()); - } - else - { - pGrfObj = new GraphicObject( pNd->GetGraphic() ); - bGrfObjCreated = true; - } - OSL_ENSURE( pGrfObj, "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>." ); - if ( pGrfObj && pGrfObj->GetType() != GraphicType::NONE ) + if(GetFormat()->GetSurround().IsContour()) { - if( !pNd->HasContour() ) + SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwContentFrame*>(Lower())->GetNode())); + // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic> + // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic + // node and method is called for paint. + const GraphicObject* pGrfObj = nullptr; + bool bGrfObjCreated = false; + const SwGrfNode* pGrfNd = pNd->GetGrfNode(); + if ( pGrfNd && _bForPaint ) { - // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic - // during paint. Thus, return (value of <bRet> should be <false>). - if ( pGrfNd && _bForPaint ) + pGrfObj = &(pGrfNd->GetGrfObj()); + } + else + { + pGrfObj = new GraphicObject( pNd->GetGraphic() ); + bGrfObjCreated = true; + } + OSL_ENSURE( pGrfObj, "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>." ); + if ( pGrfObj && pGrfObj->GetType() != GraphicType::NONE ) + { + if( !pNd->HasContour() ) { - OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." ); - return bRet; + // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic + // during paint. Thus, return (value of <bRet> should be <false>). + if ( pGrfNd && _bForPaint ) + { + OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." ); + return bRet; + } + pNd->CreateContour(); } - pNd->CreateContour(); - } - pNd->GetContour( rContour ); - // The Node holds the Polygon matching the original size of the graphic - // We need to include the scaling here - SwRect aClip; - SwRect aOrig; - Lower()->Calc(pRenderContext); - static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig ); - // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)> - // in order to avoid that graphic has to be loaded for contour scale. - //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() ); - { - OutputDevice* pOutDev = Application::GetDefaultDevice(); - const MapMode aDispMap( MapUnit::MapTwip ); - const MapMode aGrfMap( pGrfObj->GetPrefMapMode() ); - const Size aGrfSize( pGrfObj->GetPrefSize() ); - Size aOrgSize; - Point aNewPoint; - bool bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel; - - if ( bPixelMap ) - aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap ); - else - aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap ); - - if ( aOrgSize.Width() && aOrgSize.Height() ) + pNd->GetContour( rContour ); + // The Node holds the Polygon matching the original size of the graphic + // We need to include the scaling here + SwRect aClip; + SwRect aOrig; + Lower()->Calc(pRenderContext); + static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig ); + // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)> + // in order to avoid that graphic has to be loaded for contour scale. + //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() ); { - double fScaleX = (double) aOrig.Width() / aOrgSize.Width(); - double fScaleY = (double) aOrig.Height() / aOrgSize.Height(); + OutputDevice* pOutDev = Application::GetDefaultDevice(); + const MapMode aDispMap( MapUnit::MapTwip ); + const MapMode aGrfMap( pGrfObj->GetPrefMapMode() ); + const Size aGrfSize( pGrfObj->GetPrefSize() ); + Size aOrgSize; + Point aNewPoint; + bool bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel; + + if ( bPixelMap ) + aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap ); + else + aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap ); - for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ ) + if ( aOrgSize.Width() && aOrgSize.Height() ) { - tools::Polygon& rPoly = rContour[ j ]; + double fScaleX = (double) aOrig.Width() / aOrgSize.Width(); + double fScaleY = (double) aOrig.Height() / aOrgSize.Height(); - for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ ) + for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ ) { - if ( bPixelMap ) - aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap ); - else - aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap ); + tools::Polygon& rPoly = rContour[ j ]; - rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) ); + for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ ) + { + if ( bPixelMap ) + aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap ); + else + aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap ); + + rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) ); + } } } } + // OD 17.04.2003 #i13147# - destroy created <GraphicObject>. + if ( bGrfObjCreated ) + { + delete pGrfObj; + } + rContour.Move( aOrig.Left(), aOrig.Top() ); + if( !aClip.Width() ) + aClip.Width( 1 ); + if( !aClip.Height() ) + aClip.Height( 1 ); + rContour.Clip( aClip.SVRect() ); + rContour.Optimize(PolyOptimizeFlags::CLOSE); + bRet = true; } - // OD 17.04.2003 #i13147# - destroy created <GraphicObject>. - if ( bGrfObjCreated ) - { - delete pGrfObj; - } - rContour.Move( aOrig.Left(), aOrig.Top() ); - if( !aClip.Width() ) - aClip.Width( 1 ); - if( !aClip.Height() ) - aClip.Height( 1 ); - rContour.Clip( aClip.SVRect() ); - rContour.Optimize(PolyOptimizeFlags::CLOSE); - bRet = true; } - } + else + { + const SwFlyFreeFrame* pSwFlyFreeFrame(static_cast< const SwFlyFreeFrame* >(this)); - if(bRet && - rContour.Count() && - IsFlyFreeFrame() && - static_cast<const SwFlyFreeFrame*>(this)->isTransformableSwFrame()) - { - // RotateFlyFrame: Need to adapt contour to transformation - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); - - if(!basegfx::fTools::equalZero(fRotate)) - { - basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon()); - const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); - const basegfx::B2DHomMatrix aRotateAroundCenter( - basegfx::utils::createRotateAroundPoint( - aCenter.getX(), - aCenter.getY(), - fRotate)); - aSource.transform(aRotateAroundCenter); - rContour = tools::PolyPolygon(aSource); + if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->supportsAutoContour()) + { + // RotateFlyFrame: use untransformed SwFrame to allow text floating around. + // Will be transformed below + const TransformableSwFrame* pTransformableSwFrame(pSwFlyFreeFrame->getTransformableSwFrame()); + const SwRect aFrameArea(pTransformableSwFrame->getUntransformedFrameArea()); + rContour = tools::PolyPolygon(tools::Polygon(aFrameArea.SVRect())); + + if(0 != rContour.Count()) + { + // Need to adapt contour to transformation + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + if(!basegfx::fTools::equalZero(fRotate)) + { + basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon()); + const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); + const basegfx::B2DHomMatrix aRotateAroundCenter( + basegfx::utils::createRotateAroundPoint( + aCenter.getX(), + aCenter.getY(), + fRotate)); + aSource.transform(aRotateAroundCenter); + rContour = tools::PolyPolygon(aSource); + } + + bRet = true; + } + } } } diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 8a8c714ef351..c3cf51baa343 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -27,6 +27,7 @@ #include <hints.hxx> #include <sectfrm.hxx> #include <notxtfrm.hxx> +#include <txtfly.hxx> #include <svx/svdpage.hxx> #include <editeng/ulspitem.hxx> @@ -87,6 +88,8 @@ void SwFlyFreeFrame::DestroyImpl() SwFlyFreeFrame::~SwFlyFreeFrame() { + // we are possibly in ContourCache, make sure we vanish + ::ClrContourCache(GetVirtDrawObj()); } // #i28701# @@ -268,6 +271,14 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) } else { + // RotateFlyFrame3: Also need to clear ContourCache (if used), + // usually done in SwFlyFrame::NotifyDrawObj, but there relies on + // being in transform mode which is already resetted then + if(isTransformableSwFrame()) + { + ::ClrContourCache(GetVirtDrawObj()); + } + // reset transformations to show that they are not used mpTransformableSwFrame.reset(); } @@ -283,6 +294,37 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) #endif } +bool SwFlyFreeFrame::supportsAutoContour() const +{ + if(!isTransformableSwFrame()) + { + // support only when transformed, else there is no free space + return false; + } + + // Check for Borders. If we have Borders, do (currently) not support, + // since borders do not transform with the object. + // (Will need to be enhanced to take into account if we have Borders and if these + // transform with the object) + SwBorderAttrAccess aAccess(SwFrame::GetCache(), this); + const SwBorderAttrs &rAttrs(*aAccess.Get()); + + if(rAttrs.IsLine()) + { + return false; + } + + // Check for Padding. Do not support when padding is used, this will + // produce a covered space around the object (filled with fill defines) + + + + + + // else, support + return true; +} + // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const { diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 7144ee460dcd..2276f7fa2b99 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -2740,11 +2740,23 @@ void Notify( SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld, pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD ); } } - else if ( pOldPrt && *pOldPrt != pFly->getFramePrintArea() && - pFly->GetFormat()->GetSurround().IsContour() ) + else if(pOldPrt && *pOldPrt != pFly->getFramePrintArea()) { - // #i24097# - pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PREP_FLY_ARRIVE ); + bool bNotifyBackground(pFly->GetFormat()->GetSurround().IsContour()); + + if(!bNotifyBackground && + pFly->IsFlyFreeFrame() && + static_cast< const SwFlyFreeFrame* >(pFly)->supportsAutoContour()) + { + // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour + bNotifyBackground = true; + } + + if(bNotifyBackground) + { + // #i24097# + pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PREP_FLY_ARRIVE ); + } } } diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx index fff55186d725..2fb5c47a38a4 100644 --- a/sw/source/core/text/txtfly.cxx +++ b/sw/source/core/text/txtfly.cxx @@ -177,7 +177,22 @@ const SwRect SwContourCache::CalcBoundRect( const SwAnchoredObject* pAnchoredObj { SwRect aRet; const SwFrameFormat* pFormat = &(pAnchoredObj->GetFrameFormat()); - if( pFormat->GetSurround().IsContour() && + bool bHandleContour(pFormat->GetSurround().IsContour()); + + if(!bHandleContour) + { + // RotateFlyFrame3: Object has no set contour, but for rotated + // FlyFrames we can create a 'default' contour to make text + // flow around the free, non-covered + const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(pAnchoredObj)); + + if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->supportsAutoContour()) + { + bHandleContour = true; + } + } + + if( bHandleContour && ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr || ( static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower() && static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower()->IsNoTextFrame() ) ) ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits