[Libreoffice-commits] core.git: Branch 'libreoffice-7-1' - sw/inc sw/qa sw/source

Attila Bakos (NISZ) (via logerrit) logerrit at kemper.freedesktop.org
Tue Mar 2 11:15:05 UTC 2021


 sw/inc/textboxhelper.hxx                        |    5 
 sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx |binary
 sw/qa/extras/uiwriter/uiwriter3.cxx             |   52 +++++++++
 sw/source/core/doc/textboxhelper.cxx            |  137 ++++++++++++++++++++++--
 sw/source/core/text/porfly.cxx                  |   32 +++--
 5 files changed, 204 insertions(+), 22 deletions(-)

New commits:
commit 6edeb6a8209a990e83f07c02753d606226f59be7
Author:     Attila Bakos (NISZ) <bakos.attilakaroly at nisz.hu>
AuthorDate: Mon Feb 22 14:28:59 2021 +0100
Commit:     Xisco Fauli <xiscofauli at libreoffice.org>
CommitDate: Tue Mar 2 12:14:28 2021 +0100

    tdf#140158 tdf#138598 tdf#140598 sw: fix sync of AS_CHAR textboxes
    
    Textboxes anchored "As Character" fell apart, when
    typing before some characters or inserting a page break.
    
    By fixing that, the tdf#138598 bug also have fixed which
    was a regression from commit b6850bbe95418ecfde404be1696548f18d200c9b
    (tdf#106153 sw compatibility: fix textboxes exceeding the page).
    
    In addition, tdf140598 is also fixed, which was
    a regression from commit c96c386c5db45dc4d5e358915caad7474e373068
    (tdf#136516 add positioning to SwTextBoxHelper::syncProperty()).
    
    Change-Id: Ifeadd8b2055ce52a019d651369ca41185de7bbe3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111338
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: László Németh <nemeth at numbertext.org>
    Signed-off-by: Xisco Fauli <xiscofauli at libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111796
    Tested-by: Jenkins

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 45d8a6c56f5d..2043b1ffcfb3 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -16,6 +16,8 @@
 
 #include <com/sun/star/uno/Any.h>
 #include <com/sun/star/uno/Type.h>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <svx/swframetypes.hxx>
 
 #include "swdllapi.h"
 
@@ -71,6 +73,9 @@ public:
     static void getProperty(SwFrameFormat const* pShape, sal_uInt16 nWID, sal_uInt8 nMemberID,
                             css::uno::Any& rValue);
 
+    /// There are two types of enum of anchor type, so this function maps this.
+    static css::text::TextContentAnchorType mapAnchorType(const RndStdIds& rAnchorID);
+
     /// Similar to syncProperty(), but used by the internal API (e.g. for UI purposes).
     static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& rSet);
 
diff --git a/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx b/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx
new file mode 100755
index 000000000000..7603b80d2c2d
Binary files /dev/null and b/sw/qa/extras/uiwriter/data3/AsCharTxBxTest.docx differ
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx
index e568e695000a..018a96a78ee6 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -725,6 +725,58 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf134253)
     CPPUNIT_ASSERT_EQUAL(6, getPages());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, TestAsCharTextBox)
