ooxml: Preserve the original picture in artistic effects
When Word applies an artistic effect, it creates two embedded files; one contains the bitmap with the effect and the other one contains the original bitmap to be able to undo the effect. This patch reads the original bitmap, stores it in the shape grab bag and saves it back to the docx file. Added unit tests too. TODO: right now, if two effects point to the same original bitmap it is stored twice, we should improve this. Change-Id: Ia72034a257739abe4ffafa0f42b2a912e4bf9436
This commit is contained in:
parent
642a252cf1
commit
2e68a1468c
@ -26,6 +26,7 @@
|
|||||||
#include <oox/drawingml/color.hxx>
|
#include <oox/drawingml/color.hxx>
|
||||||
#include <oox/helper/helper.hxx>
|
#include <oox/helper/helper.hxx>
|
||||||
#include <oox/drawingml/embeddedwavaudiofile.hxx>
|
#include <oox/drawingml/embeddedwavaudiofile.hxx>
|
||||||
|
#include <oox/ole/oleobjecthelper.hxx>
|
||||||
|
|
||||||
namespace oox {
|
namespace oox {
|
||||||
class GraphicHelper;
|
class GraphicHelper;
|
||||||
@ -70,6 +71,7 @@ struct ArtisticEffectProperties
|
|||||||
OUString msName;
|
OUString msName;
|
||||||
std::map< OUString, css::uno::Any >
|
std::map< OUString, css::uno::Any >
|
||||||
maAttribs;
|
maAttribs;
|
||||||
|
::oox::ole::OleObjectInfo mrOleObjectInfo; /// The original graphic as embedded object.
|
||||||
|
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static int mnImageCounter;
|
static int mnImageCounter;
|
||||||
|
static int mnWdpImageCounter;
|
||||||
|
|
||||||
/// To specify where write eg. the images to (like 'ppt', or 'word' - according to the OPC).
|
/// To specify where write eg. the images to (like 'ppt', or 'word' - according to the OPC).
|
||||||
DocumentType meDocumentType;
|
DocumentType meDocumentType;
|
||||||
@ -177,6 +178,7 @@ public:
|
|||||||
void WriteShapeEffect( const OUString& sName, const css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
|
void WriteShapeEffect( const OUString& sName, const css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
|
||||||
void WriteShape3DEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
|
void WriteShape3DEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
|
||||||
void WriteArtisticEffect( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
|
void WriteArtisticEffect( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
|
||||||
|
OString WriteWdpPicture( const ::com::sun::star::uno::Sequence< sal_Int8 >& rPictureData );
|
||||||
|
|
||||||
static void ResetCounters();
|
static void ResetCounters();
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ css::beans::PropertyValue ArtisticEffectProperties::getEffect()
|
|||||||
if( msName.isEmpty() )
|
if( msName.isEmpty() )
|
||||||
return pRet;
|
return pRet;
|
||||||
|
|
||||||
css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() );
|
css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() + 1 );
|
||||||
sal_uInt32 i = 0;
|
sal_uInt32 i = 0;
|
||||||
for( std::map< OUString, css::uno::Any >::iterator it = maAttribs.begin(); it != maAttribs.end(); ++it )
|
for( std::map< OUString, css::uno::Any >::iterator it = maAttribs.begin(); it != maAttribs.end(); ++it )
|
||||||
{
|
{
|
||||||
@ -617,6 +617,12 @@ css::beans::PropertyValue ArtisticEffectProperties::getEffect()
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( mrOleObjectInfo.maEmbeddedData.hasElements() )
|
||||||
|
{
|
||||||
|
aSeq[i].Name = "OriginalGraphic";
|
||||||
|
aSeq[i].Value = uno::makeAny( mrOleObjectInfo.maEmbeddedData );
|
||||||
|
}
|
||||||
|
|
||||||
pRet.Name = msName;
|
pRet.Name = msName;
|
||||||
pRet.Value = css::uno::Any( aSeq );
|
pRet.Value = css::uno::Any( aSeq );
|
||||||
|
|
||||||
|
@ -333,9 +333,18 @@ ContextHandlerRef ArtisticEffectContext::onCreateContext(
|
|||||||
sal_Int32 nElement, const AttributeList& rAttribs )
|
sal_Int32 nElement, const AttributeList& rAttribs )
|
||||||
{
|
{
|
||||||
// containers
|
// containers
|
||||||
if( nElement == OOX_TOKEN( a14, imgLayer ) || nElement == OOX_TOKEN( a14, imgEffect ) )
|
if( nElement == OOX_TOKEN( a14, imgLayer ) )
|
||||||
|
{
|
||||||
|
if( rAttribs.hasAttribute( R_TOKEN( embed ) ) )
|
||||||
|
{
|
||||||
|
OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( embed ), OUString() ) );
|
||||||
|
if( !aFragmentPath.isEmpty() )
|
||||||
|
getFilter().importBinaryData( maEffect.mrOleObjectInfo.maEmbeddedData, aFragmentPath );
|
||||||
|
}
|
||||||
|
return new ArtisticEffectContext( *this, maEffect );
|
||||||
|
}
|
||||||
|
if( nElement == OOX_TOKEN( a14, imgEffect ) )
|
||||||
return new ArtisticEffectContext( *this, maEffect );
|
return new ArtisticEffectContext( *this, maEffect );
|
||||||
// TODO: manage r:embed attribute in a14:imgLayer
|
|
||||||
|
|
||||||
// effects
|
// effects
|
||||||
maEffect.msName = ArtisticEffectProperties::getEffectString( nElement );
|
maEffect.msName = ArtisticEffectProperties::getEffectString( nElement );
|
||||||
|
@ -119,10 +119,12 @@ namespace drawingml {
|
|||||||
|
|
||||||
// not thread safe
|
// not thread safe
|
||||||
int DrawingML::mnImageCounter = 1;
|
int DrawingML::mnImageCounter = 1;
|
||||||
|
int DrawingML::mnWdpImageCounter = 1;
|
||||||
|
|
||||||
void DrawingML::ResetCounters()
|
void DrawingML::ResetCounters()
|
||||||
{
|
{
|
||||||
mnImageCounter = 1;
|
mnImageCounter = 1;
|
||||||
|
mnWdpImageCounter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
|
bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
|
||||||
@ -2590,6 +2592,7 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
|
|||||||
Sequence< PropertyValue > aAttrs;
|
Sequence< PropertyValue > aAttrs;
|
||||||
aEffect.Value >>= aAttrs;
|
aEffect.Value >>= aAttrs;
|
||||||
sax_fastparser::FastAttributeList *aAttrList = mpFS->createAttrList();
|
sax_fastparser::FastAttributeList *aAttrList = mpFS->createAttrList();
|
||||||
|
OString sRelId;
|
||||||
for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
|
for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
|
||||||
{
|
{
|
||||||
sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
|
sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
|
||||||
@ -2599,6 +2602,12 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
|
|||||||
aAttrs[i].Value >>= nVal;
|
aAttrs[i].Value >>= nVal;
|
||||||
aAttrList->add( nToken, OString::number( nVal ).getStr() );
|
aAttrList->add( nToken, OString::number( nVal ).getStr() );
|
||||||
}
|
}
|
||||||
|
else if( aAttrs[i].Name == "OriginalGraphic" )
|
||||||
|
{
|
||||||
|
Sequence< sal_Int8 > aGraphicData;
|
||||||
|
aAttrs[i].Value >>= aGraphicData;
|
||||||
|
sRelId = WriteWdpPicture( aGraphicData );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mpFS->startElementNS( XML_a, XML_extLst, FSEND );
|
mpFS->startElementNS( XML_a, XML_extLst, FSEND );
|
||||||
@ -2608,7 +2617,9 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
|
|||||||
mpFS->startElementNS( XML_a14, XML_imgProps,
|
mpFS->startElementNS( XML_a14, XML_imgProps,
|
||||||
FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
|
FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
|
||||||
FSEND );
|
FSEND );
|
||||||
mpFS->startElementNS( XML_a14, XML_imgLayer, FSEND );
|
mpFS->startElementNS( XML_a14, XML_imgLayer,
|
||||||
|
FSNS( XML_r, XML_embed), sRelId.getStr(),
|
||||||
|
FSEND );
|
||||||
mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
|
mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
|
||||||
|
|
||||||
sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
|
sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
|
||||||
@ -2621,6 +2632,23 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
|
|||||||
mpFS->endElementNS( XML_a, XML_extLst );
|
mpFS->endElementNS( XML_a, XML_extLst );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OString DrawingML::WriteWdpPicture( const Sequence< sal_Int8 >& rPictureData )
|
||||||
|
{
|
||||||
|
OUString sFileName = "media/hdphoto" + OUString::number( mnWdpImageCounter++ ) + ".wdp";
|
||||||
|
uno::Reference< io::XOutputStream > xOutStream =
|
||||||
|
mpFB->openFragmentStream( "word/" + sFileName,
|
||||||
|
"image/vnd.ms-photo" );
|
||||||
|
OUString sId;
|
||||||
|
xOutStream->writeBytes( rPictureData );
|
||||||
|
xOutStream->closeOutput();
|
||||||
|
|
||||||
|
sId = mpFB->addRelation( mpFS->getOutputStream(),
|
||||||
|
"http://schemas.microsoft.com/office/2007/relationships/hdphoto",
|
||||||
|
sFileName, false );
|
||||||
|
|
||||||
|
return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,9 +1341,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureEffectPreservation, "picture-effects-preserv
|
|||||||
DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artistic-effects-preservation.docx")
|
DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artistic-effects-preservation.docx")
|
||||||
{
|
{
|
||||||
xmlDocPtr pXmlDoc = parseExport("word/document.xml");
|
xmlDocPtr pXmlDoc = parseExport("word/document.xml");
|
||||||
if (!pXmlDoc)
|
xmlDocPtr pRelsDoc = parseExport("word/_rels/document.xml.rels");
|
||||||
|
if (!pXmlDoc || !pRelsDoc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(
|
||||||
|
comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
|
||||||
|
|
||||||
// 1st picture: marker effect
|
// 1st picture: marker effect
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
@ -1354,6 +1358,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
|
|||||||
"a14:artisticMarker",
|
"a14:artisticMarker",
|
||||||
"size", "80");
|
"size", "80");
|
||||||
|
|
||||||
|
OUString sEmbedId1 = getXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
OUString sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId1 + "']";
|
||||||
|
OUString sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
|
|
||||||
// 2nd picture: pencil grayscale
|
// 2nd picture: pencil grayscale
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
@ -1364,6 +1375,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
|
|||||||
"a14:artisticPencilGrayscale",
|
"a14:artisticPencilGrayscale",
|
||||||
"pencilSize", "66");
|
"pencilSize", "66");
|
||||||
|
|
||||||
|
OUString sEmbedId2 = getXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId2 + "']";
|
||||||
|
sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
|
|
||||||
// 3rd picture: pencil sketch
|
// 3rd picture: pencil sketch
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
@ -1374,6 +1392,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
|
|||||||
"a14:artisticPencilSketch",
|
"a14:artisticPencilSketch",
|
||||||
"pressure", "17");
|
"pressure", "17");
|
||||||
|
|
||||||
|
OUString sEmbedId3 = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId3 + "']";
|
||||||
|
sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
|
|
||||||
// 4th picture: light screen
|
// 4th picture: light screen
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
@ -1384,16 +1409,37 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
|
|||||||
"a14:artisticLightScreen",
|
"a14:artisticLightScreen",
|
||||||
"gridSize", "1");
|
"gridSize", "1");
|
||||||
|
|
||||||
|
OUString sEmbedId4 = getXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId4 + "']";
|
||||||
|
sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
|
|
||||||
// 5th picture: watercolor sponge
|
// 5th picture: watercolor sponge
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
"a14:artisticWatercolorSponge",
|
"a14:artisticWatercolorSponge",
|
||||||
"brushSize", "4");
|
"brushSize", "4");
|
||||||
|
|
||||||
|
OUString sEmbedId5 = getXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId5 + "']";
|
||||||
|
sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
|
|
||||||
// 6th picture: photocopy (no attributes)
|
// 6th picture: photocopy (no attributes)
|
||||||
assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
|
||||||
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
"a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
|
||||||
"a14:artisticPhotocopy", 1);
|
"a14:artisticPhotocopy", 1);
|
||||||
|
|
||||||
|
OUString sEmbedId6 = getXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
|
||||||
|
"wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
|
||||||
|
"embed");
|
||||||
|
sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId6 + "']";
|
||||||
|
sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
|
DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user