summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Arato (NISZ) <arato.daniel@nisz.hu>2021-09-10 13:51:24 +0200
committerLászló Németh <nemeth@numbertext.org>2021-09-21 13:26:54 +0200
commit504808fb5c372a94c6299eec90a281655eef47e4 (patch)
tree9662f1572d6fc5d0a5ed0238b2e2d16c19274c16
parente0c7d1e4cf7e6cf73211e69a91f458e6ffe303cb (diff)
tdf#142602 DOCX: export adjustment points of custom shape arrows
When exporting custom shape arrows LO used to fall back to writing out their plain vertex coordinates, losing the customizability of the shape after loading from file. This commit changes the export of some of the most commonly used arrow custom shapes to proper adjustment value export. Follow-up to commit 63cd67e5e18f01aca303131e148c80398a181a41 "tdf#92525 tdf#142398: fix export of simple custom shapes". Change-Id: If248556764bdb7e00cfde4ebe5b32bb380b1fa19 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121901 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--oox/qa/unit/data/tdf142602_CustomShapeArrows.odtbin0 -> 11637 bytes
-rw-r--r--oox/qa/unit/export.cxx190
-rw-r--r--oox/source/export/DMLPresetShapeExport.cxx352
3 files changed, 516 insertions, 26 deletions
diff --git a/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt b/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt
new file mode 100644
index 000000000000..bc0357a1a867
--- /dev/null
+++ b/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt
Binary files differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index 0e597adb2854..b649d546ead9 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -154,6 +154,196 @@ CPPUNIT_TEST_FIXTURE(Test, testDmlGroupshapePolygon)
assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:chExt", "cx", "5328360");
assertXPath(pXmlDoc, "//wps:spPr/a:xfrm/a:ext", "cx", "5328360");
}
+
+CPPUNIT_TEST_FIXTURE(Test, testCustomShapeArrowExport)
+{
+ // Given a document with a few different kinds of arrow shapes in it:
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf142602_CustomShapeArrows.odt";
+ // When saving that to DOCX:
+ loadAndSave(aURL, "Office Open XML Text");
+
+ // Then the shapes should retain their correct control values.
+ uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
+ = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, getTempFile().GetURL());
+ uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName("word/document.xml"),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+
+ // Without the fix the output OOXML would have no <a:prstGeom> tags in it.
+
+ // Right arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "rightArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 46321");
+
+ // Left arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "leftArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 52939");
+
+ // Down arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "downArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[3]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 59399");
+
+ // Up arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "upArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[4]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 63885");
+
+ // Left-right arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "leftRightArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[5]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 53522");
+
+ // Up-down arrow
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "upDownArrow");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 50000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[6]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 62743");
+
+ // Right arrow callout
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "rightArrowCallout");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 25002");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 25000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]",
+ "fmla", "val 25052");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[7]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]",
+ "fmla", "val 66667");
+
+ // Left arrow callout
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "leftArrowCallout");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 25002");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 25000");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]",
+ "fmla", "val 25057");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[8]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]",
+ "fmla", "val 66673");
+
+ // Down arrow callout
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "downArrowCallout");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 29415");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 29413");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]",
+ "fmla", "val 16667");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[9]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]",
+ "fmla", "val 66667");
+
+ // Up arrow callout
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom",
+ "prst", "upArrowCallout");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[1]",
+ "fmla", "val 31033");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[2]",
+ "fmla", "val 31030");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[3]",
+ "fmla", "val 16667");
+ assertXPath(pXmlDoc,
+ "//w:r/mc:AlternateContent[10]/mc:Choice/w:drawing/wp:anchor/a:graphic/"
+ "a:graphicData/wps:wsp/wps:spPr/a:prstGeom/a:avLst/a:gd[4]",
+ "fmla", "val 66660");
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/source/export/DMLPresetShapeExport.cxx b/oox/source/export/DMLPresetShapeExport.cxx
index 318ce11207d9..b374eb6b6c1a 100644
--- a/oox/source/export/DMLPresetShapeExport.cxx
+++ b/oox/source/export/DMLPresetShapeExport.cxx
@@ -640,13 +640,69 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "downArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1 = std::lround((*aPointX.nMaxVal - *aPointX.nCurrVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointY.nMaxVal - *aPointY.nCurrVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "downArrowCallout")
{
- // TODO
- return false;
+ auto aNeckFromBox = GetAdjustmentPointXValue(1);
+ auto aHeadFromNeck = GetAdjustmentPointXValue(2);
+ auto aHeadHeight = GetAdjustmentPointYValue(1);
+ auto aBoxHeight = GetAdjustmentPointYValue(0);
+ if (!aNeckFromBox.nCurrVal.has_value() || !aNeckFromBox.nMaxVal.has_value()
+ || !aNeckFromBox.nMinVal.has_value() || !aHeadFromNeck.nCurrVal.has_value()
+ || !aHeadFromNeck.nMaxVal.has_value() || !aHeadFromNeck.nMinVal.has_value()
+ || !aHeadHeight.nCurrVal.has_value() || !aHeadHeight.nMaxVal.has_value()
+ || !aHeadHeight.nMinVal.has_value() || !aBoxHeight.nCurrVal.has_value()
+ || !aBoxHeight.nMaxVal.has_value() || !aBoxHeight.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1
+ = 100000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal3
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1
+ = std::lround((*aNeckFromBox.nMaxVal - *aNeckFromBox.nCurrVal)
+ / (*aNeckFromBox.nMaxVal - *aNeckFromBox.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((10800 - *aHeadFromNeck.nCurrVal)
+ / (10800 - *aHeadFromNeck.nMinVal) * nMaxVal2);
+ tools::Long nVal3
+ = std::lround((*aHeadHeight.nMaxVal - *aHeadHeight.nCurrVal)
+ / (*aHeadHeight.nMaxVal - *aHeadHeight.nMinVal) * nMaxVal3);
+ tools::Long nVal4 = std::lround((*aBoxHeight.nCurrVal - *aBoxHeight.nMinVal)
+ / (21600 - *aBoxHeight.nMinVal) * 100000);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && WriteAV(u"adj3", OUString(u"val " + OUString::number(nVal3)))
+ && WriteAV(u"adj4", OUString(u"val " + OUString::number(nVal4)))
+ && EndAVListWriting();
}
if (sShapeType == "ellipse")
{
@@ -893,13 +949,69 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "leftArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 100000
+ * (double(m_xShape->getSize().Width)
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height));
+ tools::Long nVal1 = std::lround((*aPointY.nMaxVal - *aPointY.nCurrVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointX.nCurrVal - *aPointX.nMinVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "leftArrowCallout")
{
- // TODO
- return false;
+ auto aBoxWidth = GetAdjustmentPointXValue(0);
+ auto aNeckLength = GetAdjustmentPointXValue(1);
+ auto aNeckFromBox = GetAdjustmentPointYValue(1);
+ auto aHeadFromNeck = GetAdjustmentPointYValue(2);
+ if (!aBoxWidth.nCurrVal.has_value() || !aBoxWidth.nMaxVal.has_value()
+ || !aBoxWidth.nMinVal.has_value() || !aNeckLength.nCurrVal.has_value()
+ || !aNeckLength.nMaxVal.has_value() || !aNeckLength.nMinVal.has_value()
+ || !aNeckFromBox.nCurrVal.has_value() || !aNeckFromBox.nMaxVal.has_value()
+ || !aNeckFromBox.nMinVal.has_value() || !aHeadFromNeck.nCurrVal.has_value()
+ || !aHeadFromNeck.nMaxVal.has_value() || !aHeadFromNeck.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal3
+ = 100000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1
+ = std::lround((*aNeckFromBox.nMaxVal - *aNeckFromBox.nCurrVal)
+ / (*aNeckFromBox.nMaxVal - *aNeckFromBox.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((10800 - *aHeadFromNeck.nCurrVal)
+ / (10800 - *aHeadFromNeck.nMinVal) * nMaxVal2);
+ tools::Long nVal3 = std::lround((*aNeckLength.nCurrVal - *aNeckLength.nMinVal)
+ / (21600 - *aNeckLength.nMinVal) * nMaxVal3);
+ tools::Long nVal4 = std::lround((*aBoxWidth.nMaxVal - *aBoxWidth.nCurrVal)
+ / (*aBoxWidth.nMaxVal - *aBoxWidth.nMinVal) * 100000);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && WriteAV(u"adj3", OUString(u"val " + OUString::number(nVal3)))
+ && WriteAV(u"adj4", OUString(u"val " + OUString::number(nVal4)))
+ && EndAVListWriting();
}
if (sShapeType == "leftBrace")
{
@@ -913,18 +1025,74 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "leftCircularArrow")
{
- // TODO
+ // LO does not have this type, not necessary to map
return false;
}
if (sShapeType == "leftRightArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 50000
+ * (double(m_xShape->getSize().Width)
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height));
+ tools::Long nVal1 = std::lround((*aPointY.nMaxVal - *aPointY.nCurrVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointX.nCurrVal - *aPointX.nMinVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "leftRightArrowCallout")
{
- // TODO
- return false;
+ auto aNeckFromBox = GetAdjustmentPointXValue(1);
+ auto aHeadFromNeck = GetAdjustmentPointXValue(2);
+ auto aHeadHeight = GetAdjustmentPointYValue(1);
+ auto aBoxHeight = GetAdjustmentPointYValue(0);
+ if (!aNeckFromBox.nCurrVal.has_value() || !aNeckFromBox.nMaxVal.has_value()
+ || !aNeckFromBox.nMinVal.has_value() || !aHeadFromNeck.nCurrVal.has_value()
+ || !aHeadFromNeck.nMaxVal.has_value() || !aHeadFromNeck.nMinVal.has_value()
+ || !aHeadHeight.nCurrVal.has_value() || !aHeadHeight.nMaxVal.has_value()
+ || !aHeadHeight.nMinVal.has_value() || !aBoxHeight.nCurrVal.has_value()
+ || !aBoxHeight.nMaxVal.has_value() || !aBoxHeight.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1
+ = 100000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal3
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1
+ = std::lround((*aNeckFromBox.nMaxVal - *aNeckFromBox.nCurrVal)
+ / (*aNeckFromBox.nMaxVal - *aNeckFromBox.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((10800 - *aHeadFromNeck.nCurrVal)
+ / (10800 - *aHeadFromNeck.nMinVal) * nMaxVal2);
+ tools::Long nVal3 = std::lround((*aHeadHeight.nCurrVal - *aHeadHeight.nMinVal)
+ / (21600 - *aHeadHeight.nMinVal) * nMaxVal3);
+ tools::Long nVal4 = std::lround((*aBoxHeight.nCurrVal - *aBoxHeight.nMinVal)
+ / (10800 - *aBoxHeight.nMinVal) * 100000);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && WriteAV(u"adj3", OUString(u"val " + OUString::number(nVal3)))
+ && WriteAV(u"adj4", OUString(u"val " + OUString::number(nVal4)))
+ && EndAVListWriting();
}
if (sShapeType == "leftRightCircularArrow")
{
@@ -938,13 +1106,14 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "leftRightUpArrow")
{
- // TODO
+ // TODO?
+ // MS Word stretches the arrow to fit the bounding box; LO doesn't
return false;
}
if (sShapeType == "leftUpArrow")
{
- // TODO
- return false;
+ // MS Word's and LO's interpretations of what a leftUpArrow should look like
+ // are too different to find a compromise :(
}
if (sShapeType == "lightningBolt")
{
@@ -1105,13 +1274,70 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "rightArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 100000
+ * (double(m_xShape->getSize().Width)
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height));
+ tools::Long nVal1 = std::lround((*aPointY.nMaxVal - *aPointY.nCurrVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointX.nMaxVal - *aPointX.nCurrVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "rightArrowCallout")
{
- // TODO
- return false;
+ auto aBoxWidth = GetAdjustmentPointXValue(0);
+ auto aNeckLength = GetAdjustmentPointXValue(1);
+ auto aNeckFromBox = GetAdjustmentPointYValue(1);
+ auto aHeadFromNeck = GetAdjustmentPointYValue(2);
+ if (!aBoxWidth.nCurrVal.has_value() || !aBoxWidth.nMaxVal.has_value()
+ || !aBoxWidth.nMinVal.has_value() || !aNeckLength.nCurrVal.has_value()
+ || !aNeckLength.nMaxVal.has_value() || !aNeckLength.nMinVal.has_value()
+ || !aNeckFromBox.nCurrVal.has_value() || !aNeckFromBox.nMaxVal.has_value()
+ || !aNeckFromBox.nMinVal.has_value() || !aHeadFromNeck.nCurrVal.has_value()
+ || !aHeadFromNeck.nMaxVal.has_value() || !aHeadFromNeck.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal3
+ = 100000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1
+ = std::lround((*aNeckFromBox.nMaxVal - *aNeckFromBox.nCurrVal)
+ / (*aNeckFromBox.nMaxVal - *aNeckFromBox.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((10800 - *aHeadFromNeck.nCurrVal)
+ / (10800 - *aHeadFromNeck.nMinVal) * nMaxVal2);
+ tools::Long nVal3
+ = std::lround((*aNeckLength.nMaxVal - *aNeckLength.nCurrVal)
+ / (*aNeckLength.nMaxVal - *aNeckLength.nMinVal) * nMaxVal3);
+ tools::Long nVal4 = std::lround((*aBoxWidth.nCurrVal - *aBoxWidth.nMinVal)
+ / (21600 - *aBoxWidth.nMinVal) * 100000);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && WriteAV(u"adj3", OUString(u"val " + OUString::number(nVal3)))
+ && WriteAV(u"adj4", OUString(u"val " + OUString::number(nVal4)))
+ && EndAVListWriting();
}
if (sShapeType == "rightBrace")
{
@@ -1299,18 +1525,92 @@ bool DMLPresetShapeExporter::WriteShapeWithAVlist()
}
if (sShapeType == "upArrowCallout")
{
- // TODO
- return false;
+ auto aNeckFromBox = GetAdjustmentPointXValue(1);
+ auto aHeadFromNeck = GetAdjustmentPointXValue(2);
+ auto aHeadHeight = GetAdjustmentPointYValue(1);
+ auto aBoxHeight = GetAdjustmentPointYValue(0);
+ if (!aNeckFromBox.nCurrVal.has_value() || !aNeckFromBox.nMaxVal.has_value()
+ || !aNeckFromBox.nMinVal.has_value() || !aHeadFromNeck.nCurrVal.has_value()
+ || !aHeadFromNeck.nMaxVal.has_value() || !aHeadFromNeck.nMinVal.has_value()
+ || !aHeadHeight.nCurrVal.has_value() || !aHeadHeight.nMaxVal.has_value()
+ || !aHeadHeight.nMinVal.has_value() || !aBoxHeight.nCurrVal.has_value()
+ || !aBoxHeight.nMaxVal.has_value() || !aBoxHeight.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1
+ = 100000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Width
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nMaxVal3
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1
+ = std::lround((*aNeckFromBox.nMaxVal - *aNeckFromBox.nCurrVal)
+ / (*aNeckFromBox.nMaxVal - *aNeckFromBox.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((10800 - *aHeadFromNeck.nCurrVal)
+ / (10800 - *aHeadFromNeck.nMinVal) * nMaxVal2);
+ tools::Long nVal3 = std::lround((*aHeadHeight.nCurrVal - *aHeadHeight.nMinVal)
+ / (21600 - *aHeadHeight.nMinVal) * nMaxVal3);
+ tools::Long nVal4 = std::lround((*aBoxHeight.nCurrVal - *aBoxHeight.nMinVal)
+ / (10800 - *aBoxHeight.nMinVal) * 100000);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && WriteAV(u"adj3", OUString(u"val " + OUString::number(nVal3)))
+ && WriteAV(u"adj4", OUString(u"val " + OUString::number(nVal4)))
+ && EndAVListWriting();
}
if (sShapeType == "upDownArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 50000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1 = std::lround((*aPointX.nMaxVal - *aPointX.nCurrVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointY.nCurrVal - *aPointY.nMinVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "upArrow")
{
- // TODO
- return false;
+ auto aPointX = GetAdjustmentPointXValue(0);
+ auto aPointY = GetAdjustmentPointYValue(0);
+ if (!aPointX.nCurrVal.has_value() || !aPointX.nMaxVal.has_value()
+ || !aPointX.nMinVal.has_value() || !aPointY.nCurrVal.has_value()
+ || !aPointY.nMaxVal.has_value() || !aPointY.nMinVal.has_value())
+ return false;
+
+ m_pDMLexporter->WriteShapeTransformation(m_xShape, XML_a, IsXFlipped(), IsYFlipped(),
+ false, false);
+ tools::Long nMaxVal1 = 100000;
+ tools::Long nMaxVal2
+ = 100000 * m_xShape->getSize().Height
+ / std::min(m_xShape->getSize().Width, m_xShape->getSize().Height);
+ tools::Long nVal1 = std::lround((*aPointX.nMaxVal - *aPointX.nCurrVal)
+ / (*aPointX.nMaxVal - *aPointX.nMinVal) * nMaxVal1);
+ tools::Long nVal2 = std::lround((*aPointY.nCurrVal - *aPointY.nMinVal)
+ / (*aPointY.nMaxVal - *aPointY.nMinVal) * nMaxVal2);
+ return StartAVListWriting()
+ && WriteAV(u"adj1", OUString(u"val " + OUString::number(nVal1)))
+ && WriteAV(u"adj2", OUString(u"val " + OUString::number(nVal2)))
+ && EndAVListWriting();
}
if (sShapeType == "upDownArrowCallout")
{