tdf#119187 fix: Top-aligned text in PPTX becomes bottom-aligned
Change-Id: Ic6c03e512ce3f6e240d86186fb16e24c86942343
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92051
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx
index 335e373..a781aa5 100644
--- a/oox/source/ppt/pptshape.cxx
+++ b/oox/source/ppt/pptshape.cxx
@@ -425,65 +425,102 @@ namespace
oox::drawingml::ShapePtr PPTShape::findPlaceholder( sal_Int32 nFirstSubType, sal_Int32 nSecondSubType,
const OptValue< sal_Int32 >& oSubTypeIndex, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
{
oox::drawingml::ShapePtr aShapePtr;
oox::drawingml::ShapePtr aChoiceShapePtr1;
oox::drawingml::ShapePtr aChoiceShapePtr2;
oox::drawingml::ShapePtr aChoiceShapePtr3;
oox::drawingml::ShapePtr aChoiceShapePtr4;
std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
while (aRevIter != rShapes.rend())
class Placeholders
{
public:
Placeholders()
: aChoice(5) // resize to 5
{
}
void add(const oox::drawingml::ShapePtr& aShape, sal_Int32 nFirstSubType, sal_Int32 nSecondSubType, const OptValue< sal_Int32 >& oSubTypeIndex)
{
if (!aShape.get())
return;
// get flags
const bool bSameFirstSubType = aShape->getSubType() == nFirstSubType;
const bool bSameSecondSubType = aShape->getSubType() == nSecondSubType;
const bool bSameIndex = aShape->getSubTypeIndex() == oSubTypeIndex;
// get prio
int aPrioIndex = -1;
if (bSameIndex && bSameFirstSubType)
aPrioIndex = 0;
else if (!bSameIndex && bSameFirstSubType)
aPrioIndex = 1;
else if (bSameIndex && bSameSecondSubType)
aPrioIndex = 2;
else if (!bSameIndex && bSameSecondSubType)
aPrioIndex = 3;
else if (bSameIndex)
aPrioIndex = 4;
// add
if (aPrioIndex != -1)
{
if (!aChoice.at(aPrioIndex).get())
{
aChoice.at(aPrioIndex) = aShape;
}
}
}
// return according to prio
oox::drawingml::ShapePtr getByPrio() const
{
for (const oox::drawingml::ShapePtr& aShape : aChoice)
{
if (aShape.get())
{
return aShape;
}
}
return oox::drawingml::ShapePtr();
}
bool hasByPrio(size_t aIndex) const
{
return aChoice.at(aIndex).get();
}
private:
std::vector< oox::drawingml::ShapePtr > aChoice;
} aPlaceholders;
// check all shapes
std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
for (; aRevIter != rShapes.rend(); ++aRevIter)
{
// check shape
if (!bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()))
{
if ((*aRevIter)->getSubTypeIndex() == oSubTypeIndex)
{
if ((*aRevIter)->getSubType() == nFirstSubType)
{
aShapePtr = *aRevIter;
break;
}
else if ((*aRevIter)->getSubType() == nSecondSubType && !aChoiceShapePtr2.get())
aChoiceShapePtr2 = *aRevIter;
else if (!aChoiceShapePtr4.get())
aChoiceShapePtr4 = *aRevIter;
}
else if ((*aRevIter)->getSubType() == nFirstSubType && !aChoiceShapePtr1.get())
aChoiceShapePtr1 = *aRevIter;
else if ((*aRevIter)->getSubType() == nSecondSubType && !aChoiceShapePtr3.get())
aChoiceShapePtr3 = *aRevIter;
const oox::drawingml::ShapePtr& aShape = *aRevIter;
aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
}
// check children
std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
aChoiceShapePtr4 = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly );
if (aChoiceShapePtr4.get())
if (!rChildren.empty())
{
if (aChoiceShapePtr4->getSubType() == nFirstSubType)
const oox::drawingml::ShapePtr aShape = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly );
if (aShape.get())
{
if (aChoiceShapePtr4->getSubTypeIndex() == oSubTypeIndex)
aShapePtr = aChoiceShapePtr4;
else
aChoiceShapePtr1 = aChoiceShapePtr4;
}
else if (aChoiceShapePtr4->getSubType() == nSecondSubType)
{
if (aChoiceShapePtr4->getSubTypeIndex() == oSubTypeIndex)
aChoiceShapePtr2 = aChoiceShapePtr4;
else
aChoiceShapePtr3 = aChoiceShapePtr4;
aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
}
}
if (aShapePtr.get() || aChoiceShapePtr2.get())
if (aPlaceholders.hasByPrio(0) ||
aPlaceholders.hasByPrio(2))
{
break;
++aRevIter;
}
}
if (aShapePtr.get())
return aShapePtr;
if (aChoiceShapePtr1.get())
return aChoiceShapePtr1;
if (aChoiceShapePtr2.get())
return aChoiceShapePtr2;
if (aChoiceShapePtr3.get())
return aChoiceShapePtr3;
return aChoiceShapePtr4;
// return something according to prio
return aPlaceholders.getByPrio();
}
oox::drawingml::ShapePtr PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
diff --git a/sd/qa/unit/data/pptx/tdf119187.pptx b/sd/qa/unit/data/pptx/tdf119187.pptx
new file mode 100644
index 0000000..0c4501a
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf119187.pptx
Binary files differ
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index bccfc56..ef03208 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -208,6 +208,7 @@ public:
void testTdf77747();
void testTdf116266();
void testTdf128684();
void testTdf119187();
void testShapeGlowEffectPPTXImpoer();
bool checkPattern(sd::DrawDocShellRef const & rDocRef, int nShapeNumber, std::vector<sal_uInt8>& rExpected);
@@ -327,6 +328,7 @@ public:
CPPUNIT_TEST(testTdf106638);
CPPUNIT_TEST(testTdf128684);
CPPUNIT_TEST(testTdf113198);
CPPUNIT_TEST(testTdf119187);
CPPUNIT_TEST(testShapeGlowEffectPPTXImpoer);
CPPUNIT_TEST_SUITE_END();
@@ -3080,6 +3082,31 @@ void SdImportTest::testTdf113198()
CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_CENTER, static_cast<style::ParagraphAdjust>(nParaAdjust));
}
void SdImportTest::testTdf119187()
{
std::vector< sd::DrawDocShellRef > xDocShRef;
// load document
xDocShRef.push_back(loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/tdf119187.pptx"), PPTX));
// load resaved document
xDocShRef.push_back(saveAndReload( xDocShRef.at(0).get(), PPTX ));
// check documents
for (const sd::DrawDocShellRef& xDoc : xDocShRef)
{
// get shape properties
const SdrPage* pPage = GetPage(1, xDoc);
CPPUNIT_ASSERT(pPage);
SdrObject* pObj = pPage->GetObj(0);
CPPUNIT_ASSERT(pObj);
const sdr::properties::BaseProperties & rProperties = pObj->GetProperties();
// chcek text vertical alignment
const SdrTextVertAdjustItem& rSdrTextVertAdjustItem = rProperties.GetItem(SDRATTR_TEXT_VERTADJUST);
const SdrTextVertAdjust eTVA = rSdrTextVertAdjustItem.GetValue();
CPPUNIT_ASSERT_EQUAL(SDRTEXTVERTADJUST_TOP, eTVA);
}
}
void SdImportTest::testShapeGlowEffectPPTXImpoer()
{
sd::DrawDocShellRef xDocShRef