[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - 9 commits - filter/source include/svx sfx2/inc sfx2/source svx/source sw/inc sw/qa sw/source

Juergen Funk juergen.funk_ml at cib.de
Wed Dec 13 13:55:51 UTC 2017


Rebased ref, commits from common ancestor:
commit a89aefc93fa25001a99f1cec3d5d25bab16e60b6
Author: Juergen Funk <juergen.funk_ml at cib.de>
Date:   Wed Dec 13 12:00:22 2017 +0000

    fix build: incompatible exception specs
    
    For gcc 4x and 5.2, we need to have matching, or more narrow, exception
    specs for overridden virtual methods.
    
    Change-Id: I2f2da8b8a9ac5639a3d885cd6851e1d0125651b1

diff --git a/filter/source/config/cache/typedetection.hxx b/filter/source/config/cache/typedetection.hxx
index f948e6522697..ae75131a0fa6 100644
--- a/filter/source/config/cache/typedetection.hxx
+++ b/filter/source/config/cache/typedetection.hxx
@@ -383,17 +383,17 @@ private:
 public:
 
     using cppu::WeakComponentImplHelperBase::disposing;
-    virtual void SAL_CALL disposing(const css::lang::EventObject&) override
+    virtual void SAL_CALL disposing(const css::lang::EventObject&) throw ()  override
     {
     }
 
     // XTerminateListener
-    virtual void SAL_CALL queryTermination(const css::lang::EventObject&) override
+    virtual void SAL_CALL queryTermination(const css::lang::EventObject&) throw () override
     {
         m_pTypeDetection->cancel();
     }
 
-    virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) override
+    virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) throw () override
     {
     }
 
diff --git a/sfx2/inc/preventduplicateinteraction.hxx b/sfx2/inc/preventduplicateinteraction.hxx
index f9097576e480..0f89169b6087 100644
--- a/sfx2/inc/preventduplicateinteraction.hxx
+++ b/sfx2/inc/preventduplicateinteraction.hxx
@@ -81,19 +81,19 @@ private:
 public:
 
     using cppu::WeakComponentImplHelperBase::disposing;
-    virtual void SAL_CALL disposing(const css::lang::EventObject&) override
+    virtual void SAL_CALL disposing(const css::lang::EventObject&) throw () override
     {
     }
 
     // XTerminateListener
-    virtual void SAL_CALL queryTermination(const css::lang::EventObject&) override
+    virtual void SAL_CALL queryTermination(const css::lang::EventObject&) throw () override
     {
         closewarningdialogs();
         Application::PostUserEvent(LINK(this, WarningDialogsParent, TerminateDesktop));
         throw css::frame::TerminationVetoException();
     }
 
-    virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) override
+    virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) throw () override
     {
     }
 
@@ -221,7 +221,8 @@ class PreventDuplicateInteraction : private ThreadHelpBase2
     // uno interface
     public:
 
-        virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+        virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments)
+        throw(css::uno::RuntimeException, std::exception) override;
 
         /**
             @interface  XInteractionHandler
diff --git a/sfx2/source/appl/preventduplicateinteraction.cxx b/sfx2/source/appl/preventduplicateinteraction.cxx
index 7ef25e70e82d..dd7263d51c6d 100644
--- a/sfx2/source/appl/preventduplicateinteraction.cxx
+++ b/sfx2/source/appl/preventduplicateinteraction.cxx
@@ -243,6 +243,7 @@ bool PreventDuplicateInteraction::getInteractionInfo(const css::uno::Type&
 }
 
 void SAL_CALL PreventDuplicateInteraction::initialize(const css::uno::Sequence<css::uno::Any>& rArguments)
+              throw (css::uno::RuntimeException, std::exception)
 {
     // If we're re-initialized to set a specific new window as a parent then drop our temporary
     // dialog parent
commit 5722c826a0eecc52892df4e839aa78f0861be80f
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jul 22 18:00:59 2016 +0200

    Remove now unused SwTextBoxHelper functions
    
    (Manually cherry picked from commit f7f5d27066b696ac4e33246d3794bde8058e8622)
    
    Change-Id: I39500424c79040b1887ea74081fdf0ea0bc5f009
    Reviewed-on: https://gerrit.libreoffice.org/46331
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 98983bad9f42..32fc2167c72a 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -73,8 +73,6 @@ public:
     static SwFrameFormat* getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType);
     /// If we have an associated TextFrame, then return that.
     static SwFrameFormat* getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> xShape);
-    static SwFrameFormat* findTextBox(const SwFrameFormat* pShape);
-    static SwFrameFormat* findTextBox(const css::uno::Reference<css::drawing::XShape>& xShape);
     /// Return the textbox rectangle of a draw shape (in twips).
     static Rectangle getTextRectangle(SwFrameFormat* pShape, bool bAbsolute = true);
 
@@ -91,17 +89,6 @@ public:
     /// Is pObject a textbox of a drawinglayer shape?
     static bool isTextBox(const SdrObject* pObject);
 
-    /// Look up TextFrames in a document, which are in fact TextBoxes.
-    static std::set<const SwFrameFormat*> findTextBoxes(const SwDoc* pDoc);
-    /**
-     * Look up TextFrames in a document, which are in fact TextBoxes.
-     *
-     * If rNode has a matching SwContentFrame, then only TextBoxes of rNode are
-     * returned.
-     */
-    static std::set<const SwFrameFormat*> findTextBoxes(const SwNode& rNode);
-    /// Build a textbox -> shape format map.
-    static std::map<SwFrameFormat*, SwFrameFormat*> findShapes(const SwDoc* pDoc);
     /// Count number of shapes in the document, excluding TextBoxes.
     static sal_Int32 getCount(const SwDoc* pDoc);
     /// Count number of shapes on the page, excluding TextBoxes.
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 12464e37e4b6..23033eaeea38 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -126,27 +126,6 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape)
     }
 }
 
-std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
-{
-    std::set<const SwFrameFormat*> aTextBoxes;
-
-    const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
-    for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
-    {
-        const SwFrameFormat* pFormat = *it;
-
-        // A TextBox in the context of this class is a fly frame that has a
-        // matching (same RES_CNTNT) draw frame.
-        if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || !pFormat->GetContent().GetContentIdx())
-            continue;
-
-        if (pFormat->Which() == RES_FLYFRMFMT && nullptr != pFormat->GetOtherTextBoxFormat())
-            aTextBoxes.insert(pFormat);
-    }
-
-    return aTextBoxes;
-}
-
 bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType)
 {
    assert(nType == RES_FLYFRMFMT || nType == RES_DRAWFRMFMT);
@@ -169,49 +148,6 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType)
    return true;
 }
 
-std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode)
-{
-    const SwDoc* pDoc = rNode.GetDoc();
-    const SwContentNode* pContentNode = nullptr;
-    const SwContentFrame* pContentFrame = nullptr;
-    bool bHaveViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
-    if (bHaveViewShell && (pContentNode = rNode.GetContentNode()) && (pContentFrame = pContentNode->getLayoutFrame(pDoc->getIDocumentLayoutAccess().GetCurrentLayout())))
-    {
-        // We can use the layout information to iterate over only the frames which are anchored to us.
-        std::set<const SwFrameFormat*> aRet;
-        const SwSortedObjs* pSortedObjs = pContentFrame->GetDrawObjs();
-        if (pSortedObjs)
-        {
-            for (SwAnchoredObject* pAnchoredObject : *pSortedObjs)
-            {
-                SwFrameFormat* pTextBox = getOtherTextBoxFormat(&pAnchoredObject->GetFrameFormat(), RES_DRAWFRMFMT);
-                if (pTextBox)
-                    aRet.insert(pTextBox);
-            }
-        }
-        return aRet;
-    }
-    else
-        // If necessary, here we could manually limit the returned set to the
-        // ones which are anchored to rNode, but currently no need to do so.
-        return findTextBoxes(pDoc);
-}
-
-std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc* pDoc)
-{
-    std::map<SwFrameFormat*, SwFrameFormat*> aRet;
-
-    const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
-    for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
-    {
-        SwFrameFormat* pTextBox = getOtherTextBoxFormat(*it, RES_DRAWFRMFMT);
-        if (pTextBox)
-            aRet[pTextBox] = *it;
-    }
-
-    return aRet;
-}
-
 bool SwTextBoxHelper::isTextBox(const SdrObject* pObject)
 {
     const SwVirtFlyDrawObj* pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObject);
@@ -312,39 +248,6 @@ SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XS
     return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT);
 }
 
-SwFrameFormat* SwTextBoxHelper::findTextBox(const uno::Reference<drawing::XShape>& xShape)
-{
-    SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
-    if (!pShape)
-        return nullptr;
-
-    return findTextBox(pShape->GetFrameFormat());
-}
-
-SwFrameFormat* SwTextBoxHelper::findTextBox(const SwFrameFormat* pShape)
-{
-    SwFrameFormat* pRet = nullptr;
-
-    // Only draw frames can have TextBoxes.
-    if (pShape && pShape->Which() == RES_DRAWFRMFMT && pShape->GetAttrSet().HasItem(RES_CNTNT))
-    {
-        const SwFormatContent& rContent = pShape->GetContent();
-        const SwFrameFormats& rSpzFrameFormats = *pShape->GetDoc()->GetSpzFrameFormats();
-        for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
-        {
-            SwFrameFormat* pFormat = *it;
-            // Only a fly frame can be a TextBox.
-            if (pFormat->Which() == RES_FLYFRMFMT && pFormat->GetAttrSet().HasItem(RES_CNTNT) && pFormat->GetContent() == rContent)
-            {
-                pRet = pFormat;
-                break;
-            }
-        }
-    }
-
-    return pRet;
-}
-
 template < typename T >
 void lcl_queryInterface(SwFrameFormat* pShape, uno::Any& rAny)
 {
commit db35f3d3a066305147721ad5dae1027415297035
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jul 22 17:59:28 2016 +0200

    Add convenience function getOtherTextBoxFormat
    
    Since we already have isTextBox to identify a text box, this
    just adds a call to SwFrameFormat::GetOtherTextBoxFormat() to
    actually return the corresponding SwFrameFormat.
    
    This gets rid off all the remaining occurences of the
    SwFrameFormat / Textbox sets and maps.
    
    (Manually cherry picked from commit f7f5d27066b696ac4e33246d3794bde8058e8622)
    
    Change-Id: Id5f05a1ff71e604658e7d8a0d0825f5671335b3f
    Reviewed-on: https://gerrit.libreoffice.org/46330
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index eb94bbc1d194..98983bad9f42 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -62,7 +62,17 @@ public:
     /// Similar to syncProperty(), but used by the internal API (e.g. for UI purposes).
     static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet& rSet);
 
+    /**
+     * If we have an associated TextFrame, then return that.
+     *
+     * @param nType Expected frame format type.
+     *              Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT.
+     *
+     * @see isTextBox
+     */
+    static SwFrameFormat* getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType);
     /// If we have an associated TextFrame, then return that.
+    static SwFrameFormat* getOtherTextBoxFormat(css::uno::Reference<css::drawing::XShape> xShape);
     static SwFrameFormat* findTextBox(const SwFrameFormat* pShape);
     static SwFrameFormat* findTextBox(const css::uno::Reference<css::drawing::XShape>& xShape);
     /// Return the textbox rectangle of a draw shape (in twips).
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx
index 5fc0d4cc7483..254a4ee14ba7 100644
--- a/sw/source/core/doc/DocumentLayoutManager.cxx
+++ b/sw/source/core/doc/DocumentLayoutManager.cxx
@@ -494,7 +494,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
         pDest->MakeFrames();
 
     // If the draw format has a TextBox, then copy its fly format as well.
