diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index e4099dd6e2ad..c69cfee4c4d6 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -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; } diff --git a/oox/source/drawingml/transform2dcontext.cxx b/oox/source/drawingml/transform2dcontext.cxx index 656cb41a4b7f..63d197abb81b 100644 --- a/oox/source/drawingml/transform2dcontext.cxx +++ b/oox/source/drawingml/transform2dcontext.cxx @@ -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(adj3, 0, maxAdj3); + double q2 = adj3 * std::min(nWidth, nHeight) / nHeight; + double maxAdj4 = 100000.0 - q2; + adj4 = std::clamp(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 diff --git a/sd/qa/unit/data/pptx/tdf150789.pptx b/sd/qa/unit/data/pptx/tdf150789.pptx new file mode 100644 index 000000000000..6e0a9442949c Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf150789.pptx differ diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index 3d9423497232..41beb185e0c6 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -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(pPage->GetObj(0)); + + const std::array 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"); diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx index 2f5e6a21a03e..996071b27e92 100644 --- a/svx/source/svdraw/svdoashp.cxx +++ b/svx/source/svdraw/svdoashp.cxx @@ -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 diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 3b4cf6ba72eb..88def27d0d2c 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -619,7 +619,7 @@ void SdrTextObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const } // See also: ::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()) {