[Libreoffice-commits] core.git: include/oox oox/source sc/source sd/qa
GülÅah Köse (via logerrit)
logerrit at kemper.freedesktop.org
Thu Jul 8 21:12:43 UTC 2021
include/oox/core/contexthandler2.hxx | 19 +++++
include/oox/core/fragmenthandler2.hxx | 11 ---
include/oox/drawingml/graphicshapecontext.hxx | 1
include/oox/ole/oleobjecthelper.hxx | 1
oox/source/core/contexthandler2.cxx | 85 +++++++++++++++++++++++++-
oox/source/core/fragmenthandler2.cxx | 70 ---------------------
oox/source/drawingml/graphicshapecontext.cxx | 11 +++
sc/source/filter/oox/worksheetfragment.cxx | 6 -
sd/qa/unit/data/pptx/tdf143222.pptx |binary
sd/qa/unit/export-tests-ooxml3.cxx | 30 +++++++++
10 files changed, 148 insertions(+), 86 deletions(-)
New commits:
commit 92a407b7f90a98704a238c5ffa3a3491eaf3263a
Author: Gülşah Köse <gulsah.kose at collabora.com>
AuthorDate: Wed Jul 7 00:27:58 2021 +0300
Commit: Gülşah Köse <gulsah.kose at collabora.com>
CommitDate: Thu Jul 8 23:12:07 2021 +0200
tdf143222 Handle alternate content of graphicData element.
Handle alternate content and make true choice.
According to ooxml spec ole object requires exactly one pic
element. (ECMA-376 Part 1, Annex A, CT_OleObject). In the
current case first choice has not pic element and we should
allow fallback processing.
Change-Id: I30b7de703b8c2f00d6bf286e05eea505ac3627f2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118539
Tested-by: Jenkins
Reviewed-by: Gülşah Köse <gulsah.kose at collabora.com>
diff --git a/include/oox/core/contexthandler2.hxx b/include/oox/core/contexthandler2.hxx
index 4e256089ac8e..3a75aff5706a 100644
--- a/include/oox/core/contexthandler2.hxx
+++ b/include/oox/core/contexthandler2.hxx
@@ -72,7 +72,7 @@ struct ElementInfo;
class OOX_DLLPUBLIC ContextHandler2Helper
{
public:
- explicit ContextHandler2Helper( bool bEnableTrimSpace );
+ explicit ContextHandler2Helper( bool bEnableTrimSpace, XmlFilterBase& rFilter );
explicit ContextHandler2Helper( const ContextHandler2Helper& rParent );
virtual ~ContextHandler2Helper();
@@ -201,6 +201,21 @@ protected:
/** Must be called from endRecord() in derived classes. */
void implEndRecord( sal_Int32 nRecId );
+ bool prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs );
+ XmlFilterBase& getDocFilter() const { return mrFilter; }
+
+ enum class MCE_STATE
+ {
+ Started,
+ FoundChoice
+ };
+
+ MCE_STATE getMCEState() const { return aMceState.back(); }
+ void setMCEState( MCE_STATE aState ) { aMceState.back() = aState; }
+ void addMCEState( MCE_STATE aState ) { aMceState.push_back( aState ); }
+ void removeMCEState() { aMceState.pop_back(); }
+ bool isMCEStateEmpty() { return aMceState.empty(); }
+
private:
ContextHandler2Helper& operator=( const ContextHandler2Helper& ) = delete;
@@ -214,9 +229,11 @@ private:
ContextStackRef mxContextStack; ///< Stack of all processed elements.
size_t mnRootStackSize; ///< Stack size on construction time.
+ std::vector<MCE_STATE> aMceState;
protected:
bool mbEnableTrimSpace; ///< True = trim whitespace in characters().
+ XmlFilterBase& mrFilter;
};
class OOX_DLLPUBLIC ContextHandler2 : public ContextHandler, public ContextHandler2Helper
diff --git a/include/oox/core/fragmenthandler2.hxx b/include/oox/core/fragmenthandler2.hxx
index 86d1453f13a1..598426ee681e 100644
--- a/include/oox/core/fragmenthandler2.hxx
+++ b/include/oox/core/fragmenthandler2.hxx
@@ -47,17 +47,6 @@ class XmlFilterBase;
class OOX_DLLPUBLIC FragmentHandler2 : public FragmentHandler, public ContextHandler2Helper
{
-protected:
- enum class MCE_STATE
- {
- Started,
- FoundChoice
- };
- ::std::vector<MCE_STATE> aMceState;
-
- bool prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs );
-
-
public:
explicit FragmentHandler2(
XmlFilterBase& rFilter,
diff --git a/include/oox/drawingml/graphicshapecontext.hxx b/include/oox/drawingml/graphicshapecontext.hxx
index 4813d5fc9aed..ffd579f00bb1 100644
--- a/include/oox/drawingml/graphicshapecontext.hxx
+++ b/include/oox/drawingml/graphicshapecontext.hxx
@@ -62,6 +62,7 @@ public:
OleObjectGraphicDataContext( ::oox::core::ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr );
virtual ~OleObjectGraphicDataContext() override;
virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) override;
+ virtual void onEndElement() override;
private:
::oox::vml::OleObjectInfo& mrOleObjectInfo;
diff --git a/include/oox/ole/oleobjecthelper.hxx b/include/oox/ole/oleobjecthelper.hxx
index d2506f3d4949..5b792f2048b1 100644
--- a/include/oox/ole/oleobjecthelper.hxx
+++ b/include/oox/ole/oleobjecthelper.hxx
@@ -47,6 +47,7 @@ struct OleObjectInfo
bool mbLinked; ///< True = linked OLE object, false = embedded OLE object.
bool mbShowAsIcon; ///< True = show as icon, false = show contents.
bool mbAutoUpdate;
+ bool mbHasPicture; ///<Ole object requires a picture element according to spec.>
explicit OleObjectInfo();
};
diff --git a/oox/source/core/contexthandler2.cxx b/oox/source/core/contexthandler2.cxx
index 8ce9784b99ef..1613a3d330cc 100644
--- a/oox/source/core/contexthandler2.cxx
+++ b/oox/source/core/contexthandler2.cxx
@@ -18,16 +18,20 @@
*/
#include <oox/core/contexthandler2.hxx>
+#include <oox/core/xmlfilterbase.hxx>
#include <oox/helper/attributelist.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/token/tokens.hxx>
#include <rtl/ustrbuf.hxx>
#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
namespace oox::core {
using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::xml::sax;
/** Information about a processed element. */
@@ -40,10 +44,11 @@ struct ElementInfo
explicit ElementInfo() : maChars( 0), mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {}
};
-ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
+ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace, XmlFilterBase& rFilter ) :
mxContextStack( std::make_shared<ContextStack>() ),
mnRootStackSize( 0 ),
- mbEnableTrimSpace( bEnableTrimSpace )
+ mbEnableTrimSpace( bEnableTrimSpace ),
+ mrFilter( rFilter )
{
pushElementInfo( XML_ROOT_CONTEXT );
}
@@ -51,7 +56,8 @@ ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) :
mxContextStack( rParent.mxContextStack ),
mnRootStackSize( rParent.mxContextStack->size() ),
- mbEnableTrimSpace( rParent.mbEnableTrimSpace )
+ mbEnableTrimSpace( rParent.mbEnableTrimSpace ),
+ mrFilter(rParent.mrFilter)
{
}
@@ -188,6 +194,13 @@ ContextHandler2::~ContextHandler2()
Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext(
sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
{
+ if( getNamespace( nElement ) == NMSP_mce ) // TODO for checking 'Ignorable'
+ {
+ if( prepareMceContext( nElement, AttributeList( rxAttribs ) ) )
+ return this;
+ return nullptr;
+ }
+
return implCreateChildContext( nElement, rxAttribs );
}
@@ -207,6 +220,72 @@ void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement )
implEndElement( nElement );
}
+bool ContextHandler2Helper::prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs )
+{
+ switch( nElement )
+ {
+ case MCE_TOKEN( AlternateContent ):
+ addMCEState( MCE_STATE::Started );
+ break;
+
+ case MCE_TOKEN( Choice ):
+ {
+ if (isMCEStateEmpty() || getMCEState() != MCE_STATE::Started)
+ return false;
+
+ OUString aRequires = rAttribs.getString( XML_Requires, "none" );
+
+ // At this point we can't access namespaces as the correct xml filter
+ // is long gone. For now let's decide depending on a list of supported
+ // namespaces like we do in writerfilter
+
+ std::vector<OUString> aSupportedNS =
+ {
+ "a14", // Impress needs this to import math formulas.
+ "p14",
+ "p15",
+ "x12ac",
+ "v"
+ };
+
+ Reference<XServiceInfo> xModel(getDocFilter().getModel(), UNO_QUERY);
+ if (xModel.is() && xModel->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
+ {
+ // No a14 for Calc documents, it would cause duplicated shapes as-is.
+ auto it = std::find(aSupportedNS.begin(), aSupportedNS.end(), "a14");
+ if (it != aSupportedNS.end())
+ {
+ aSupportedNS.erase(it);
+ }
+ }
+
+ if (std::find(aSupportedNS.begin(), aSupportedNS.end(), aRequires) != aSupportedNS.end())
+ setMCEState( MCE_STATE::FoundChoice ) ;
+ else
+ return false;
+ }
+ break;
+
+ case MCE_TOKEN( Fallback ):
+ if( !isMCEStateEmpty() && getMCEState() == MCE_STATE::Started )
+ break;
+ return false;
+ default:
+ {
+ OUString str = rAttribs.getString( MCE_TOKEN( Ignorable ), OUString() );
+ if( !str.isEmpty() )
+ {
+ // Sequence< css::xml::FastAttribute > attrs = rAttribs.getFastAttributeList()->getFastAttributes();
+ // printf("MCE: %s\n", OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ // TODO: Check & Get the namespaces in "Ignorable"
+ // printf("NS: %d : %s\n", attrs.getLength(), OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ return false;
+ }
+ return true;
+}
+
// oox.core.RecordContext interface -------------------------------------------
ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
diff --git a/oox/source/core/fragmenthandler2.cxx b/oox/source/core/fragmenthandler2.cxx
index 121f3443731f..3ee410fad854 100644
--- a/oox/source/core/fragmenthandler2.cxx
+++ b/oox/source/core/fragmenthandler2.cxx
@@ -34,7 +34,7 @@ using namespace ::com::sun::star::xml::sax;
FragmentHandler2::FragmentHandler2( XmlFilterBase& rFilter, const OUString& rFragmentPath, bool bEnableTrimSpace ) :
FragmentHandler( rFilter, rFragmentPath ),
- ContextHandler2Helper( bEnableTrimSpace )
+ ContextHandler2Helper( bEnableTrimSpace, rFilter )
{
}
@@ -54,72 +54,6 @@ void SAL_CALL FragmentHandler2::endDocument()
finalizeImport();
}
-bool FragmentHandler2::prepareMceContext( sal_Int32 nElement, const AttributeList& rAttribs )
-{
- switch( nElement )
- {
- case MCE_TOKEN( AlternateContent ):
- aMceState.push_back( MCE_STATE::Started );
- break;
-
- case MCE_TOKEN( Choice ):
- {
- if (aMceState.empty() || aMceState.back() != MCE_STATE::Started)
- return false;
-
- OUString aRequires = rAttribs.getString( XML_Requires, "none" );
-
- // At this point we can't access namespaces as the correct xml filter
- // is long gone. For now let's decide depending on a list of supported
- // namespaces like we do in writerfilter
-
- std::vector<OUString> aSupportedNS =
- {
- "a14", // Impress needs this to import math formulas.
- "p14",
- "p15",
- "x12ac",
- "v",
- };
-
- uno::Reference<lang::XServiceInfo> xModel(getFilter().getModel(), uno::UNO_QUERY);
- if (xModel.is() && xModel->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
- {
- // No a14 for Calc documents, it would cause duplicated shapes as-is.
- auto it = std::find(aSupportedNS.begin(), aSupportedNS.end(), "a14");
- if (it != aSupportedNS.end())
- {
- aSupportedNS.erase(it);
- }
- }
-
- if (std::find(aSupportedNS.begin(), aSupportedNS.end(), aRequires) != aSupportedNS.end())
- aMceState.back() = MCE_STATE::FoundChoice;
- else
- return false;
- }
- break;
-
- case MCE_TOKEN( Fallback ):
- if( !aMceState.empty() && aMceState.back() == MCE_STATE::Started )
- break;
- return false;
- default:
- {
- OUString str = rAttribs.getString( MCE_TOKEN( Ignorable ), OUString() );
- if( !str.isEmpty() )
- {
- // Sequence< css::xml::FastAttribute > attrs = rAttribs.getFastAttributeList()->getFastAttributes();
- // printf("MCE: %s\n", OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
- // TODO: Check & Get the namespaces in "Ignorable"
- // printf("NS: %d : %s\n", attrs.getLength(), OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
- }
- }
- return false;
- }
- return true;
-}
-
// com.sun.star.xml.sax.XFastContextHandler interface -------------------------
Reference< XFastContextHandler > SAL_CALL FragmentHandler2::createFastChildContext(
@@ -151,7 +85,7 @@ void SAL_CALL FragmentHandler2::endFastElement( sal_Int32 nElement )
switch( nElement )
{
case MCE_TOKEN( AlternateContent ):
- aMceState.pop_back();
+ removeMCEState();
break;
}
diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx
index 113e5490c51d..3ed00edfd28c 100644
--- a/oox/source/drawingml/graphicshapecontext.cxx
+++ b/oox/source/drawingml/graphicshapecontext.cxx
@@ -214,6 +214,7 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
mrOleObjectInfo.maName = rAttribs.getXString( XML_name, OUString() );
mrOleObjectInfo.maProgId = rAttribs.getXString( XML_progId, OUString() );
mrOleObjectInfo.mbShowAsIcon = rAttribs.getBool( XML_showAsIcon, false );
+ mrOleObjectInfo.mbHasPicture = false; // Initialize as false
return this;
}
break;
@@ -227,6 +228,7 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
mrOleObjectInfo.mbAutoUpdate = rAttribs.getBool( XML_updateAutomatic, false );
break;
case PPT_TOKEN( pic ):
+ mrOleObjectInfo.mbHasPicture = true; // Set true if ole object has picture element.
return new GraphicShapeContext( *this, mpMasterShapePtr, mpShapePtr );
}
SAL_WARN("oox", "OleObjectGraphicDataContext::onCreateContext: unhandled element: "
@@ -234,6 +236,15 @@ ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nEleme
return nullptr;
}
+void OleObjectGraphicDataContext::onEndElement()
+{
+ if( getCurrentElement() == PPT_TOKEN( oleObj ) && !isMCEStateEmpty() )
+ {
+ if( getMCEState() == MCE_STATE::FoundChoice && !mrOleObjectInfo.mbHasPicture )
+ setMCEState( MCE_STATE::Started );
+ }
+}
+
DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr )
: ShapeContext( rParent, ShapePtr(), pShapePtr )
{
diff --git a/sc/source/filter/oox/worksheetfragment.cxx b/sc/source/filter/oox/worksheetfragment.cxx
index 20e802d96224..a0e01c915dcf 100644
--- a/sc/source/filter/oox/worksheetfragment.cxx
+++ b/sc/source/filter/oox/worksheetfragment.cxx
@@ -466,17 +466,17 @@ ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const
case XLS_TOKEN( oleObjects ):
if ( getCurrentElement() == XLS_TOKEN( controls ) )
{
- if( aMceState.empty() || aMceState.back() == MCE_STATE::Started )
+ if( isMCEStateEmpty() || getMCEState() == MCE_STATE::Started )
{
if ( getCurrentElement() == XLS_TOKEN( oleObjects ) ) importOleObject( rAttribs );
else
importControl( rAttribs );
}
- else if ( !aMceState.empty() && aMceState.back() == MCE_STATE::FoundChoice )
+ else if ( !isMCEStateEmpty() && getMCEState() == MCE_STATE::FoundChoice )
{
// reset the handling within 'Choice'
// this will force attempted handling in Fallback
- aMceState.back() = MCE_STATE::Started;
+ setMCEState( MCE_STATE::Started );
}
}
break;
diff --git a/sd/qa/unit/data/pptx/tdf143222.pptx b/sd/qa/unit/data/pptx/tdf143222.pptx
new file mode 100644
index 000000000000..63938d1bdc71
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf143222.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx
index 6632934e430e..f773c364f395 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -22,6 +22,7 @@
#include <svx/svdotable.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlndsit.hxx>
+#include <svx/svdoole2.hxx>
#include <rtl/ustring.hxx>
#include <com/sun/star/drawing/XDrawPage.hpp>
@@ -116,6 +117,7 @@ public:
void testTdf125560_textDeflate();
void testTdf125560_textInflateTop();
void testTdf96061_textHighlight();
+ void testTdf143222_embeddedWorksheet();
void testTdf142235_TestPlaceholderTextAlignment();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest3);
@@ -185,6 +187,7 @@ public:
CPPUNIT_TEST(testTdf125560_textDeflate);
CPPUNIT_TEST(testTdf125560_textInflateTop);
CPPUNIT_TEST(testTdf96061_textHighlight);
+ CPPUNIT_TEST(testTdf143222_embeddedWorksheet);
CPPUNIT_TEST(testTdf142235_TestPlaceholderTextAlignment);
CPPUNIT_TEST_SUITE_END();
@@ -1743,6 +1746,33 @@ void SdOOXMLExportTest3::testTdf96061_textHighlight()
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aColor);
}
+void SdOOXMLExportTest3::testTdf143222_embeddedWorksheet()
+{
+ // Check import of embedded worksheet in slide.
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tdf143222.pptx"), PPTX);
+
+ const SdrPage* pPage = GetPage(1, xDocShRef.get());
+ const SdrOle2Obj* pOleObj = static_cast<SdrOle2Obj*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object", pOleObj != nullptr);
+
+ // Without the fix we lost the graphic of ole object.
+ const Graphic* pGraphic = pOleObj->GetGraphic();
+ CPPUNIT_ASSERT_MESSAGE("no graphic", pGraphic != nullptr);
+
+ // Check export of embedded worksheet in slide.
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX);
+
+ pPage = GetPage(1, xDocShRef.get());
+ pOleObj = static_cast<SdrOle2Obj*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object after the export", pOleObj != nullptr);
+
+ pGraphic = pOleObj->GetGraphic();
+ CPPUNIT_ASSERT_MESSAGE("no graphic after the export", pGraphic != nullptr);
+
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest3);
CPPUNIT_PLUGIN_IMPLEMENT();
More information about the Libreoffice-commits
mailing list