tdf#126746 Add support for import/export line caps for .pptx format

With this commit I have added importing and exporting line caps,
which could be (for pptx format:
  rnd	Round Line Cap
  sq	Square Line Cap
  flat	Flat Line Cap

Also exporting of these caps are added.

Change-Id: I799485048a2a7ac8df89f004e177d507f86ce99d
Reviewed-on: https://gerrit.libreoffice.org/77233
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Tested-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
diff --git a/include/oox/drawingml/shapepropertymap.hxx b/include/oox/drawingml/shapepropertymap.hxx
index eff203a..cc55b24 100644
--- a/include/oox/drawingml/shapepropertymap.hxx
+++ b/include/oox/drawingml/shapepropertymap.hxx
@@ -49,6 +49,7 @@ enum class ShapeProperty
    LineColor,
    LineTransparency,
    LineDash,                     ///< Explicit line dash or name of a line dash stored in a global container.
    LineCap,
    LineJoint,
    LineStart,                    ///< Explicit line start marker or name of a line marker stored in a global container.
    LineStartWidth,
diff --git a/oox/inc/drawingml/lineproperties.hxx b/oox/inc/drawingml/lineproperties.hxx
index 512c1ab..b0d27a2 100644
--- a/oox/inc/drawingml/lineproperties.hxx
+++ b/oox/inc/drawingml/lineproperties.hxx
@@ -23,6 +23,7 @@
#include <utility>
#include <vector>

#include <com/sun/star/drawing/LineCap.hpp>
#include <com/sun/star/drawing/LineJoint.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <oox/dllapi.h>
@@ -74,6 +75,8 @@ struct OOX_DLLPUBLIC LineProperties

    /** Calculates the line style attribute from the internal state of the object */
    css::drawing::LineStyle  getLineStyle() const;
    /** Calculates the line cap attribute from the internal state of the object */
    css::drawing::LineCap  getLineCap() const;
    /** Calculates the line joint attribute from the internal state of the object */
    css::drawing::LineJoint  getLineJoint() const;
    /** Calculates the line width attribute from the internal state of the object */
diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx
index 9c64530..ed52ccf 100644
--- a/oox/source/drawingml/chart/objectformatter.cxx
+++ b/oox/source/drawingml/chart/objectformatter.cxx
@@ -446,7 +446,7 @@ const AutoTextEntry* lclGetAutoTextEntry( const AutoTextEntry* pEntries, sal_Int
static const ShapePropertyIds spnCommonPropIds =
{
    PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_INVALID, PROP_FillGradientName,
    PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY,
    PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint,
@@ -456,7 +456,7 @@ static const ShapePropertyIds spnCommonPropIds =
static const ShapePropertyIds spnLinearPropIds =
{
    PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
    PROP_INVALID, PROP_INVALID, PROP_INVALID,
@@ -477,6 +477,7 @@ static const ShapePropertyIds spnFilledPropIds =
    PROP_INVALID,
    PROP_INVALID,
    PROP_INVALID,
    PROP_INVALID,
    PROP_FillStyle,
    PROP_Color,
    PROP_Transparency,
diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx
index 2b5de7a..a7ea239 100644
--- a/oox/source/drawingml/lineproperties.cxx
+++ b/oox/source/drawingml/lineproperties.cxx
@@ -23,6 +23,7 @@
#include <osl/diagnose.h>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/LineCap.hpp>
#include <com/sun/star/drawing/LineDash.hpp>
#include <com/sun/star/drawing/LineJoint.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
@@ -126,6 +127,18 @@ DashStyle lclGetDashStyle( sal_Int32 nToken )
    return DashStyle_ROUNDRELATIVE;
}

LineCap lclGetLineCap( sal_Int32 nToken )
{
    OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
    switch( nToken )
    {
        case XML_rnd:   return LineCap_ROUND;
        case XML_sq:    return LineCap_SQUARE;
        case XML_flat:  return LineCap_BUTT;
    }
    return LineCap_BUTT;
}

LineJoint lclGetLineJoint( sal_Int32 nToken )
{
    OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
@@ -382,6 +395,9 @@ void LineProperties::pushToPropMap( ShapePropertyMap& rPropMap,
            if( rPropMap.setProperty( ShapeProperty::LineDash, aLineDash ) )
                eLineStyle = drawing::LineStyle_DASH;
        }
        // line cap type
        if( moLineCap.has() )
            rPropMap.setProperty( ShapeProperty::LineCap, lclGetLineCap( moLineCap.get() ) );

        // set final line style property
        rPropMap.setProperty( ShapeProperty::LineStyle, eLineStyle );
@@ -418,6 +434,14 @@ drawing::LineStyle LineProperties::getLineStyle() const
                    drawing::LineStyle_SOLID;
}

drawing::LineCap LineProperties::getLineCap() const
{
    if( moLineCap.has() )
        return lclGetLineCap( moLineCap.get() );

    return drawing::LineCap_BUTT;
}

drawing::LineJoint LineProperties::getLineJoint() const
{
    if( moLineJoint.has() )
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index ae5afd4..960b632 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -974,6 +974,7 @@ Reference< XShape > const & Shape::createAndInsert(
                    {"Idx", uno::makeAny(pLineRef->mnThemedIdx)},
                    {"Color", uno::makeAny(nLinePhClr)},
                    {"LineStyle", uno::makeAny(aLineProperties.getLineStyle())},
                    {"LineCap", uno::makeAny(aLineProperties.getLineCap())},
                    {"LineJoint", uno::makeAny(aLineProperties.getLineJoint())},
                    {"LineWidth", uno::makeAny(aLineProperties.getLineWidth())},
                    {"Transformations", uno::makeAny(pLineRef->maPhClr.getTransformations())}
diff --git a/oox/source/drawingml/shapepropertymap.cxx b/oox/source/drawingml/shapepropertymap.cxx
index 5e34fff..c6168be 100644
--- a/oox/source/drawingml/shapepropertymap.cxx
+++ b/oox/source/drawingml/shapepropertymap.cxx
@@ -41,7 +41,7 @@ namespace {

static const ShapePropertyIds spnDefaultShapeIds =
{
    PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDash, PROP_LineJoint,
    PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDash, PROP_LineCap, PROP_LineJoint,
    PROP_LineStartName, PROP_LineStartWidth, PROP_LineStartCenter, PROP_LineEndName, PROP_LineEndWidth, PROP_LineEndCenter,
    PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillTransparenceGradientName, PROP_FillGradient,
    PROP_FillBitmap, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY,
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 718b76f..021a1e0 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -821,6 +821,14 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet, Referenc
            {
                nColorAlpha = MAX_PERCENT - (mAny.get<sal_Int16>() * PER_PERCENT);
            }
            if (GetProperty(rXPropSet, "LineCap"))
            {
                const LineCap aLineCap = mAny.get<drawing::LineCap>();
                if (aLineCap == LineCap_ROUND)
                    cap = "rnd";
                else if (aLineCap == LineCap_SQUARE)
                    cap = "sq";
            }
            break;
    }

diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index 13734d0..15db0c2 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -289,6 +289,7 @@ LeftMargin
LeftPageFooterContent
LeftPageHeaderContent
LegacyFragment
LineCap
LineColor
LineCount
LineDash
diff --git a/sd/qa/unit/data/odp/closed-shapes.odp b/sd/qa/unit/data/odp/closed-shapes.odp
index 23460c7..d422c74 100644
--- a/sd/qa/unit/data/odp/closed-shapes.odp
+++ b/sd/qa/unit/data/odp/closed-shapes.odp
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 031156c..9cef83c 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -152,7 +152,7 @@ public:
    void testTdf111863();
    void testTdf111518();
    void testTdf100387();
    void testClosingShapes();
    void testClosingShapesAndLineCaps();
    void testRotateFlip();
    void testTdf106867();
    void testTdf112280();
@@ -246,7 +246,7 @@ public:
    CPPUNIT_TEST(testTdf111863);
    CPPUNIT_TEST(testTdf111518);
    CPPUNIT_TEST(testTdf100387);
    CPPUNIT_TEST(testClosingShapes);
    CPPUNIT_TEST(testClosingShapesAndLineCaps);
    CPPUNIT_TEST(testRotateFlip);
    CPPUNIT_TEST(testTdf106867);
    CPPUNIT_TEST(testTdf112280);
@@ -1135,15 +1135,40 @@ void SdOOXMLExportTest2::testTdf100387()
                             "/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:tgtEl/p:spTgt/p:txEl/p:pRg", "end", "2");
}

void SdOOXMLExportTest2::testClosingShapes()
// tdf#126746 Add support for Line Caps import and export
void SdOOXMLExportTest2::testClosingShapesAndLineCaps()
{
    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/closed-shapes.odp"), ODP);
    utl::TempFile tempFile;
    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
    xDocShRef->DoClose();
    xmlDocPtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo/a:pt", 1);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:lnTo[1]/a:pt", 1);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:lnTo[2]/a:pt", 1);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 1);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln", "cap", "rnd");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:miter", 1);

    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 0);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:ln", "cap", "rnd");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:spPr/a:ln/a:miter", 1);

    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 0);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:ln", "cap", "rnd");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[3]/p:spPr/a:ln/a:miter", 1);

    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 0);
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:ln", "cap", "sq");
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[4]/p:spPr/a:ln/a:round", 1);

    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[5]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 0);
    assertXPathNoAttribute(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[5]/p:spPr/a:ln", "cap"); // by default it is "flat" cap style
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[5]/p:spPr/a:ln/a:bevel", 1);

    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[6]/p:spPr/a:custGeom/a:pathLst/a:path/a:close", 0);
    assertXPathNoAttribute(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[5]/p:spPr/a:ln", "cap"); // by default it is "flat" cap style
    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[6]/p:spPr/a:ln/a:round", 1);
}

void SdOOXMLExportTest2::testRotateFlip()
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index e738ec7..b2b8512 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -1584,18 +1584,21 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
            </a:schemeClr>\
          </a:solidFill>\
          <a:prstDash val=\"solid\"/>\
          <a:miter/>\
        </a:ln>\
        <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
          <a:solidFill>\
            <a:schemeClr val=\"phClr\"/>\
          </a:solidFill>\
          <a:prstDash val=\"solid\"/>\
          <a:miter/>\
        </a:ln>\
        <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
          <a:solidFill>\
            <a:schemeClr val=\"phClr\"/>\
          </a:solidFill>\
          <a:prstDash val=\"solid\"/>\
          <a:miter/>\
        </a:ln>\
      </a:lnStyleLst>\
      <a:effectStyleLst>\