+{
+    // Releated tickets:
+    // tdf#138598 Replace vertical alignment of As_char textboxes in footer
+    // tdf#140158 Remove horizontal positioning of As_char textboxes, because
+    // the anchor moving does the same for it.
+
+    load(DATA_DIRECTORY, "AsCharTxBxTest.docx");
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+
+    // Add 3x tab to the doc
+    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+    Scheduler::ProcessEventsToIdle();
+
+    auto pExportDump = parseLayoutDump();
+    CPPUNIT_ASSERT(pExportDump);
+
+    // Check if the texbox fallen apart due to the tabs
+    const double nLeftSideOfShape1
+        = getXPath(pExportDump, "/root/page/body/txt/anchored/SwAnchoredDrawObject/bounds", "left")
+              .toDouble();
+    const double nLeftSideOfTxBx1
+        = getXPath(pExportDump, "/root/page/body/txt/anchored/fly/infos/bounds", "left").toDouble();
+
+    CPPUNIT_ASSERT(nLeftSideOfShape1 < nLeftSideOfTxBx1);
+
+    // Another test is for the tdf#138598: Check footer textbox
+    const double nLeftSideOfShape2
+        = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/SwAnchoredDrawObject/bounds",
+                   "left")
+              .toDouble();
+    const double nLeftSideOfTxBx2
+        = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/fly/infos/bounds", "left")
+              .toDouble();
+
+    CPPUNIT_ASSERT(nLeftSideOfShape2 < nLeftSideOfTxBx2);
+
+    const double nTopSideOfShape2
+        = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/SwAnchoredDrawObject/bounds",
+                   "top")
+              .toDouble();
+    const double nTopSideOfTxBx2
+        = getXPath(pExportDump, "/root/page[2]/footer/txt/anchored/fly/infos/bounds", "top")
+              .toDouble();
+
+    CPPUNIT_ASSERT(nTopSideOfShape2 < nTopSideOfTxBx2);
+    // Without the fix in place the two texboxes has been fallen apart, and  asserts will broken.
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf76636)
 {
     load(DATA_DIRECTORY, "tdf76636.doc");
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 4d44d1c35ff8..5257d448bd55 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -33,6 +33,7 @@
 #include <editeng/memberids.h>
 #include <svx/svdoashp.hxx>
 #include <svx/svdpage.hxx>
+#include <svx/swframetypes.hxx>
 #include <svl/itemiter.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <sal/log.hxx>
@@ -686,10 +687,39 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
                     if (aValue.get<text::TextContentAnchorType>()
                         == text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER)
                     {
-                        xPropertySet->setPropertyValue(
-                            UNO_NAME_ANCHOR_TYPE,
-                            uno::makeAny(
-                                text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER));
+                        if (const auto aPos = pShape->GetAnchor().GetContentAnchor())
+                        {
+                            xPropertySet->setPropertyValue(
+                                UNO_NAME_ANCHOR_TYPE,
+                                uno::makeAny(text::TextContentAnchorType::
+                                                 TextContentAnchorType_AT_CHARACTER));
+                            xPropertySet->setPropertyValue(
+                                UNO_NAME_HORI_ORIENT_RELATION,
+                                uno::makeAny(text::RelOrientation::CHAR));
+
+                            auto pAnch = pFormat->GetAnchor();
+                            pAnch.SetAnchor(pShape->GetAnchor().GetContentAnchor());
+                            tools::Rectangle aRect(getTextRectangle(pShape, false));
+
+                            SwFormatHoriOrient aNewHOri(pFormat->GetHoriOrient());
+                            aNewHOri.SetPos(aRect.getX());
+
+                            SwFormatVertOrient aNewVOri(pFormat->GetVertOrient());
+                            aNewVOri.SetPos(aRect.getY());
+
+                            pFormat->SetFormatAttr(pAnch);
+                            // tdf#140598: Do not apply wrong rectangle position.
+                            if (aRect.TopLeft() != Point(0, 0))
+                            {
+                                pFormat->SetFormatAttr(aNewHOri);
+                                pFormat->SetFormatAttr(aNewVOri);
+                            }
+                            else
+                                SAL_WARN("sw.core",
+                                         "SwTextBoxHelper::syncProperty: Repositioning failed!");
+                        }
+
+                        return;
                     }
                     else // Otherwise copy the anchor type of the shape
                     {
@@ -699,11 +729,55 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
                     if (aValue.get<text::TextContentAnchorType>()
                         == text::TextContentAnchorType::TextContentAnchorType_AT_PAGE)
                     {
-                        xPropertySet->setPropertyValue(
-                            UNO_NAME_ANCHOR_PAGE_NO,
-                            uno::makeAny(pShape->GetAnchor().GetPageNum()));
+                        if (pShape->GetAnchor().GetPageNum())
+                            xPropertySet->setPropertyValue(
+                                UNO_NAME_ANCHOR_PAGE_NO,
+                                uno::makeAny(pShape->GetAnchor().GetPageNum()));
+                        else
+                        {
+                            SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: Invalid Page Num!");
+                            return;
+                        }
                     }
 
+                    // At-Content Anchors have to be synced:
+                    if (aValue.get<text::TextContentAnchorType>()
+                            == text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH
+                        || aValue.get<text::TextContentAnchorType>()
+                               == text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER)
+                    {
+                        // If the shape has content...
+                        if (auto aPos = pShape->GetAnchor().GetContentAnchor())
+                        {
+                            SwFormatAnchor aAnch(pFormat->GetAnchor());
+                            // ...set it for the textframe too.
+                            aAnch.SetAnchor(aPos);
+                            pFormat->SetFormatAttr(aAnch);
+                        }
+                        else
+                            SAL_WARN("sw.core",
+                                     "SwTextBoxHelper::syncProperty: Anchor without content!");
+                    }
+                    // And the repositioning:
+                    if (pShape->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
+                    {
+                        tools::Rectangle aRect(getTextRectangle(pShape, false));
+
+                        // tdf#140598: Do not apply wrong rectangle position.
+                        if (aRect.TopLeft() != Point(0, 0))
+                        {
+                            SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient());
+                            aNewHOri.SetPos(aNewHOri.GetPos() + aRect.getX());
+                            SwFormatVertOrient aNewVOri(pShape->GetVertOrient());
+                            aNewVOri.SetPos(aNewVOri.GetPos() + aRect.getY());
+
+                            pFormat->SetFormatAttr(aNewHOri);
+                            pFormat->SetFormatAttr(aNewVOri);
+                        }
+                        else
+                            SAL_WARN("sw.core",
+                                     "SwTextBoxHelper::syncProperty: Repositioning failed!");
+                    }
                     return;
                 }
                 break;
@@ -834,12 +908,41 @@ void SwTextBoxHelper::restoreLinks(std::set<ZSortFly>& rOld, std::vector<SwFrame
     }
 }
 