-    if (SwFrameFormat* pSourceTextBox = SwTextBoxHelper::findTextBox(&rSource))
+    if (SwFrameFormat* pSourceTextBox = SwTextBoxHelper::getOtherTextBoxFormat(&rSource, RES_DRAWFRMFMT))
     {
         SwFormatAnchor boxAnchor(rNewAnchor);
         if (FLY_AS_CHAR == boxAnchor.GetAnchorId())
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 33571730300e..12464e37e4b6 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -115,7 +115,7 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape)
     // If a TextBox was enabled previously
     if (pShape->GetAttrSet().HasItem(RES_CNTNT))
     {
-        SwFrameFormat* pFormat = findTextBox(pShape);
+        SwFrameFormat* pFormat = pShape->GetOtherTextBoxFormat();
 
         // Unlink the TextBox's text range from the original shape.
         pShape->ResetFormatAttr(RES_CNTNT);
@@ -129,7 +129,6 @@ void SwTextBoxHelper::destroy(SwFrameFormat* pShape)
 std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
 {
     std::set<const SwFrameFormat*> aTextBoxes;
-    std::map<SwNodeIndex, const SwFrameFormat*> aFlyFormats, aDrawFormats;
 
     const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
     for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
@@ -141,22 +140,8 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
         if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || !pFormat->GetContent().GetContentIdx())
             continue;
 
-        const SwNodeIndex& rIndex = *pFormat->GetContent().GetContentIdx();
-
-        if (pFormat->Which() == RES_FLYFRMFMT)
-        {
-            if (aDrawFormats.find(rIndex) != aDrawFormats.end())
-                aTextBoxes.insert(pFormat);
-            else
-                aFlyFormats[rIndex] = pFormat;
-        }
-        else if (pFormat->Which() == RES_DRAWFRMFMT)
-        {
-            if (aFlyFormats.find(rIndex) != aFlyFormats.end())
-                aTextBoxes.insert(aFlyFormats[rIndex]);
-            else
-                aDrawFormats[rIndex] = pFormat;
-        }
+        if (pFormat->Which() == RES_FLYFRMFMT && nullptr != pFormat->GetOtherTextBoxFormat())
+            aTextBoxes.insert(pFormat);
     }
 
     return aTextBoxes;
@@ -199,7 +184,7 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNod
         {
             for (SwAnchoredObject* pAnchoredObject : *pSortedObjs)
             {
-                SwFrameFormat* pTextBox = findTextBox(&pAnchoredObject->GetFrameFormat());
+                SwFrameFormat* pTextBox = getOtherTextBoxFormat(&pAnchoredObject->GetFrameFormat(), RES_DRAWFRMFMT);
                 if (pTextBox)
                     aRet.insert(pTextBox);
             }
@@ -219,7 +204,7 @@ std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc
     const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
     for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
     {
-        SwFrameFormat* pTextBox = findTextBox(*it);
+        SwFrameFormat* pTextBox = getOtherTextBoxFormat(*it, RES_DRAWFRMFMT);
         if (pTextBox)
             aRet[pTextBox] = *it;
     }
@@ -305,11 +290,26 @@ sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject)
 
 void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough)
 {
-    std::map<SwFrameFormat*, SwFrameFormat*> aMap = findShapes(pTextBox->GetDoc());
-    std::map<SwFrameFormat*, SwFrameFormat*>::iterator it = aMap.find(const_cast<SwFrameFormat*>(pTextBox));
-    if (it != aMap.end())
-        // pTextBox is indeed a TextBox, it->second is its shape.
-        rWrapThrough = it->second->GetSurround().GetSurround() == SURROUND_THROUGHT;
+    SwFrameFormat *pShape = SwTextBoxHelper::getOtherTextBoxFormat(pTextBox, RES_FLYFRMFMT);
+    if (pShape)
+        rWrapThrough = pShape->GetSurround().GetSurround() == SURROUND_THROUGHT;
+}
+
+SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(const SwFrameFormat* pFormat, sal_uInt16 nType)
+{
+    if (!isTextBox(pFormat, nType))
+        return nullptr;
+    return pFormat->GetOtherTextBoxFormat();
+}
+
+SwFrameFormat* SwTextBoxHelper::getOtherTextBoxFormat(uno::Reference<drawing::XShape> xShape)
+{
+    SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
+    if (!pShape)
+        return nullptr;
+
+    SwFrameFormat *pFormat = pShape->GetFrameFormat();
+    return getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT);
 }
 
 SwFrameFormat* SwTextBoxHelper::findTextBox(const uno::Reference<drawing::XShape>& xShape)
@@ -348,7 +348,7 @@ SwFrameFormat* SwTextBoxHelper::findTextBox(const SwFrameFormat* pShape)
 template < typename T >
 void lcl_queryInterface(SwFrameFormat* pShape, uno::Any& rAny)
 {
-    if (SwFrameFormat* pFormat = SwTextBoxHelper::findTextBox(pShape))
+    if (SwFrameFormat* pFormat = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
     {
         uno::Reference<T> const xInterface(
             SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), pFormat),
@@ -426,7 +426,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, const OUString& rPrope
             syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION, uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
         }
 
-        if (SwFrameFormat* pFormat = findTextBox(pShape))
+        if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
         {
             comphelper::SequenceAsHashMap aCustomShapeGeometry(rValue);
             // That would be the btLr text direction which we don't support at a frame level, so do it at a character level.
@@ -460,7 +460,7 @@ void SwTextBoxHelper::getProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uI
 
     nMemberId &= ~CONVERT_TWIPS;
 
-    if (SwFrameFormat* pFormat = findTextBox(pShape))
+    if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
     {
         if (nWID == RES_CHAIN)
         {
@@ -490,7 +490,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
     uno::Any aValue(rValue);
     nMemberId &= ~CONVERT_TWIPS;
 
-    if (SwFrameFormat* pFormat = findTextBox(pShape))
+    if (SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
     {
         OUString aPropertyName;
         bool bAdjustX = false;
@@ -631,9 +631,7 @@ void SwTextBoxHelper::saveLinks(const SwFrameFormats& rFormats, std::map<const S
     for (std::size_t i = 0; i < rFormats.size(); ++i)
     {
         const SwFrameFormat* pFormat = rFormats[i];
-        if (pFormat->Which() != RES_DRAWFRMFMT)
-            continue;
-        if (SwFrameFormat* pTextBox = findTextBox(pFormat))
+        if (SwFrameFormat* pTextBox = getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
             rLinks[pFormat] = pTextBox;
     }
 }
@@ -670,7 +668,7 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame
 
 void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet& rSet)
 {
-    if (SwFrameFormat* pFormat = findTextBox(&rShape))
+    if (SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT))
     {
         SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange);
 
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index 2bd03bfce93c..1d036aa7d125 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -966,7 +966,7 @@ void SwDrawView::DeleteMarked()
         SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj();
         SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall(pObject));
         SwFrameFormat* pFormat = pDrawContact->GetFormat();
-        if (SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pFormat))
+        if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
             aTextBoxesToDelete.push_back(pTextBox);
     }
 
diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx
index e41ee3965cde..2c8553b64efc 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -232,15 +232,13 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj )
     if (!(nFlag & SW_ALLOW_TEXTBOX))
     {
         // If the fly frame is a textbox of a shape, then select the shape instead.
-        std::map<SwFrameFormat*, SwFrameFormat*> aTextBoxShapes = SwTextBoxHelper::findShapes(mpDoc);
         for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i)
         {
             SdrObject* pObject = rMrkList.GetMark(i)->GetMarkedSdrObj();
-            SwContact* pDrawContact = static_cast<SwContact*>(GetUserCall(pObject));
-            SwFrameFormat* pFormat = pDrawContact->GetFormat();
-            if (aTextBoxShapes.find(pFormat) != aTextBoxShapes.end())
+            SwFrameFormat* pFormat = GetUserCall(pObject)->GetFormat();
+            if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT))
             {
-                SdrObject* pShape = aTextBoxShapes[pFormat]->FindSdrObject();
+                SdrObject* pShape = pShapeFormat->FindSdrObject();
                 pDView->UnmarkAll();
                 pDView->MarkObj(pShape, Imp()->GetPageView(), bAddSelect, bEnterGroup);
                 break;
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 66c131d80f6d..fa98ceaf5c4c 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -1294,11 +1294,10 @@ void SwFlyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderA
             }
             mbValidSize = true;
 
-            std::map<SwFrameFormat*, SwFrameFormat*> aShapes = SwTextBoxHelper::findShapes(GetFormat()->GetDoc());
-            if (aShapes.find(GetFormat()) != aShapes.end())
+            if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT))
             {
                 // This fly is a textbox of a draw shape.
-                SdrObject* pShape = aShapes[GetFormat()]->FindSdrObject();
+                SdrObject* pShape = pShapeFormat->FindSdrObject();
                 if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pShape) )
                 {
                     // The shape is a customshape: then inform it about the calculated fly size.
diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx
index 43ab530992ae..a0b91031522d 100644
--- a/sw/source/core/text/porfly.cxx
+++ b/sw/source/core/text/porfly.cxx
@@ -359,7 +359,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase,
     if (rAnchor.GetAnchorId() == FLY_AS_CHAR)
     {
         // This is an inline draw shape, see if it has a textbox.
-        SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pShape);
+        SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
         if (pTextBox)
         {
             // It has, so look up its text rectangle, and adjust the position
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index f05afd2652ab..fcd5bcf5f498 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5428,7 +5428,7 @@ void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
     DocxTableExportContext aTableExportContext;
     pushToTableExportContext(aTableExportContext);
 
-    SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(xShape);
+    SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(xShape);
     const SwPosition* pAnchor = pTextBox->GetAnchor().GetContentAnchor();
     ww8::Frame aFrame(*pTextBox, *pAnchor);
     m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++, /*bTextBoxOnly=*/true);
@@ -5441,7 +5441,7 @@ void DocxAttributeOutput::WriteVMLTextBox(uno::Reference<drawing::XShape> xShape
     DocxTableExportContext aTableExportContext;
     pushToTableExportContext(aTableExportContext);
 
-    SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(xShape);
+    SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(xShape);
     const SwPosition* pAnchor = pTextBox->GetAnchor().GetContentAnchor();
     ww8::Frame aFrame(*pTextBox, *pAnchor);
     m_rExport.SdrExporter().writeVMLTextFrame(&aFrame, /*bTextBoxOnly=*/true);
diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx
index f303e8a379a6..48da64f56d56 100644
--- a/sw/source/filter/ww8/rtfsdrexport.cxx
+++ b/sw/source/filter/ww8/rtfsdrexport.cxx
@@ -39,8 +39,7 @@ RtfSdrExport::RtfSdrExport(RtfExport& rExport)
       m_nShapeType(ESCHER_ShpInst_Nil),
       m_nShapeFlags(0) ,
       m_aShapeStyle(200),
-      m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ]),
-      m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.m_pDoc))
+      m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ])
 {
     mnGroupLevel = 1;
     memset(m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof(bool));
@@ -514,7 +513,7 @@ sal_Int32 RtfSdrExport::StartShape()
     const SwFrameFormat* pShape = FindFrameFormat(m_pSdrObject);
     if (pShape)
     {
-        if (SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pShape))
+        if (SwFrameFormat* pTextBox = SwTextBoxHelper::getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
         {
             ww8::Frame* pFrame = nullptr;
             for (ww8::FrameIter it = m_rExport.m_aFrames.begin(); it != m_rExport.m_aFrames.end(); ++it)
diff --git a/sw/source/filter/ww8/rtfsdrexport.hxx b/sw/source/filter/ww8/rtfsdrexport.hxx
index 15a7fbf7e705..eef0b5047a54 100644
--- a/sw/source/filter/ww8/rtfsdrexport.hxx
+++ b/sw/source/filter/ww8/rtfsdrexport.hxx
@@ -56,9 +56,6 @@ class RtfSdrExport : public EscherEx
     /// Remember which shape types we had already written.
     bool* m_pShapeTypeWritten;
 
-    /// List of TextBoxes in this document: they are exported as part of their shape, never alone.
-    std::set<const SwFrameFormat*> m_aTextBoxes;
-
 public:
     explicit RtfSdrExport(RtfExport& rExport);
     virtual             ~RtfSdrExport();
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 2ded67656383..b8b8b588c296 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -204,7 +204,7 @@ static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
 {
     SdrObject* pSdrObject = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
     SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
-    if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::findTextBox(pObjectFormat))
+    if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
     {
         SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
         SdrView* pSdrView = rSh.GetDrawView();
@@ -4402,10 +4402,9 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
             SdrPageView* pPV;
             if (pSdrView && pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER ))
             {
-                std::map<SwFrameFormat*, SwFrameFormat*> aTextBoxShapes = SwTextBoxHelper::findShapes(rSh.GetDoc());
-                auto pDrawContact = GetUserCall(pObj);
-                SwFrameFormat* pFormat = pDrawContact->GetFormat();
-                if (aTextBoxShapes.find(pFormat) == aTextBoxShapes.end())
+                SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
+                SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT);
+                if (!pShapeFormat)
                 {
                     pSdrView->UnmarkAllObj();
                     pSdrView->MarkObj(pObj,pPV);
@@ -4413,7 +4412,7 @@ void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
                 else
                 {
                     // If the fly frame is a textbox of a shape, then select the shape instead.
-                    SdrObject* pShape = aTextBoxShapes[pFormat]->FindSdrObject();
+                    SdrObject* pShape = pShapeFormat->FindSdrObject();
                     pSdrView->UnmarkAllObj();
                     pSdrView->MarkObj(pShape, pPV);
                 }
commit 8f47312716d0a36ecee5ebf6d4ebffce61d74df0
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jul 22 17:50:52 2016 +0200

    Switch isTextBox to use the format pointers
    
    This replaces all possible occurences of the text box format
    maps, which just want to know, if a SwFrameFormat is part of a
    text box to use the direct lookup via the isTextBox, which is
    now a cheap call.
    
    (Manually cherry picked from commit 0bcc5b3daebeb2a7d2b5ba132af4745cc6c78cd0)
    
    Change-Id: I3b4e2301f816aead1b719cd70a8ef118e685ccfc
    Reviewed-on: https://gerrit.libreoffice.org/46306
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index cce179607181..eb94bbc1d194 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -68,6 +68,19 @@ public:
     /// Return the textbox rectangle of a draw shape (in twips).
     static Rectangle getTextRectangle(SwFrameFormat* pShape, bool bAbsolute = true);
 
+    /**
+     * Is the frame format a text box?
+     *
+     * A text box consists of a coupled fly and draw format. Most times you
+     * just want to check for a single type, otherwise you get duplicate results.
+     *
+     * @param nType Expected frame format input type.
+     *              Valid types are RES_DRAWFRMFMT and RES_FLYFRMFMT.
+     */
+    static bool isTextBox(const SwFrameFormat* pFormat, sal_uInt16 nType);
+    /// Is pObject a textbox of a drawinglayer shape?
+    static bool isTextBox(const SdrObject* pObject);
+
     /// Look up TextFrames in a document, which are in fact TextBoxes.
     static std::set<const SwFrameFormat*> findTextBoxes(const SwDoc* pDoc);
     /**
@@ -77,16 +90,16 @@ public:
      * returned.
      */
     static std::set<const SwFrameFormat*> findTextBoxes(const SwNode& rNode);
-    /// Is pObject a textbox of a drawinglayer shape?
-    static bool isTextBox(const SdrObject* pObject);
     /// Build a textbox -> shape format map.
     static std::map<SwFrameFormat*, SwFrameFormat*> findShapes(const SwDoc* pDoc);
     /// Count number of shapes in the document, excluding TextBoxes.
-    static sal_Int32 getCount(SdrPage* pPage, std::set<const SwFrameFormat*>& rTextBoxes);
+    static sal_Int32 getCount(const SwDoc* pDoc);
+    /// Count number of shapes on the page, excluding TextBoxes.
+    static sal_Int32 getCount(SdrPage* pPage);
     /// Get a shape by index, excluding TextBoxes.
-    static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(css::lang::IndexOutOfBoundsException);
+    static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex) throw(css::lang::IndexOutOfBoundsException);
     /// Get the order of the shape, excluding TextBoxes.
-    static sal_Int32 getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes);
+    static sal_Int32 getOrdNum(const SdrObject* pObject);
     /// If pTextBox is a textbox, then set rWrapThrough to the surround of its shape.
     static void getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough);
 
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 119ff204d179..766ab7199419 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -858,9 +858,8 @@ void SwUiWriterTest::testFdo82191()
 {
     SwDoc* pDoc = createDoc("fdo82191.odt");
     SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
-    std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
     // Make sure we have a single draw shape.
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), SwTextBoxHelper::getCount(pPage, aTextBoxes));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), SwTextBoxHelper::getCount(pPage));
 
     SwDoc aClipboard;
     SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
