diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-11-22 08:40:47 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-11-22 10:07:52 +0100 |
commit | 2302ebefb2e25878e8fe1e64d208f265f87d5b9b (patch) | |
tree | 3dffdb748e7c81b9d91aef5bc1005efc2192a94c /sw/qa/uibase | |
parent | 4c8411a55aa10bafdda35b8e60b6a1a5e1600329 (diff) |
sw, createTextRangeByPixelPosition(): fix crash when the position is an image
Using createTextRangeByPixelPosition() with a pixel position that leads
to a graphic node resulted in a crash.
The direct reason for this is that the makeMark() call in
SwXTextRange::SetPositions() returns nullptr in case rPaM points to a
graphic node, but later we dereference that result unconditionally. This
also uncovers that the XTextRange returned by
createTextRangeByPixelPosition() is meant to point to a text node, but a
pixel position may be closest to a graphic node.
Fix the problem by explicitly checking for graphic nodes; and try to
look up the anchor position of such graphics, which will be definitely a
text node.
In practice this will mean that in case the image's anchor type is
as-char, then we'll return a cursor position which will be on the left
hand side of the image.
Change-Id: Ief58148247fe3cd4371ed245b4eff5b45ca2aa15
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143092
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw/qa/uibase')
-rw-r--r-- | sw/qa/uibase/uno/uno.cxx | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index a1484b1ce629..3364ef8b0cd2 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -12,6 +12,7 @@ #include <com/sun/star/frame/XModel2.hpp> #include <com/sun/star/text/XTextViewTextRangeSupplier.hpp> #include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/text/XTextDocument.hpp> #include <vcl/scheduler.hxx> @@ -20,6 +21,11 @@ #include <unotextrange.hxx> #include <view.hxx> #include <wrtsh.hxx> +#include <rootfrm.hxx> +#include <sortedobjs.hxx> +#include <anchoredobject.hxx> +#include <frameformats.hxx> +#include <fmtanchr.hxx> /// Covers sw/source/uibase/uno/ fixes. class SwUibaseUnoTest : public SwModelTestBase @@ -94,6 +100,57 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testCreateTextRangeByPixelPosition) CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nActual); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testCreateTextRangeByPixelPositionGraphic) +{ + // Given a document with an as-char image and the center of that image in pixels: + createSwDoc(); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xTextGraphic( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + xTextGraphic->setPropertyValue("AnchorType", + uno::Any(text::TextContentAnchorType_AS_CHARACTER)); + xTextGraphic->setPropertyValue("Width", uno::Any(static_cast<sal_Int32>(10000))); + xTextGraphic->setPropertyValue("Height", uno::Any(static_cast<sal_Int32>(10000))); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xBodyText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor(xBodyText->createTextCursor()); + uno::Reference<text::XTextContent> xTextContent(xTextGraphic, uno::UNO_QUERY); + xBodyText->insertTextContent(xCursor, xTextContent, false); + SwDoc* pDoc = getSwDoc(); + SwDocShell* pDocShell = pDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwRootFrame* pLayout = pWrtShell->GetLayout(); + SwFrame* pPage = pLayout->GetLower(); + SwFrame* pBody = pPage->GetLower(); + SwFrame* pText = pBody->GetLower(); + SwSortedObjs& rDrawObjs = *pText->GetDrawObjs(); + SwAnchoredObject* pAnchored = rDrawObjs[0]; + Point aLogic = pAnchored->GetObjRect().Center(); + SwView* pView = pDocShell->GetView(); + SwEditWin& rEditWin = pView->GetEditWin(); + Point aPixel = rEditWin.LogicToPixel(aLogic); + + // When converting that pixel position to a document model position (text range): + uno::Reference<frame::XModel2> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xControllers = xModel->getControllers(); + uno::Reference<text::XTextViewTextRangeSupplier> xController(xControllers->nextElement(), + uno::UNO_QUERY); + awt::Point aPoint(aPixel.getX(), aPixel.getY()); + // Without the accompanying fix in place, this test would have crashed, because an XTextRange + // can't point to a graphic node. + uno::Reference<text::XTextRange> xTextRange + = xController->createTextRangeByPixelPosition(aPoint); + + // Then make sure that the anchor of the image is returned: + const SwFrameFormats& rFormats = *pDoc->GetSpzFrameFormats(); + const SwFrameFormat* pFormat = rFormats[0]; + SwPosition aAnchorPos(*pFormat->GetAnchor().GetContentAnchor()); + auto pTextRange = dynamic_cast<SwXTextRange*>(xTextRange.get()); + SwPaM aPaM(pDoc->GetNodes()); + pTextRange->GetPositions(aPaM); + CPPUNIT_ASSERT_EQUAL(aAnchorPos, *aPaM.GetPoint()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |