[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

Miklos Vajna vmiklos at collabora.co.uk
Fri Apr 1 14:23:25 UTC 2016


 sw/inc/textboxhelper.hxx                                            |    2 
 sw/qa/extras/uiwriter/data/tdf99004.docx                            |binary
 sw/qa/extras/uiwriter/uiwriter.cxx                                  |   17 ++++++
 sw/source/core/doc/textboxhelper.cxx                                |   10 +++
 sw/source/core/inc/anchoredobjectposition.hxx                       |    9 +--
 sw/source/core/objectpositioning/anchoredobjectposition.cxx         |   28 ++++++----
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx  |   20 +++----
 sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx |    4 -
 8 files changed, 60 insertions(+), 30 deletions(-)

New commits:
commit cd1b2f923e0b0be89a5d1c8cbc647133aac09ed5
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 1 14:44:09 2016 +0200

    tdf#99004 SwAnchoredObjectPosition: handle textboxes when determining surround
    
    Writer TextBoxes are always wrapped "through", so that they can appear
    inside their shapes. However, the surround of the shape may influence
    its position. So when surround is asked for anchor position purposes,
    take the surround of the TextBox's "parent" shape instead of the one of
    the TextBox directly.
    
    With this, the TextBox in the bugdoc is properly positioned inside its
    parent shape as expected. (The problem only happens when at least two
    shapes are anchored to the same paragraph.)
    
    Change-Id: I0cf8a41080e6759aa395c119d862c4be79574d66
    Reviewed-on: https://gerrit.libreoffice.org/23720
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index d72ba4d..2b3e0873 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -87,6 +87,8 @@ public:
     static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(css::lang::IndexOutOfBoundsException);
     /// Get the order of the shape, excluding TextBoxes.
     static sal_Int32 getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes);
+    /// If pTextBox is a textbox, then set rWrapThrough to the surround of its shape.
+    static void getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough);
 
     /// Saves the current shape -> textbox links in a map, so they can be restored later.
     static void saveLinks(const SwFrameFormats& rFormats, std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks);
diff --git a/sw/qa/extras/uiwriter/data/tdf99004.docx b/sw/qa/extras/uiwriter/data/tdf99004.docx
new file mode 100644
index 0000000..ef86440
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf99004.docx differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index b450520..56db245 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -195,6 +195,7 @@ public:
     void testTdf88453Table();
     void testClassificationPaste();
     void testTdf98987();
+    void testTdf99004();
 
     CPPUNIT_TEST_SUITE(SwUiWriterTest);
     CPPUNIT_TEST(testReplaceForward);
@@ -292,6 +293,7 @@ public:
     CPPUNIT_TEST(testTdf88453Table);
     CPPUNIT_TEST(testClassificationPaste);
     CPPUNIT_TEST(testTdf98987);
+    CPPUNIT_TEST(testTdf99004);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -3592,6 +3594,21 @@ void SwUiWriterTest::testTdf98987()
     CPPUNIT_ASSERT(nRectangle2 < nRectangle3);
 }
 
+void SwUiWriterTest::testTdf99004()
+{
+    createDoc("tdf99004.docx");
+    calcLayout();
+    xmlDocPtr pXmlDoc = parseLayoutDump();
+    sal_Int32 nTextbox1Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "top").toInt32();
+    sal_Int32 nTextBox1Height = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32();
+    sal_Int32 nTextBox1Bottom = nTextbox1Top + nTextBox1Height;
+
+    assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/sdrObject", "name", "Rectangle 2");
+    sal_Int32 nRectangle2Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top").toInt32();
+    // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
+    CPPUNIT_ASSERT(nTextBox1Bottom < nRectangle2Top);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 1d334b5..b52c9cd 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -27,6 +27,7 @@
 #include <mvsave.hxx>
 #include <sortedobjs.hxx>
 #include <cntfrm.hxx>
+#include <fmtsrnd.hxx>
 
 #include <editeng/unoprnms.hxx>
 #include <editeng/charrotateitem.hxx>
@@ -264,6 +265,15 @@ sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject, std::set<const Sw
     return pObject->GetOrdNum();
 }
 
+void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough)
+{
+    std::map<SwFrameFormat*, SwFrameFormat*> aMap = findShapes(pTextBox->GetDoc());
+    std::map<SwFrameFormat*, SwFrameFormat*>::iterator it = aMap.find(const_cast<SwFrameFormat*>(pTextBox));
+    if (it != aMap.end())
+        // pTextBox is indeed a TextBox, it->second is its shape.
+        rWrapThrough = it->second->GetSurround().GetSurround() == SURROUND_THROUGHT;
+}
+
 SwFrameFormat* SwTextBoxHelper::findTextBox(uno::Reference<drawing::XShape> xShape)
 {
     SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
diff --git a/sw/source/core/inc/anchoredobjectposition.hxx b/sw/source/core/inc/anchoredobjectposition.hxx
index d6c6224..d50c0a5 100644
--- a/sw/source/core/inc/anchoredobjectposition.hxx
+++ b/sw/source/core/inc/anchoredobjectposition.hxx
@@ -126,17 +126,15 @@ namespace objectpositioning
 
             #i11860#
         */
-        static SwTwips _GetTopForObjPos( const SwFrame& _rFrame,
+        SwTwips _GetTopForObjPos( const SwFrame& _rFrame,
                                   const SwRectFn& _fnRect,
-                                  const bool _bVert,
-                                  bool bWrapThrough );
+                                  const bool _bVert ) const;
 
         void _GetVertAlignmentValues( const SwFrame& _rVertOrientFrame,
                                       const SwFrame& _rPageAlignLayFrame,
                                       const sal_Int16 _eRelOrient,
                                       SwTwips&      _orAlignAreaHeight,
-                                      SwTwips&      _orAlignAreaOffset,
-                                      bool bWrapThrough ) const;
+                                      SwTwips&      _orAlignAreaOffset ) const;
 
         // #i26791# - add output parameter <_roVertOffsetToFrameAnchorPos>
         SwTwips _GetVertRelPos( const SwFrame& _rVertOrientFrame,
@@ -146,7 +144,6 @@ namespace objectpositioning
                                 const SwTwips          _nVertPos,
                                 const SvxLRSpaceItem& _rLRSpacing,
                                 const SvxULSpaceItem& _rULSpacing,
-                                bool bWrapThrough,
                                 SwTwips& _roVertOffsetToFrameAnchorPos ) const;
 
         /** adjust calculated vertical in order to keep object inside
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
index fbadb3a..f47c720 100644
--- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -37,6 +37,7 @@
 #include <ndtxt.hxx>
 #include <IDocumentSettingAccess.hxx>
 #include <textboxhelper.hxx>
+#include <fmtsrnd.hxx>
 
 using namespace ::com::sun::star;
 using namespace objectpositioning;
@@ -156,8 +157,7 @@ SwTwips SwAnchoredObjectPosition::ToCharTopOfLine() const
 */
 SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrame& _rFrame,
                                                     const SwRectFn& _fnRect,
-                                                    const bool _bVert,
-                                                    bool bWrapThrough )
+                                                    const bool _bVert ) const
 {
     SwTwips nTopOfFrameForObjPos = (_rFrame.Frame().*_fnRect->fnGetTop)();
 
@@ -174,6 +174,12 @@ SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrame& _rFrame,
             nTopOfFrameForObjPos +=
                 rTextFrame.GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid();
 
+            const SwFormatSurround& rSurround = mpFrameFormat->GetSurround();
+            bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
+            // If the frame format is a TextBox of a draw shape, then use the
+            // surround of the original shape.
+            SwTextBoxHelper::getShapeWrapThrough(mpFrameFormat, bWrapThrough);
+
             // Get the offset between the top of the text frame and the top of
             // the first line inside the frame that has more than just fly
             // portions.
@@ -189,14 +195,13 @@ void SwAnchoredObjectPosition::_GetVertAlignmentValues(
                                         const SwFrame& _rPageAlignLayFrame,
                                         const sal_Int16 _eRelOrient,
                                         SwTwips&      _orAlignAreaHeight,
-                                        SwTwips&      _orAlignAreaOffset,
-                                        bool bWrapThrough ) const
+                                        SwTwips&      _orAlignAreaOffset ) const
 {
     SwTwips nHeight = 0;
     SwTwips nOffset = 0;
     SWRECTFN( (&_rVertOrientFrame) )
     // #i11860# - top of <_rVertOrientFrame> for object positioning
-    const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrame, fnRect, bVert, bWrapThrough );
+    const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrame, fnRect, bVert );
     // #i11860# - upper space amount of <_rVertOrientFrame> considered
     // for previous frame
     const SwTwips nVertOrientUpperSpaceForPrevFrameAndPageGrid =
