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

New commits:
commit 1c4128cf789dea9fd27515b62472162588cd0038
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Jan 28 15:26:24 2026 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Thu Jan 29 08:15:50 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/+/198282
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Tested-by: Caolán McNamara <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/sw/qa/core/text/itrpaint.cxx b/sw/qa/core/text/itrpaint.cxx
index 21306cccb708..e84c1183468d 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 edab63b8f4de..e5b34953e0e5 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -2350,7 +2350,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