Kaydet (Commit) b1751e6e authored tarafından Andras Timar's avatar Andras Timar Kaydeden (comit) Miklos Vajna

bnc#637947 improve DrawingML export of custom shapes

Change-Id: Iaa880528cf3c899ce66e4349c6d989dfbe5cbeb6
Reviewed-on: https://gerrit.libreoffice.org/14346Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
üst 2c03d6fb
...@@ -701,6 +701,7 @@ struct CustomShapeTypeTranslationTable ...@@ -701,6 +701,7 @@ struct CustomShapeTypeTranslationTable
static const CustomShapeTypeTranslationTable pCustomShapeTypeTranslationTable[] = static const CustomShapeTypeTranslationTable pCustomShapeTypeTranslationTable[] =
{ {
// { "non-primitive", mso_sptMin }, // { "non-primitive", mso_sptMin },
{ "frame", "frame" },
{ "rectangle", "rect" }, { "rectangle", "rect" },
{ "round-rectangle", "roundRect" }, { "round-rectangle", "roundRect" },
{ "ellipse", "ellipse" }, { "ellipse", "ellipse" },
......
...@@ -279,12 +279,87 @@ ShapeExport& ShapeExport::WriteGroupShape(uno::Reference<drawing::XShape> xShape ...@@ -279,12 +279,87 @@ ShapeExport& ShapeExport::WriteGroupShape(uno::Reference<drawing::XShape> xShape
return *this; return *this;
} }
static bool lcl_IsOnBlacklist(OUString& rShapeType)
{
OUString aBlacklist[] = {
"ring",
"can",
"cube",
"paper",
"frame",
"smiley",
"sun",
"flower",
"forbidden",
"bracket-pair",
"brace-pair",
"col-60da8460",
"col-502ad400",
"quad-bevel",
"cloud-callout",
"line-callout-1",
"line-callout-2",
"line-callout-3",
"paper",
"vertical-scroll",
"horizontal-scroll",
"mso-spt34",
"mso-spt75",
"mso-spt164",
"mso-spt180",
"flowchart-process",
"flowchart-alternate-process",
"flowchart-decision",
"flowchart-data",
"flowchart-predefined-process",
"flowchart-internal-storage",
"flowchart-document",
"flowchart-multidocument",
"flowchart-terminator",
"flowchart-preparation",
"flowchart-manual-input",
"flowchart-manual-operation",
"flowchart-connector",
"flowchart-off-page-connector",
"flowchart-card",
"flowchart-punched-tape",
"flowchart-summing-junction",
"flowchart-or",
"flowchart-collate",
"flowchart-sort",
"flowchart-extract",
"flowchart-merge",
"flowchart-stored-data",
"flowchart-delay",
"flowchart-sequential-access",
"flowchart-magnetic-disk",
"flowchart-direct-access-storage",
"flowchart-display"
};
std::vector<OUString> vBlacklist(aBlacklist, aBlacklist + SAL_N_ELEMENTS(aBlacklist));
return std::find(vBlacklist.begin(), vBlacklist.end(), rShapeType) != vBlacklist.end();
}
static bool lcl_IsOnWhitelist(OUString& rShapeType)
{
OUString aWhitelist[] = {
"heart",
"puzzle"
};
std::vector<OUString> vWhitelist(aWhitelist, aWhitelist + SAL_N_ELEMENTS(aWhitelist));
return std::find(vWhitelist.begin(), vWhitelist.end(), rShapeType) != vWhitelist.end();
}
ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape )
{ {
DBG(fprintf(stderr, "write custom shape\n")); DBG(fprintf(stderr, "write custom shape\n"));
Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY ); Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY );
bool bPredefinedHandlesUsed = true; bool bPredefinedHandlesUsed = true;
bool bHasHandles = false;
OUString sShapeType; OUString sShapeType;
sal_uInt32 nMirrorFlags = 0; sal_uInt32 nMirrorFlags = 0;
MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType ); MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType );
...@@ -315,6 +390,7 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) ...@@ -315,6 +390,7 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape )
if ( rProp.Name == "AdjustmentValues" ) if ( rProp.Name == "AdjustmentValues" )
nAdjustmentValuesIndex = i; nAdjustmentValuesIndex = i;
else if ( rProp.Name == "Handles" ) { else if ( rProp.Name == "Handles" ) {
bHasHandles = true;
if( !bIsDefaultObject ) if( !bIsDefaultObject )
bPredefinedHandlesUsed = false; bPredefinedHandlesUsed = false;
// TODO: update nAdjustmentsWhichNeedsToBeConverted here // TODO: update nAdjustmentsWhichNeedsToBeConverted here
...@@ -347,11 +423,40 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) ...@@ -347,11 +423,40 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape )
// visual shape properties // visual shape properties
pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND );
WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, false); // moon is flipped in MSO, and mso-spt89 (right up arrow) is mapped to leftUpArrow
if ( sShapeType == "moon" || sShapeType == "mso-spt89" )
if( sShapeType == "ooxml-non-primitive" ) // non-primitiv -> custom geometry WriteShapeTransformation( xShape, XML_a, !bFlipH, bFlipV, false);
else
WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, false);
// we export non-primitive shapes to custom geometry
// we also export non-ooxml shapes which have handles/equations to custom geometry, because
// we cannot convert ODF equations to DrawingML equations. TODO: see what binary DOC export filter does.
// but our WritePolyPolygon() function is incomplete, therefore we use a blacklist
// we use a whitelist for shapes where mapping to MSO preset shape is not optimal
bool bCustGeom = true;
if( sShapeType == "ooxml-non-primitive" )
bCustGeom = true;
else if( sShapeType.startsWith("ooxml") )
bCustGeom = false;
else if( lcl_IsOnWhitelist(sShapeType) )
bCustGeom = true;
else if( lcl_IsOnBlacklist(sShapeType) )
bCustGeom = false;
else if( bHasHandles )
bCustGeom = true;
if( bCustGeom )
{ {
WritePolyPolygon( EscherPropertyContainer::GetPolyPolygon( xShape ) ); basegfx::B2DPolyPolygon aB2DPolyPolygon = pShape->GetLineGeometry(true);
tools::PolyPolygon aPolyPolygon;
for( sal_uInt32 i = 0; i < aB2DPolyPolygon.count(); ++i )
{
basegfx::B2DPolygon aB2DPolygon = aB2DPolyPolygon.getB2DPolygon(i);
aPolyPolygon.Insert( Polygon( aB2DPolygon ), POLYPOLY_APPEND );
}
WritePolyPolygon( aPolyPolygon );
} }
else // preset geometry else // preset geometry
{ {
......
...@@ -708,6 +708,10 @@ DECLARE_OOXMLEXPORT_TEST(testSdtContent, "SdtContent.docx") ...@@ -708,6 +708,10 @@ DECLARE_OOXMLEXPORT_TEST(testSdtContent, "SdtContent.docx")
assertXPath(pXmlDoc, "/w:hdr[1]/w:sdt[1]/w:sdtContent[1]/w:p[1]/w:del[1]"); assertXPath(pXmlDoc, "/w:hdr[1]/w:sdt[1]/w:sdtContent[1]/w:p[1]/w:del[1]");
} }
#if 0
// Currently LibreOffice exports custom geometry for this up arrow, not preset shape.
// When LibreOffice can export preset shape with correct modifiers, then this test can be re-enabled.
DECLARE_OOXMLEXPORT_TEST(testFdo76016, "fdo76016.docx") DECLARE_OOXMLEXPORT_TEST(testFdo76016, "fdo76016.docx")
{ {
// check XML // check XML
...@@ -717,6 +721,7 @@ DECLARE_OOXMLEXPORT_TEST(testFdo76016, "fdo76016.docx") ...@@ -717,6 +721,7 @@ DECLARE_OOXMLEXPORT_TEST(testFdo76016, "fdo76016.docx")
assertXPath(pXmlDoc, "//a:graphic/a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]", "name", "adj1"); assertXPath(pXmlDoc, "//a:graphic/a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]", "name", "adj1");
assertXPath(pXmlDoc, "//a:graphic/a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]", "name", "adj2"); assertXPath(pXmlDoc, "//a:graphic/a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]", "name", "adj2");
} }
#endif
DECLARE_OOXMLEXPORT_TEST(testFileWithInvalidImageLink, "FileWithInvalidImageLink.docx") DECLARE_OOXMLEXPORT_TEST(testFileWithInvalidImageLink, "FileWithInvalidImageLink.docx")
{ {
......
...@@ -161,28 +161,28 @@ DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier. ...@@ -161,28 +161,28 @@ DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier.
CPPUNIT_ASSERT_EQUAL(nLength, aPairs.getLength()); CPPUNIT_ASSERT_EQUAL(nLength, aPairs.getLength());
std::pair<sal_Int32,sal_Int32> aCoordinates[] = std::pair<sal_Int32,sal_Int32> aCoordinates[] =
{ {
std::pair<sal_Int32,sal_Int32>(607, 0), std::pair<sal_Int32,sal_Int32>(9084, 0),
std::pair<sal_Int32,sal_Int32>(450, 44), std::pair<sal_Int32,sal_Int32>(6734, 689),
std::pair<sal_Int32,sal_Int32>(300, 57), std::pair<sal_Int32,sal_Int32>(4489, 893),
std::pair<sal_Int32,sal_Int32>(176, 57), std::pair<sal_Int32,sal_Int32>(2633, 893),
std::pair<sal_Int32,sal_Int32>(109, 57), std::pair<sal_Int32,sal_Int32>(1631, 893),
std::pair<sal_Int32,sal_Int32>(49, 53), std::pair<sal_Int32,sal_Int32>(733, 830),
std::pair<sal_Int32,sal_Int32>(0, 48), std::pair<sal_Int32,sal_Int32>(0, 752),
std::pair<sal_Int32,sal_Int32>(66, 58), std::pair<sal_Int32,sal_Int32>(987, 908),
std::pair<sal_Int32,sal_Int32>(152, 66), std::pair<sal_Int32,sal_Int32>(2274, 1034),
std::pair<sal_Int32,sal_Int32>(251, 66), std::pair<sal_Int32,sal_Int32>(3756, 1034),
std::pair<sal_Int32,sal_Int32>(358, 66), std::pair<sal_Int32,sal_Int32>(5357, 1034),
std::pair<sal_Int32,sal_Int32>(480, 56), std::pair<sal_Int32,sal_Int32>(7183, 877),
std::pair<sal_Int32,sal_Int32>(607, 27), std::pair<sal_Int32,sal_Int32>(9084, 423),
std::pair<sal_Int32,sal_Int32>(607, 0), std::pair<sal_Int32,sal_Int32>(9084, 0),
std::pair<sal_Int32,sal_Int32>(607, 0), std::pair<sal_Int32,sal_Int32>(9084, 0),
std::pair<sal_Int32,sal_Int32>(607, 0) std::pair<sal_Int32,sal_Int32>(9084, 0)
}; };
for( int i = 0; i < nLength; ++i ) for( int i = 0; i < nLength; ++i )
{ {
CPPUNIT_ASSERT_EQUAL(aCoordinates[i].first, aPairs[i].First.Value.get<sal_Int32>()); CPPUNIT_ASSERT(abs(aCoordinates[i].first - aPairs[i].First.Value.get<sal_Int32>()) < 20);
CPPUNIT_ASSERT_EQUAL(aCoordinates[i].second, aPairs[i].Second.Value.get<sal_Int32>()); CPPUNIT_ASSERT(abs(aCoordinates[i].second - aPairs[i].Second.Value.get<sal_Int32>()) < 20);
} }
} }
...@@ -1443,6 +1443,10 @@ DECLARE_OOXMLEXPORT_TEST(testNestedAlternateContent, "nestedAlternateContent.doc ...@@ -1443,6 +1443,10 @@ DECLARE_OOXMLEXPORT_TEST(testNestedAlternateContent, "nestedAlternateContent.doc
assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wpg:wgp[1]/wps:wsp[2]/wps:txbx[1]/w:txbxContent[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]",0); assertXPath(pXmlDoc,"/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wpg:wgp[1]/wps:wsp[2]/wps:txbx[1]/w:txbxContent[1]/w:p[1]/w:r[2]/mc:AlternateContent[1]",0);
} }
#if 0
// Currently LibreOffice exports custom geometry for this hexagon, not preset shape.
// When LibreOffice can export preset shapes with correct modifiers, then this test can be re-enabled.
DECLARE_OOXMLEXPORT_TEST(test76317, "test76317.docx") DECLARE_OOXMLEXPORT_TEST(test76317, "test76317.docx")
{ {
xmlDocPtr pXmlDoc = parseExport("word/document.xml"); xmlDocPtr pXmlDoc = parseExport("word/document.xml");
...@@ -1450,6 +1454,8 @@ DECLARE_OOXMLEXPORT_TEST(test76317, "test76317.docx") ...@@ -1450,6 +1454,8 @@ DECLARE_OOXMLEXPORT_TEST(test76317, "test76317.docx")
assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:prstGeom[1]", "prst", "hexagon"); assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:prstGeom[1]", "prst", "hexagon");
} }
#endif
DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx") DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx")
{ {
xmlDocPtr pXmlDoc = parseExport("word/document.xml"); xmlDocPtr pXmlDoc = parseExport("word/document.xml");
......
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