include/svx/svdmodel.hxx                                |    4 +
 sc/source/ui/docshell/docsh.cxx                         |    2 
 sd/source/ui/docshell/docshel4.cxx                      |    1 
 svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx         |binary
 svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp   |binary
 svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp      |binary
 svx/qa/unit/svdraw.cxx                                  |   42 +++++++++++
 svx/source/customshapes/EnhancedCustomShapeFontWork.cxx |   57 ++++++++++++----
 svx/source/svdraw/svdmodel.cxx                          |   42 +++++++++++
 sw/source/uibase/app/docshini.cxx                       |   10 +-
 10 files changed, 142 insertions(+), 16 deletions(-)

New commits:
commit 497298874961fb335caf4cc91e531667394588bc
Author:     Attila Szűcs <attila.sz...@collabora.com>
AuthorDate: Fri Jan 13 04:49:33 2023 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 23 12:47:04 2023 +0000

    tdf#148000 impress: Handle linebreaks on fontwork.
    
    Split text lines in a paragraph, right before polygons are created
    for rendering, so eol will brake line in fontwork just like eop.
    
    Change-Id: Ie9e6764f9f91c2e19afd43dc9a212bd18c41c99d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145425
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit f9d6dd788e82a1964dab9cc0d0436c8c54b775c0)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145804
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx
index 7c23b5a24712..b5d93fa53eb7 100644
--- a/include/svx/svdmodel.hxx
+++ b/include/svx/svdmodel.hxx
@@ -575,6 +575,10 @@ public:
     void SetAnchoredTextOverflowLegacy(bool bEnabled);
     bool IsAnchoredTextOverflowLegacy() const;
 
+    // tdf#148000 compatibility flag
+    void SetLegacySingleLineFontwork(bool bEnabled);
+    bool IsLegacySingleLineFontwork() const;
+
     void ReformatAllTextObjects();
 
     std::unique_ptr<SdrOutliner> createOutliner( OutlinerMode nOutlinerMode );
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 2f2f3521ae4e..458feb6dea2a 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -590,6 +590,8 @@ bool ScDocShell::Load( SfxMedium& rMedium )
     {
         if (m_pDocument->GetDrawLayer())
             m_pDocument->GetDrawLayer()->SetAnchoredTextOverflowLegacy(true);
+        if (m_pDocument->GetDrawLayer())
+            m_pDocument->GetDrawLayer()->SetLegacySingleLineFontwork(true); 
//for tdf#148000
     }
 
     GetUndoManager()->Clear();
diff --git a/sd/source/ui/docshell/docshel4.cxx 
b/sd/source/ui/docshell/docshel4.cxx
index 13b08deafa1a..0bdfef02b7db 100644
--- a/sd/source/ui/docshell/docshel4.cxx
+++ b/sd/source/ui/docshell/docshel4.cxx
@@ -269,6 +269,7 @@ bool DrawDocShell::Load( SfxMedium& rMedium )
     if (IsOwnStorageFormat(rMedium))
     {
         mpDoc->SetAnchoredTextOverflowLegacy(true);
+        mpDoc->SetLegacySingleLineFontwork(true); //for tdf#148000
     }
 
     bool       bRet = false;
diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx 
b/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx
new file mode 100644
index 000000000000..137fc816697a
Binary files /dev/null and b/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx 
differ
diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp 
b/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp
new file mode 100644
index 000000000000..13e7cc4e5c8a
Binary files /dev/null and 
b/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp differ
diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp 
b/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp
new file mode 100644
index 000000000000..7ebdb9431b72
Binary files /dev/null and b/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp 
differ
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index c2a7f244b8ab..7bf1ceb9d4a1 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -382,6 +382,48 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testFontWorks)
                 "32");
 }
 