@@ -870,9 +869,8 @@ void SwUiWriterTest::testFdo82191()
     pWrtShell->Copy(&aClipboard);
     pWrtShell->Paste(&aClipboard);
 
-    aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
     // This was one: the textbox of the shape wasn't copied.
-    CPPUNIT_ASSERT_EQUAL(size_t(2), aTextBoxes.size());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), SwTextBoxHelper::getCount(pDoc));
 }
 
 void SwUiWriterTest::testCommentedWord()
@@ -3389,15 +3387,20 @@ void SwUiWriterTest::testTdf92648()
 {
     SwDoc* pDoc = createDoc("tdf92648.docx");
     SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
-    std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
     // Make sure we have ten draw shapes.
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage, aTextBoxes));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage));
     // and the text boxes haven't got zero height
-    for (std::set<const SwFrameFormat*>::iterator it=aTextBoxes.begin(); it!=aTextBoxes.end(); ++it)
+    sal_Int32 nCount = 0;
+    for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats())
     {
-        SwFormatFrameSize aSize((*it)->GetFrameSize());
+        if (!SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT))
+            continue;
+        SwFormatFrameSize aSize(pFormat->GetFrameSize());
         CPPUNIT_ASSERT(aSize.GetHeight() != 0);
+        ++nCount;
     }
+    // and we have had five of them.
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), nCount);
 }
 
 void SwUiWriterTest::testTdf96515()
@@ -3721,8 +3724,7 @@ void SwUiWriterTest::testTdf78727()
     SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
     // This was 1: make sure we don't loose the TextBox anchored inside the
     // table that is moved inside a text frame.
-    std::set<const SwFrameFormat*> aSet;
-    CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage, aSet) > 1);
+    CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage) > 1);
 }
 
 // accepting change tracking gets stuck on change
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index e1291b6673ba..98ffdae260f3 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -79,15 +79,11 @@ size_t SwDoc::GetFlyCount( FlyCntType eType, bool bIgnoreTextBoxes ) const
     size_t nCount = 0;
     const SwNodeIndex* pIdx;
 
-    std::set<const SwFrameFormat*> aTextBoxes;
-    if (bIgnoreTextBoxes)
-        aTextBoxes = SwTextBoxHelper::findTextBoxes(this);
-
     for ( size_t i = 0; i < nSize; ++i)
     {
         const SwFrameFormat* pFlyFormat = rFormats[ i ];
 
-        if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end())
+        if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT))
             continue;
 
         if( RES_FLYFRMFMT == pFlyFormat->Which()
@@ -131,15 +127,11 @@ SwFrameFormat* SwDoc::GetFlyNum( size_t nIdx, FlyCntType eType, bool bIgnoreText
     const SwNodeIndex* pIdx;
     size_t nCount = 0;
 
-    std::set<const SwFrameFormat*> aTextBoxes;
-    if (bIgnoreTextBoxes)
-        aTextBoxes = SwTextBoxHelper::findTextBoxes(this);
-
     for( size_t i = 0; !pRetFormat && i < nSize; ++i )
     {
         SwFrameFormat* pFlyFormat = rFormats[ i ];
 
-        if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end())
+        if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT))
             continue;
 
         if( RES_FLYFRMFMT == pFlyFormat->Which()
@@ -177,10 +169,6 @@ std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats(
     SwFrameFormats& rFormats = *GetSpzFrameFormats();
     const size_t nSize = rFormats.size();
 
-    std::set<const SwFrameFormat*> aTextBoxes;
-    if (bIgnoreTextBoxes)
-        aTextBoxes = SwTextBoxHelper::findTextBoxes(this);
-
     std::vector<SwFrameFormat const*> ret;
     ret.reserve(nSize);
 
@@ -188,7 +176,7 @@ std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats(
     {
         SwFrameFormat const*const pFlyFormat = rFormats[ i ];
 
-        if (bIgnoreTextBoxes && aTextBoxes.find(pFlyFormat) != aTextBoxes.end())
+        if (bIgnoreTextBoxes && SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT))
         {
             continue;
         }
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index c75908384ebf..33571730300e 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -162,6 +162,28 @@ std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwDoc* pDoc)
     return aTextBoxes;
 }
 
+bool SwTextBoxHelper::isTextBox(const SwFrameFormat* pShape, sal_uInt16 nType)
+{
+   assert(nType == RES_FLYFRMFMT || nType == RES_DRAWFRMFMT);
+   if (!pShape || pShape->Which() != nType || !pShape->GetAttrSet().HasItem(RES_CNTNT))
+       return false;
+
+   sal_uInt16 nOtherType = (pShape->Which() == RES_FLYFRMFMT) ? RES_DRAWFRMFMT : RES_FLYFRMFMT;
+   SwFrameFormat* pFormat = pShape->GetOtherTextBoxFormat();
+   if (!pFormat)
+       return false;
+
+   assert(pFormat->Which() == nOtherType);
+   if (pFormat->Which() != nOtherType)
+       return false;
+
+   const SwFormatContent& rContent = pShape->GetContent();
+   if (!pFormat->GetAttrSet().HasItem(RES_CNTNT) || pFormat->GetContent() != rContent)
+       return false;
+
+   return true;
+}
+
 std::set<const SwFrameFormat*> SwTextBoxHelper::findTextBoxes(const SwNode& rNode)
 {
     const SwDoc* pDoc = rNode.GetDoc();
@@ -205,35 +227,39 @@ std::map<SwFrameFormat*, SwFrameFormat*> SwTextBoxHelper::findShapes(const SwDoc
     return aRet;
 }
 
-/// If the passed SdrObject is in fact a TextFrame, that is used as a TextBox.
-bool lcl_isTextBox(SdrObject* pSdrObject, std::set<const SwFrameFormat*>& rTextBoxes)
-{
-    SwVirtFlyDrawObj* pObject = dynamic_cast<SwVirtFlyDrawObj*>(pSdrObject);
-    return pObject && rTextBoxes.find(pObject->GetFormat()) != rTextBoxes.end();
-}
-
 bool SwTextBoxHelper::isTextBox(const SdrObject* pObject)
 {
     const SwVirtFlyDrawObj* pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObject);
     if (!pVirtFlyDrawObj)
         return false;
-    std::set<const SwFrameFormat*> aTextBoxes = findTextBoxes(pVirtFlyDrawObj->GetFormat()->GetDoc());
-    return aTextBoxes.find(pVirtFlyDrawObj->GetFormat()) != aTextBoxes.end();
+    return isTextBox(pVirtFlyDrawObj->GetFormat(), RES_FLYFRMFMT);
 }
 
-sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage, std::set<const SwFrameFormat*>& rTextBoxes)
+sal_Int32 SwTextBoxHelper::getCount(SdrPage* pPage)
 {
     sal_Int32 nRet = 0;
     for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
     {
-        if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
+        if (isTextBox(pPage->GetObj(i)))
             continue;
         ++nRet;
     }
     return nRet;
 }
 
-uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(lang::IndexOutOfBoundsException)
+sal_Int32 SwTextBoxHelper::getCount(const SwDoc* pDoc)
+{
+    sal_Int32 nRet = 0;
+    const SwFrameFormats& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
+    for (SwFrameFormats::const_iterator it = rSpzFrameFormats.begin(); it != rSpzFrameFormats.end(); ++it)
+    {
+        if (isTextBox(*it, RES_FLYFRMFMT))
+            ++nRet;
+    }
+    return nRet;
+}
+
+uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex) throw(lang::IndexOutOfBoundsException)
 {
     if (nIndex < 0)
         throw lang::IndexOutOfBoundsException();
@@ -242,7 +268,7 @@ uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<
     sal_Int32 nCount = 0; // Current logical index.
     for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
     {
-        if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
+        if (isTextBox(pPage->GetObj(i)))
             continue;
         if (nCount == nIndex)
         {
@@ -258,14 +284,14 @@ uno::Any SwTextBoxHelper::getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<
     return uno::makeAny(uno::Reference<drawing::XShape>(pRet->getUnoShape(), uno::UNO_QUERY));
 }
 
-sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes)
+sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject)
 {
     if (const SdrPage* pPage = pObject->GetPage())
     {
         sal_Int32 nOrder = 0; // Current logical order.
         for (std::size_t i = 0; i < pPage->GetObjCount(); ++i)
         {
-            if (lcl_isTextBox(pPage->GetObj(i), rTextBoxes))
+            if (isTextBox(pPage->GetObj(i)))
                 continue;
             if (pPage->GetObj(i) == pObject)
                 return nOrder;
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
index b9ef741b2d35..080af8dc9386 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -1151,7 +1151,7 @@ class NestedUserCallHdl
 /// Notify the format's textbox that it should reconsider its position / size.
 void lcl_textBoxSizeNotify(SwFrameFormat* pFormat)
 {
-    if (SwTextBoxHelper::findTextBox(pFormat))
+    if (SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT))
     {
         // Just notify the textbox that the size has changed, the actual object size is not interesting.
         SfxItemSet aResizeSet(pFormat->GetDoc()->GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE, 0);
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 5506cb9b8e58..a33f4bb906bf 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -902,7 +902,6 @@ bool SwFEShell::Paste( SwDoc* pClpDoc )
                 if( !Imp()->GetDrawView() )
                     MakeDrawView();
 
-                std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pClpDoc);
                 for ( auto pCpyFormat : *pClpDoc->GetSpzFrameFormats() )
                 {
                     bool bInsWithFormat = true;
@@ -972,7 +971,7 @@ bool SwFEShell::Paste( SwDoc* pClpDoc )
                             }
 
                             // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
-                            if (aTextBoxes.find(pCpyFormat) != aTextBoxes.end())
+                            if (SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT))
                                 continue;
 
                             aAnchor.SetAnchor( pPos );
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
index d369ac46132a..2f387808b11e 100644
--- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -505,7 +505,7 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( const SwTwips nTopOfAnch
                     pFrameFormat->SetFormatAttr(aSize);
                 }
                 nAdjustedRelPosY = nProposedRelPosY;
-            } else if ( SwTextBoxHelper::findTextBox(pFormat) )
+            } else if ( SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT) )
                 // when the shape has a textbox, use only the proposed vertical position
                 nAdjustedRelPosY = nProposedRelPosY;
         }
diff --git a/sw/source/core/unocore/unocoll.cxx b/sw/source/core/unocore/unocoll.cxx
index 09ee314ace34..c37608ddb3ab 100644
--- a/sw/source/core/unocore/unocoll.cxx
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -1080,13 +1080,11 @@ SwXFrameEnumeration<T>::SwXFrameEnumeration(const SwDoc* const pDoc)
     // #i104937#
     SwFrameFormat* pFormat( nullptr );
 
-    std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
-
     for( size_t i = 0; i < nSize; ++i )
     {
         // #i104937#
         pFormat = (*pFormats)[i];
-        if(pFormat->Which() != RES_FLYFRMFMT || aTextBoxes.find(pFormat) != aTextBoxes.end())
+        if(pFormat->Which() != RES_FLYFRMFMT || SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT))
             continue;
         const SwNodeIndex* pIdx =  pFormat->GetContent().GetContentIdx();
         if(!pIdx || !pIdx->GetNodes().IsDocNodes())
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
index 47ebb0b719e5..8ecd6d4ba2a0 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -400,10 +400,9 @@ SwXShapesEnumeration::SwXShapesEnumeration(SwXDrawPage* const pDrawPage)
     SolarMutexGuard aGuard;
     ::std::insert_iterator<shapescontainer_t> pInserter = ::std::insert_iterator<shapescontainer_t>(m_aShapes, m_aShapes.begin());
     sal_Int32 nCount = pDrawPage->getCount();
-    std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDrawPage->GetDoc());
     for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
     {
-        uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx, &aTextBoxes), uno::UNO_QUERY);
+        uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
         *pInserter++ = uno::makeAny(xShape);
     }
 }
@@ -526,13 +525,7 @@ sal_Int32 SwXDrawPage::getCount() throw( uno::RuntimeException, std::exception )
     else
     {
         static_cast<SwXDrawPage*>(this)->GetSvxPage();
-
-        std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
-
-        if (aTextBoxes.empty())
-            return pDrawPage->getCount();
-        else
-            return SwTextBoxHelper::getCount(pDrawPage->GetSdrPage(), aTextBoxes);
+        return SwTextBoxHelper::getCount(pDrawPage->GetSdrPage());
     }
 }
 
@@ -540,12 +533,6 @@ uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex)
         throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
                uno::RuntimeException, std::exception )
 {
-    return getByIndex(nIndex, nullptr);
-}
-
-uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex, std::set<const SwFrameFormat*>* pTextBoxes)
-    throw(lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
-{
     SolarMutexGuard aGuard;
     if(!pDoc)
         throw uno::RuntimeException();
@@ -553,17 +540,7 @@ uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex, std::set<const SwFrameFormat*
         throw lang::IndexOutOfBoundsException();
 
     static_cast<SwXDrawPage*>(this)->GetSvxPage();
-    std::set<const SwFrameFormat*> aTextBoxes;
-    if (!pTextBoxes)
-    {
-        // We got no set, so let's generate one.
-        aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
-        pTextBoxes = &aTextBoxes;
-    }
-    if (pTextBoxes->empty())
-        return pDrawPage->getByIndex( nIndex );
-    else
-        return SwTextBoxHelper::getByIndex(pDrawPage->GetSdrPage(), nIndex, *pTextBoxes);
+    return SwTextBoxHelper::getByIndex(pDrawPage->GetSdrPage(), nIndex);
 }
 
 uno::Type  SwXDrawPage::getElementType() throw( uno::RuntimeException, std::exception )
@@ -1564,7 +1541,7 @@ uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
                 }
                 else if (pEntry->nWID == FN_TEXT_BOX)
                 {
-                    bool bValue = SwTextBoxHelper::findTextBox(pFormat);
+                    bool bValue = SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT);
                     aRet <<= bValue;
                 }
                 else if (pEntry->nWID == RES_CHAIN)
@@ -1770,8 +1747,7 @@ uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
                                 bConvert = false;
                         if (bConvert)
                         {
-                            std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pFormat->GetDoc());
-                            aRet <<= SwTextBoxHelper::getOrdNum(pObj, aTextBoxes);
+                            aRet <<= SwTextBoxHelper::getOrdNum(pObj);
                         }
                     }
                 }
@@ -1852,7 +1828,7 @@ uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
                 else if (pEntry->nWID == FN_TEXT_BOX)
                 {
                     // The TextBox property is set, if we can find a textbox for this shape.
-                    if (pFormat && SwTextBoxHelper::findTextBox(pFormat))
+                    if (pFormat && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT))
                         pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                     else
                         pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 2bb4a87ce860..15abdb2193bf 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1750,8 +1750,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any&
             aValue >>= nZOrder;
 
             // Don't set an explicit ZOrder on TextBoxes.
