diff options
author | Daniel Arato (NISZ) <arato.daniel@nisz.hu> | 2020-09-16 08:48:32 +0200 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2020-10-06 12:31:04 +0200 |
commit | af4e5ee0f93c1ff442d08caed5c875f2b2c1fd43 (patch) | |
tree | acf3133451bec3246d8736268d48513efbe6c324 | |
parent | 94b73fb5e206a8718e5127cf58c826099ae92f5a (diff) |
tdf#97128 DOCX import: fix frame direction
Frames used to be imported with zero rotation even if a w:textDirection
tag explicitly called for a non-default orientation.
I found no other solution to pass the incoming frame direction property
on to the SwXFrame about to be created.
1. If you put the property into the GetSectionContext(), it gets
overwritten when the next w:pPr tag is parsed, so all three frames will
end up having the same direction.
2. If you put the property into the GetTopContextOfType(CONTEXT_PARAGRAPH)
that context gets popped off the stack before control even gets to
CheckUnregisteredFrameConversion().
3. If you use PushStyleSheetProperties (which is bad in and of itself),
the order will be messed up because the frames are not necessarily
created in the same order as they are described in the file, so each
frame gets a wrong frame direction in the end.
Follow-up of commit 5a5597655a4bf12e4ca07c9c2b6f6221e217f080
(tentative fix for fdo#30474# [DOCX rotated text import failure]).
Change-Id: I6e3d68fe60c6e2a5b6684c65a964dd86d0168181
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103553
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r-- | sw/source/core/unocore/unoframe.cxx | 17 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx | 21 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/data/frame-direction.docx | bin | 0 -> 28204 bytes | |||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 30 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 6 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 21 |
6 files changed, 94 insertions, 1 deletions
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index e8461393ea6f..a73b8e74fa95 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -1402,6 +1402,23 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& { SolarMutexGuard aGuard; SwFrameFormat* pFormat = GetFrameFormat(); + + // Hack to support hidden property to transfer textDirection + if(rPropertyName == "FRMDirection") + { + if (pFormat) + { + SvxFrameDirectionItem aItem(SvxFrameDirection::Environment, RES_FRAMEDIR); + aItem.PutValue(_rValue, 0); + GetFrameFormat()->SetFormatAttr(aItem); + } + else if(IsDescriptor()) + { + m_pProps->SetProperty(static_cast<sal_uInt16>(RES_FRAMEDIR), 0, _rValue); + } + return; + } + const ::SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap().getByName(rPropertyName); if (!pEntry) diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx index 893db1607112..de63ec4084d9 100644 --- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx @@ -14,6 +14,8 @@ #include <com/sun/star/text/XTextDocument.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/style/BreakType.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/text/WritingMode2.hpp> using namespace ::com::sun::star; @@ -104,6 +106,25 @@ CPPUNIT_TEST_FIXTURE(Test, testNumberingRestartStyleParent) xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("2."), xPara->getPropertyValue(aProp).get<OUString>()); } + +CPPUNIT_TEST_FIXTURE(Test, testFrameDirection) +{ + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "frame-direction.docx"; + getComponent() = loadFromDesktop(aURL); + + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<beans::XPropertySet> xFrame0(xDrawPage->getByIndex(0), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xFrame1(xDrawPage->getByIndex(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xFrame2(xDrawPage->getByIndex(2), uno::UNO_QUERY); + // Without the accompanying fix in place, all of the following values would be text::WritingMode2::CONTEXT + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::CONTEXT, + xFrame0->getPropertyValue("WritingMode").get<sal_Int16>()); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, + xFrame1->getPropertyValue("WritingMode").get<sal_Int16>()); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, + xFrame2->getPropertyValue("WritingMode").get<sal_Int16>()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/frame-direction.docx b/writerfilter/qa/cppunittests/dmapper/data/frame-direction.docx Binary files differnew file mode 100644 index 000000000000..33f191e80350 --- /dev/null +++ b/writerfilter/qa/cppunittests/dmapper/data/frame-direction.docx diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index b3faa5682ab6..ca118c0f9c9b 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1501,6 +1501,35 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) } break; case NS_ooxml::LN_CT_PPrBase_textDirection: + { + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_TextDirection_tbRl: + { + m_pImpl->SetFrameDirection(text::WritingMode2::TB_RL); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_btLr: + { + m_pImpl->SetFrameDirection(text::WritingMode2::BT_LR); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_lrTbV: + { + m_pImpl->SetFrameDirection(text::WritingMode2::LR_TB); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_tbRlV: + { + m_pImpl->SetFrameDirection(text::WritingMode2::TB_RL); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_lrTb: + case NS_ooxml::LN_Value_ST_TextDirection_tbLrV: + default: + SAL_WARN("writerfilter", "DomainMapper::sprmWithProps: unhandled textDirection"); + } + } break; case NS_ooxml::LN_CT_PPrBase_outlineLvl: { @@ -2088,6 +2117,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) { //TODO: What about style sheet import of frame properties } + m_pImpl->NewFrameDirection(); resolveSprmProps(*this, rSprm); } break; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index cd78ab36bd0a..2fcd6ba2e362 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1155,6 +1155,11 @@ void DomainMapper_Impl::CheckUnregisteredFrameConversion( ) aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_WIDTH_TYPE), bAutoWidth ? text::SizeType::MIN : text::SizeType::FIX)); + if (const std::optional<sal_Int16> nDirection = PopFrameDirection()) + { + aFrameProperties.push_back(comphelper::makePropertyValue(getPropertyName(PROP_FRM_DIRECTION), *nDirection)); + } + sal_Int16 nHoriOrient = sal_Int16( rAppendContext.pLastParagraphProperties->GetxAlign() >= 0 ? rAppendContext.pLastParagraphProperties->GetxAlign() : @@ -1538,7 +1543,6 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con if ( hasTableManager() && getTableManager().isInCell() ) getTableManager().setCellLastParaAfterAutospacing( bApplyAutospacing ); - if (xTextAppend.is() && pParaContext && hasTableManager() && !getTableManager().isIgnore()) { try diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 1a9f9340bac6..ba81c4c55e39 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -490,6 +490,8 @@ private: //each context needs a stack of currently used attributes std::stack<PropertyMapPtr> m_aPropertyStacks[NUMBER_OF_CONTEXTS]; std::stack<ContextType> m_aContextStack; + std::queue<std::optional<sal_Int16>> m_aFrameDirectionQueue; + bool m_bFrameDirectionSet; FontTablePtr m_pFontTable; ListsManager::Pointer m_pListTable; std::deque< css::uno::Reference<css::drawing::XShape> > m_aPendingShapes; @@ -954,6 +956,25 @@ public: return m_aTextAppendStack.empty() ? nullptr : m_aTextAppendStack.top().xTextAppend; } + void NewFrameDirection() { + m_aFrameDirectionQueue.push(std::nullopt); + m_bFrameDirectionSet = false; + } + void SetFrameDirection(sal_Int16 nDirection) { + if (!m_bFrameDirectionSet) { + assert(!m_aFrameDirectionQueue.empty()); + m_aFrameDirectionQueue.back() = nDirection; + m_bFrameDirectionSet = true; + } + } + std::optional<sal_Int16> PopFrameDirection() { + if (m_aFrameDirectionQueue.empty()) + return {}; + const std::optional<sal_Int16> nDirection = m_aFrameDirectionQueue.front(); + m_aFrameDirectionQueue.pop(); + return nDirection; + } + SectionPropertyMap * GetSectionContext(); /// If the current paragraph has a numbering style associated, this method returns its character style (part of the numbering rules) css::uno::Reference<css::beans::XPropertySet> GetCurrentNumberingCharStyle(); |