tdf#109223: PPTX: Vertical flip of child shape is not imported correctly

Group shape level vertical flip is not handled well. Recent handling
of group shape's transformation makes it hard to import this attribute,
but we can import the right text direction at least.

Change-Id: Ib9e39e3dcb28a95fabc61c13152a3f7296fbd4c3
Reviewed-on: https://gerrit.libreoffice.org/40554
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 6591ebc..c98bf4e 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -137,6 +137,7 @@ public:

    void                            setRotation( sal_Int32 nRotation ) { mnRotation = nRotation; }
    void                            setFlip( bool bFlipH, bool bFlipV ) { mbFlipH = bFlipH; mbFlipV = bFlipV; }
    void                            applyParentTextFlipV(bool bTextFlipV) { mbInheritedTextFlipV = bTextFlipV; }
    void                            addChild( const ShapePtr& rChildPtr ) { maChildren.push_back( rChildPtr ); }
    std::vector< ShapePtr >&        getChildren() { return maChildren; }

@@ -310,6 +311,7 @@ private:
    sal_Int32                       mnRotation;
    bool                            mbFlipH;
    bool                            mbFlipV;
    bool                            mbInheritedTextFlipV; // Used by group shapes only
    bool                            mbHidden;
    bool                            mbHiddenMasterShape; // master shapes can be hidden in layout slides
                                                         // we need separate flag because we don't want
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 3368cd0..ccc73d8 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -115,6 +115,7 @@ Shape::Shape( const sal_Char* pServiceName, bool bDefaultHeight )
, mnRotation( 0 )
, mbFlipH( false )
, mbFlipV( false )
, mbInheritedTextFlipV(false)
, mbHidden( false )
, mbHiddenMasterShape( false )
, mbLockedCanvas( false )
@@ -156,6 +157,7 @@ Shape::Shape( const ShapePtr& pSourceShape )
, mnRotation( pSourceShape->mnRotation )
, mbFlipH( pSourceShape->mbFlipH )
, mbFlipV( pSourceShape->mbFlipV )
, mbInheritedTextFlipV(pSourceShape->mbInheritedTextFlipV)
, mbHidden( pSourceShape->mbHidden )
, mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape )
, mbLockedCanvas( pSourceShape->mbLockedCanvas )
@@ -312,6 +314,7 @@ void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText )
    mnRotation = rReferencedShape.mnRotation;
    mbFlipH = rReferencedShape.mbFlipH;
    mbFlipV = rReferencedShape.mbFlipV;
    mbInheritedTextFlipV = rReferencedShape.mbInheritedTextFlipV;
    mbHidden = rReferencedShape.mbHidden;
}

@@ -385,6 +388,7 @@ void Shape::addChildren(
    std::vector< ShapePtr >::iterator aIter( rMaster.maChildren.begin() );
    while( aIter != rMaster.maChildren.end() ) {
        (*aIter)->setMasterTextListStyle( mpMasterTextListStyle );
        (*aIter)->applyParentTextFlipV(mbInheritedTextFlipV != mbFlipV);
        (*aIter++)->addShape( rFilterBase, pTheme, rxShapes, aChildTransformation, getFillProperties(), pShapeMap );
    }
}
@@ -1065,6 +1069,8 @@ Reference< XShape > const & Shape::createAndInsert(
            if( getTextBody() )
            {
                sal_Int32 nTextRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moRotation.get( 0 ) );
                if(mbInheritedTextFlipV)
                    nTextRotateAngle -= 180 * 60000;
                /* OOX measures text rotation clockwise in 1/60000th degrees,
                   relative to the containing shape. setTextRotateAngle wants
                   degrees anticlockwise. */
diff --git a/sd/qa/unit/data/pptx/tdf109223.pptx b/sd/qa/unit/data/pptx/tdf109223.pptx
new file mode 100755
index 0000000..0f68796
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf109223.pptx
Binary files differ
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 58681c8..dab76b1d 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -163,6 +163,7 @@ public:
    void testTdf108925();
    void testTdf109067();
    void testSmartArt1();
    void testTdf109223();

    bool checkPattern(sd::DrawDocShellRef& rDocRef, int nShapeNumber, std::vector<sal_uInt8>& rExpected);
    void testPatternImport();
@@ -234,6 +235,7 @@ public:
    CPPUNIT_TEST(testTdf108925);
    CPPUNIT_TEST(testTdf109067);
    CPPUNIT_TEST(testSmartArt1);
    CPPUNIT_TEST(testTdf109223);

    CPPUNIT_TEST_SUITE_END();
};
@@ -2254,6 +2256,38 @@ void SdImportTest::testSmartArt1()
    xDocShRef->DoClose();
}

void SdImportTest::testTdf109223()
{
    // In the test document flipV attribute is defined for a group shape
    // This transformation is not applied on child shapes
    // To make the text direction right at least I added an additional text rotation when parent shape is flipped.
    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/tdf109223.pptx"), PPTX);
    uno::Reference< container::XIndexAccess > xGroupShape(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY_THROW);
    uno::Reference< beans::XPropertySet > xShape(xGroupShape->getByIndex(1), uno::UNO_QUERY);

    // Check the shape text to make sure we test the right shape
    OUString sText = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY)->getString();
    CPPUNIT_ASSERT_EQUAL(OUString("Tested child shape"), sText);

    // Check the attribute inherited from parent shape
    bool bAttributeFound = false;
    uno::Sequence<beans::PropertyValue> aProps;
    CPPUNIT_ASSERT(xShape->getPropertyValue("CustomShapeGeometry") >>= aProps);
    for (sal_Int32 i = 0; i < aProps.getLength(); ++i)
    {
        const beans::PropertyValue& rProp = aProps[i];
        if (rProp.Name == "TextPreRotateAngle")
        {
            CPPUNIT_ASSERT_EQUAL(sal_Int32(180), rProp.Value.get<sal_Int32>());
            bAttributeFound = true;
            break;
        }
    }

    CPPUNIT_ASSERT_EQUAL(true, bAttributeFound);
    xDocShRef->DoClose();
}

CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest);

CPPUNIT_PLUGIN_IMPLEMENT();