-            std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
-            if( nZOrder >= 0 && aTextBoxes.find(pFormat) == aTextBoxes.end())
+            if( nZOrder >= 0 && !SwTextBoxHelper::isTextBox(pFormat, RES_FLYFRMFMT) )
             {
                 SdrObject* pObject =
                     GetOrCreateSdrObject( static_cast<SwFlyFrameFormat&>(*pFormat) );
diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx
index 71619b352d6b..9ae7b3cca044 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -165,19 +165,18 @@ struct FrameClientSortListLess
 
 namespace
 {
-    void lcl_CollectFrameAtNodeWithLayout(SwDoc* pDoc, const SwContentFrame* pCFrame,
+    void lcl_CollectFrameAtNodeWithLayout(const SwContentFrame* pCFrame,
             FrameClientSortList_t& rFrames,
             const sal_uInt16 nAnchorType)
     {
         auto pObjs = pCFrame->GetDrawObjs();
         if(!pObjs)
             return;
-        const auto aTextBoxes = SwTextBoxHelper::findTextBoxes(pDoc);
         for(const auto pAnchoredObj : *pObjs)
         {
             SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
             // Filter out textboxes, which are not interesting at an UNO level.
-            if(aTextBoxes.find(&rFormat) != aTextBoxes.end())
+            if(SwTextBoxHelper::isTextBox(&rFormat, RES_FLYFRMFMT))
                 continue;
             if(rFormat.GetAnchor().GetAnchorId() == nAnchorType)
             {
@@ -211,7 +210,7 @@ void CollectFrameAtNode( const SwNodeIndex& rIdx,
         nullptr != (pCNd = rIdx.GetNode().GetContentNode()) &&
         nullptr != (pCFrame = pCNd->getLayoutFrame( pDoc->getIDocumentLayoutAccess().GetCurrentLayout())) )
     {
-        lcl_CollectFrameAtNodeWithLayout(pDoc, pCFrame, rFrames, nChkType);
+        lcl_CollectFrameAtNodeWithLayout(pCFrame, rFrames, nChkType);
     }
     else
     {
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 920f3b70b8f6..c45d88a6908c 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -716,8 +716,7 @@ lcl_ExportHints(
     const sal_Int32 nCurrentIndex,
     const bool bRightMoveForbidden,
     bool & o_rbCursorMoved,
-    sal_Int32 & o_rNextAttrPosition,
-    std::set<const SwFrameFormat*>& rTextBoxes)
+    sal_Int32 & o_rNextAttrPosition)
 {
     // if the attribute has a dummy character, then xRef is set (except META)
     // otherwise, the portion for the attribute is inserted into rPortions!
@@ -887,7 +886,7 @@ lcl_ExportHints(
                             break; // Robust #i81708 content in covered cells
 
                         // Do not expose inline anchored textboxes.
-                        if (rTextBoxes.find(pAttr->GetFlyCnt().GetFrameFormat()) != rTextBoxes.end())
+                        if (SwTextBoxHelper::isTextBox(pAttr->GetFlyCnt().GetFrameFormat(), RES_FLYFRMFMT))
                             break;
 
                         pUnoCursor->Exchange();
@@ -1272,8 +1271,6 @@ static void lcl_CreatePortions(
     PortionStack_t PortionStack;
     PortionStack.push( PortionList_t(&i_rPortions, nullptr) );
 
-    std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(pUnoCursor->GetNode());
-
     bool bAtEnd( false );
     while (!bAtEnd) // every iteration consumes at least current character!
     {
@@ -1324,7 +1321,7 @@ static void lcl_CreatePortions(
             // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
             xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCursor,
                         pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
-                        bCursorMoved, nNextAttrIndex, aTextBoxes);
+                        bCursorMoved, nNextAttrIndex);
             if (PortionStack.empty())
             {
                 OSL_FAIL("CreatePortions: stack underflow");
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index a5b2c38b72a6..01a546650e1d 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -145,7 +145,6 @@ struct DocxSdrExport::Impl
     css::uno::Reference<sax_fastparser::FastAttributeList> m_pDashLineStyleAttr;
     bool m_bDMLAndVMLDrawingOpen;
     /// List of TextBoxes in this document: they are exported as part of their shape, never alone.
-    std::set<const SwFrameFormat*> m_aTextBoxes;
     /// Preserved rotation for TextFrames.
     sal_Int32 m_nDMLandVMLTextFrameRotation;
 
@@ -165,7 +164,6 @@ struct DocxSdrExport::Impl
           m_pFlyWrapAttrList(nullptr),
           m_pBodyPrAttrList(nullptr),
           m_bDMLAndVMLDrawingOpen(false),
-          m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.m_pDoc)),
           m_nDMLandVMLTextFrameRotation(0)
     {
     }
@@ -1798,7 +1796,7 @@ bool DocxSdrExport::Impl::checkFrameBtlr(SwNode* pStartNode, bool bDML)
 
 bool DocxSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
 {
-    return m_pImpl->m_aTextBoxes.find(&rFrameFormat) != m_pImpl->m_aTextBoxes.end();
+    return SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx
index 77d4645db57e..f303e8a379a6 100644
--- a/sw/source/filter/ww8/rtfsdrexport.cxx
+++ b/sw/source/filter/ww8/rtfsdrexport.cxx
@@ -640,7 +640,7 @@ void RtfSdrExport::AddSdrObject(const SdrObject& rObj)
 
 bool RtfSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
 {
-    return m_aTextBoxes.find(&rFrameFormat) != m_aTextBoxes.end();
+    return SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/xml/xmltble.cxx b/sw/source/filter/xml/xmltble.cxx
index d1bb91069812..172c4e588c02 100644
--- a/sw/source/filter/xml/xmltble.cxx
+++ b/sw/source/filter/xml/xmltble.cxx
@@ -1097,8 +1097,7 @@ void SwXMLExport::ExportTable( const SwTableNode& rTableNd )
     sal_uInt16 nPrefix = XML_NAMESPACE_TABLE;
     if (const SwFrameFormat* pFlyFormat = rTableNd.GetFlyFormat())
     {
-        std::set<const SwFrameFormat*> aTextBoxes = SwTextBoxHelper::findTextBoxes(rTableNd.GetDoc());
-        if (aTextBoxes.find(pFlyFormat) != aTextBoxes.end())
+        if (SwTextBoxHelper::isTextBox(pFlyFormat, RES_FLYFRMFMT))
             nPrefix = XML_NAMESPACE_LO_EXT;
     }
 
diff --git a/sw/source/uibase/shells/drawsh.cxx b/sw/source/uibase/shells/drawsh.cxx
index 6c1fc4360ab9..332497da5c35 100644
--- a/sw/source/uibase/shells/drawsh.cxx
+++ b/sw/source/uibase/shells/drawsh.cxx
@@ -494,7 +494,7 @@ void SwDrawShell::GetState(SfxItemSet& rSet)
                 {
                     SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
                     // Allow creating a TextBox only in case this is a draw format without a TextBox so far.
-                    if (pFrameFormat && pFrameFormat->Which() == RES_DRAWFRMFMT && !SwTextBoxHelper::findTextBox(pFrameFormat))
+                    if (pFrameFormat && pFrameFormat->Which() == RES_DRAWFRMFMT && !SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT))
                     {
                         if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pObj) )
                         {
@@ -517,7 +517,7 @@ void SwDrawShell::GetState(SfxItemSet& rSet)
                 {
                     SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
                     // Allow removing a TextBox only in case it has one.
-                    if (pFrameFormat && SwTextBoxHelper::findTextBox(pFrameFormat))
+                    if (pFrameFormat && SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT))
                         bDisable = false;
                 }
 
diff --git a/sw/source/uibase/uiview/viewdraw.cxx b/sw/source/uibase/uiview/viewdraw.cxx
index 2ab98fea04b9..fda4a3b2d244 100644
--- a/sw/source/uibase/uiview/viewdraw.cxx
+++ b/sw/source/uibase/uiview/viewdraw.cxx
@@ -438,7 +438,7 @@ static bool lcl_isTextBox(SdrObject* pObject)
     if (SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pObject->GetUserCall()))
     {
         if (SwFrameFormat* pFormat = pDrawContact->GetFormat())
-            return SwTextBoxHelper::findTextBox(pFormat);
+            return SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT);
     }
     return false;
 }
commit 2dafbb537b6347a9b2f16d21a48d79a8caceddce
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jul 22 17:23:40 2016 +0200

    Link DRAW and FLY format for faster textbox lookup
    
    Currently we have to rebuild the list of text boxes for every
    lookup. Instead of a managed set, or a per-document list etc.,
    this introduces direct pointers between the corresponding
    SwDrawFramFormat and SwFlyFrameFormat of a text box.
    
    (Manually cherry picked from commit 5bed080c77f99f22fd52ad6cf2d6274e7c1e12a8)
    
    Change-Id: Iefba2d153d9d8b3f1185aa305e9f463a50e78f89
    Reviewed-on: https://gerrit.libreoffice.org/46305
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx
index 4291ced05f6e..c2a19706160c 100644
--- a/sw/inc/frmfmt.hxx
+++ b/sw/inc/frmfmt.hxx
@@ -41,12 +41,15 @@ class SW_DLLPUBLIC SwFrameFormat: public SwFormat
     friend class SwDoc;
     friend class SwPageDesc;    ///< Is allowed to call protected CTor.
     friend class ::sw::DocumentLayoutManager; ///< Is allowed to call protected CTor.
+    friend class SwTextBoxHelper;
 
     css::uno::WeakReference<css::uno::XInterface> m_wXObject;
 
     //UUUU DrawingLayer FillAttributes in a preprocessed form for primitive usage
     drawinglayer::attribute::SdrAllFillAttributesHelperPtr  maFillAttributes;
 
+    SwFrameFormat *m_pOtherTextBoxFormat;
+
 protected:
     SwFrameFormat(
         SwAttrPool& rPool,
@@ -64,6 +67,9 @@ protected:
 
     virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNewValue ) override;
 
+    SwFrameFormat* GetOtherTextBoxFormat() const { return m_pOtherTextBoxFormat; }
+    void SetOtherTextBoxFormat( SwFrameFormat *pFormat );
+
 public:
     virtual ~SwFrameFormat();
 
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx
index c5380df0b3de..5fc0d4cc7483 100644
--- a/sw/source/core/doc/DocumentLayoutManager.cxx
+++ b/sw/source/core/doc/DocumentLayoutManager.cxx
@@ -510,6 +510,10 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
         SwFormatContent aContent(pDestTextBox->GetContent().GetContentIdx()->GetNode().GetStartNode());
         aSet.Put(aContent);
         pDest->SetFormatAttr(aSet);
+
+        // Link FLY and DRAW formats, so it becomes a text box
+        pDest->SetOtherTextBoxFormat(pDestTextBox);
+        pDestTextBox->SetOtherTextBoxFormat(pDest);
     }
 
     return pDest;
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 61402fe02c94..c75908384ebf 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -28,6 +28,7 @@
 #include <sortedobjs.hxx>
 #include <cntfrm.hxx>
 #include <fmtsrnd.hxx>
+#include <frmfmt.hxx>
 
 #include <editeng/unoprnms.hxx>
 #include <editeng/charrotateitem.hxx>
@@ -55,6 +56,18 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape)
         uno::Reference<text::XTextContentAppend> xTextContentAppend(xTextDocument->getText(), uno::UNO_QUERY);
         xTextContentAppend->appendTextContent(xTextFrame, uno::Sequence<beans::PropertyValue>());
 
+        // Link FLY and DRAW formats, so it becomes a text box (needed for syncProperty calls).
+        uno::Reference<text::XTextFrame> xRealTextFrame(xTextFrame, uno::UNO_QUERY);
+        SwXTextFrame* pTextFrame = dynamic_cast<SwXTextFrame *>(xRealTextFrame.get());
+        assert(nullptr != pTextFrame);
+        SwFrameFormat* pFormat = pTextFrame->GetFrameFormat();
+
+        assert(nullptr != dynamic_cast<SwDrawFrameFormat*>(pShape));
+        assert(nullptr != dynamic_cast<SwFlyFrameFormat*>(pFormat));
+
+        pShape->SetOtherTextBoxFormat(pFormat);
+        pFormat->SetOtherTextBoxFormat(pShape);
+
         // Initialize properties.
         uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, uno::UNO_QUERY);
         uno::Any aEmptyBorder = uno::makeAny(table::BorderLine2());
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 849af3b88ed0..4a67225681e4 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -2502,7 +2502,8 @@ SwFrameFormat::SwFrameFormat(
     const sal_uInt16* pWhichRange)
 :   SwFormat(rPool, pFormatNm, (pWhichRange ? pWhichRange : aFrameFormatSetRange), pDrvdFrame, nFormatWhich),
     m_wXObject(),
-    maFillAttributes()
+    maFillAttributes(),
+    m_pOtherTextBoxFormat(nullptr)
 {
 }
 
@@ -2514,7 +2515,8 @@ SwFrameFormat::SwFrameFormat(
     const sal_uInt16* pWhichRange)
 :   SwFormat(rPool, rFormatNm, (pWhichRange ? pWhichRange : aFrameFormatSetRange), pDrvdFrame, nFormatWhich),
     m_wXObject(),
-    maFillAttributes()
+    maFillAttributes(),
+    m_pOtherTextBoxFormat(nullptr)
 {
 }
 
@@ -2528,6 +2530,27 @@ SwFrameFormat::~SwFrameFormat()
             rAnchor.GetContentAnchor()->nNode.GetNode().RemoveAnchoredFly(this);
         }
     }
+
+    if( nullptr != m_pOtherTextBoxFormat )
+    {
+        m_pOtherTextBoxFormat->SetOtherTextBoxFormat( nullptr );
+        m_pOtherTextBoxFormat = nullptr;
+    }
+}
+
+void SwFrameFormat::SetOtherTextBoxFormat( SwFrameFormat *pFormat )
+{
+    if( nullptr != pFormat )
+    {
+        assert( (Which() == RES_DRAWFRMFMT && pFormat->Which() == RES_FLYFRMFMT)
+             || (Which() == RES_FLYFRMFMT && pFormat->Which() == RES_DRAWFRMFMT) );
+        assert( nullptr == m_pOtherTextBoxFormat );
+    }
+    else
+    {
+        assert( nullptr != m_pOtherTextBoxFormat );
+    }
+    m_pOtherTextBoxFormat = pFormat;
 }
 
 bool SwFrameFormat::supportsFullDrawingLayerFillAttributeSet() const
commit bc20bd3296efffe024235f82e40bca1ef116bce5
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Dec 5 19:35:20 2017 +0100

    SwFrameBorder: Converted BorderRectangle functionality
    
    to primitive usage, added a SwBorderRectanglePrimitive2D
    which now encapsulates the four Styles and the transformation
    of a single BorderLineRectangle. This is a preparation for
    later buffered primitive usage at SwFrame level
    
    Change-Id: I6689b94fe996ead8142553e8442e151e53d10e8a

diff --git a/sw/inc/sw_primitivetypes2d.hxx b/sw/inc/sw_primitivetypes2d.hxx
index 4ded8572088b..44509820f72c 100644
--- a/sw/inc/sw_primitivetypes2d.hxx
+++ b/sw/inc/sw_primitivetypes2d.hxx
@@ -25,6 +25,7 @@
 #define PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D  (PRIMITIVE2D_ID_RANGE_SW| 0)
 #define PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE     (PRIMITIVE2D_ID_RANGE_SW| 1)
 #define PRIMITIVE2D_ID_SWSIDEBARSHADOWPRIMITIVE     (PRIMITIVE2D_ID_RANGE_SW| 2)
+#define PRIMITIVE2D_ID_SWBORDERRECTANGLERIMITIVE    (PRIMITIVE2D_ID_RANGE_SW| 3)
 
 #endif // INCLUDED_SW_INC_SW_PRIMITIVETYPES2D_HXX
 
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index b2e16581b253..207afbede1fa 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -62,6 +62,8 @@
 #include <bodyfrm.hxx>
 #include <hffrm.hxx>
 #include <colfrm.hxx>
+#include <sw_primitivetypes2d.hxx>
+
 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
 #include <svx/sdr/contact/viewobjectcontact.hxx>
 #include <svx/sdr/contact/viewcontact.hxx>
@@ -224,7 +226,6 @@ public:
 };
 
 // Default zoom factor
-const static double aMinDistScale = 0.73;
 const static double aEdgeScale = 0.5;
 
 //To optimize the expensive RetouchColor determination
@@ -1183,42 +1184,6 @@ void SwAlignRect( SwRect &rRect, const SwViewShell *pSh, const vcl::RenderContex
 }
 
 /**
- * Helper for twip adjustments on pixel base
- *
- * This method compares the x- or y-pixel position of two twip-points.
- * If the x-/y-pixel positions are the same, the x-/y-pixel position of
- * the second twip point is adjusted by a given amount of pixels
-*/
-static void lcl_CompPxPosAndAdjustPos( const vcl::RenderContext&  _rOut,
-                                const Point&         _rRefPt,
-                                Point&               _rCompPt,
-                                const bool          _bChkXPos,
-                                const sal_Int8       _nPxAdjustment )
-{
-    const Point aRefPxPt = _rOut.LogicToPixel( _rRefPt );
-    Point aCompPxPt = _rOut.LogicToPixel( _rCompPt );
-
-    if ( _bChkXPos )
-    {
-        if ( aCompPxPt.X() == aRefPxPt.X() )
-        {
-            aCompPxPt.X() += _nPxAdjustment ;
-            const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
-            _rCompPt.X() = aAdjustedCompPt.X();
-        }
-    }
-    else
-    {
-        if ( aCompPxPt.Y() == aRefPxPt.Y() )
-        {
-            aCompPxPt.Y() += _nPxAdjustment ;
-            const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
-            _rCompPt.Y() = aAdjustedCompPt.Y();
-        }
-    }
-}
-
-/**
  * Method to pixel-align rectangle for drawing graphic object
  *
  * Because we are drawing graphics from the left-top-corner in conjunction
@@ -1264,13 +1229,6 @@ static long lcl_AlignHeight( const long nHeight, SwPaintProperties& properties )
     return nHeight;
 }
 
-static long lcl_MinHeightDist( const long nDist, SwPaintProperties& properties )
-{
-    if ( properties.aSScaleX < aMinDistScale || properties.aSScaleY < aMinDistScale )
-        return nDist;
-    return ::lcl_AlignHeight( std::max( nDist, properties.nSMinDistPixelH ), properties);
-}
-
 /**
  * Calculate PrtArea plus surrounding plus shadow
  */
@@ -4473,298 +4431,254 @@ void SwFrame::PaintBorderLine( const SwRect& rRect,
         gProp.pSLines->AddLineRect( aOut, pColor, nStyle, pTab, nSubCol, gProp );
 }
 
-/**
- * @note Only all lines once or all lines twice!
- *
- * OD 29.04.2003 #107169# - method called for left and right border rectangles.
- * For a printer output device perform adjustment for non-overlapping top and
- * bottom border rectangles. Thus, add parameter <_bPrtOutputDev> to indicate
- * printer output device.
- * NOTE: For printer output device left/right border rectangle <_iorRect>
- *        has to be already non-overlapping the outer top/bottom border rectangle.
- */
-static void lcl_SubTopBottom( SwRect&              _iorRect,
-                                   const SvxBoxItem&    _rBox,
-                                   const SwBorderAttrs& _rAttrs,
-                                   const SwFrame&         _rFrame,
-                                   const SwRectFn&      _rRectFn,
-                                   const bool       _bPrtOutputDev,
-                                   SwPaintProperties& properties )
+namespace drawinglayer
 {
-    const bool bCnt = _rFrame.IsContentFrame();
-    if ( _rBox.GetTop() && _rBox.GetTop()->GetInWidth() &&
-         ( !bCnt || _rAttrs.GetTopLine( _rFrame ) )
-       )
+    namespace primitive2d
     {
-        // subtract distance between outer and inner line.
-        SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetTop()->GetDistance(), properties );
-        // OD 19.05.2003 #109667# - non-overlapping border rectangles:
-        // adjust x-/y-position, if inner top line is a hair line (width = 1)
-        bool bIsInnerTopLineHairline = false;
-        if ( !_bPrtOutputDev )
-        {
-            // additionally subtract width of top outer line
-            // --> left/right inner/outer line doesn't overlap top outer line.
-            nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetOutWidth(), properties );
-        }
-        else
+        class SW_DLLPUBLIC SwBorderRectanglePrimitive2D : public BufferedDecompositionPrimitive2D
         {
-            // OD 29.04.2003 #107169# - additionally subtract width of top inner line
-            // --> left/right inner/outer line doesn't overlap top inner line.
-            nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetInWidth(), properties );
-            bIsInnerTopLineHairline = _rBox.GetTop()->GetInWidth() == 1;
-        }
-        (_iorRect.*_rRectFn->fnSubTop)( -nDist );
-        // OD 19.05.2003 #109667# - adjust calculated border top, if inner top line
-        // is a hair line
-        if ( bIsInnerTopLineHairline )
-        {
-            if ( _rFrame.IsVertical() )
+        private:
+            /// the transformation defining the geometry of this BorderRectangle
+            basegfx::B2DHomMatrix       maB2DHomMatrix;
+
+            /// the four styles to be used
+            svx::frame::Style           maStyleTop;
+            svx::frame::Style           maStyleRight;
+            svx::frame::Style           maStyleBottom;
+            svx::frame::Style           maStyleLeft;
+
+        protected:
+            /// local decomposition.
+            virtual Primitive2DContainer create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+
+        public:
+            /// constructor
+            SwBorderRectanglePrimitive2D(
+                const basegfx::B2DHomMatrix& rB2DHomMatrix,
+                const svx::frame::Style& rStyleTop,
+                const svx::frame::Style& rStyleRight,
+                const svx::frame::Style& rStyleBottom,
+                const svx::frame::Style& rStyleLeft);
+
+            /// data read access
+            const basegfx::B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; }
+            const svx::frame::Style& getStyleTop() const { return maStyleTop; }
+            const svx::frame::Style& getStyleRight() const { return maStyleRight; }
+            const svx::frame::Style& getStyleBottom() const { return maStyleBottom; }
+            const svx::frame::Style& getStyleLeft() const { return maStyleLeft; }
+
+            /// compare operator
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+
+            /// get range
+            virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
+
+            /// provide unique ID
+            DeclPrimitive2DIDBlock()
+        };
+
+        Primitive2DContainer SwBorderRectanglePrimitive2D::create2DDecomposition(
+            const geometry::ViewInformation2D& /*rViewInformation*/) const
+        {
+            Primitive2DContainer aRetval;
+            basegfx::B2DPoint aTopLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 0.0));
+            basegfx::B2DPoint aTopRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 0.0));
+            basegfx::B2DPoint aBottomLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 1.0));
+            basegfx::B2DPoint aBottomRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 1.0));
+
+            if(getStyleTop().IsUsed())
             {
-                // right of border rectangle has to be checked and adjusted
-                Point aCompPt( _iorRect.Right(), 0 );
-                Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
-                lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
-                                          aRefPt, aCompPt,
-                                          true, -1 );
-                _iorRect.Right( aCompPt.X() );
+                // move top left/right inwards half border width
+                basegfx::B2DVector aDown(getB2DHomMatrix() * basegfx::B2DVector(0.0, 1.0));
+                aDown.setLength(getStyleTop().GetWidth() * 0.5);
+                aTopLeft += aDown;
+                aTopRight += aDown;
             }
-            else
+
+            if(getStyleBottom().IsUsed())
             {
-                // top of border rectangle has to be checked and adjusted
-                Point aCompPt( 0, _iorRect.Top() );
-                Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
-                lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
-                                          aRefPt, aCompPt,
-                                          false, +1 );
-                _iorRect.Top( aCompPt.Y() );
+                // move bottom left/right inwards half border width
+                basegfx::B2DVector aUp(getB2DHomMatrix() * basegfx::B2DVector(0.0, -1.0));
+                aUp.setLength(getStyleBottom().GetWidth() * 0.5);
+                aBottomLeft += aUp;
+                aBottomRight += aUp;
             }
-        }
-    }
 
-    if ( _rBox.GetBottom() && _rBox.GetBottom()->GetInWidth() &&
-         ( !bCnt || _rAttrs.GetBottomLine( _rFrame ) )
-       )
-    {
-        // subtract distance between outer and inner line.
-        SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetBottom()->GetDistance(), properties );
-        // OD 19.05.2003 #109667# - non-overlapping border rectangles:
-        // adjust x-/y-position, if inner bottom line is a hair line (width = 1)
-        bool bIsInnerBottomLineHairline = false;
-        if ( !_bPrtOutputDev )
-        {
-            // additionally subtract width of bottom outer line
-            // --> left/right inner/outer line doesn't overlap bottom outer line.
-            nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetOutWidth(), properties );
-        }
-        else
-        {
-            // OD 29.04.2003 #107169# - additionally subtract width of bottom inner line
-            // --> left/right inner/outer line doesn't overlap bottom inner line.
-            nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetInWidth(), properties );
-            bIsInnerBottomLineHairline = _rBox.GetBottom()->GetInWidth() == 1;
-        }
-        (_iorRect.*_rRectFn->fnAddBottom)( -nDist );
-        // OD 19.05.2003 #109667# - adjust calculated border bottom, if inner
-        // bottom line is a hair line.
-        if ( bIsInnerBottomLineHairline )
-        {
-            if ( _rFrame.IsVertical() )
+            if(getStyleLeft().IsUsed())
             {
-                // left of border rectangle has to be checked and adjusted
-                Point aCompPt( _iorRect.Left(), 0 );
-                Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
-                lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
-                                          aRefPt, aCompPt,
-                                          true, +1 );
-                _iorRect.Left( aCompPt.X() );
+                // move left top/bottom inwards half border width
+                basegfx::B2DVector aRight(getB2DHomMatrix() * basegfx::B2DVector(1.0, 0.0));
+                aRight.setLength(getStyleLeft().GetWidth() * 0.5);
+                aTopLeft += aRight;
+                aBottomLeft += aRight;
             }
