sc/source/ui/view/gridwin4.cxx |   36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

New commits:
commit 95e6f942b3fa5c6f3e5473ac474a4702ab815502
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Feb 18 11:26:50 2024 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Feb 18 12:02:52 2024 +0100

    Clarify unit conversions in calculation
    
    Commit f840a0d54d873d3003f8b624a50557f8c9872477 looks confusing with
    the different units mixed in the same expression. It seems to do this:
    
    1. Multiply a side of aOrigOutputAreaTw by other zoom (so it looks to
       be using scaled twips!);
    2. subtract a side of aOtherEditRectPx multiplied by twipFactor, i.e.
       some size in mm/100s (!);
    3. The result is divided by other zoom, and multiplied by this zoom;
    4. The result is divided by twipFactor, i.e., converted from mm/100s
       to pixels;
    5. The result is added to a side of aEditRectPx.
    
    But if #1 is in (scaled) twips, #2 is wrong when adds mm/100s to it.
    
    This change refactors the calculation, breaking it into steps, using
    correct unit (taken from the respective OutputDevice), zooming using
    o3tl::convert (to avoid integer truncation), and minimizing resulting
    rounding error.
    
    Change-Id: Ic85eea12063720b2962828ab96408c4140a09202
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163529
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 6cd017d271b2..3aa36bebb597 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -32,6 +32,7 @@
 #include <vcl/settings.hxx>
 #include <o3tl/unit_conversion.hxx>
 #include <osl/diagnose.h>
+#include <tools/UnitConversion.hxx>
 
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/lok.hxx>
@@ -1170,8 +1171,12 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
             // paint the background
             rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
 
+            OutputDevice& rOtherWin = pOtherEditView->GetOutputDevice();
+            const MapMode aOrigMapMode = rOtherWin.GetMapMode();
+            const o3tl::Length aOrigOutputAreaUnit = 
MapToO3tlLength(aOrigMapMode.GetMapUnit());
+
             // paint text
-            const tools::Rectangle 
aOrigOutputAreaTw(pOtherEditView->GetOutputArea()); // Not in pixels.
+            const tools::Rectangle 
aOrigOutputArea(pOtherEditView->GetOutputArea()); // Not in pixels.
 
             tools::Rectangle aNewOutputArea;
             // compute output area for view with a different zoom level wrt 
the view used for painting
@@ -1180,17 +1185,26 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
             {
                 Point aOtherStart = rOtherViewData.GetScrPos( nCol1, nRow1, 
eOtherWhich );
                 Point aOtherEnd = rOtherViewData.GetScrPos( nCol2+1, nRow2+1, 
eOtherWhich );
-                tools::Rectangle aOtherEditRectPx(aOtherStart, aOtherEnd);
+                tools::Rectangle aOtherEditRect(
+                    o3tl::convert(tools::Rectangle(aOtherStart, aOtherEnd), 
o3tl::Length::px,
+                                  aOrigOutputAreaUnit));
 
                 tools::Long sides[4];
                 for (auto i: {0, 1, 2, 3})
                 {
-                    sides[i] = static_cast<tools::Long>(
-                        GetSide(aEditRectPx, i)
-                        + double(::GetZoom(mrViewData, i) / 
::GetZoom(rOtherViewData, i))
-                              * (double(::GetZoom(rOtherViewData, i)) * 
GetSide(aOrigOutputAreaTw, i)
-                                 - GetSide(aOtherEditRectPx, i) * twipFactor)
-                              / twipFactor);
+                    const Fraction zoomThis = ::GetZoom(mrViewData, i);
+                    const Fraction zoomOther = ::GetZoom(rOtherViewData, i);
+
+                    const auto unscaledOtherEditRectSide
+                        = o3tl::convert(GetSide(aOtherEditRect, i),
+                                        zoomOther.GetDenominator(), 
zoomOther.GetNumerator());
+
+                    const auto scaledAdd
+                        = o3tl::convert(GetSide(aOrigOutputArea, i) - 
unscaledOtherEditRectSide,
+                                        zoomThis.GetNumerator(), 
zoomThis.GetDenominator());
+
+                    sides[i] = GetSide(aEditRectPx, i)
+                               + o3tl::convert(scaledAdd, aOrigOutputAreaUnit, 
o3tl::Length::px);
                 }
 
                 aNewOutputArea = tools::Rectangle(sides[0], sides[1], 
sides[2], sides[3]);
@@ -1202,7 +1216,7 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
                 if (aNewOutputArea.IsEmpty())
                 {
                     // same zoom level as view used for painting
-                    aNewOutputArea = rDevice.LogicToPixel(aOrigOutputAreaTw);
+                    aNewOutputArea = rDevice.LogicToPixel(aOrigOutputArea);
                 }
                 // a small workaround for getting text position matching 
cursor position horizontally.
                 const tools::Long nCursorGapPx = 2;
@@ -1227,8 +1241,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
                 // So they need to be in the same coordinates/units. This is 
tied to the mapmode of the gridwin
                 // attached to the EditView, so we have to change its mapmode 
too (temporarily). We save the
                 // original mapmode and 'output area' and roll them back when 
we finish painting to rDevice.
-                OutputDevice& rOtherWin = pOtherEditView->GetOutputDevice();
-                const MapMode aOrigMapMode = rOtherWin.GetMapMode();
                 rOtherWin.SetMapMode(rDevice.GetMapMode());
 
                 // Avoid sending wrong cursor/selection messages by the 
'other' view, as the output-area is going
@@ -1266,7 +1278,7 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
 
                 // Rollback the mapmode and 'output area'.
                 rOtherWin.SetMapMode(aOrigMapMode);
-                pOtherEditView->SetOutputArea(aOrigOutputAreaTw);
+                pOtherEditView->SetOutputArea(aOrigOutputArea);
             }
             rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
         }

Reply via email to