drawinglayer/source/processor2d/hittestprocessor2d.cxx |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

New commits:
commit 07d80edb0b2cc979510c5f69de2269f315ae0f7a
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Aug 15 14:41:32 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Fri Aug 15 14:05:49 2025 +0200

    Fix relative position to pixel index calculation
    
    After commit 7caf45bc06e5b4459aeb173393e5898dff761d50 (BitmapEx->Bitmap
    in HitTestProcessor2D, 2025-08-15), I saw a crash when hovering mouse
    over a bitmap on a slide:
    
      vcllo.dll!BitmapReadAccess::GetScanline(__int64 nY) Line 50
      vcllo.dll!BitmapReadAccess::GetColor(__int64 nY, __int64 nX) Line 100
      vcllo.dll!Bitmap::GetPixelColor(long nX, long nY) Line 1894
      
drawinglayerlo.dll!drawinglayer::processor2d::HitTestProcessor2D::checkBitmapHit(basegfx::B2DRange
 aRange, const Bitmap & rBitmap, const basegfx::B2DHomMatrix & rTransform) Line 
174
      
drawinglayerlo.dll!drawinglayer::processor2d::HitTestProcessor2D::processBasePrimitive2D(const
 drawinglayer::primitive2d::BasePrimitive2D & rCandidate) Line 478
      
drawinglayerlo.dll!drawinglayer::processor2d::BaseProcessor2D::visit(const 
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> & rCandidate) Line 50
      
drawinglayercorelo.dll!drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::get2DDecomposition(drawinglayer::primitive2d::Primitive2DDecompositionVisitor
 & rVisitor, const drawinglayer::geometry::ViewInformation2D & 
rViewInformation) Line 81
      
drawinglayerlo.dll!drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::get2DDecomposition(drawinglayer::primitive2d::Primitive2DDecompositionVisitor
 & rVisitor, const drawinglayer::geometry::ViewInformation2D & 
rViewInformation) Line 46
      
drawinglayerlo.dll!drawinglayer::processor2d::BaseProcessor2D::process(const 
drawinglayer::primitive2d::BasePrimitive2D & rCandidate) Line 43
      
drawinglayerlo.dll!drawinglayer::processor2d::HitTestProcessor2D::processBasePrimitive2D(const
 drawinglayer::primitive2d::BasePrimitive2D & rCandidate) Line 553
      
drawinglayerlo.dll!drawinglayer::processor2d::BaseProcessor2D::process(const 
drawinglayer::primitive2d::Primitive2DContainer & rSource) Line 67
      svxcorelo.dll!sdr::overlay::OverlayObjectList::isHitLogic(const 
basegfx::B2DPoint & rLogicPosition, double fLogicTolerance) Line 94
      svxcorelo.dll!SdrHdl::IsHdlHit(const Point & rPnt) Line 948
      svxcorelo.dll!SdrHdlList::IsHdlListHit(const Point & rPnt) Line 2306
      svxcorelo.dll!SdrMarkView::PickHandle(const Point & rPnt) Line 2117
      svxcorelo.dll!SdrMarkView::MouseMove(const MouseEvent & rMEvt, 
OutputDevice * pWin) Line 1849
      svxcorelo.dll!SdrObjEditView::MouseMove(const MouseEvent & rMEvt, 
OutputDevice * pWin) Line 2210
      svxcorelo.dll!SdrCreateView::MouseMove(const MouseEvent & rMEvt, 
OutputDevice * pWin) Line 314
      svxcorelo.dll!SdrView::MouseMove(const MouseEvent & rMEvt, OutputDevice * 
pWin) Line 223
      sdlo.dll!sd::FuDraw::MouseMove(const MouseEvent & rMEvt) Line 260
      sdlo.dll!sd::FuSelection::MouseMove(const MouseEvent & rMEvt) Line 611
      sdlo.dll!sd::ViewShell::MouseMove(const MouseEvent & rMEvt, sd::Window * 
pWin) Line 689
      sdlo.dll!sd::DrawViewShell::MouseMove(const MouseEvent & rMEvt, 
sd::Window * pWin) Line 405
      sdlo.dll!sd::Window::MouseMove(const MouseEvent & rMEvt) Line 248
    
    The problem was pre-existing miscalculation of the pixel indices, which
    were hidden previously by BitmapEx::GetAlpha sanitizing the input.
    
    The calculation must not round, but truncate: we are on the first pixel,
    until we cross the "1/aSizePixel.Width()" boundary. Also, we must handle
    1.0 separately in aRelativePoint, because that special case produces bad
    result: we must either treat it as "outside" (treat aUnitRange as half-
    open interval), or as "over the last pixel" (implemented here now).
    
    Change-Id: Id39dbd889e8d6f3e063962b2a621d0c438a1f90a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189670
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx 
b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
index bc363cf74117..488b9ac97781 100644
--- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -168,8 +168,16 @@ namespace drawinglayer::processor2d
 
                         if(aUnitRange.isInside(aRelativePoint))
                         {
-                            const sal_Int32 
nX(basegfx::fround(aRelativePoint.getX() * aSizePixel.Width()));
-                            const sal_Int32 
nY(basegfx::fround(aRelativePoint.getY() * aSizePixel.Height()));
+                            // aRelativePoint.getX() == 0.0 -> 0
+                            // aRelativePoint.getX() == 0.999... -> 
aSizePixel.Width() - 1
+                            // Since isInside includes upper bound (1.0), 
force also this:
+                            // aRelativePoint.getX() == 1.0 -> 
aSizePixel.Width() - 1
+                            sal_Int32 nX(aRelativePoint.getX() * 
aSizePixel.Width());
+                            if (nX == aSizePixel.Width())
+                                --nX;
+                            sal_Int32 nY(aRelativePoint.getY() * 
aSizePixel.Height());
+                            if (nY == aSizePixel.Height())
+                                --nY;
 
                             mbHit = (0 != rBitmap.GetPixelColor(nX, 
nY).GetAlpha());
                         }

Reply via email to