diff options
-rw-r--r-- | sw/source/core/inc/unoparaframeenum.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/unocore/unoobj2.cxx | 25 | ||||
-rw-r--r-- | sw/source/core/unocore/unoparagraph.cxx | 18 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 79 |
4 files changed, 92 insertions, 34 deletions
diff --git a/sw/source/core/inc/unoparaframeenum.hxx b/sw/source/core/inc/unoparaframeenum.hxx index 81a653aac57f..c44e0f660c6d 100644 --- a/sw/source/core/inc/unoparaframeenum.hxx +++ b/sw/source/core/inc/unoparaframeenum.hxx @@ -31,6 +31,8 @@ class SwNodeIndex; class SwPaM; class SwFrameFormat; +namespace com { namespace sun { namespace star { namespace text { class XTextContent; } } } } + namespace sw { struct FrameClient final : public SwClient @@ -70,6 +72,8 @@ struct SwXParaFrameEnumeration static rtl::Reference<SwXParaFrameEnumeration> Create(const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode, SwFrameFormat* const pFormat = nullptr); }; +css::uno::Reference<css::text::XTextContent> FrameClientToXTextContent(sw::FrameClient* pClient); + #endif // INCLUDED_SW_SOURCE_CORE_INC_UNOPARAFRAMEENUM_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx index e4f5ccdf22d9..7614f0a31485 100644 --- a/sw/source/core/unocore/unoobj2.cxx +++ b/sw/source/core/unocore/unoobj2.cxx @@ -1788,9 +1788,17 @@ bool SwXParaFrameEnumerationImpl::CreateNextObject() if (m_vFrames.empty()) return false; - SwFrameFormat* const pFormat = static_cast<SwFrameFormat*>( - m_vFrames.front()->GetRegisteredIn()); + m_xNextObject.set(FrameClientToXTextContent(m_vFrames.front().get())); m_vFrames.pop_front(); + return m_xNextObject.is(); +} + +uno::Reference<text::XTextContent> FrameClientToXTextContent(sw::FrameClient* pClient) +{ + assert(pClient); + + uno::Reference<text::XTextContent> xRet; + SwFrameFormat* const pFormat = static_cast<SwFrameFormat*>(pClient->GetRegisteredIn()); // the format should be valid here, otherwise the client // would have been removed by PurgeFrameClients // check for a shape first @@ -1799,33 +1807,32 @@ bool SwXParaFrameEnumerationImpl::CreateNextObject() SdrObject* pObject(nullptr); pFormat->CallSwClientNotify(sw::FindSdrObjectHint(pObject)); if(pObject) - m_xNextObject.set(pObject->getUnoShape(), uno::UNO_QUERY); + xRet.set(pObject->getUnoShape(), uno::UNO_QUERY); } else { const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx(); OSL_ENSURE(pIdx, "where is the index?"); - SwNode const*const pNd = - m_pUnoCursor->GetDoc().GetNodes()[ pIdx->GetIndex() + 1 ]; + SwNode const* const pNd = pIdx->GetNodes()[pIdx->GetIndex() + 1]; if (!pNd->IsNoTextNode()) { - m_xNextObject = static_cast<SwXFrame*>(SwXTextFrame::CreateXTextFrame( + xRet = static_cast<SwXFrame*>(SwXTextFrame::CreateXTextFrame( *pFormat->GetDoc(), pFormat).get()); } else if (pNd->IsGrfNode()) { - m_xNextObject.set(SwXTextGraphicObject::CreateXTextGraphicObject( + xRet.set(SwXTextGraphicObject::CreateXTextGraphicObject( *pFormat->GetDoc(), pFormat)); } else { assert(pNd->IsOLENode()); - m_xNextObject.set(SwXTextEmbeddedObject::CreateXTextEmbeddedObject( + xRet.set(SwXTextEmbeddedObject::CreateXTextEmbeddedObject( *pFormat->GetDoc(), pFormat)); } } - return m_xNextObject.is(); + return xRet; } sal_Bool SAL_CALL diff --git a/sw/source/core/unocore/unoparagraph.cxx b/sw/source/core/unocore/unoparagraph.cxx index 68dbe34f55d5..dab5270588e3 100644 --- a/sw/source/core/unocore/unoparagraph.cxx +++ b/sw/source/core/unocore/unoparagraph.cxx @@ -54,6 +54,7 @@ #include <com/sun/star/drawing/BitmapMode.hpp> #include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> #include <comphelper/servicehelper.hxx> #include <editeng/unoipset.hxx> #include <svl/listener.hxx> @@ -550,6 +551,23 @@ uno::Sequence< uno::Any > SwXParagraph::Impl::GetPropertyValues_Impl( continue; } + if (pPropertyNames[nProp] == "OOXMLImport_AnchoredShapes") + { + // A hack to provide list of anchored objects fast + // See reanchorObjects in writerfilter/source/dmapper/DomainMapper_Impl.cxx + FrameClientSortList_t aFrames; + CollectFrameAtNode(rTextNode, aFrames, false); // Frames anchored to paragraph + CollectFrameAtNode(rTextNode, aFrames, true); // Frames anchored to character + std::vector<uno::Reference<text::XTextContent>> aRet; + aRet.reserve(aFrames.size()); + for (const auto& rFrame : aFrames) + if (auto xContent = FrameClientToXTextContent(rFrame.pFrameClient.get())) + aRet.push_back(xContent); + + pValues[nProp] <<= comphelper::containerToSequence(aRet); + continue; + } + SfxItemPropertyMapEntry const*const pEntry = rMap.getByName( pPropertyNames[nProp] ); if (!pEntry) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 57a9f3bc5223..0ae745eec97a 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -750,6 +750,59 @@ void DomainMapper_Impl::AddDummyParaForTableInSection() return sName; } +static void reanchorObjects(const uno::Reference<uno::XInterface>& xFrom, + const uno::Reference<text::XTextRange>& xTo, + const uno::Reference<drawing::XDrawPage>& xDrawPage) +{ + std::vector<uno::Reference<text::XTextContent>> aShapes; + bool bFastPathDone = false; + if (uno::Reference<beans::XPropertySet> xProps{ xFrom, uno::UNO_QUERY }) + { + try + { + // See SwXParagraph::Impl::GetPropertyValues_Impl + uno::Sequence<uno::Reference<text::XTextContent>> aSeq; + xProps->getPropertyValue(u"OOXMLImport_AnchoredShapes"_ustr) >>= aSeq; + aShapes.insert(aShapes.end(), aSeq.begin(), aSeq.end()); + bFastPathDone = true; + } + catch (const uno::Exception&) + { + } + } + + if (!bFastPathDone) + { + // Can this happen? Fallback to slow DrawPage iteration and range comparison + uno::Reference<text::XTextRange> xRange(xFrom, uno::UNO_QUERY_THROW); + uno::Reference<text::XTextRangeCompare> xCompare(xRange->getText(), uno::UNO_QUERY_THROW); + + const sal_Int32 count = xDrawPage->getCount(); + for (sal_Int32 i = 0; i < count; ++i) + { + try + { + uno::Reference<text::XTextContent> xShape(xDrawPage->getByIndex(i), + uno::UNO_QUERY_THROW); + uno::Reference<text::XTextRange> xAnchor(xShape->getAnchor(), uno::UNO_SET_THROW); + if (xCompare->compareRegionStarts(xAnchor, xRange) <= 0 + && xCompare->compareRegionEnds(xAnchor, xRange) >= 0) + { + aShapes.push_back(xShape); + } + } + catch (const uno::Exception&) + { + // Can happen e.g. in compareRegion*, when the shape is in a header, + // and paragraph in body + } + } + } + + for (const auto& xShape : aShapes) + xShape->attach(xTo); +} + void DomainMapper_Impl::RemoveLastParagraph( ) { if (m_bDiscardHeaderFooter) @@ -828,31 +881,7 @@ void DomainMapper_Impl::RemoveLastParagraph( ) auto xEnumeration = xEA->createEnumeration(); uno::Reference<text::XTextRange> xPrevParagraph(xEnumeration->nextElement(), uno::UNO_QUERY_THROW); - - uno::Reference<text::XTextRange> xParaRange(xParagraph, uno::UNO_QUERY_THROW); - uno::Reference<text::XTextRangeCompare> xRegionCompare(xParaRange->getText(), - uno::UNO_QUERY_THROW); - const sal_Int32 count = xDrawPage->getCount(); - for (sal_Int32 i = 0; i < count; ++i) - { - try - { - uno::Reference<text::XTextContent> xShape(xDrawPage->getByIndex(i), - uno::UNO_QUERY_THROW); - uno::Reference<text::XTextRange> xAnchor(xShape->getAnchor(), - uno::UNO_SET_THROW); - if (xRegionCompare->compareRegionStarts(xAnchor, xParaRange) <= 0 - && xRegionCompare->compareRegionEnds(xAnchor, xParaRange) >= 0) - { - xShape->attach(xPrevParagraph); - } - } - catch (const uno::Exception&) - { - // Can happen e.g. in compareRegion*, when the shape is in a header, - // and paragraph in body - } - } + reanchorObjects(xParagraph, xPrevParagraph, xDrawPage); } xParagraph->dispose(); |