+text::TextContentAnchorType SwTextBoxHelper::mapAnchorType(const RndStdIds& rAnchorID)
+{
+    text::TextContentAnchorType aAnchorType;
+    switch (rAnchorID)
+    {
+        case RndStdIds::FLY_AS_CHAR:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER;
+            break;
+        case RndStdIds::FLY_AT_CHAR:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER;
+            break;
+        case RndStdIds::FLY_AT_PARA:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH;
+            break;
+        case RndStdIds::FLY_AT_PAGE:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PAGE;
+            break;
+        case RndStdIds::FLY_AT_FLY:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_FRAME;
+            break;
+        default:
+            aAnchorType = text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH;
+            SAL_WARN("sw.core", "SwTextBoxHelper::mapAnchorType: Unknown AnchorType!");
+            break;
+    }
+    return aAnchorType;
+}
+
 void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& rSet)
 {
     SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT);
     if (!pFormat)
         return;
 
+    const bool bInlineAnchored = rShape.GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR;
     SfxItemSet aTextBoxSet(pFormat->GetDoc()->GetAttrPool(), aFrameFormatSetRange);
 
     SfxItemIter aIter(rSet);
@@ -861,6 +964,13 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const&
         {
             case RES_VERT_ORIENT:
             {
+                // The new position can be with anchor changing so sync it!
+                const text::TextContentAnchorType aNewAnchorType
+                    = mapAnchorType(rShape.GetAnchor().GetAnchorId());
+                syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, uno::Any(aNewAnchorType));
+                if (bInlineAnchored)
+                    return;
+
                 auto& rOrient = static_cast<const SwFormatVertOrient&>(*pItem);
                 SwFormatVertOrient aOrient(rOrient);
 
@@ -885,6 +995,8 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const&
             case RES_HORI_ORIENT:
             {
                 auto& rOrient = static_cast<const SwFormatHoriOrient&>(*pItem);
+                if (bInlineAnchored)
+                    return;
                 SwFormatHoriOrient aOrient(rOrient);
 
                 tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
@@ -910,11 +1022,14 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const&
                 tools::Rectangle aRect = getTextRectangle(&rShape, /*bAbsolute=*/false);
                 if (!aRect.IsEmpty())
                 {
-                    aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY());
-                    aTextBoxSet.Put(aVertOrient);
+                    if (!bInlineAnchored)
+                    {
+                        aVertOrient.SetPos(aVertOrient.GetPos() + aRect.getY());
+                        aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX());
 
-                    aHoriOrient.SetPos(aHoriOrient.GetPos() + aRect.getX());
-                    aTextBoxSet.Put(aHoriOrient);
+                        aTextBoxSet.Put(aVertOrient);
+                        aTextBoxSet.Put(aHoriOrient);
+                    }
 
                     aSize.SetWidth(aRect.getWidth());
                     aSize.SetHeight(aRect.getHeight());
diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx
index 24961c08b68d..cafa70c48227 100644
--- a/sw/source/core/text/porfly.cxx
+++ b/sw/source/core/text/porfly.cxx
@@ -352,20 +352,30 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, const Point &rBase,
             // is relative to the print area of the anchor text frame.
             tools::Rectangle aTextRectangle = SwTextBoxHelper::getTextRectangle(pShape);
 
-            SwFormatHoriOrient aHori(pTextBox->GetHoriOrient());
-            aHori.SetHoriOrient(css::text::HoriOrientation::NONE);
-            sal_Int32 nLeft = aTextRectangle.getX() - rFrame.getFrameArea().Left()
-                              - rFrame.getFramePrintArea().Left();
-            aHori.SetPos(nLeft);
-
+            const auto aPos(pShape->GetAnchor().GetContentAnchor());
             SwFormatVertOrient aVert(pTextBox->GetVertOrient());
-            aVert.SetVertOrient(css::text::VertOrientation::NONE);
-            sal_Int32 const nTop = aTextRectangle.getY() - rFrame.getFrameArea().Top()
-                                   - rFrame.getFramePrintArea().Top();
-            aVert.SetPos(nTop);
+
+            // tdf#138598 Replace vertical alignment of As_char textboxes in footer
+            // tdf#140158 Remove horizontal positioning of As_char textboxes, because
+            // the anchor moving does the same for it.
+            if (!aPos->nNode.GetNode().FindFooterStartNode())
+            {
+                aVert.SetVertOrient(css::text::VertOrientation::NONE);
+                sal_Int32 const nTop = aTextRectangle.getY() - rFrame.getFrameArea().Top()
+                                       - rFrame.getFramePrintArea().Top();
+                aVert.SetPos(nTop);
+            }
+            else
+            {
+                aVert.SetVertOrient(css::text::VertOrientation::NONE);
+                aVert.SetPos(SwTextBoxHelper::getTextRectangle(pShape, false).getY());
+            }
+
+            SwFormatAnchor aNewTxBxAnchor(pTextBox->GetAnchor());
+            aNewTxBxAnchor.SetAnchor(aPos);
 
             pTextBox->LockModify();
-            pTextBox->SetFormatAttr(aHori);
+            pTextBox->SetFormatAttr(aNewTxBxAnchor);
             pTextBox->SetFormatAttr(aVert);
             pTextBox->UnlockModify();
         }


More information about the Libreoffice-commits mailing list