diff options
author | Attila Szűcs <attila.szucs@collabora.com> | 2023-01-13 04:49:33 +0100 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2023-01-23 12:47:04 +0000 |
commit | 497298874961fb335caf4cc91e531667394588bc (patch) | |
tree | 07cac688a8d24145f21d67575f5eb98b321b4b13 /svx | |
parent | 4a26d67dced163d79617b05131d66a05dafebc86 (diff) |
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 <vmiklos@collabora.com>
(cherry picked from commit f9d6dd788e82a1964dab9cc0d0436c8c54b775c0)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145804
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'svx')
-rw-r--r-- | svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx | bin | 0 -> 29206 bytes | |||
-rw-r--r-- | svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp | bin | 0 -> 13692 bytes | |||
-rw-r--r-- | svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp | bin | 0 -> 13750 bytes | |||
-rw-r--r-- | svx/qa/unit/svdraw.cxx | 42 | ||||
-rw-r--r-- | svx/source/customshapes/EnhancedCustomShapeFontWork.cxx | 57 | ||||
-rw-r--r-- | svx/source/svdraw/svdmodel.cxx | 42 |
6 files changed, 129 insertions, 12 deletions
diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx b/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx Binary files differnew file mode 100644 index 000000000000..137fc816697a --- /dev/null +++ b/svx/qa/unit/data/tdf148000_EOLinCurvedText.pptx diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp b/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp Binary files differnew file mode 100644 index 000000000000..13e7cc4e5c8a --- /dev/null +++ b/svx/qa/unit/data/tdf148000_EOLinCurvedText_Legacy.odp diff --git a/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp b/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp Binary files differnew file mode 100644 index 000000000000..7ebdb9431b72 --- /dev/null +++ b/svx/qa/unit/data/tdf148000_EOLinCurvedText_New.odp 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()); |