tdf#138711 sw textbox: capture fly when its draw object is captured

Load the bugdoc, notice that the only shape in the document has a
captured (inside the page frame) draw shape, but its inner fly frame is
not captured inside the page frame, so a small top margin is paired with
a larger right margin, which is unexpected.

This is nominally a regression from commit
9835a5823e (sw textboxes: reimplement ODF
import/export, 2014-10-04), because previously the ODF markup for Writer
TextBoxes were ignored, so we had correct position of the shape text at
the price of losing complex content.

Fix the problem similar to what commit
a0b6587c4a (tdf#161199 sw
DoNotCaptureDrawObjsOnPage: capture wrap=none draw objects, 2024-06-13)
did: if we detect that the fly frame is part of a TextBox, then work
with the wrap type of the draw format, since these inner fly frames
always have their wrap type set to "through".

This fixes the unexpected position of the fly frame and keeps the import
of complex content working.

Change-Id: Ib0d861af0fac74d93a09178c10bc19a1b45e3ce7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174987
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Miklos Vajna 2024-10-16 08:13:07 +02:00
parent 71d69554b2
commit c8549fa320
4 changed files with 65 additions and 1 deletions

View file

@ -14,6 +14,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,sw_core_layout))
$(eval $(call gb_CppunitTest_use_common_precompiled_header,sw_core_layout))
$(eval $(call gb_CppunitTest_add_exception_objects,sw_core_layout, \
sw/qa/core/layout/anchoredobject \
sw/qa/core/layout/calcmove \
sw/qa/core/layout/fly \
sw/qa/core/layout/flycnt \

View file

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <swmodeltestbase.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <docsh.hxx>
#include <pagefrm.hxx>
#include <rootfrm.hxx>
#include <sortedobjs.hxx>
#include <anchoredobject.hxx>
namespace
{
/// Covers sw/source/core/layout/anchoredobject.cxx fixes.
class Test : public SwModelTestBase
{
public:
Test()
: SwModelTestBase(u"/sw/qa/core/layout/data/"_ustr)
{
}
};
CPPUNIT_TEST_FIXTURE(Test, testTextBoxFlyPageCapture)
{
// Given a document with a draw shape with complex content, positioned to be outside the page
// frame, but capture to page frame is enabled:
// When loading that document:
createSwDoc("textbox-fly-page-capture.odt");
// Then make sure the right edge of the inner fly frame is the same as the right edge of the
// draw frame:
SwDoc* pDoc = getSwDocShell()->GetDoc();
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
auto pPage = pLayout->GetLower()->DynCastPageFrame();
CPPUNIT_ASSERT(pPage->GetSortedObjs());
const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPageObjs.size());
SwAnchoredObject* pDraw = rPageObjs[0];
SwTwips nDrawRight = pDraw->GetObjRect().Right();
SwAnchoredObject* pFly = rPageObjs[1];
SwTwips nFlyRight = pFly->GetObjRect().Right();
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 5081
// - Actual : 4798
// i.e. the position of the draw shape was corrected to be inside the page frame, but this
// didn't happen for the inner fly frame.
CPPUNIT_ASSERT_EQUAL(nDrawRight, nFlyRight);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Binary file not shown.

View file

@ -781,7 +781,11 @@ bool SwAnchoredObject::IsDraggingOffPageAllowed(const SwFrameFormat* pFrameForma
{
assert(pFrameFormat);
const bool bDisablePositioning = pFrameFormat->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING);
const bool bIsWrapThrough = pFrameFormat->GetSurround().GetSurround() == text::WrapTextMode::WrapTextMode_THROUGH;
// If this fly is paired with a draw format, then take the wrap text mode from the outer draw
// format, since the fly format is always wrap through.
SwFrameFormat* pDrawFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFrameFormat, RES_FLYFRMFMT);
const SwFrameFormat* pFormat = pDrawFormat ? pDrawFormat : pFrameFormat;
const bool bIsWrapThrough = pFormat->GetSurround().GetSurround() == text::WrapTextMode::WrapTextMode_THROUGH;
return bDisablePositioning && bIsWrapThrough;
}