@@ -327,7 +332,6 @@ SwTwips SwAnchoredObjectPosition::_GetVertRelPos(
                                     const SwTwips          _nVertPos,
                                     const SvxLRSpaceItem& _rLRSpacing,
                                     const SvxULSpaceItem& _rULSpacing,
-                                    bool bWrapThrough,
                                     SwTwips& _roVertOffsetToFrameAnchorPos ) const
 {
     SwTwips nRelPosY = 0;
@@ -336,7 +340,7 @@ SwTwips SwAnchoredObjectPosition::_GetVertRelPos(
     SwTwips nAlignAreaHeight;
     SwTwips nAlignAreaOffset;
     _GetVertAlignmentValues( _rVertOrientFrame, _rPageAlignLayFrame,
-                             _eRelOrient, nAlignAreaHeight, nAlignAreaOffset, bWrapThrough );
+                             _eRelOrient, nAlignAreaHeight, nAlignAreaOffset );
 
     nRelPosY = nAlignAreaOffset;
     const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
@@ -693,10 +697,12 @@ void SwAnchoredObjectPosition::_GetHoriAlignmentValues( const SwFrame&  _rHoriOr
         {
             nWidth = (_rHoriOrientFrame.Frame().*fnRect->fnGetWidth)();
 
-            // When positioning TextBoxes, always ignore flys anchored at the
-            // text frame, as we do want to have the textbox overlap with its
-            // draw shape.
-            bool bIgnoreFlysAnchoredAtFrame = !_bObjWrapThrough || SwTextBoxHelper::isTextBox(&GetObject());
+            bool bWrapThrough = _bObjWrapThrough;
+            // If the frame format is a TextBox of a draw shape, then use the
+            // surround of the original shape.
+            SwTextBoxHelper::getShapeWrapThrough(mpFrameFormat, bWrapThrough);
+
+            bool bIgnoreFlysAnchoredAtFrame = !bWrapThrough;
             nOffset = _rHoriOrientFrame.IsTextFrame() ?
                    static_cast<const SwTextFrame&>(_rHoriOrientFrame).GetBaseOfstForFly( bIgnoreFlysAnchoredAtFrame ) :
                    0;
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 5abf15b..f51d061 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -248,7 +248,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
             SwTwips nAlignAreaOffset;
             _GetVertAlignmentValues( *pOrientFrame, rPageAlignLayFrame,
                                      aVert.GetRelationOrient(),
-                                     nAlignAreaHeight, nAlignAreaOffset, bWrapThrough );
+                                     nAlignAreaHeight, nAlignAreaOffset );
 
             // determine relative vertical position
             SwTwips nRelPosY = nAlignAreaOffset;
@@ -380,16 +380,16 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
             {
                 // #i11860# - use new method <_GetTopForObjPos>
                 // to get top of frame for object positioning.
-                const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+                const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
                 nRelPosY += (*fnRect->fnYDiff)( nTopOfOrient,
-                                      _GetTopForObjPos( rAnchorTextFrame, fnRect, bVert, bWrapThrough ) );
+                                      _GetTopForObjPos( rAnchorTextFrame, fnRect, bVert ) );
             }
 
             // #i42124# - capture object inside vertical
             // layout environment.
             {
                 const SwTwips nTopOfAnch =
-                                _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+                                _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
                 const SwLayoutFrame& rVertEnvironLayFrame =
                     aEnvOfObj.GetVertEnvironmentLayoutFrame(
                                             *(pOrientFrame->GetUpper()) );
@@ -486,7 +486,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
             {
                 // #i11860# - use new method <_GetTopForObjPos>
                 // to get top of frame for object positioning.
-                SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+                SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
                 if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR )
                 {
                     nVertOffsetToFrameAnchorPos = (*fnRect->fnYDiff)(
@@ -509,7 +509,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                 // #i11860# - use new method <_GetTopForObjPos>
                 // to get top of frame for object positioning.
                 const SwTwips nTopOfOrient =
-                        _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+                        _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
                 // Increase <nRelPosY> by margin height,
                 // if position is vertical aligned to "paragraph text area"
                 if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
@@ -562,7 +562,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                 maOffsetToFrameAnchorPos.Y() = nVertOffsetToFrameAnchorPos;
             // #i11860# - use new method <_GetTopForObjPos>
             // to get top of frame for object positioning.
-            const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+            const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
             if( nRelPosY <= 0 )
             {
                 // Allow negative position, but keep it
@@ -717,7 +717,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
         // We need to calculate the part's absolute position, in order for
         // it to be put onto the right page and to be pulled into the
         // LayLeaf's PrtArea
-        const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+        const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
         if( bVert )
         {
             // --> OD 2009-08-31 #monglianlayout#
@@ -979,7 +979,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
 
         // set calculated vertical position in order to determine correct
         // frame, the horizontal position is oriented at.
-        const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+        const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
         if( bVert )
         {
             // --> OD 2009-08-31 #mongolianlayout#
@@ -1039,7 +1039,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
     }
 
     // set absolute position at object
-    const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+    const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
     if( bVert )
     {
         // --> OD 2009-08-31 #mongolianlayout#
diff --git a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
index 09b6172..45d8f09 100644
--- a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
@@ -81,12 +81,10 @@ void SwToLayoutAnchoredObjectPosition::CalcPosition()
         }
         // #i26791# - get vertical offset to frame anchor position.
         SwTwips nVertOffsetToFrameAnchorPos( 0L );
-        const SwFormatSurround& rSurround = rFrameFormat.GetSurround();
-        const bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
         SwTwips nRelPosY =
                 _GetVertRelPos( GetAnchorFrame(), GetAnchorFrame(), eVertOrient,
                                 aVert.GetRelationOrient(), aVert.GetPos(),
-                                rLR, rUL, bWrapThrough, nVertOffsetToFrameAnchorPos );
+                                rLR, rUL, nVertOffsetToFrameAnchorPos );
 
         // keep the calculated relative vertical position - needed for filters
         // (including the xml-filter)


More information about the Libreoffice-commits mailing list