diff options
author | Daniel Arato (NISZ) <arato.daniel@nisz.hu> | 2021-09-10 13:51:24 +0200 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2021-09-21 13:26:54 +0200 |
commit | 504808fb5c372a94c6299eec90a281655eef47e4 (patch) | |
tree | 9662f1572d6fc5d0a5ed0238b2e2d16c19274c16 /oox | |
parent | e0c7d1e4cf7e6cf73211e69a91f458e6ffe303cb (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>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/qa/unit/data/tdf142602_CustomShapeArrows.odt | bin | 0 -> 11637 bytes | |||
-rw-r--r-- | oox/qa/unit/export.cxx | 190 | ||||
-rw-r--r-- | oox/source/export/DMLPresetShapeExport.cxx | 352 |
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 Binary files differnew file mode 100644 index 000000000000..bc0357a1a867 --- /dev/null +++ b/oox/qa/unit/data/tdf142602_CustomShapeArrows.odt 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") { |