Kaydet (Commit) 6f9f9491 authored tarafından Miklos Vajna's avatar Miklos Vajna

tdf#106132 DOCX import: fix handling of nested textbox margins

drawingML shapes are independent, and having a separate parser for each
shape is a good thing, so that when we have an XML fragment like this:

<wps:wsp>
  <wps:txbx>
  ...
  </wps:txbx>
  <wps:bodyPr .../>
</wps:wsp>

where <wps:txbx> may contain nested <wps:wsp> tags, we apply the
properties specified in <wps:bodyPr> to the correct shape.

In contrast, doing the same for VML is not a good idea, see commit
476316bf (do reuse shape context,
2012-05-22).

So conditionally (for DML) maintain a stack of shape parsers, this way
the outer <wps:bodyPr> is parsed and the result is applied to the
correct shape, at the end resulting in correct inner margin for the outer
shape in the bugdoc.

This requires moving the context setup code from
the OOXMLFastContextHandlerShape ctor to setToken(), as only then we
know if this shape context will be used for VML or DML purposes. This
should be OK, given that
writerfilter::ooxml::OOXMLFastHelper::createAndSetParentAndDefine()
calls setToken() right after allocating the context.

Change-Id: I8c0d2f49cac76589fe269230698b203b5ca6996c
Reviewed-on: https://gerrit.libreoffice.org/39798Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
üst 2a226965
......@@ -439,6 +439,13 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx")
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not centered horizontally relatively to right page border", text::RelOrientation::PAGE_RIGHT, nValue);
}
DECLARE_OOXMLEXPORT_TEST(testTdf106132, "tdf106132.docx")
{
uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
// This was 250, <wps:bodyPr ... rIns="0" ...> was ignored for an outer shape.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(xShape, "TextRightDistance"));
}
DECLARE_OOXMLEXPORT_TEST(testBnc519228OddBreaks, "bnc519228_odd-breaksB.docx")
{
// Check that all the normal styles are not set as right-only, those should be only those used after odd page breaks.
......
......@@ -221,6 +221,10 @@ public:
virtual const OUString & getTarget() const = 0;
virtual css::uno::Reference<css::xml::sax::XFastShapeContextHandler> getShapeContext( ) = 0;
virtual void setShapeContext( css::uno::Reference<css::xml::sax::XFastShapeContextHandler> xContext ) = 0;
/// Push context of drawingML shapes, so nested shapes are handled separately.
virtual void pushShapeContext() = 0;
/// Pop context of a previously pushed drawingML shape.
virtual void popShapeContext() = 0;
virtual css::uno::Reference<css::xml::dom::XDocument> getThemeDom( ) = 0;
virtual css::uno::Reference<css::xml::dom::XDocument> getGlossaryDocDom( ) = 0;
virtual css::uno::Sequence<css::uno::Sequence< css::uno::Any> > getGlossaryDomList() = 0;
......
......@@ -65,6 +65,7 @@ OOXMLDocumentImpl::OOXMLDocumentImpl(OOXMLStream::Pointer_t const & pStream, con
, m_rBaseURL(utl::MediaDescriptor(rDescriptor).getUnpackedValueOrDefault("DocumentBaseURL", OUString()))
, maMediaDescriptor(rDescriptor)
{
pushShapeContext();
}
OOXMLDocumentImpl::~OOXMLDocumentImpl()
......@@ -903,12 +904,27 @@ const uno::Sequence<beans::PropertyValue>& OOXMLDocumentImpl::getMediaDescriptor
void OOXMLDocumentImpl::setShapeContext( uno::Reference<xml::sax::XFastShapeContextHandler> xContext )
{
mxShapeContext = xContext;
if (!maShapeContexts.empty())
maShapeContexts.top() = xContext;
}
uno::Reference<xml::sax::XFastShapeContextHandler> OOXMLDocumentImpl::getShapeContext( )
{
return mxShapeContext;
if (!maShapeContexts.empty())
return maShapeContexts.top();
else
return uno::Reference<xml::sax::XFastShapeContextHandler>();
}
void OOXMLDocumentImpl::pushShapeContext()
{
maShapeContexts.push(uno::Reference<xml::sax::XFastShapeContextHandler>());
}
void OOXMLDocumentImpl::popShapeContext()
{
if (!maShapeContexts.empty())
maShapeContexts.pop();
}
uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::getThemeDom( )
......
......@@ -27,6 +27,7 @@
#include "OOXMLPropertySet.hxx"
#include <vector>
#include <stack>
namespace writerfilter {
namespace ooxml
......@@ -42,7 +43,8 @@ class OOXMLDocumentImpl : public OOXMLDocument
css::uno::Reference<css::drawing::XDrawPage> mxDrawPage;
css::uno::Reference<css::xml::dom::XDocument> mxGlossaryDocDom;
css::uno::Sequence < css::uno::Sequence< css::uno::Any > > mxGlossaryDomList;
css::uno::Reference<css::xml::sax::XFastShapeContextHandler> mxShapeContext;
/// Stack of shape contexts, 1 element for VML, 1 element / nesting level for drawingML.
std::stack< css::uno::Reference<css::xml::sax::XFastShapeContextHandler> > maShapeContexts;
css::uno::Reference<css::xml::dom::XDocument> mxThemeDom;
css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > mxCustomXmlDomList;
css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > mxCustomXmlDomPropsList;
......@@ -128,6 +130,8 @@ public:
virtual const OUString & getTarget() const override;
virtual css::uno::Reference<css::xml::sax::XFastShapeContextHandler> getShapeContext( ) override;
virtual void setShapeContext( css::uno::Reference<css::xml::sax::XFastShapeContextHandler> xContext ) override;
void pushShapeContext() override;
void popShapeContext() override;
virtual css::uno::Reference<css::xml::dom::XDocument> getThemeDom() override;
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomList() override;
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomPropsList() override;
......
......@@ -1587,29 +1587,14 @@ void OOXMLFastContextHandlerTextTable::lcl_endFastElement
OOXMLFastContextHandlerShape::OOXMLFastContextHandlerShape
(OOXMLFastContextHandler * pContext)
: OOXMLFastContextHandlerProperties(pContext), m_bShapeSent( false ),
m_bShapeStarted(false)
m_bShapeStarted(false), m_bShapeContextPushed(false)
{
mrShapeContext.set( getDocument( )->getShapeContext( ) );
if ( !mrShapeContext.is( ) )
{
// Define the shape context for the whole document
mrShapeContext = css::xml::sax::FastShapeContextHandler::create(
getComponentContext());
getDocument()->setShapeContext( mrShapeContext );
}
mrShapeContext->setModel(getDocument()->getModel());
uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
mrShapeContext->setDrawPage(getDocument()->getDrawPage());
mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
mrShapeContext->setRelationFragmentPath
(mpParserState->getTarget());
}
OOXMLFastContextHandlerShape::~OOXMLFastContextHandlerShape()
{
if (m_bShapeContextPushed)
getDocument()->popShapeContext();
}
void OOXMLFastContextHandlerShape::lcl_startFastElement
......@@ -1635,6 +1620,30 @@ void SAL_CALL OOXMLFastContextHandlerShape::startUnknownElement
void OOXMLFastContextHandlerShape::setToken(Token_t nToken)
{
if (nToken == Token_t(NMSP_wps | XML_wsp) || nToken == Token_t(NMSP_dmlPicture | XML_pic))
{
// drawingML shapes are independent, <wps:bodyPr> is not parsed after
// shape contents without pushing/popping the stack.
m_bShapeContextPushed = true;
getDocument()->pushShapeContext();
}
mrShapeContext.set(getDocument()->getShapeContext());
if (!mrShapeContext.is())
{
// Define the shape context for the whole document
mrShapeContext = css::xml::sax::FastShapeContextHandler::create(getComponentContext());
getDocument()->setShapeContext(mrShapeContext);
}
mrShapeContext->setModel(getDocument()->getModel());
uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
mrShapeContext->setDrawPage(getDocument()->getDrawPage());
mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
mrShapeContext->setRelationFragmentPath(mpParserState->getTarget());
OOXMLFastContextHandler::setToken(nToken);
if (mrShapeContext.is())
......
......@@ -432,6 +432,8 @@ class OOXMLFastContextHandlerShape: public OOXMLFastContextHandlerProperties
private:
bool m_bShapeSent;
bool m_bShapeStarted;
/// Is it necessary to pop the stack in the dtor?
bool m_bShapeContextPushed;
public:
explicit OOXMLFastContextHandlerShape(OOXMLFastContextHandler * pContext);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment