tdf#103389: Resaving a DOCX document with two canvases leads to a broken file.

Make custom shape export more robust. In case of the test
document, WriteCustomGeometry is called, but this call
does not export anything, and so we get a shape without
any geometry in the DOCX file, which causes problem to MS Word.

Change-Id: Ie7a4e2b8a18bfddaeeb81425ae5f1de04140d43f
Reviewed-on: https://gerrit.libreoffice.org/30241
Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
Tested-by: Tamás Zolnai <tamas.zolnai@collabora.com>
This commit is contained in:
Tamás Zolnai
2016-10-25 01:51:25 +00:00
parent 419e4fa1b5
commit f7c61b08d5
5 changed files with 23 additions and 9 deletions

View File

@@ -204,7 +204,7 @@ public:
void WritePresetShape( const char* pShape , std::vector< std::pair<sal_Int32,sal_Int32>> & rAvList ); void WritePresetShape( const char* pShape , std::vector< std::pair<sal_Int32,sal_Int32>> & rAvList );
void WritePresetShape( const char* pShape ); void WritePresetShape( const char* pShape );
void WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const css::beans::PropertyValue& rProp ); void WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const css::beans::PropertyValue& rProp );
void WriteCustomGeometry( const css::uno::Reference<css::drawing::XShape>& rXShape ); bool WriteCustomGeometry( const css::uno::Reference<css::drawing::XShape>& rXShape );
void WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon ); void WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon );
void WriteFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet ); void WriteFill( const css::uno::Reference< css::beans::XPropertySet >& xPropSet );
void WriteShapeStyle( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet ); void WriteShapeStyle( const css::uno::Reference< css::beans::XPropertySet >& rXPropSet );

View File

@@ -2298,23 +2298,23 @@ void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool b
mpFS->endElementNS( XML_a, XML_prstGeom ); mpFS->endElementNS( XML_a, XML_prstGeom );
} }
void DrawingML::WriteCustomGeometry( const Reference< XShape >& rXShape ) bool DrawingML::WriteCustomGeometry( const Reference< XShape >& rXShape )
{ {
uno::Reference< beans::XPropertySet > aXPropSet; uno::Reference< beans::XPropertySet > aXPropSet;
uno::Any aAny( rXShape->queryInterface(cppu::UnoType<beans::XPropertySet>::get())); uno::Any aAny( rXShape->queryInterface(cppu::UnoType<beans::XPropertySet>::get()));
if ( ! (aAny >>= aXPropSet) ) if ( ! (aAny >>= aXPropSet) )
return; return false;
try try
{ {
aAny = aXPropSet->getPropertyValue( "CustomShapeGeometry" ); aAny = aXPropSet->getPropertyValue( "CustomShapeGeometry" );
if ( !aAny.hasValue() ) if ( !aAny.hasValue() )
return; return false;
} }
catch( const ::uno::Exception& ) catch( const ::uno::Exception& )
{ {
return; return false;
} }
@@ -2345,7 +2345,7 @@ void DrawingML::WriteCustomGeometry( const Reference< XShape >& rXShape )
} }
if ( !aPairs.hasElements() ) if ( !aPairs.hasElements() )
return; return false;
if ( !aSegments.hasElements() ) if ( !aSegments.hasElements() )
{ {
@@ -2369,7 +2369,7 @@ void DrawingML::WriteCustomGeometry( const Reference< XShape >& rXShape )
if ( nExpectedPairCount > aPairs.getLength() ) if ( nExpectedPairCount > aPairs.getLength() )
{ {
SAL_WARN("oox", "Segments need " << nExpectedPairCount << " coordinates, but Coordinates have only " << aPairs.getLength() << " pairs."); SAL_WARN("oox", "Segments need " << nExpectedPairCount << " coordinates, but Coordinates have only " << aPairs.getLength() << " pairs.");
return; return false;
} }
mpFS->startElementNS( XML_a, XML_custGeom, FSEND ); mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
@@ -2531,10 +2531,11 @@ void DrawingML::WriteCustomGeometry( const Reference< XShape >& rXShape )
mpFS->endElementNS( XML_a, XML_path ); mpFS->endElementNS( XML_a, XML_path );
mpFS->endElementNS( XML_a, XML_pathLst ); mpFS->endElementNS( XML_a, XML_pathLst );
mpFS->endElementNS( XML_a, XML_custGeom ); mpFS->endElementNS( XML_a, XML_custGeom );
return true;
} }
} }
} }
return false;
} }
void DrawingML::WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon ) void DrawingML::WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon )

View File

@@ -834,7 +834,9 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
else if (bCustGeom) else if (bCustGeom)
{ {
WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV ); WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
WriteCustomGeometry( xShape ); bool bSuccess = WriteCustomGeometry( xShape );
if (!bSuccess)
WritePresetShape( sPresetShape );
} }
else if (bOnBlacklist && bHasHandles && nAdjustmentValuesIndex !=-1 && !sShapeType.startsWith("mso-spt")) else if (bOnBlacklist && bHasHandles && nAdjustmentValuesIndex !=-1 && !sShapeType.startsWith("mso-spt"))
{ {

Binary file not shown.

View File

@@ -52,6 +52,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf89377, "tdf89377_tableWithBreakBeforeParaStyle.d
CPPUNIT_ASSERT_EQUAL( 3, getPages() ); CPPUNIT_ASSERT_EQUAL( 3, getPages() );
} }
DECLARE_OOXMLEXPORT_TEST(testTdf103389, "tdf103389.docx")
{
xmlDocPtr pXmlDoc = parseExport("word/document.xml");
if (!pXmlDoc)
return;
// No geometry was exported for the second canvas
// Check both canvases' geometry
assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wpg:wgp/wps:wsp/wps:spPr/a:prstGeom", "prst", "rect");
assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wpg:wgp/wps:wsp/wps:spPr/a:prstGeom", "prst", "rect");
}
CPPUNIT_PLUGIN_IMPLEMENT(); CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */