summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorAttila Bakos (NISZ) <bakos.attilakaroly@nisz.hu>2021-11-11 14:02:12 +0100
committerLászló Németh <nemeth@numbertext.org>2022-01-06 10:41:32 +0100
commit121cbc250b36290f0f8c7265fea57256dad69553 (patch)
tree6ecc1d2c1b9905a1a8a8899cdf6343734d0d1483 /writerfilter
parent470d1be4ec5a3a5a0aba8febda06600ea39852c5 (diff)
tdf#66039 DOCX: import textboxes (with tables, images etc.) in group shapes
Text boxes in group shapes were imported as shapes, losing complex text content: tables (tdf#66039), colors (tdf#73022), images (tdf#81958), lists, paragraph styles, hyperlinks (tdf#122960) and track changes. Note: a few unit tests have been deactivated temporarily. Test document "groupshape-trackedchanges.docx" of testGroupshapeTrackedchanges is imported correctly now: with track changes, and the test was modified accordingly. Follow-up to commit 2951cbdf3a6e2b62461665546b47e1d253fcb834 "tdf#143574 OOXML export/import of textboxes in group shapes". Change-Id: I6eb918dbf64393fd723fe43f798f93b5b9a12575 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125051 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/inc/dmapper/resourcemodel.hxx7
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx11
-rw-r--r--writerfilter/source/dmapper/DomainMapper.hxx3
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx69
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx10
-rw-r--r--writerfilter/source/dmapper/FontTable.hxx2
-rw-r--r--writerfilter/source/dmapper/GraphicImport.hxx2
-rw-r--r--writerfilter/source/dmapper/LoggedResources.cxx4
-rw-r--r--writerfilter/source/dmapper/LoggedResources.hxx4
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx23
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.hxx1
11 files changed, 133 insertions, 3 deletions
diff --git a/writerfilter/inc/dmapper/resourcemodel.hxx b/writerfilter/inc/dmapper/resourcemodel.hxx
index 65682d78e381..91fda417c2d9 100644
--- a/writerfilter/inc/dmapper/resourcemodel.hxx
+++ b/writerfilter/inc/dmapper/resourcemodel.hxx
@@ -239,6 +239,13 @@ public:
virtual void endShape() = 0;
/**
+ Receives a text-box-content.
+ */
+ virtual void startTextBoxContent() = 0;
+
+ virtual void endTextBoxContent() = 0;
+
+ /**
Receives 8-bit per character text.
@param data buffer containing the text
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 43d134b23805..e8b5a3f40e5b 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3245,6 +3245,7 @@ void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape)
{
assert(xShape.is());
+ m_pImpl->AttachTextBoxContentToShape(xShape);
if (m_pImpl->GetTopContext())
{
// If there is a deferred page break, handle it now, so that the
@@ -3292,6 +3293,16 @@ void DomainMapper::lcl_endShape( )
m_pImpl->SetIsOutsideAParagraph(false);
}
+void DomainMapper::lcl_startTextBoxContent()
+{
+ m_pImpl->PushTextBoxContent();
+}
+
+void DomainMapper::lcl_endTextBoxContent()
+{
+ m_pImpl->PopTextBoxContent();
+}
+
void DomainMapper::PushStyleSheetProperties( const PropertyMapPtr& pStyleProperties, bool bAffectTableMngr )
{
m_pImpl->PushStyleProperties( pStyleProperties );
diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx
index c0134866537c..07d089e22348 100644
--- a/writerfilter/source/dmapper/DomainMapper.hxx
+++ b/writerfilter/source/dmapper/DomainMapper.hxx
@@ -149,7 +149,8 @@ private:
virtual void lcl_endCharacterGroup() override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
virtual void lcl_endShape( ) override;
-
+ virtual void lcl_startTextBoxContent() override;
+ virtual void lcl_endTextBoxContent() override;
virtual void lcl_text(const sal_uInt8 * data, size_t len) override;
virtual void lcl_utext(const sal_uInt8 * data, size_t len) override;
virtual void lcl_positionOffset(const OUString& rText, bool bVertical) override;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 2857d113a913..57ffccbac8f6 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -333,6 +333,7 @@ DomainMapper_Impl::DomainMapper_Impl(
m_aSmartTagHandler(m_xComponentContext, m_xTextDocument),
m_xInsertTextRange(rMediaDesc.getUnpackedValueOrDefault("TextInsertModeRange", uno::Reference<text::XTextRange>())),
m_xAltChunkStartingRange(rMediaDesc.getUnpackedValueOrDefault("AltChunkStartingRange", uno::Reference<text::XTextRange>())),
+ m_bIsInTextBox(false),
m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
m_bIsAltChunk(rMediaDesc.getUnpackedValueOrDefault("AltChunkMode", false)),
m_bIsReadGlossaries(rMediaDesc.getUnpackedValueOrDefault("ReadGlossaries", false)),
@@ -3468,7 +3469,8 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape
{
try
{
- uno::Reference<beans::XPropertySet> xSyncedPropertySet(xShapes->getByIndex(i), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextRange> xFrame(xShapes->getByIndex(i), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xSyncedPropertySet(xFrame, uno::UNO_QUERY_THROW);
comphelper::SequenceAsHashMap aGrabBag( xSyncedPropertySet->getPropertyValue("CharInteropGrabBag") );
// only VML import has checked for style. Don't apply default parastyle properties to other imported shapes
@@ -4408,6 +4410,71 @@ void DomainMapper_Impl::ChainTextFrames()
}
}
+void DomainMapper_Impl::PushTextBoxContent()
+{
+ if (m_bIsInTextBox)
+ return;
+
+ try
+ {
+ uno::Reference<text::XTextFrame> xTBoxFrame(
+ m_xTextFactory->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY_THROW);
+ uno::Reference<container::XNamed>(xTBoxFrame, uno::UNO_QUERY_THROW)
+ ->setName("textbox" + OUString::number(m_xPendingTextBoxFrames.size() + 1));
+ uno::Reference<text::XTextAppendAndConvert>(m_aTextAppendStack.top().xTextAppend,
+ uno::UNO_QUERY_THROW)
+ ->appendTextContent(xTBoxFrame, beans::PropertyValues());
+ m_xPendingTextBoxFrames.push(xTBoxFrame);
+
+ m_aTextAppendStack.push(TextAppendContext(uno::Reference<text::XTextAppend>(xTBoxFrame, uno::UNO_QUERY_THROW), {}));
+ m_bIsInTextBox = true;
+
+ appendTableManager();
+ appendTableHandler();
+ getTableManager().startLevel();
+ }
+ catch (uno::Exception& e)
+ {
+ SAL_WARN("writerfilter.dmapper", "Exception during creating textbox (" + e.Message + ")!");
+ }
+}
+
+void DomainMapper_Impl::PopTextBoxContent()
+{
+ if (!m_bIsInTextBox || m_xPendingTextBoxFrames.empty())
+ return;
+
+ if (uno::Reference<text::XTextFrame>(m_aTextAppendStack.top().xTextAppend, uno::UNO_QUERY).is())
+ {
+ if (hasTableManager())
+ {
+ getTableManager().endLevel();
+ popTableManager();
+ }
+ m_aTextAppendStack.pop();
+ m_bIsInTextBox = false;
+ }
+}
+
+void DomainMapper_Impl::AttachTextBoxContentToShape(css::uno::Reference<css::drawing::XShape> xShape)
+{
+ if (m_xPendingTextBoxFrames.empty() || !xShape)
+ return;
+
+ uno::Reference< drawing::XShapes >xGroup(xShape, uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet >xProps(xShape, uno::UNO_QUERY);
+
+ if (xGroup)
+ for (sal_Int32 i = 0; i < xGroup->getCount(); ++i)
+ AttachTextBoxContentToShape(uno::Reference<drawing::XShape>(xGroup->getByIndex(i),uno::UNO_QUERY_THROW));
+
+ if (xProps->getPropertyValue("TextBox").get<bool>())
+ {
+ xProps->setPropertyValue("TextBoxContent", uno::Any(m_xPendingTextBoxFrames.front()));
+ m_xPendingTextBoxFrames.pop();
+ }
+}
+
uno::Reference<beans::XPropertySet> DomainMapper_Impl::FindOrCreateFieldMaster(const char* pFieldMasterService, const OUString& rFieldMasterName)
{
// query master, create if not available
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index ae267c5c390e..7238d129f766 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -22,6 +22,7 @@
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/text/XTextCursor.hpp>
#include <com/sun/star/text/XTextAppend.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/style/TabStop.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/embed/XStorage.hpp>
@@ -62,6 +63,7 @@ namespace com::sun::star{
namespace text
{
class XTextField;
+ class XTextFrame;
class XFormField;
}
namespace beans{ class XPropertySet;}
@@ -618,9 +620,13 @@ private:
css::uno::Reference<css::text::XTextRange> m_xGlossaryEntryStart;
css::uno::Reference<css::text::XTextRange> m_xSdtEntryStart;
+ std::queue< css::uno::Reference< css::text::XTextFrame > > m_xPendingTextBoxFrames;
+
public:
css::uno::Reference<css::text::XTextRange> m_xInsertTextRange;
css::uno::Reference<css::text::XTextRange> m_xAltChunkStartingRange;
+
+ bool m_bIsInTextBox;
private:
bool m_bIsNewDoc;
bool m_bIsAltChunk = false;
@@ -667,6 +673,10 @@ public:
void EndParaMarkerChange( );
void ChainTextFrames();
+ void PushTextBoxContent();
+ void PopTextBoxContent();
+ void AttachTextBoxContentToShape(css::uno::Reference<css::drawing::XShape> xShape);
+
void RemoveDummyParaForTableInSection();
void AddDummyParaForTableInSection();
void RemoveLastParagraph( );
diff --git a/writerfilter/source/dmapper/FontTable.hxx b/writerfilter/source/dmapper/FontTable.hxx
index ff4d11fba83e..5f32776a2819 100644
--- a/writerfilter/source/dmapper/FontTable.hxx
+++ b/writerfilter/source/dmapper/FontTable.hxx
@@ -80,6 +80,8 @@ class FontTable : public LoggedProperties, public LoggedTable
::writerfilter::Reference<Stream>::Pointer_t ref) override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
virtual void lcl_endShape( ) override;
+ virtual void lcl_startTextBoxContent() override {};
+ virtual void lcl_endTextBoxContent() override {};
};
typedef tools::SvRef< FontTable > FontTablePtr;
diff --git a/writerfilter/source/dmapper/GraphicImport.hxx b/writerfilter/source/dmapper/GraphicImport.hxx
index 7ca4e09ed30d..57c3dbef906a 100644
--- a/writerfilter/source/dmapper/GraphicImport.hxx
+++ b/writerfilter/source/dmapper/GraphicImport.hxx
@@ -122,6 +122,8 @@ public:
writerfilter::Reference<Table>::Pointer_t ref) override;
virtual void lcl_substream(Id name, writerfilter::Reference<Stream>::Pointer_t ref) override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
+ virtual void lcl_startTextBoxContent() override {};
+ virtual void lcl_endTextBoxContent() override {};
virtual void lcl_endShape() override;
void handleWrapTextValue(sal_uInt32 nVal);
diff --git a/writerfilter/source/dmapper/LoggedResources.cxx b/writerfilter/source/dmapper/LoggedResources.cxx
index 4a0886e44812..661bf17cd1e8 100644
--- a/writerfilter/source/dmapper/LoggedResources.cxx
+++ b/writerfilter/source/dmapper/LoggedResources.cxx
@@ -147,6 +147,10 @@ void LoggedStream::endShape()
#endif
}
+void LoggedStream::startTextBoxContent() { lcl_startTextBoxContent(); }
+
+void LoggedStream::endTextBoxContent() { lcl_endTextBoxContent(); }
+
void LoggedStream::text(const sal_uInt8* data, size_t len)
{
#ifdef DBG_UTIL
diff --git a/writerfilter/source/dmapper/LoggedResources.hxx b/writerfilter/source/dmapper/LoggedResources.hxx
index 74b7b0b2c9a5..cecf64c91b23 100644
--- a/writerfilter/source/dmapper/LoggedResources.hxx
+++ b/writerfilter/source/dmapper/LoggedResources.hxx
@@ -60,6 +60,8 @@ public:
void endCharacterGroup() override;
void startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
void endShape() override;
+ void startTextBoxContent() override;
+ void endTextBoxContent() override;
void text(const sal_uInt8* data, size_t len) override;
void utext(const sal_uInt8* data, size_t len) override;
void positionOffset(const OUString& rText, bool bVertical) override;
@@ -83,6 +85,8 @@ protected:
virtual void lcl_endCharacterGroup() = 0;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) = 0;
virtual void lcl_endShape() = 0;
+ virtual void lcl_startTextBoxContent() = 0;
+ virtual void lcl_endTextBoxContent() = 0;
virtual void lcl_text(const sal_uInt8* data, size_t len) = 0;
virtual void lcl_utext(const sal_uInt8* data, size_t len) = 0;
virtual void lcl_positionOffset(const OUString& /*rText*/, bool /*bVertical*/) {}
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index a4b592c66066..e245e37b4772 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -1759,6 +1759,12 @@ void OOXMLFastContextHandlerShape::sendShape( Token_t Element )
}
}
+bool OOXMLFastContextHandlerShape::isDMLGroupShape() const
+{
+ return (mrShapeContext->getFullWPGSupport() &&
+ (mrShapeContext->getStartToken() == Token_t(oox::NMSP_wpg | oox::XML_wgp)));
+};
+
void OOXMLFastContextHandlerShape::lcl_endFastElement
(Token_t Element)
{
@@ -1805,7 +1811,8 @@ OOXMLFastContextHandlerShape::lcl_createFastChildContext
bool bGroupShape = Element == Token_t(NMSP_vml | XML_group);
// drawingML version also counts as a group shape.
- bGroupShape |= mrShapeContext->getStartToken() == Token_t(NMSP_wpg | XML_wgp);
+ if (!mrShapeContext->getFullWPGSupport())
+ bGroupShape |= mrShapeContext->getStartToken() == Token_t(NMSP_wpg | XML_wgp);
mbIsVMLfound = (getNamespace(Element) == NMSP_vmlOffice) || (getNamespace(Element) == NMSP_vml);
switch (oox::getNamespace(Element))
{
@@ -1969,6 +1976,13 @@ void OOXMLFastContextHandlerWrapper::lcl_startFastElement
{
if (mxWrappedContext.is())
mxWrappedContext->startFastElement(Element, Attribs);
+
+ if (mxShapeHandler->isDMLGroupShape()
+ && (Element == Token_t(NMSP_wps | XML_txbx)
+ || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
+ {
+ mpStream->startTextBoxContent();
+ }
}
void OOXMLFastContextHandlerWrapper::lcl_endFastElement
@@ -1976,6 +1990,13 @@ void OOXMLFastContextHandlerWrapper::lcl_endFastElement
{
if (mxWrappedContext.is())
mxWrappedContext->endFastElement(Element);
+
+ if (mxShapeHandler->isDMLGroupShape()
+ && (Element == Token_t(NMSP_wps | XML_txbx)
+ || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
+ {
+ mpStream->endTextBoxContent();
+ }
}
uno::Reference< xml::sax::XFastContextHandler >
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
index 0b79f9450afa..b64a87e6f18c 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
@@ -467,6 +467,7 @@ public:
void sendShape( Token_t Element );
bool isShapeSent( ) const { return m_bShapeSent; }
+ bool isDMLGroupShape() const;
protected:
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override;