+CPPUNIT_TEST_FIXTURE(SvdrawTest, testTdf148000_EOLinCurvedText)
+{
+    std::vector<OUString> aFilenames
+        = { u"tdf148000_EOLinCurvedText.pptx", 
u"tdf148000_EOLinCurvedText_New.odp",
+            u"tdf148000_EOLinCurvedText_Legacy.odp" };
+
+    for (int i = 0; i < 3; i++)
+    {
+        loadFromURL(aFilenames[i]);
+
+        SdrPage* pSdrPage = getFirstDrawPageWithAssert();
+
+        xmlDocUniquePtr pXmlDoc = 
lcl_dumpAndParseFirstObjectWithAssert(pSdrPage);
+
+        OString aBasePath
+            = 
"/primitive2D/objectinfo[4]/unhandled/unhandled/polypolygoncolor/polypolygon/";
+
+        // The text is: "O" + eop + "O" + eol + "O"
+        // It should be displayed as 3 line of text. (1 "O" letter in every 
line)
+        sal_Int32 nY1 = getXPath(pXmlDoc, aBasePath + "polygon[1]/point[1]", 
"y").toInt32();
+        sal_Int32 nY2 = getXPath(pXmlDoc, aBasePath + "polygon[3]/point[1]", 
"y").toInt32();
+        sal_Int32 nY3 = getXPath(pXmlDoc, aBasePath + "polygon[5]/point[1]", 
"y").toInt32();
+
+        sal_Int32 nDiff21 = nY2 - nY1;
+        sal_Int32 nDiff32 = nY3 - nY2;
+
+        // the 2. "O" must be positioned much lower as the 1. "O". (the eop 
break the line)
+        CPPUNIT_ASSERT_GREATER(sal_Int32(300), nDiff21);
+        if (i < 2)
+        {
+            // the 3. "O" must be positioned even lower with 1 line. (the eol 
must break the line as well)
+            CPPUNIT_ASSERT_LESS(sal_Int32(50), abs(nDiff32 - nDiff21));
+        }
+        else
+        {
+            // In legacy mode, the 3. "O" must be positioned about the same 
high as the 2. "O"
+            // the eol not break the line.
+            CPPUNIT_ASSERT_LESS(sal_Int32(50), nDiff32);
+        }
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(SvdrawTest, testSurfaceMetal)
 {
     loadFromURL(u"tdf140321_metal.odp");
diff --git a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx 
b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx
index e8e3bd026cd1..672cd28fbc8e 100644
--- a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx
+++ b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx
@@ -36,6 +36,7 @@
 #include <editeng/charscaleitem.hxx>
 #include <svx/svdoashp.hxx>
 #include <svx/sdshitm.hxx>
+#include <svx/svdmodel.hxx>
 #include <editeng/outlobj.hxx>
 #include <editeng/editobj.hxx>
 #include <o3tl/numeric.hxx>
@@ -50,6 +51,7 @@
 #include <sal/log.hxx>
 #include <rtl/math.hxx>
 #include <unotools/configmgr.hxx>
+#include <comphelper/string.hxx>
 
 using namespace com::sun::star;
 using namespace com::sun::star::uno;
@@ -116,27 +118,58 @@ static bool InitializeFontWorkData(
         if ( pParaObj )
         {
             const EditTextObject& rTextObj = pParaObj->GetTextObject();
-            sal_Int32 nParagraphsLeft = rTextObj.GetParagraphCount();
+            sal_Int32 nParagraphsCount = rTextObj.GetParagraphCount();
+
+            // Collect all the lines from all paragraphs
+            std::vector<int> aLineParaID;      // which para this line is in
+            std::vector<int> aLineStart;       // where this line start in 
that para
+            std::vector<int> aLineLength;
+            std::vector<OUString> aParaText;
+            for (sal_Int32 nPara = 0; nPara < nParagraphsCount; ++nPara)
+            {
+                aParaText.push_back(rTextObj.GetText(nPara));
+                sal_Int32 nPos = 0;
+                sal_Int32 nPrevPos = 0;
+                do
+                {
+                    // search line break.
+                    if 
(!rSdrObjCustomShape.getSdrModelFromSdrObject().IsLegacySingleLineFontwork())
+                        nPos = aParaText[nPara].indexOf(sal_Unicode(u'\1'), 
nPrevPos);
+                    else
+                        nPos = -1; // tdf#148000: ignore line breaks in legacy 
fontworks
+
+                    aLineParaID.push_back(nPara);
+                    aLineStart.push_back(nPrevPos);
+                    aLineLength.push_back((nPos >= 0 ? nPos : 
aParaText[nPara].getLength())
+                                          - nPrevPos);
+                    nPrevPos = nPos + 1;
+                } while (nPos >= 0);
+            }
+
+            sal_Int32 nLinesLeft = aLineParaID.size();
 
-            rFWData.nMaxParagraphsPerTextArea = ( ( nParagraphsLeft - 1 ) / 
nTextAreaCount ) + 1;
-            sal_Int32 j = 0;
-            while( nParagraphsLeft && nTextAreaCount )
+            rFWData.nMaxParagraphsPerTextArea = ((nLinesLeft - 1) / 
nTextAreaCount) + 1;
+            sal_Int32 nLine = 0;
+            while (nLinesLeft && nTextAreaCount)
             {
                 FWTextArea aTextArea;
-                sal_Int32 i, nParagraphs = ( ( nParagraphsLeft - 1 ) / 
nTextAreaCount ) + 1;
-                for ( i = 0; i < nParagraphs; ++i, ++j )
+                sal_Int32 nLinesInPara = ((nLinesLeft - 1) / nTextAreaCount) + 
1;
+                for (sal_Int32 i = 0; i < nLinesInPara; ++i, ++nLine)
                 {
                     FWParagraphData aParagraphData;
-                    aParagraphData.aString = rTextObj.GetText( j );
+                    aParagraphData.aString = 
aParaText[aLineParaID[nLine]].subView(
+                        aLineStart[nLine], aLineLength[nLine]);
 
-                    const SfxItemSet& rParaSet = rTextObj.GetParaAttribs( j ); 
 // retrieving some paragraph attributes
-                    aParagraphData.nFrameDirection = rParaSet.Get( 
EE_PARA_WRITINGDIR ).GetValue();
-                    aTextArea.vParagraphs.push_back( aParagraphData );
+                    // retrieving some paragraph attributes
+                    const SfxItemSet& rParaSet = 
rTextObj.GetParaAttribs(aLineParaID[nLine]);
+                    aParagraphData.nFrameDirection = 
rParaSet.Get(EE_PARA_WRITINGDIR).GetValue();
+                    aTextArea.vParagraphs.push_back(aParagraphData);
                 }
-                rFWData.vTextAreas.push_back( aTextArea );
-                nParagraphsLeft -= nParagraphs;
+                rFWData.vTextAreas.push_back(aTextArea);
+                nLinesLeft -= nLinesInPara;
                 nTextAreaCount--;
             }
+
             bNoErr = true;
         }
     }
diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx
index 3feb1ae0669b..bc86671c9437 100644
--- a/svx/source/svdraw/svdmodel.cxx
+++ b/svx/source/svdraw/svdmodel.cxx
@@ -72,6 +72,9 @@
 #include <comphelper/diagnose_ex.hxx>
 #include <tools/UnitConversion.hxx>
 #include <svx/ColorSets.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdoashp.hxx>
+
 
 using namespace ::com::sun::star;
 
@@ -80,12 +83,14 @@ struct SdrModelImpl
     SfxUndoManager* mpUndoManager;
     SdrUndoFactory* mpUndoFactory;
     bool mbAnchoredTextOverflowLegacy; // tdf#99729 compatibility flag
+    bool mbLegacySingleLineFontwork;   // tdf#148000 compatibility flag
     std::unique_ptr<svx::Theme> mpTheme;
 
     SdrModelImpl()
         : mpUndoManager(nullptr)
         , mpUndoFactory(nullptr)
         , mbAnchoredTextOverflowLegacy(false)
+        , mbLegacySingleLineFontwork(false)
     {}
 };
 