-            else
+
+            if(getStyleRight().IsUsed())
             {
-                // bottom of border rectangle has to be checked and adjusted
-                Point aCompPt( 0, _iorRect.Bottom() );
-                Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
-                lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
-                                          aRefPt, aCompPt,
-                                          false, -1 );
-                _iorRect.Bottom( aCompPt.Y() );
+                // move right top/bottom inwards half border width
+                basegfx::B2DVector aLeft(getB2DHomMatrix() * basegfx::B2DVector(-1.0, 0.0));
+                aLeft.setLength(getStyleRight().GetWidth() * 0.5);
+                aTopRight += aLeft;
+                aBottomRight += aLeft;
             }
-        }
-    }
-}
-
-static sal_uInt16 lcl_GetLineWidth( const SvxBorderLine* pLine )
-{
-    if ( pLine != nullptr )
-        return pLine->GetScaledWidth();
 
-    return 0;
-}
-
-static double lcl_GetExtent( const SvxBorderLine* pSideLine, const SvxBorderLine* pOppositeLine )
-{
-    double nExtent = 0.0;
-
-    if ( pSideLine && !pSideLine->isEmpty() )
-        nExtent = -lcl_GetLineWidth( pSideLine ) / 2.0;
-    else if ( pOppositeLine )
-        nExtent = lcl_GetLineWidth( pOppositeLine ) / 2.0;
+            // go round-robin, from TopLeft to TopRight, down, left and back up. That
+            // way, the borders will not need to be mirrored in any way
+            if(getStyleTop().IsUsed())
+            {
+                // create BorderPrimitive(s) for top border
+                const basegfx::B2DVector aVector(aTopRight - aTopLeft);
+                svx::frame::StyleVectorTable aStartStyleVectorTable;
+                svx::frame::StyleVectorTable aEndStyleVectorTable;
 
-    return nExtent;
-}
+                if(getStyleLeft().IsUsed())
+                {
+                    aStartStyleVectorTable.add(getStyleLeft(), aVector, basegfx::B2DVector(aBottomLeft - aTopLeft), false);
+                }
 
-namespace
-{
-    void CreateBorderLinePrimitivesForRectangle(
-        drawinglayer::primitive2d::Primitive2DContainer& rBorderLineTarget,
-        const svx::frame::Style& rStyleTop,
-        const svx::frame::Style& rStyleRight,
-        const svx::frame::Style& rStyleBottom,
-        const svx::frame::Style& rStyleLeft,
-        basegfx::B2DPoint aTopLeft,
-        basegfx::B2DPoint aTopRight,
-        basegfx::B2DPoint aBottomLeft,
-        basegfx::B2DPoint aBottomRight)
-    {
-        if(rStyleTop.IsUsed())
-        {
-            // move top left/right inwards half border width
-            aTopLeft.setY(aTopLeft.getY() + (rStyleTop.GetWidth() * 0.5));
-            aTopRight.setY(aTopRight.getY() + (rStyleTop.GetWidth() * 0.5));
-        }
+                if(getStyleRight().IsUsed())
+                {
+                    aEndStyleVectorTable.add(getStyleRight(), -aVector, basegfx::B2DVector(aBottomRight - aTopRight), false);
+                }
 
-        if(rStyleBottom.IsUsed())
-        {
-            // move bottom left/right inwards half border width
-            aBottomLeft.setY(aBottomLeft.getY() - (rStyleBottom.GetWidth() * 0.5));
-            aBottomRight.setY(aBottomRight.getY() - (rStyleBottom.GetWidth() * 0.5));
-        }
+                CreateBorderPrimitives(
+                    aRetval,
+                    aTopLeft,
+                    aVector,
+                    getStyleTop(),
+                    aStartStyleVectorTable,
+                    aEndStyleVectorTable,
+                    nullptr);
+            }
 
-        if(rStyleLeft.IsUsed())
-        {
-            // move left top/bottom inwards half border width
-            aTopLeft.setX(aTopLeft.getX() + (rStyleLeft.GetWidth() * 0.5));
-            aBottomLeft.setX(aBottomLeft.getX() + (rStyleLeft.GetWidth() * 0.5));
-        }
+            if(getStyleRight().IsUsed())
+            {
+                // create BorderPrimitive(s) for right border
+                const basegfx::B2DVector aVector(aBottomRight - aTopRight);
+                svx::frame::StyleVectorTable aStartStyleVectorTable;
+                svx::frame::StyleVectorTable aEndStyleVectorTable;
 
-        if(rStyleRight.IsUsed())
-        {
-            // move right top/bottom inwards half border width
-            aTopRight.setX(aTopRight.getX() - (rStyleRight.GetWidth() * 0.5));
-            aBottomRight.setX(aBottomRight.getX() - (rStyleRight.GetWidth() * 0.5));
-        }
+                if(getStyleTop().IsUsed())
+                {
+                    aStartStyleVectorTable.add(getStyleTop(), aVector, basegfx::B2DVector(aTopLeft - aTopRight), false);
+                }
 
-        // go round-robin, from TopLeft to TopRight, down, left and back up. That
-        // way, the borders will not need to be mirrored in any way
-        if(rStyleTop.IsUsed())
-        {
-            // create BorderPrimitive(s) for top border
-            const basegfx::B2DVector aVector(aTopRight - aTopLeft);
-            svx::frame::StyleVectorTable aStartStyleVectorTable;
-            svx::frame::StyleVectorTable aEndStyleVectorTable;
+                if(getStyleBottom().IsUsed())
+                {
+                    aEndStyleVectorTable.add(getStyleBottom(), -aVector, basegfx::B2DVector(aBottomLeft - aBottomRight), false);
+                }
 
-            if(rStyleLeft.IsUsed())
-            {
-                aStartStyleVectorTable.add(rStyleLeft, aVector, basegfx::B2DVector(aBottomLeft - aTopLeft), false);
+                CreateBorderPrimitives(
+                    aRetval,
+                    aTopRight,
+                    aVector,
+                    getStyleRight(),
+                    aStartStyleVectorTable,
+                    aEndStyleVectorTable,
+                    nullptr);
             }
 
-            if(rStyleRight.IsUsed())
+            if(getStyleBottom().IsUsed())
             {
-                aEndStyleVectorTable.add(rStyleRight, -aVector, basegfx::B2DVector(aBottomRight - aTopRight), false);
-            }
+                // create BorderPrimitive(s) for bottom border
+                const basegfx::B2DVector aVector(aBottomLeft - aBottomRight);
+                svx::frame::StyleVectorTable aStartStyleVectorTable;
+                svx::frame::StyleVectorTable aEndStyleVectorTable;
 
-            CreateBorderPrimitives(
-                rBorderLineTarget,
-                aTopLeft,
-                aVector,
-                rStyleTop,
-                aStartStyleVectorTable,
-                aEndStyleVectorTable,
-                nullptr);
-        }
+                if(getStyleRight().IsUsed())
+                {
+                    aStartStyleVectorTable.add(getStyleRight(), aVector, basegfx::B2DVector(aTopRight - aBottomRight), false);
+                }
 
-        if(rStyleRight.IsUsed())
-        {
-            // create BorderPrimitive(s) for right border
-            const basegfx::B2DVector aVector(aBottomRight - aTopRight);
-            svx::frame::StyleVectorTable aStartStyleVectorTable;
-            svx::frame::StyleVectorTable aEndStyleVectorTable;
+                if(getStyleLeft().IsUsed())
+                {
+                    aEndStyleVectorTable.add(getStyleLeft(), -aVector, basegfx::B2DVector(aTopLeft - aBottomLeft), false);
+                }
 
-            if(rStyleTop.IsUsed())
-            {
-                aStartStyleVectorTable.add(rStyleTop, aVector, basegfx::B2DVector(aTopLeft - aTopRight), false);
+                CreateBorderPrimitives(
+                    aRetval,
+                    aBottomRight,
+                    aVector,
+                    getStyleBottom(),
+                    aStartStyleVectorTable,
+                    aEndStyleVectorTable,
+                    nullptr);
             }
 
-            if(rStyleBottom.IsUsed())
+            if(getStyleLeft().IsUsed())
             {
-                aEndStyleVectorTable.add(rStyleBottom, -aVector, basegfx::B2DVector(aBottomLeft - aBottomRight), false);
+                // create BorderPrimitive(s) for left border
+                const basegfx::B2DVector aVector(aTopLeft - aBottomLeft);
+                svx::frame::StyleVectorTable aStartStyleVectorTable;
+                svx::frame::StyleVectorTable aEndStyleVectorTable;
+
+                if(getStyleBottom().IsUsed())
+                {
+                    aStartStyleVectorTable.add(getStyleBottom(), aVector, basegfx::B2DVector(aBottomRight - aBottomLeft), false);
+                }
+
+                if(getStyleTop().IsUsed())
+                {
+                    aEndStyleVectorTable.add(getStyleTop(), -aVector, basegfx::B2DVector(aTopRight - aTopLeft), false);
+                }
+
+                CreateBorderPrimitives(
+                    aRetval,
+                    aBottomLeft,
+                    aVector,
+                    getStyleLeft(),
+                    aStartStyleVectorTable,
+                    aEndStyleVectorTable,
+                    nullptr);
             }
 
-            CreateBorderPrimitives(
-                rBorderLineTarget,
-                aTopRight,
-                aVector,
-                rStyleRight,
-                aStartStyleVectorTable,
-                aEndStyleVectorTable,
-                nullptr);
+            return aRetval;
         }
 
-        if(rStyleBottom.IsUsed())
+        SwBorderRectanglePrimitive2D::SwBorderRectanglePrimitive2D(
+            const basegfx::B2DHomMatrix& rB2DHomMatrix,
+            const svx::frame::Style& rStyleTop,
+            const svx::frame::Style& rStyleRight,
+            const svx::frame::Style& rStyleBottom,
+            const svx::frame::Style& rStyleLeft)
+        :   BufferedDecompositionPrimitive2D(),
+            maB2DHomMatrix(rB2DHomMatrix),
+            maStyleTop(rStyleTop),
+            maStyleRight(rStyleRight),
+            maStyleBottom(rStyleBottom),
+            maStyleLeft(rStyleLeft)
         {
-            // create BorderPrimitive(s) for bottom border
-            const basegfx::B2DVector aVector(aBottomLeft - aBottomRight);
-            svx::frame::StyleVectorTable aStartStyleVectorTable;
-            svx::frame::StyleVectorTable aEndStyleVectorTable;
+        }
 
-            if(rStyleRight.IsUsed())
+        bool SwBorderRectanglePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+        {
+            if(BasePrimitive2D::operator==(rPrimitive))
             {
-                aStartStyleVectorTable.add(rStyleRight, aVector, basegfx::B2DVector(aTopRight - aBottomRight), false);
-            }
+                const SwBorderRectanglePrimitive2D& rCompare = static_cast<const SwBorderRectanglePrimitive2D&>(rPrimitive);
 
-            if(rStyleLeft.IsUsed())
-            {
-                aEndStyleVectorTable.add(rStyleLeft, -aVector, basegfx::B2DVector(aTopLeft - aBottomLeft), false);
+                return (getB2DHomMatrix() == rCompare.getB2DHomMatrix() &&
+                    getStyleTop() == rCompare.getStyleTop() &&
+                    getStyleRight() == rCompare.getStyleRight() &&
+                    getStyleBottom() == rCompare.getStyleBottom() &&
+                    getStyleLeft() == rCompare.getStyleLeft());
             }
 
-            CreateBorderPrimitives(
-                rBorderLineTarget,
-                aBottomRight,
-                aVector,
-                rStyleBottom,
-                aStartStyleVectorTable,
-                aEndStyleVectorTable,
-                nullptr);
+            return false;
         }
 
-        if(rStyleLeft.IsUsed())
+        basegfx::B2DRange SwBorderRectanglePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
         {
-            // create BorderPrimitive(s) for left border
-            const basegfx::B2DVector aVector(aTopLeft - aBottomLeft);
-            svx::frame::StyleVectorTable aStartStyleVectorTable;
-            svx::frame::StyleVectorTable aEndStyleVectorTable;
+            basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
 
-            if(rStyleBottom.IsUsed())
-            {
-                aStartStyleVectorTable.add(rStyleBottom, aVector, basegfx::B2DVector(aBottomRight - aBottomLeft), false);
-            }
+            aRetval.transform(getB2DHomMatrix());
+            return aRetval;
+        }
 
-            if(rStyleTop.IsUsed())
-            {
-                aEndStyleVectorTable.add(rStyleTop, -aVector, basegfx::B2DVector(aTopRight - aTopLeft), false);
-            }
+        // provide unique ID
+        ImplPrimitive2DIDBlock(SwBorderRectanglePrimitive2D, PRIMITIVE2D_ID_SWBORDERRECTANGLERIMITIVE)
 
-            CreateBorderPrimitives(
-                rBorderLineTarget,
-                aBottomLeft,
-                aVector,
-                rStyleLeft,
-                aStartStyleVectorTable,
-                aEndStyleVectorTable,
-                nullptr);
-        }
-    }
-} // end of anonymous namespace
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
 
 void PaintCharacterBorder(
     const SwFont& rFont,
@@ -4814,20 +4728,24 @@ void PaintCharacterBorder(
         }
     }
 
+    const basegfx::B2DHomMatrix aBorderTransform(
+        basegfx::tools::createScaleTranslateB2DHomMatrix(
+            aAlignedRect.Width(), aAlignedRect.Height(),
+            aAlignedRect.Left(), aAlignedRect.Top()));
+    const svx::frame::Style aStyleTop(bTop ? rFont.GetAbsTopBorder(bVerticalLayout).get_ptr() : nullptr, 1.0);
+    const svx::frame::Style aStyleRight(bRight ? rFont.GetAbsRightBorder(bVerticalLayout).get_ptr() : nullptr, 1.0);
+    const svx::frame::Style aStyleBottom(bBottom ? rFont.GetAbsBottomBorder(bVerticalLayout).get_ptr() : nullptr, 1.0);
+    const svx::frame::Style aStyleLeft(bLeft ? rFont.GetAbsLeftBorder(bVerticalLayout).get_ptr() : nullptr, 1.0);
     drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget;
-    CreateBorderLinePrimitivesForRectangle(
-        aBorderLineTarget,
-        svx::frame::Style(bTop ? rFont.GetAbsTopBorder(bVerticalLayout).get_ptr() : nullptr, 1.0),
-        svx::frame::Style(bRight ? rFont.GetAbsRightBorder(bVerticalLayout).get_ptr() : nullptr, 1.0),
-        svx::frame::Style(bBottom ? rFont.GetAbsBottomBorder(bVerticalLayout).get_ptr() : nullptr, 1.0),
-        svx::frame::Style(bLeft ? rFont.GetAbsLeftBorder(bVerticalLayout).get_ptr() : nullptr, 1.0),
-        basegfx::B2DPoint(aAlignedRect.Left(), aAlignedRect.Top()),
-        basegfx::B2DPoint(aAlignedRect.Right(), aAlignedRect.Top()),
-        basegfx::B2DPoint(aAlignedRect.Left(), aAlignedRect.Bottom()),
-        basegfx::B2DPoint(aAlignedRect.Right(), aAlignedRect.Bottom()));
-
-    // no need to use AddBorderLine and try to merge BorderLinePrimitives, in this combination
-    // tis cannot happen
+
+    aBorderLineTarget.push_back(
+        drawinglayer::primitive2d::Primitive2DReference(
+            new drawinglayer::primitive2d::SwBorderRectanglePrimitive2D(
+                aBorderTransform,
+                aStyleTop,
+                aStyleRight,
+                aStyleBottom,
+                aStyleLeft)));
     gProp.pBLines->AddBorderLines(aBorderLineTarget);
 }
 
@@ -5140,46 +5058,27 @@ void SwFrame::PaintSwFrameShadowAndBorder(
             const SvxBorderLine* pTopBorder(rBox.GetTop());
             const SvxBorderLine* pBottomBorder(rBox.GetBottom());
 
-            // if R2L, exchange Right/Left
-            const bool bR2L(IsCellFrame() && IsRightToLeft());
-
-            if(bR2L)
-            {
-                std::swap(pLeftBorder, pRightBorder);
-            }
-
-            // if ContentFrame and joined Prev/Next, reset top/bottom as needed
-            if(IsContentFrame())
-            {
-                if(rAttrs.JoinedWithPrev(*this))
-                {
-                        pTopBorder = nullptr;
-                }
-
-                if(rAttrs.JoinedWithNext(*this))
-                {
-                        pBottomBorder = nullptr;
-                }
-            }
-
             if(nullptr != pLeftBorder || nullptr != pRightBorder || nullptr != pTopBorder || nullptr != pBottomBorder)
             {
                 // now we have all SvxBorderLine(s) sorted out, create geometry
+                const basegfx::B2DHomMatrix aBorderTransform(
+                    basegfx::tools::createScaleTranslateB2DHomMatrix(
+                        aRect.Width(), aRect.Height(),
+                        aRect.Left(), aRect.Top()));
+                const svx::frame::Style aStyleTop(pTopBorder, 1.0);
+                const svx::frame::Style aStyleRight(pRightBorder, 1.0);
+                const svx::frame::Style aStyleBottom(pBottomBorder, 1.0);
+                const svx::frame::Style aStyleLeft(pLeftBorder, 1.0);
                 drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget;
 
-                CreateBorderLinePrimitivesForRectangle(
-                    aBorderLineTarget,
-                    svx::frame::Style(pTopBorder, 1.0),
-                    svx::frame::Style(pRightBorder, 1.0),
-                    svx::frame::Style(pBottomBorder, 1.0),
-                    svx::frame::Style(pLeftBorder, 1.0),
-                    basegfx::B2DPoint(aRect.Left(), aRect.Top()),       // TopLeft
-                    basegfx::B2DPoint(aRect.Right(), aRect.Top()),      // TopRight
-                    basegfx::B2DPoint(aRect.Left(), aRect.Bottom()),    // BottomLeft
-                    basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));  // BottomRight
-
-                // no need to use AddBorderLine and try to merge BorderLinePrimitives, in this combination
-                // tis cannot happen
+                aBorderLineTarget.push_back(
+                    drawinglayer::primitive2d::Primitive2DReference(
+                        new drawinglayer::primitive2d::SwBorderRectanglePrimitive2D(
+                            aBorderTransform,
+                            aStyleTop,
+                            aStyleRight,
+                            aStyleBottom,
+                            aStyleLeft)));
                 gProp.pBLines->AddBorderLines(aBorderLineTarget);
             }
         }
commit 579c8ad3aeb299b4d2c5f49080eb6e6daf40281e
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Dec 5 15:28:08 2017 +0100

    SwFrameBorder: Use enhanced FrameBorders for Character
    
    Adapted PaintCharacterBorder to also use new, enhanced
    FrameBorders. Adapted some places, cleaned up old code,
    enhanced tooling method CreateBorderLinePrimitivesForRectangle,
    tested including PDF, Pint, PrintPreview.
    
    Change-Id: If7b793b6520e899bde6f4211c993847af21ce7b9

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 8a8f3a6bfb16..b78324072219 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -277,6 +277,41 @@ public:
     const std::vector< StyleVectorCombination >& getEntries() const{ return maEntries; }
 };
 
+/**
+ *  Helper method to create the correct drawinglayer::primitive2d::BorderLinePrimitive2D
+ *  for the given data, especially the correct drawinglayer::primitive2d::BorderLine entries
+ *  including the correctly solved/created LineStartEnd extends
+ *
+ *  rTarget : Here the evtl. created BorderLinePrimitive2D will be appended
+ *  rOrigin : StartPoint of the Borderline
+ *  rX      : Vector of the Borderline
+ *  rBorder : svx::frame::Style of the of the Borderline
+ *  rStartStyleVectorTable : All other Borderlines which have to be taken into account because
+ *      they have the same StartPoint as the current Borderline. These will be used to calculate
+ *      the correct LineStartEnd extends tor the BorderLinePrimitive2D. The definition should be
+ *      built up using svx::frame::StyleVectorTable and StyleVectorTable::add and includes:
+ *          rStyle      : the svx::frame::Style of one other BorderLine
+ *          rMyVector   : the Vector of the *new* to-be-defined BorderLine, identical to rX
+ *          rOtherVector: the Vector of one other BorderLine (may be, but does not need to be normalized),
+ *                        always *pointing away* from the common StartPoint rOrigin
+ *          bMirrored   : define if rStyle of one other BorderLine shall be mirrored (e.g. bottom-right edges)
+ *      With multiple BorderLines the definitions have to be CounterClockWise. This will be
+ *      ensured by StyleVectorTable sorting the entries, but knowing this may allow more efficcient
+ *      data creation.
+ *  rEndStyleVectorTable: All other BorderLines that have the same EndPoint. There are differences to
+ *      the Start definitions:
+ *          - do not forget to consequently use -rX for rMyVector
+ *          - definitions have to be ClockWise for the EndBorderLines, will be ensured by sorting
+ *
+ *  If you take all this into account, you will gett correctly extended BorderLinePrimitive2D
+ *  reprsentations for the new to be defined BorderLine. That extensions will overlap nicely
+ *  with the corresponding BordreLines and take all multiple line definitions in the ::Style into
+ *  account.
+ *  The internal solver is *not limitied* to ::Style(s) with three parts (Left/Gap/Right), this is
+ *  just due to svx::frame::Style's definitions. A new solver based on this one can be created
+ *  anytime using more mulötiple borders based on the more flexible
+ *  std::vector< drawinglayer::primitive2d::BorderLine > if needed.
+ */
 SVX_DLLPUBLIC void CreateBorderPrimitives(
     drawinglayer::primitive2d::Primitive2DContainer&    rTarget,        /// target for created primitives
     const basegfx::B2DPoint&    rOrigin,                /// start point of borderline
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index e8429bc6801e..db117bd99b2b 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -278,6 +278,8 @@ Style& Style::MirrorSelf()
     if (pTarget->mfSecn)
     {
         std::swap( pTarget->mfPrim, pTarget->mfSecn );
+        // also need to swap colors
+        std::swap( pTarget->maColorPrim, pTarget->maColorSecn );
     }
 
     if( pTarget->meRefMode != RefMode::REFMODE_CENTERED )
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index 320cfa09f83e..7e19619752fc 100644

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list