tdf#150789 - FILEOPEN PPTX: fix text in SmartArt vertically off

Calculate correctly the textbox area of upArrowCallout and
downArrowCallout shapes in group shapes. In grouped list
text area does not cover the whole shape but just a part of it at the top.

In case of upArrowCallout and downArrowCallout the arrow size of the shape
is not included in the textbox area of the full shape.

Change-Id: If732305747c20da55bbd2896522c0b9c05cc4b4b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178343
Tested-by: Gabor Kelemen <gabor.kelemen.extern@allotropia.de>
Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Balazs Varga 2024-12-12 09:23:48 +01:00
parent e7763739ae
commit 9948c2ed03
6 changed files with 82 additions and 7 deletions

View File

@ -418,7 +418,7 @@ public:
virtual void TakeTextRect( SdrOutliner& rOutliner, tools::Rectangle& rTextRect, bool bNoEditText,
tools::Rectangle* pAnchorRect, bool bLineWidth = true ) const;
// Takes writing direction into account when adjusting the rectangle
void AdjustRectToTextDistance(tools::Rectangle& rAnchorRect) const;
void AdjustRectToTextDistance(tools::Rectangle& rAnchorRect, double fExtraRot = 0.0) const;
virtual void TakeTextAnchorRect(::tools::Rectangle& rAnchorRect) const;
const GeoStat& GetGeoStat() const { return maGeo; }

View File

@ -135,6 +135,39 @@ bool ConstructPresetTextRectangle(Shape& rShape, awt::Rectangle& rRect)
rRect.Height = rShape.getSize().Height;
return true;
}
case XML_upArrowCallout:
case XML_downArrowCallout:
{
// The identifiers here reflect the guides name value in presetShapeDefinitions.xml
sal_Int32 nWidth = rShape.getSize().Width;
sal_Int32 nHeight = rShape.getSize().Height;
if (nWidth == 0 || nHeight == 0)
return false;
// double adj1 = 25000.0;
// double adj2 = 25000.0;
double adj3 = 25000.0; // height of arrow head
double adj4 = 64977.0; // height of arrow shaft
const auto& aAdjGdList = rShape.getCustomShapeProperties()->getAdjustmentGuideList();
if (aAdjGdList.size() == 4)
{
// adj1 = aAdjGdList[0].maFormula.toDouble();
// adj2 = aAdjGdList[1].maFormula.toDouble();
adj3 = aAdjGdList[2].maFormula.toDouble();
adj4 = aAdjGdList[3].maFormula.toDouble();
}
double maxAdj3 = 100000.0 * nHeight / std::min(nWidth, nHeight);
adj3 = std::clamp<double>(adj3, 0, maxAdj3);
double q2 = adj3 * std::min(nWidth, nHeight) / nHeight;
double maxAdj4 = 100000.0 - q2;
adj4 = std::clamp<double>(adj4, 0, maxAdj4);
rRect.X = rShape.getPosition().X;
rRect.Y = rShape.getPosition().Y;
rRect.Width = rShape.getSize().Width;
rRect.Height = nHeight * adj4 / 100000.0;
return true;
}
case XML_gear6:
{
// The identifiers here reflect the guides name value in presetShapeDefinitions.xml

Binary file not shown.

View File

@ -1340,6 +1340,37 @@ CPPUNIT_TEST_FIXTURE(SdImportTest, testBnc870237)
CPPUNIT_ASSERT_EQUAL(sal_Int32(-158), pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST).GetValue());
}
CPPUNIT_TEST_FIXTURE(SdImportTest, testTdf150789)
{
createSdImpressDoc("pptx/tdf150789.pptx");
const SdrPage* pPage = GetPage(1);
// Simulate a:ext inside dsp:txXfrm with changing the lower distance of prst="upArrowCallout" textbox
const SdrObjGroup* pGroupObj = dynamic_cast<SdrObjGroup*>(pPage->GetObj(0));
const std::array<size_t, 2> nShapes = { 4, 7 };
for (auto i : nShapes)
{
const SdrObject* pObj = pGroupObj->GetSubList()->GetObj(i);
CPPUNIT_ASSERT_MESSAGE("no object", pObj != nullptr);
OUString sShapeType;
const SdrCustomShapeGeometryItem& rGeometryItem(
pObj->GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY));
const css::uno::Any aAny = *rGeometryItem.GetPropertyValueByName("Type");
if (aAny.hasValue())
aAny >>= sShapeType;
CPPUNIT_ASSERT_EQUAL(OUString("ooxml-upArrowCallout"), sShapeType);
CPPUNIT_ASSERT_EQUAL(sal_Int32(395),
pObj->GetMergedItem(SDRATTR_TEXT_UPPERDIST).GetValue());
CPPUNIT_ASSERT_EQUAL(sal_Int32(1424),
pObj->GetMergedItem(SDRATTR_TEXT_LOWERDIST).GetValue());
CPPUNIT_ASSERT_EQUAL(sal_Int32(395),
pObj->GetMergedItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
CPPUNIT_ASSERT_EQUAL(sal_Int32(395), pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST).GetValue());
}
}
CPPUNIT_TEST_FIXTURE(SdImportTest, testCreationDate)
{
createSdImpressDoc("fdo71434.pptx");

View File

@ -2650,7 +2650,8 @@ void SdrObjCustomShape::TakeTextAnchorRect( tools::Rectangle& rAnchorRect ) cons
if ( GetTextBounds( rAnchorRect ) )
{
Point aRotateRef( maSnapRect.Center() );
AdjustRectToTextDistance(rAnchorRect);
const double fExtraTextRotation(GetExtraTextRotation());
AdjustRectToTextDistance(rAnchorRect, fExtraTextRotation);
if ( rAnchorRect.GetWidth() < 2 )
rAnchorRect.SetRight( rAnchorRect.Left() + 1 ); // minimal width is 2

View File

@ -619,7 +619,7 @@ void SdrTextObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const
}
// See also: <unnamed>::getTextAnchorRange in svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
void SdrTextObj::AdjustRectToTextDistance(tools::Rectangle& rAnchorRect) const
void SdrTextObj::AdjustRectToTextDistance(tools::Rectangle& rAnchorRect, double fExtraRot) const
{
const tools::Long nLeftDist = GetTextLeftDistance();
const tools::Long nRightDist = GetTextRightDistance();
@ -627,10 +627,20 @@ void SdrTextObj::AdjustRectToTextDistance(tools::Rectangle& rAnchorRect) const
const tools::Long nLowerDist = GetTextLowerDistance();
if (!IsVerticalWriting())
{
rAnchorRect.AdjustLeft(nLeftDist);
rAnchorRect.AdjustTop(nUpperDist);
rAnchorRect.AdjustRight(-nRightDist);
rAnchorRect.AdjustBottom(-nLowerDist);
if (fExtraRot == 180.0)
{
rAnchorRect.AdjustLeft(nLeftDist);
rAnchorRect.AdjustTop(-nUpperDist);
rAnchorRect.AdjustRight(-nRightDist);
rAnchorRect.AdjustBottom(nLowerDist);
}
else
{
rAnchorRect.AdjustLeft(nLeftDist);
rAnchorRect.AdjustTop(nUpperDist);
rAnchorRect.AdjustRight(-nRightDist);
rAnchorRect.AdjustBottom(-nLowerDist);
}
}
else if (IsTopToBottom())
{