sw/qa/core/text/itrpaint.cxx  |   11 +++++++++++
 sw/source/core/layout/fly.cxx |    7 ++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

New commits:
commit 36a6ca3e6de7106bdd0497386d29a05337c5a90c
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Jan 28 15:26:24 2026 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Thu Jan 29 12:31:10 2026 +0100

    cool#13988 sw redline render mode: add colored border for inline images
    
    Anchored images conditionally got a red/green frame in since commit
    afdf4e287fb91c7baf2767eb95b0565472b8343d (cool#13988 sw redline render
    mode: add colored border for anchored images, 2026-01-27), but the same
    didn't work for inline images.
    
    Seems what happens is that SwFlyFrame::GetRedlineRenderModeFrame() sets
    the border line with to 1 (in twips, so some minimal value), but then
    this is turned into a SdrFrameBorderPrimitive2D, which gets decomposed
    into a PolygonStrokePrimitive2D. At this point the cairo pixel processor
    handles it at CairoPixelProcessor2D::processPolygonStrokePrimitive2D(),
    which assumes that hairline is when the width is 0. The trouble is that
    in case Writer sets the width to 0, then we don't even start processing
    such stroke primitives.
    
    Solve the problem by going with a larger border width: just query from
    output device what would be a logic value for a 1px border, so it does
    show up reliably.
    
    This is similar to how SwViewOption::s_nPixelTwips gets configured
    already. Note that the testcase just asserts these polygons are painted,
    but it can't verify how CairoPixelProcessor2D simply didn't paint the
    old bad width.
    
    Change-Id: I83f7aec4d09fc628dd314e1325bfd47af07308ca
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198339
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins

diff --git a/sw/qa/core/text/itrpaint.cxx b/sw/qa/core/text/itrpaint.cxx
index 14c1af1a02b4..b5debdfa8f83 100644
--- a/sw/qa/core/text/itrpaint.cxx
+++ b/sw/qa/core/text/itrpaint.cxx
@@ -290,6 +290,9 @@ CPPUNIT_TEST_FIXTURE(Test, 
testInlineImageRedlineRenderModeOmitInsertDelete)
     CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
     CPPUNIT_ASSERT(!IsGrayScale(aImages[1]));
     CPPUNIT_ASSERT(!IsGrayScale(aImages[2]));
+    std::vector<tools::Polygon> aPolygons = GetMetaFilePolylines(*xMetaFile);
+    // No frames around images.
+    CPPUNIT_ASSERT(aPolygons.empty());
 
     // Omit insert: default, default, grayscale.
     SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
@@ -306,6 +309,10 @@ CPPUNIT_TEST_FIXTURE(Test, 
testInlineImageRedlineRenderModeOmitInsertDelete)
     // Without the accompanying fix in place, this test would have failed, the 
image's center pixel
     // wasn't gray.
     CPPUNIT_ASSERT(IsGrayScale(aImages[2]));
+    aPolygons = GetMetaFilePolylines(*xMetaFile);
+    // Frame around the deleted image: no polygons -> no frame.
+    CPPUNIT_ASSERT(!aPolygons.empty());
+    CPPUNIT_ASSERT(RectangleContainsPolygons(aImages[1].m_aRectangle, 
aPolygons));
 
     // Omit deletes: default, grayscale, default.
     aOpt.SetRedlineRenderMode(SwRedlineRenderMode::OmitDeletes);
@@ -318,6 +325,10 @@ CPPUNIT_TEST_FIXTURE(Test, 
testInlineImageRedlineRenderModeOmitInsertDelete)
     CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
     CPPUNIT_ASSERT(IsGrayScale(aImages[1]));
     CPPUNIT_ASSERT(!IsGrayScale(aImages[2]));
+    aPolygons = GetMetaFilePolylines(*xMetaFile);
+    // Frame around the inserted image.
+    CPPUNIT_ASSERT(!aPolygons.empty());
+    CPPUNIT_ASSERT(RectangleContainsPolygons(aImages[2].m_aRectangle, 
aPolygons));
 }
 }
 
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 3a746fc009a4..4d3de4f88efb 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -2362,7 +2362,12 @@ bool SwFlyFrame::GetRedlineRenderModeFrame(SvxBoxItem& 
rBoxItem) const
     }
 
     editeng::SvxBorderLine aBorderLine;
-    aBorderLine.SetWidth(1);
+
+    // Set a logic value which is roughly 1 pixel wide, so the border is 
visible.
+    vcl::RenderContext* pOut = pViewShell->GetOut();
+    tools::Long nWidth = pOut ? pOut->PixelToLogic(Size(1, 1)).Width() : 0;
+    aBorderLine.SetWidth(nWidth);
+
     aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
     aBorderLine.SetColor(*oColor);
     rBoxItem.SetLine(&aBorderLine, SvxBoxItemLine::LEFT);

Reply via email to