@@ -1718,6 +1723,16 @@ bool SdrModel::IsAnchoredTextOverflowLegacy() const
     return mpImpl->mbAnchoredTextOverflowLegacy;
 }
 
+void SdrModel::SetLegacySingleLineFontwork(bool bEnabled)
+{
+    mpImpl->mbLegacySingleLineFontwork = bEnabled;
+}
+
+bool SdrModel::IsLegacySingleLineFontwork() const
+{
+    return mpImpl->mbLegacySingleLineFontwork;
+}
+
 void SdrModel::ReformatAllTextObjects()
 {
     ImpReformatAllTextObjects();
@@ -1761,6 +1776,32 @@ void SdrModel::ReadUserDataSequenceValue(const 
beans::PropertyValue* pValue)
             mpImpl->mbAnchoredTextOverflowLegacy = bBool;
         }
     }
+    else if (pValue->Name == "LegacySingleLineFontwork")
+    {
+        bool bBool = false;
+        if (pValue->Value >>= bBool)
+        {
+            mpImpl->mbLegacySingleLineFontwork = bBool;
+            // tdf#148000 hack: reset all CustomShape geometry as they may 
depend on this property
+            // Ideally this ReadUserDataSequenceValue should be called before 
geometry creation
+            // Once the calling order will be fixed, this hack will not be 
needed.
+            for (size_t i = 0; i < maPages.size(); ++i)
+            {
+                if (const SdrPage* pPage = maPages[i].get())
+                {
+                    SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
+                    while (aIter.IsMore())
+                    {
+                        SdrObject* pTempObj = aIter.Next();
+                        if (SdrObjCustomShape* pShape = 
dynamic_cast<SdrObjCustomShape*>(pTempObj))
+                        {
+                            pShape->InvalidateRenderGeometry();
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
 
 template <typename T>
@@ -1773,6 +1814,7 @@ void SdrModel::WriteUserDataSequence(uno::Sequence 
<beans::PropertyValue>& rValu
 {
     std::vector< std::pair< OUString, uno::Any > > aUserData;
     addPair(aUserData, "AnchoredTextOverflowLegacy", 
IsAnchoredTextOverflowLegacy());
+    addPair(aUserData, "LegacySingleLineFontwork", 
IsLegacySingleLineFontwork());
 
     const sal_Int32 nOldLength = rValues.getLength();
     rValues.realloc(nOldLength + aUserData.size());
diff --git a/sw/source/uibase/app/docshini.cxx 
b/sw/source/uibase/app/docshini.cxx
index c5432a98af29..72e630ac02b2 100644
--- a/sw/source/uibase/app/docshini.cxx
+++ b/sw/source/uibase/app/docshini.cxx
@@ -476,10 +476,12 @@ bool  SwDocShell::Load( SfxMedium& rMedium )
         // (if required, they will be overridden later when settings will be 
read)
         if (IsOwnStorageFormat(rMedium))
         {
-            // legacy processing for tdf#99729
-            if (m_xDoc->getIDocumentDrawModelAccess().GetDrawModel())
-                
m_xDoc->getIDocumentDrawModelAccess().GetDrawModel()->SetAnchoredTextOverflowLegacy(
-                    true);
+            SwDrawModel* pDrawModel = 
m_xDoc->getIDocumentDrawModelAccess().GetDrawModel();
+            if (pDrawModel)
+            {
+                pDrawModel->SetAnchoredTextOverflowLegacy(true); // legacy 
processing for tdf#99729
+                pDrawModel->SetLegacySingleLineFontwork(true); // legacy 
processing for tdf#148000
+            }
         }
 
         // Loading

Reply via email to