basegfx/source/curve/b2dcubicbezier.cxx                      |   24 +--
 canvas/source/directx/dx_textlayout_drawhelper.cxx           |    4 
 canvas/source/opengl/ogl_canvashelper.cxx                    |    2 
 canvas/source/tools/surface.cxx                              |    9 -
 canvas/source/vcl/canvasfont.cxx                             |    2 
 canvas/source/vcl/canvashelper.cxx                           |    4 
 canvas/source/vcl/canvashelper_texturefill.cxx               |   36 ++---
 canvas/source/vcl/impltools.cxx                              |    8 -
 chart2/source/controller/main/SelectionHelper.cxx            |    2 
 cppcanvas/source/mtfrenderer/transparencygroupaction.cxx     |    4 
 cui/source/dialogs/cuigrfflt.cxx                             |    8 -
 cui/source/tabpages/transfrm.cxx                             |    4 
 drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx |    2 
 drawinglayer/source/primitive2d/textlayoutdevice.cxx         |   67 +++++++--
 drawinglayer/source/processor2d/helperwrongspellrenderer.cxx |    6 
 drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx   |   16 +-
 drawinglayer/source/processor2d/vclprocessor2d.cxx           |   76 +++++++----
 drawinglayer/source/tools/converters.cxx                     |    2 
 drawinglayer/source/tools/emfphelperdata.cxx                 |   34 ++--
 drawinglayer/source/tools/emfphelperdata.hxx                 |   10 +
 editeng/source/editeng/impedit3.cxx                          |    6 
 editeng/source/items/svxfont.cxx                             |    2 
 editeng/source/outliner/outliner.cxx                         |    4 
 emfio/qa/cppunit/emf/EmfImportTest.cxx                       |    4 
 emfio/source/reader/mtftools.cxx                             |    6 
 filter/source/msfilter/escherex.cxx                          |    2 
 filter/source/msfilter/eschesdo.cxx                          |   15 +-
 filter/source/svg/svgfilter.cxx                              |    2 
 filter/source/svg/svgwriter.cxx                              |   24 +--
 hwpfilter/source/drawing.h                                   |    1 
 include/basegfx/numeric/ftools.hxx                           |   20 +-
 include/drawinglayer/primitive2d/textlayoutdevice.hxx        |    2 
 include/svx/svdtrans.hxx                                     |   12 -
 include/svx/transfrmhelper.hxx                               |    8 -
 include/tools/helpers.hxx                                    |    8 -
 include/vcl/bitmap.hxx                                       |    8 +
 include/vcl/outdev.hxx                                       |   21 ++-
 include/vcl/vcllayout.hxx                                    |   11 +
 sc/qa/uitest/chart/chartLegend.py                            |    4 
 sc/source/core/data/drwlayer.cxx                             |   12 -
 sc/source/ui/miscdlgs/autofmt.cxx                            |    8 -
 sc/source/ui/view/drawview.cxx                               |    4 
 sd/qa/unit/layout-tests.cxx                                  |    4 
 sd/qa/unit/tiledrendering/LOKitSearchTest.cxx                |    6 
 sd/source/core/sdpage.cxx                                    |   16 +-
 sd/source/filter/html/htmlex.cxx                             |    3 
 sd/source/ui/app/optsitem.cxx                                |    4 
 sd/source/ui/dlg/vectdlg.cxx                                 |    6 
 sd/source/ui/func/fuoaprms.cxx                               |    3 
 sd/source/ui/view/drviews8.cxx                               |    4 
 sfx2/source/doc/objcont.cxx                                  |    4 
 slideshow/source/engine/shapes/drawinglayeranimation.cxx     |    6 
 slideshow/source/engine/slideview.cxx                        |    4 
 svgio/inc/SvgNumber.hxx                                      |    8 -
 svgio/inc/svgnode.hxx                                        |    7 -
 svgio/inc/svgtspannode.hxx                                   |    2 
 svgio/qa/cppunit/SvgImportTest.cxx                           |   61 ++++++++
 svgio/qa/cppunit/SvgNumberTest.cxx                           |    4 
 svgio/qa/cppunit/data/dy_in_ems.svg                          |    7 +
 svgio/qa/cppunit/data/dy_in_exs.svg                          |    7 +
 svgio/source/svgreader/SvgNumber.cxx                         |    5 
 svgio/source/svgreader/svgcharacternode.cxx                  |   18 +-
 svgio/source/svgreader/svgnode.cxx                           |   36 +----
 svgio/source/svgreader/svgstyleattributes.cxx                |    8 -
 svgio/source/svgreader/svgtspannode.cxx                      |    5 
 svx/qa/unit/customshapes.cxx                                 |   10 -
 svx/source/customshapes/EnhancedCustomShape2d.cxx            |    4 
 svx/source/customshapes/EnhancedCustomShape3d.cxx            |    2 
 svx/source/dialog/_contdlg.cxx                               |    4 
 svx/source/dialog/frmsel.cxx                                 |   12 -
 svx/source/engine3d/obj3d.cxx                                |    2 
 svx/source/engine3d/view3d.cxx                               |    6 
 svx/source/gallery2/galobj.cxx                               |    4 
 svx/source/svdraw/gradtrns.cxx                               |   24 +--
 svx/source/svdraw/sdrpagewindow.cxx                          |    7 -
 svx/source/svdraw/svdcrtv.cxx                                |    4 
 svx/source/svdraw/svddrgmt.cxx                               |   16 +-
 svx/source/svdraw/svddrgv.cxx                                |   16 +-
 svx/source/svdraw/svdedtv1.cxx                               |    4 
 svx/source/svdraw/svdedxv.cxx                                |    8 -
 svx/source/svdraw/svdfmtf.cxx                                |   15 +-
 svx/source/svdraw/svdhdl.cxx                                 |   12 +
 svx/source/svdraw/svdmrkv.cxx                                |   12 -
 svx/source/svdraw/svdoashp.cxx                               |   18 +-
 svx/source/svdraw/svdobj.cxx                                 |    6 
 svx/source/svdraw/svdocapt.cxx                               |    6 
 svx/source/svdraw/svdocirc.cxx                               |   11 +
 svx/source/svdraw/svdoedge.cxx                               |   16 +-
 svx/source/svdraw/svdograf.cxx                               |   18 +-
 svx/source/svdraw/svdomeas.cxx                               |   22 +--
 svx/source/svdraw/svdopath.cxx                               |   37 +++--
 svx/source/svdraw/svdorect.cxx                               |    2 
 svx/source/svdraw/svdotext.cxx                               |   10 -
 svx/source/svdraw/svdotextdecomposition.cxx                  |   12 -
 svx/source/svdraw/svdpdf.cxx                                 |   20 +-
 svx/source/svdraw/svdpoev.cxx                                |    9 -
 svx/source/svdraw/svdtrans.cxx                               |   24 +--
 svx/source/unodraw/UnoGraphicExporter.cxx                    |    8 -
 svx/source/unodraw/unoshape.cxx                              |    8 -
 svx/source/xoutdev/_xpoly.cxx                                |    7 -
 sw/qa/extras/layout/layout.cxx                               |    6 
 sw/qa/extras/ww8export/data/empty_group.docx                 |binary
 sw/qa/extras/ww8export/ww8export4.cxx                        |   24 +++
 sw/source/core/draw/dflyobj.cxx                              |   32 ++--
 sw/source/core/graphic/ndgrf.cxx                             |    3 
 sw/source/core/layout/fly.cxx                                |    2 
 sw/source/core/layout/wsfrm.cxx                              |   28 ++--
 sw/source/ui/table/autoformatpreview.cxx                     |   15 +-
 toolkit/source/awt/vclxfont.cxx                              |    2 
 tools/CppunitTest_tools_test.mk                              |    1 
 tools/qa/cppunit/test_fround.cxx                             |   62 --------
 tools/source/generic/color.cxx                               |    7 -
 tools/source/generic/line.cxx                                |    7 -
 tools/source/generic/poly.cxx                                |   37 +++--
 vcl/inc/font/LogicalFontInstance.hxx                         |    5 
 vcl/inc/impfontcache.hxx                                     |    8 -
 vcl/inc/impglyphitem.hxx                                     |    6 
 vcl/inc/pdf/pdfbuildin_fonts.hxx                             |    2 
 vcl/inc/qt5/QtFont.hxx                                       |    1 
 vcl/inc/quartz/salgdi.h                                      |    2 
 vcl/inc/unx/freetype_glyphcache.hxx                          |    2 
 vcl/inc/unx/glyphcache.hxx                                   |    1 
 vcl/inc/win/DWriteTextRenderer.hxx                           |   15 --
 vcl/inc/win/winlayout.hxx                                    |    4 
 vcl/osx/salframeview.mm                                      |    3 
 vcl/qa/cppunit/cjktext.cxx                                   |    2 
 vcl/qa/cppunit/complextext.cxx                               |    2 
 vcl/qa/cppunit/fontmocks.hxx                                 |    3 
 vcl/qa/cppunit/logicalfontinstance.cxx                       |   67 ++++++++-
 vcl/qt5/QtFont.cxx                                           |    7 -
 vcl/quartz/ctfonts.cxx                                       |   21 ---
 vcl/skia/gdiimpl.cxx                                         |   17 +-
 vcl/skia/salbmp.cxx                                          |    3 
 vcl/skia/win/gdiimpl.cxx                                     |   33 ++--
 vcl/skia/x11/textrender.cxx                                  |   10 -
 vcl/source/animate/AnimationRenderer.cxx                     |    8 -
 vcl/source/bitmap/BitmapEmbossGreyFilter.cxx                 |    6 
 vcl/source/bitmap/BitmapEx.cxx                               |    2 
 vcl/source/bitmap/BitmapFastScaleFilter.cxx                  |    4 
 vcl/source/bitmap/BitmapInterpolateScaleFilter.cxx           |    4 
 vcl/source/bitmap/BitmapScaleConvolutionFilter.cxx           |    8 -
 vcl/source/bitmap/BitmapScaleSuperFilter.cxx                 |    4 
 vcl/source/bitmap/BitmapTools.cxx                            |   16 +-
 vcl/source/bitmap/bitmap.cxx                                 |   52 +++----
 vcl/source/bitmap/impvect.cxx                                |    6 
 vcl/source/filter/eps/eps.cxx                                |    4 
 vcl/source/filter/wmf/emfwr.cxx                              |    8 -
 vcl/source/filter/wmf/wmfwr.cxx                              |    6 
 vcl/source/font/LogicalFontInstance.cxx                      |   36 ++++-
 vcl/source/font/fontcache.cxx                                |    4 
 vcl/source/gdi/CommonSalLayout.cxx                           |    6 
 vcl/source/gdi/gdimetafiletools.cxx                          |    8 -
 vcl/source/gdi/gdimtf.cxx                                    |   28 ++--
 vcl/source/gdi/impgraph.cxx                                  |    6 
 vcl/source/gdi/metaact.cxx                                   |   30 ++--
 vcl/source/gdi/pdfbuildin_fonts.cxx                          |    5 
 vcl/source/gdi/pdfwriter_impl.cxx                            |   37 ++++-
 vcl/source/gdi/pdfwriter_impl2.cxx                           |    8 -
 vcl/source/gdi/print.cxx                                     |   10 -
 vcl/source/gdi/regband.cxx                                   |    7 -
 vcl/source/gdi/region.cxx                                    |    4 
 vcl/source/gdi/regionband.cxx                                |    4 
 vcl/source/gdi/sallayout.cxx                                 |   40 +++--
 vcl/source/gdi/textlayout.cxx                                |    2 
 vcl/source/graphic/GraphicObject.cxx                         |   24 +--
 vcl/source/helper/canvastools.cxx                            |    4 
 vcl/source/outdev/bitmapex.cxx                               |   18 +-
 vcl/source/outdev/font.cxx                                   |    6 
 vcl/source/outdev/hatch.cxx                                  |   19 +-
 vcl/source/outdev/map.cxx                                    |   37 +++++
 vcl/source/outdev/rect.cxx                                   |   16 +-
 vcl/source/outdev/text.cxx                                   |   73 +++++++---
 vcl/source/outdev/textline.cxx                               |    4 
 vcl/source/outdev/transparent.cxx                            |    2 
 vcl/source/window/printdlg.cxx                               |    4 
 vcl/source/window/window2.cxx                                |    6 
 vcl/unx/generic/glyphs/freetype_glyphcache.cxx               |   38 -----
 vcl/unx/generic/glyphs/glyphcache.cxx                        |    8 -
 vcl/unx/gtk3/gtkinst.cxx                                     |    3 
 vcl/win/gdi/DWriteTextRenderer.cxx                           |   72 +++++++---
 vcl/win/gdi/gdiimpl.cxx                                      |    4 
 vcl/win/gdi/salfont.cxx                                      |   53 -------
 vcl/win/gdi/winlayout.cxx                                    |   18 --
 vcl/workben/listglyphs.cxx                                   |    2 
 xmloff/source/draw/shapeexport.cxx                           |   17 +-
 185 files changed, 1274 insertions(+), 1085 deletions(-)

New commits:
commit cba231b431274e9709c6afc2cec1354265e182a5
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri May 17 20:40:37 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:20 2024 +0500

    tdf#161154: pass "scaling is done externally" information down the stack
    
    VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D does the
    scaling, taking into account the font scaling. Before commit
    8557ea84c9336ba8061246f1f46ddb6e02f413a1, D2DWriteTextOutRenderer was
    doing own scaling in addition, but it seems that it somehow didn't
    affect the result much. The said commit removed the scalng from
    D2DWriteTextOutRenderer. As tdf#160901 demonstrated, the scaling is
    necessary in different code paths - and it turns out, that we need to
    know, if the caller does its own scaling or not, to make a decision,
    if the scaling should be fone in D2DWriteTextOutRenderer.
    
    This hack passes this from VclProcessor2D to D2DWriteTextOutRenderer
    through OutputDevice. Thanks to Miklos for the isea. I still don't
    understand, why all this seemingly doesn't affect other renderers.
    
    Change-Id: I001036f4574898b8e7606652525638df43c35240

diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 109be5cd40f9..f401c220f170 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -428,17 +428,21 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
             mpOutputDevice->SetFont(aFont);
             mpOutputDevice->SetTextColor(Color(aRGBFontColor));
 
-            if (!aDXArray.empty())
             {
-                const SalLayoutGlyphs* pGlyphs = 
SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
-                    mpOutputDevice, aText, nPos, nLen);
-                mpOutputDevice->DrawTextArray(aStartPoint, aText, aDXArray,
-                                              
rTextCandidate.getKashidaArray(), nPos, nLen,
-                                              SalLayoutFlags::NONE, pGlyphs);
-            }
-            else
-            {
-                mpOutputDevice->DrawText(aStartPoint, aText, nPos, nLen);
+                // For D2DWriteTextOutRenderer, we must pass a flag to not use 
font scaling
+                auto guard = mpOutputDevice->ScopedNoFontScaling();
+                if (!aDXArray.empty())
+                {
+                    const SalLayoutGlyphs* pGlyphs = 
SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+                        mpOutputDevice, aText, nPos, nLen);
+                    mpOutputDevice->DrawTextArray(aStartPoint, aText, aDXArray,
+                                                  
rTextCandidate.getKashidaArray(), nPos, nLen,
+                                                  SalLayoutFlags::NONE, 
pGlyphs);
+                }
+                else
+                {
+                    mpOutputDevice->DrawText(aStartPoint, aText, nPos, nLen);
+                }
             }
 
             if (rTextCandidate.getFontAttribute().getRTL())
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 098a5ccc5ef0..7142fee006df 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -21,6 +21,7 @@
 
 #include <sal/config.h>
 
+#include <comphelper/flagguard.hxx>
 #include <o3tl/span.hxx>
 #include <tools/gen.hxx>
 #include <tools/ref.hxx>
@@ -258,6 +259,8 @@ private:
     mutable bool                    mbRefPoint : 1;
     mutable bool                    mbEnableRTL : 1;
 
+    bool mbNoFontScaling = false; // Used only by D2DWriteTextOutRenderer
+
 protected:
     mutable std::shared_ptr<vcl::font::PhysicalFontCollection> 
mxFontCollection;
     mutable std::shared_ptr<ImplFontCache> mxFontCache;
@@ -340,6 +343,8 @@ public:
     /// request XSpriteCanvas render interface
     css::uno::Reference< css::rendering::XSpriteCanvas > GetSpriteCanvas() 
const;
 
+    auto ScopedNoFontScaling() { return 
comphelper::FlagRestorationGuard(mbNoFontScaling, true); }
+
 protected:
 
     /** Acquire a graphics device that the output device uses to draw on.
diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index 887480ce3ee9..a70fdaaddc1c 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -21,6 +21,7 @@
 
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/range/b2drectangle.hxx>
+#include <comphelper/flagguard.hxx>
 #include <i18nlangtag/languagetag.hxx>
 #include <tools/gen.hxx>
 #include <tools/degree.hxx>
@@ -110,6 +111,9 @@ public:
 
     virtual SalLayoutGlyphs GetGlyphs() const;
 
+    auto ScopedFontScaling(bool v) { return 
comphelper::FlagRestorationGuard(mbScaleFont, v); }
+    bool ScaleFont() const { return mbScaleFont; }
+
 protected:
     // used by layout engines
     SalLayout();
@@ -118,6 +122,8 @@ private:
     SalLayout(const SalLayout&) = delete;
     SalLayout& operator=(const SalLayout&) = delete;
 
+    bool mbScaleFont = true; // Used only by D2DWriteTextOutRenderer
+
 protected:
     int             mnMinCharPos;
     int             mnEndCharPos;
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 0ff3ac91f177..ce652f4506dd 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -468,7 +468,7 @@ void OutputDevice::ImplDrawSpecialText( SalLayout& 
rSalLayout )
 
 void OutputDevice::ImplDrawText( SalLayout& rSalLayout )
 {
-
+    auto guard = rSalLayout.ScopedFontScaling(!mbNoFontScaling);
     if( mbInitClipRegion )
         InitClipRegion();
     if( mbOutputClipped )
diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx 
b/vcl/win/gdi/DWriteTextRenderer.cxx
index f8c8c93958d7..57bd0ff62b83 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -332,12 +332,14 @@ 
WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget,
                                              bool bIsVertical)
     : mpRenderTarget(pRenderTarget)
 {
-    const float hscale = [&font = rLayout.GetFont()]
+    const float hscale = [&rLayout]
     {
-        const auto& rPattern = font.GetFontSelectPattern();
+        if (!rLayout.ScaleFont())
+            return 1.0;
+        const auto& rPattern = rLayout.GetFont().GetFontSelectPattern();
         if (!rPattern.mnHeight || !rPattern.mnWidth)
             return 1.0;
-        return rPattern.mnWidth * font.GetAverageWidthFactor() / 
rPattern.mnHeight;
+        return rPattern.mnWidth * rLayout.GetFont().GetAverageWidthFactor() / 
rPattern.mnHeight;
     }();
 
     Degree10 angle = rLayout.GetOrientation();
commit dbc4b74a175d80e2ee006ee92fb5c0feecdd9a1d
Author:     Mike Kaganski <[email protected]>
AuthorDate: Thu May 2 14:23:53 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    tdf#160901: partially revert 8557ea84c9336ba8061246f1f46ddb6e02f413a1
    
    It turns out, that the horizontal scale is needed in the applied transform.
    
    Change-Id: Ic07e015f0ddeee3d66653b683d83435d04b9ab81
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167004
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx 
b/vcl/win/gdi/DWriteTextRenderer.cxx
index a962cbcbb801..f8c8c93958d7 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -332,19 +332,32 @@ 
WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget,
                                              bool bIsVertical)
     : mpRenderTarget(pRenderTarget)
 {
+    const float hscale = [&font = rLayout.GetFont()]
+    {
+        const auto& rPattern = font.GetFontSelectPattern();
+        if (!rPattern.mnHeight || !rPattern.mnWidth)
+            return 1.0;
+        return rPattern.mnWidth * font.GetAverageWidthFactor() / 
rPattern.mnHeight;
+    }();
+
     Degree10 angle = rLayout.GetOrientation();
     if (bIsVertical)
         angle += 900_deg10;
 
-    if (angle)
+    if (hscale != 1.0f || angle)
     {
         D2D1::Matrix3x2F aTransform;
         pRenderTarget->GetTransform(&aTransform);
         moTransform = aTransform;
 
+        if (hscale != 1.0f) // basegfx::fTools::equal is useless with float
+            aTransform = aTransform * D2D1::Matrix3x2F::Scale(hscale, 1.0f, { 
0, 0 });
+
         // DWrite angle is in clockwise degrees, our orientation is in 
counter-clockwise 10th
         // degrees.
-        aTransform = aTransform * 
D2D1::Matrix3x2F::Rotation(-toDegrees(angle), rBaseline);
+        if (angle)
+            aTransform = aTransform * 
D2D1::Matrix3x2F::Rotation(-toDegrees(angle), rBaseline);
+
         mpRenderTarget->SetTransform(aTransform);
     }
 }
commit ed7409a32faeea0d54d2a07db8dd24c53a25b421
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Apr 10 22:45:41 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    Only call ID2D1RenderTarget::Get/SetTransform when needed
    
    Change-Id: Ifde2c24c222e3c316f5a4f47e86c2c08f676639a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165983
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx 
b/vcl/win/gdi/DWriteTextRenderer.cxx
index fb96cfa68659..a962cbcbb801 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -108,7 +108,7 @@ public:
 
 private:
     ID2D1RenderTarget* mpRenderTarget;
-    D2D1::Matrix3x2F maTransform;
+    std::optional<D2D1::Matrix3x2F> moTransform;
 };
 
 } // end anonymous namespace
@@ -332,25 +332,27 @@ 
WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget,
                                              bool bIsVertical)
     : mpRenderTarget(pRenderTarget)
 {
-    pRenderTarget->GetTransform(&maTransform);
-    D2D1::Matrix3x2F aTransform = maTransform;
-
     Degree10 angle = rLayout.GetOrientation();
-
     if (bIsVertical)
         angle += 900_deg10;
 
     if (angle)
     {
+        D2D1::Matrix3x2F aTransform;
+        pRenderTarget->GetTransform(&aTransform);
+        moTransform = aTransform;
+
         // DWrite angle is in clockwise degrees, our orientation is in 
counter-clockwise 10th
         // degrees.
-        aTransform = aTransform
-                     * D2D1::Matrix3x2F::Rotation(
-                           -toDegrees(angle), rBaseline);
+        aTransform = aTransform * 
D2D1::Matrix3x2F::Rotation(-toDegrees(angle), rBaseline);
+        mpRenderTarget->SetTransform(aTransform);
     }
-    mpRenderTarget->SetTransform(aTransform);
 }
 
-WinFontTransformGuard::~WinFontTransformGuard() { 
mpRenderTarget->SetTransform(maTransform); }
+WinFontTransformGuard::~WinFontTransformGuard()
+{
+    if (moTransform)
+        mpRenderTarget->SetTransform(*moTransform);
+}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit c9db962242abcaf7025865d9444e59c3e89a2bec
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Apr 26 01:00:21 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    tdf#157240: also set font color together with font
    
    Commit b008831a5545e5a777d77547ef96b9798d795f30 (tdf#152990 set the font
    after the MapMode is (potentially) set, 2023-01-14) had moved setting of
    font forward, but left setting the font color behind. This fixed that.
    
    Change-Id: I73fadc7c139da3b6f84b7fc875c585d02fc1c719
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166654
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index f8e5d0457583..109be5cd40f9 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -329,8 +329,6 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
                 mpOutputDevice->SetLayoutMode(nRTLLayoutMode);
             }
 
-            mpOutputDevice->SetTextColor(Color(aRGBFontColor));
-
             OUString aText(rTextCandidate.getText());
             sal_Int32 nPos = rTextCandidate.getTextPosition();
             sal_Int32 nLen = rTextCandidate.getTextLength();
@@ -428,6 +426,7 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
             // tdf#152990 set the font after the MapMode is (potentially) set 
so canvas uses the desired
             // font size
             mpOutputDevice->SetFont(aFont);
+            mpOutputDevice->SetTextColor(Color(aRGBFontColor));
 
             if (!aDXArray.empty())
             {
commit 474ef30244dcbcba075cb7201e60bbf5e3ecd7a2
Author:     Mike Kaganski <[email protected]>
AuthorDate: Tue Apr 23 05:25:34 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    Fix a thinko in 8a97f1ba8d9ccb65b2c89106de20666311d90c30
    
    Change-Id: I07bb67e9384470269d1fd3df087acee377cce729
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166490
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 31120279a732..a9b78c599042 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -188,7 +188,7 @@ void TextLayouterDevice::setFontAttribute(const 
attribute::FontAttribute& rFontA
     }
     else
     {
-        mnFontScalingFixX = mnFontScalingFixY = 0;
+        mnFontScalingFixX = mnFontScalingFixY = 1.0;
     }
 }
 
commit 6f434f2d8a05cf85fa8d55a6d5be882c425ba5d5
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Apr 22 14:45:37 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    tdf#160773: handle 0-size font height
    
    Regression from commit cc3663bbaed4f65d64154e5f9abb51a5f622f710
    (tdf#160702: improve text positioning, 2024-04-20), where I didn't
    know yet that this was possible :-)
    
    Change-Id: I1316db48b8acbacd077eeb4a8989c3dbf7e4a7b5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166425
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 5bc82301b794..31120279a732 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -179,8 +179,17 @@ void TextLayouterDevice::setFontAttribute(const 
attribute::FontAttribute& rFontA
         = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale);
     setFont(aFont);
     Size aFontSize = aFont.GetFontSize();
-    mnFontScalingFixY = fFontScaleY / aFontSize.Height();
-    mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
+    if (aFontSize.Height())
+    {
+        mnFontScalingFixY = fFontScaleY / aFontSize.Height();
+        // aFontSize.Width() is 0 for uninformly scaled fonts: see 
getVclFontFromFontAttribute
+        mnFontScalingFixX
+            = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
+    }
+    else
+    {
+        mnFontScalingFixX = mnFontScalingFixY = 0;
+    }
 }
 
 double TextLayouterDevice::getOverlineOffset() const
commit bec812bb7c15a62dbc620e6d94fd3ee0bd56c9a8
Author:     Mike Kaganski <[email protected]>
AuthorDate: Tue Apr 16 10:48:06 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    tdf#160702: improve text positioning
    
    Opening an SVG with text in different elements (e.g., tspans) in the
    same text element performs calculations to position the parts properly
    (i.e., the next part will start where the previous part ended, unless
    the position in overridden explicitly). These calculations require to
    know the text widths. The first problem leas here: the text width was
    calculated for a typically small text size (numerically equal to the
    pixel size defined in the SVG), but these calculations aren't truly
    linear, because font rendering may change depending on font height.
    Additionally, the rounding gives much higher error in smaller sizes
    than in larger. There was already a workaround for a similar problem
    in ViewRedirector::createRedirectedPrimitive2DSequence, where a large
    font (with 100 times greater height) was used to increase correctness.
    This was also used here, with the same large height (50000) used as a
    reference.
    
    Then, at the time of wrawing the text at different zoom levels, the
    code in VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D
    creates a font of a calculated size, and uses it to output the text.
    But the font is always created with an integral height, which means,
    that for a wanted height of 2.5 (in a zoomed out view), the really
    used height will be 3, which is 20% larger; or for wanted height of
    2.4, the actual height will be 2 (20% smaller). This resulted in odd
    jumps of the text widths, when the text may overlap the following
    part, or conversely, create a big gap before the next gap. To try to
    mitigate that, the function now takes the difference between the
    wanted and the actual font size into account, and adjusts the MapMode
    accordingly. This doesn't fix the jumping completely (e.g., because
    of the mentioned special handling of small font sizes in the fonts
    thenselves, like hinting), but still makes the calculations much more
    stable, decreasing the amount of jumping. Similar changes are made in
    TextLayouterDevice.
    
    Use of the functions that return text size as a double, not rounded
    value, should additionally help improving stability.
    
    Change-Id: I455845d8ca43ee9c06a0fc980947f35d8a25797a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166238
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index e36abffe2e64..5bc82301b794 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -22,6 +22,8 @@
 #include <algorithm>
 
 #include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <drawinglayer/attribute/fontattribute.hxx>
 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
 #include <comphelper/processfactory.hxx>
@@ -162,56 +164,69 @@ TextLayouterDevice::TextLayouterDevice()
 
 TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE { 
releaseGlobalVirtualDevice(); }
 
-void TextLayouterDevice::setFont(const vcl::Font& rFont) { 
mrDevice.SetFont(rFont); }
+void TextLayouterDevice::setFont(const vcl::Font& rFont)
+{
+    mrDevice.SetFont(rFont);
+    mnFontScalingFixX = 1.0;
+    mnFontScalingFixY = 1.0;
+}
 
 void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& 
rFontAttribute,
                                           double fFontScaleX, double 
fFontScaleY,
                                           const css::lang::Locale& rLocale)
 {
-    setFont(getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale));
+    vcl::Font aFont
+        = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, 
fFontScaleY, 0.0, rLocale);
+    setFont(aFont);
+    Size aFontSize = aFont.GetFontSize();
+    mnFontScalingFixY = fFontScaleY / aFontSize.Height();
+    mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : 
aFontSize.Height());
 }
 
 double TextLayouterDevice::getOverlineOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = (rMetric.GetInternalLeading() / 2.0) - rMetric.GetAscent();
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getUnderlineOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetDescent() / 2.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getStrikeoutOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = (rMetric.GetAscent() - rMetric.GetInternalLeading()) / 3.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getOverlineHeight() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetInternalLeading() / 2.5;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getUnderlineHeight() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     double fRet = rMetric.GetDescent() / 4.0;
-    return fRet;
+    return fRet * mnFontScalingFixY;
 }
 
-double TextLayouterDevice::getTextHeight() const { return 
mrDevice.GetTextHeight(); }
+double TextLayouterDevice::getTextHeight() const
+{
+    return mrDevice.GetTextHeightDouble() * mnFontScalingFixY;
+}
 
 double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 
nIndex,
                                         sal_uInt32 nLength) const
 {
-    return mrDevice.GetTextWidth(rText, nIndex, nLength);
+    return mrDevice.GetTextWidthDouble(rText, nIndex, nLength) * 
mnFontScalingFixX;
 }
 
 void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& 
rB2DPolyPolyVector,
@@ -245,6 +260,13 @@ void 
TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly
     {
         mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, 
nLength);
     }
+    if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+        || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
+    {
+        auto scale = 
basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY);
+        for (auto& poly : rB2DPolyPolyVector)
+            poly.transform(scale);
+    }
 }
 
 basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, 
sal_uInt32 nIndex,
@@ -262,6 +284,12 @@ basegfx::B2DRange 
TextLayouterDevice::getTextBoundRect(const OUString& rText, sa
     {
         basegfx::B2DRange aRect;
         mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength);
+        if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
+            || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
+        {
+            aRect.transform(
+                basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, 
mnFontScalingFixY));
+        }
         return aRect;
     }
 
@@ -271,13 +299,13 @@ basegfx::B2DRange 
TextLayouterDevice::getTextBoundRect(const OUString& rText, sa
 double TextLayouterDevice::getFontAscent() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
-    return rMetric.GetAscent();
+    return rMetric.GetAscent() * mnFontScalingFixY;
 }
 
 double TextLayouterDevice::getFontDescent() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
-    return rMetric.GetDescent();
+    return rMetric.GetDescent() * mnFontScalingFixY;
 }
 
 void TextLayouterDevice::addTextRectActions(const ::tools::Rectangle& 
rRectangle,
@@ -305,7 +333,7 @@ std::vector<double> TextLayouterDevice::getTextArray(const 
OUString& rText, sal_
         mrDevice.GetTextArray(rText, &aArray, nIndex, nTextLength);
         aRetval.reserve(aArray.size());
         for (size_t i = 0, nEnd = aArray.size(); i < nEnd; ++i)
-            aRetval.push_back(aArray[i]);
+            aRetval.push_back(aArray[i] * mnFontScalingFixX);
     }
 
     return aRetval;
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 6a1073fa9d5b..f8e5d0457583 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -180,7 +180,8 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
             }
 
             // Don't draw fonts without height
-            if (aFont.GetFontHeight() <= 0)
+            Size aResultFontSize = aFont.GetFontSize();
+            if (aResultFontSize.Height() <= 0)
                 return;
 
             // set FillColor Attribute
@@ -397,8 +398,31 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
             else
             {
                 const basegfx::B2DPoint aPoint(aLocalTransform * 
basegfx::B2DPoint(0.0, 0.0));
-                aStartPoint = 
Point(basegfx::fround<tools::Long>(aPoint.getX()),
-                                    
basegfx::fround<tools::Long>(aPoint.getY()));
+                double aPointX = aPoint.getX(), aPointY = aPoint.getY();
+
+                // aFont has an integer size; we must scale a bit for precision
+                double nFontScalingFixY = aFontScaling.getY() / 
aResultFontSize.Height();
+                double nFontScalingFixX = aFontScaling.getX()
+                                          / (aResultFontSize.Width() ? 
aResultFontSize.Width()
+                                                                     : 
aResultFontSize.Height());
+
+                if (!rtl_math_approxEqual(nFontScalingFixY, 1.0)
+                    || !rtl_math_approxEqual(nFontScalingFixX, 1.0))
+                {
+                    MapMode aMapMode = mpOutputDevice->GetMapMode();
+                    aMapMode.SetScaleX(aMapMode.GetScaleX() * 
nFontScalingFixX);
+                    aMapMode.SetScaleY(aMapMode.GetScaleY() * 
nFontScalingFixY);
+
+                    mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
+                    mpOutputDevice->SetRelativeMapMode(aMapMode);
+                    bChangeMapMode = true;
+
+                    aPointX /= nFontScalingFixX;
+                    aPointY /= nFontScalingFixY;
+                }
+
+                aStartPoint = Point(basegfx::fround<tools::Long>(aPointX),
+                                    basegfx::fround<tools::Long>(aPointY));
             }
 
             // tdf#152990 set the font after the MapMode is (potentially) set 
so canvas uses the desired
diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx 
b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
index 6348de0ddd25..a2e45f1bd8b5 100644
--- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx
+++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
@@ -63,6 +63,8 @@ class DRAWINGLAYER_DLLPUBLIC TextLayouterDevice
     /// internally used VirtualDevice
     SolarMutexGuard maSolarGuard;
     VirtualDevice& mrDevice;
+    double mnFontScalingFixX = 1.0;
+    double mnFontScalingFixY = 1.0;
 
 public:
     /// constructor/destructor
diff --git a/svgio/source/svgreader/svgcharacternode.cxx 
b/svgio/source/svgreader/svgcharacternode.cxx
index 4ffc46a483db..d83c8b645202 100644
--- a/svgio/source/svgreader/svgcharacternode.cxx
+++ b/svgio/source/svgreader/svgcharacternode.cxx
@@ -257,9 +257,12 @@ namespace svgio::svgreader
                 // prepare locale
                 css::lang::Locale aLocale;
 
-                // prepare TextLayouterDevice
+                // prepare TextLayouterDevice; use a larger font size for more 
linear size
+                // calculations. Similar to nTextSizeFactor in 
sd/source/ui/view/sdview.cxx
+                // (ViewRedirector::createRedirectedPrimitive2DSequence).
+                const double sizeFactor = fFontHeight < 50000 ? 50000 / 
fFontHeight : 1.0;
                 TextLayouterDevice aTextLayouterDevice;
-                aTextLayouterDevice.setFontAttribute(aFontAttribute, 
fFontWidth, fFontHeight, aLocale);
+                aTextLayouterDevice.setFontAttribute(aFontAttribute, 
fFontWidth * sizeFactor, fFontHeight * sizeFactor, aLocale);
 
                 // prepare TextArray
                 ::std::vector< double > aTextArray(rSvgTextPosition.getX());
@@ -293,7 +296,7 @@ namespace svgio::svgreader
 
                 // get current TextPosition and TextWidth in units
                 basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition());
-                double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), 
nIndex, nLength));
+                double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), 
nIndex, nLength) / sizeFactor);
 
                 // check for user-given TextLength
                 if(0.0 != rSvgTextPosition.getTextLength()
@@ -306,7 +309,10 @@ namespace svgio::svgreader
                         // spacing, need to create and expand TextArray
                         if(aTextArray.empty())
                         {
-                            aTextArray = 
aTextLayouterDevice.getTextArray(getText(), nIndex, nLength);
+                            auto 
aExtendArray(aTextLayouterDevice.getTextArray(getText(), nIndex, nLength));
+                            aTextArray.reserve(aExtendArray.size());
+                            for (auto n : aExtendArray)
+                                aTextArray.push_back(n / sizeFactor);
                         }
 
                         for(auto &a : aTextArray)
@@ -384,12 +390,12 @@ namespace svgio::svgreader
                 {
                     case BaselineShift::Sub:
                     {
-                        aPosition.setY(aPosition.getY() + 
aTextLayouterDevice.getUnderlineOffset());
+                        aPosition.setY(aPosition.getY() + 
aTextLayouterDevice.getUnderlineOffset() / sizeFactor);
                         break;
                     }
                     case BaselineShift::Super:
                     {
-                        aPosition.setY(aPosition.getY() + 
aTextLayouterDevice.getOverlineOffset());
+                        aPosition.setY(aPosition.getY() + 
aTextLayouterDevice.getOverlineOffset() / sizeFactor);
                         break;
                     }
                     case BaselineShift::Percentage:
commit b46ff244140dc5f4b3609174cacdec1a4300bf04
Author:     Mike Kaganski <[email protected]>
AuthorDate: Thu Apr 18 13:18:37 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    Return double from OutputDevice::GetTextArray
    
    And introduce GetTextWidth / GetTextHeight variants returning double.
    It allows to avoid premature rounding.
    
    At least in one case - testTdf145111_anchor_in_Fontwork - it allowed
    to make the test DPI-independent (at least in my testing on Windows,
    using 125, 150, and 175% UI scaling).
    
    Change-Id: I973d2c729ec6bb7114b4f99b9027f1ead7c1d061
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166237
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 13025b27d8a2..6a1073fa9d5b 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -340,8 +340,8 @@ void 
VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
             {
                 tools::Long nWidthToFill = rTextCandidate.getWidthToFill();
 
-                tools::Long nWidth
-                    = mpOutputDevice->GetTextArray(rTextCandidate.getText(), 
&aDXArray, 0, 1);
+                tools::Long nWidth = basegfx::fround<tools::Long>(
+                    mpOutputDevice->GetTextArray(rTextCandidate.getText(), 
&aDXArray, 0, 1));
                 sal_Int32 nChars = 2;
                 if (nWidth)
                     nChars = nWidthToFill / nWidth;
diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx
index b484a645a7f6..306b378fc133 100644
--- a/editeng/source/items/svxfont.cxx
+++ b/editeng/source/items/svxfont.cxx
@@ -37,7 +37,7 @@ static tools::Long GetTextArray( const OutputDevice* pOut, 
const OUString& rStr,
 
 {
     const SalLayoutGlyphs* layoutGlyphs = 
SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
-    return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, true, nullptr, 
layoutGlyphs);
+    return basegfx::fround<tools::Long>(pOut->GetTextArray( rStr, pDXAry, 
nIndex, nLen, true, nullptr, layoutGlyphs));
 }
 
 SvxFont::SvxFont()
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 1e03cc15dc20..627423117b37 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -1343,7 +1343,7 @@ void Test::TestExtTextOutOpaqueAndClipWMF()
     assertXPath(pDocument, aXPathPrefix + 
"mask/group[3]/mask/group/polypolygoncolor", "color",
                 "#ff8000");
     assertXPath(pDocument, aXPathPrefix + 
"mask/group[3]/mask/group/polypolygoncolor/polypolygon",
-                "path", "m1067 1067h1270v473h-1270z");
+                "path", "m1067 1067h1317v473h-1317z");
     assertXPath(pDocument, aXPathPrefix + 
"mask/group[3]/mask/group/textsimpleportion", "text",
                 "OOOO");
     assertXPath(pDocument, aXPathPrefix + 
"mask/group[3]/mask/group/textsimpleportion", "fontcolor",
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index ff444a6ce284..aa83250f53b6 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2690,7 +2690,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, 
const OUString& rText,
     }
     else
     {
-        aNormSize = Size( mpVDev->GetTextArray( rText, &aTmpArray ), 0 );
+        aNormSize = 
Size(basegfx::fround<tools::Long>(mpVDev->GetTextArray(rText, &aTmpArray)), 0);
     }
 
     // if text is rotated, set transform matrix at new g element
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 8bcf883c8fc9..098a5ccc5ef0 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1033,12 +1033,16 @@ public:
     tools::Long                        GetTextWidth( const OUString& rStr, 
sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
                                   vcl::text::TextLayoutCache const* = nullptr,
                                   SalLayoutGlyphs const*const pLayoutCache = 
nullptr) const;
+    double GetTextWidthDouble(const OUString& rStr, sal_Int32 nIndex = 0, 
sal_Int32 nLen = -1,
+                              vcl::text::TextLayoutCache const* = nullptr,
+                              SalLayoutGlyphs const* const pLayoutCache = 
nullptr) const;
 
     /** Height where any character of the current font fits; in logic 
coordinates.
 
         See also GetTextBoundRect() for more explanation + code examples.
     */
     tools::Long                        GetTextHeight() const;
+    double GetTextHeightDouble() const;
     float                       approximate_digit_width() const;
 
     void                        DrawTextArray( const Point& rStartPt, const 
OUString& rStr,
@@ -1048,7 +1052,7 @@ public:
                                                sal_Int32 nLen,
                                                SalLayoutFlags flags = 
SalLayoutFlags::NONE,
                                                const SalLayoutGlyphs* 
pLayoutCache = nullptr);
-    tools::Long                        GetTextArray( const OUString& rStr, 
KernArray* pDXAry,
+    double                      GetTextArray( const OUString& rStr, KernArray* 
pDXAry,
                                               sal_Int32 nIndex = 0, sal_Int32 
nLen = -1, bool bCaret = false,
                                               vcl::text::TextLayoutCache 
const* = nullptr,
                                               SalLayoutGlyphs const*const 
pLayoutCache = nullptr) const;
@@ -1841,6 +1845,9 @@ private:
      */
     SAL_DLLPRIVATE tools::Long         ImplLogicYToDevicePixel( tools::Long nY 
) const;
 
+    SAL_DLLPRIVATE double ImplDevicePixelToLogicWidthDouble(double nWidth) 
const;
+    SAL_DLLPRIVATE double ImplDevicePixelToLogicHeightDouble(double nHeight) 
const;
+
     /** @name Native Widget Rendering functions
 
         These all just call through to the private mpGraphics functions of the 
same name.
diff --git a/sc/qa/uitest/chart/chartLegend.py 
b/sc/qa/uitest/chart/chartLegend.py
index 45938e23017d..fe0525a0746d 100644
--- a/sc/qa/uitest/chart/chartLegend.py
+++ b/sc/qa/uitest/chart/chartLegend.py
@@ -88,7 +88,7 @@ class chartLegend(UITestCase):
       xLegends.executeAction("SELECT", tuple())
 
       with self.ui_test.execute_dialog_through_action(xLegends, "COMMAND", 
mkPropertyValues({"COMMAND": "TransformDialog"})) as xDialog:
-        self.assertEqual("4.61", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value'])
+        self.assertEqual("4.59", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value'])
         self.assertEqual("1.54", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_Y"))['Value'])
 
       xChartMain.executeAction("TYPE", mkPropertyValues({"KEYCODE": "UP"}))
@@ -96,7 +96,7 @@ class chartLegend(UITestCase):
 
       # Check the position has changed after moving the label using the arrows 
keys
       with self.ui_test.execute_dialog_through_action(xLegends, "COMMAND", 
mkPropertyValues({"COMMAND": "TransformDialog"})) as xDialog:
-        self.assertEqual("4.51", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value'])
+        self.assertEqual("4.49", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value'])
         self.assertEqual("1.44", 
get_state_as_dict(xDialog.getChild("MTR_FLD_POS_Y"))['Value'])
 
    def test_Tdf147394(self):
diff --git a/sd/qa/unit/layout-tests.cxx b/sd/qa/unit/layout-tests.cxx
index 1c4429f62aec..681f137f4dbb 100644
--- a/sd/qa/unit/layout-tests.cxx
+++ b/sd/qa/unit/layout-tests.cxx
@@ -103,7 +103,7 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf128212)
     xmlDocUniquePtr pXmlDoc = load("pptx/tdf128212.pptx");
 
     // Without the fix in place, this test would have failed with
-    // - Expected: 7793
+    // - Expected: 7795
     // - Actual  : 12068
     assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray", "x", "4525");
     assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray", "y", "7797");
@@ -310,7 +310,7 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, 
testFitToFrameTextFitting)
     assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]", "y", "406");
     assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", 
"first", "114");
 #ifndef _WIN32 // Windows seems to differ in text layouting, so ignore for now
-    assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", 
"last", "7010");
+    assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", 
"last", "6984");
 #endif
 }
 
diff --git a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx 
b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
index f3beb12b3ce1..1468f130cf11 100644
--- a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
+++ b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
@@ -655,8 +655,7 @@ void LOKitSearchTest::testSearchIn2MixedObjects()
     CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
     CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(OString("3546, 3174, 738, 402"),
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402", 
mpCallbackRecorder->m_aSearchResultSelection[0]);
 
     // Search next
 
@@ -681,8 +680,7 @@ void LOKitSearchTest::testSearchIn2MixedObjects()
     CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
     CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(OString("3546, 3174, 738, 402"),
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402", 
mpCallbackRecorder->m_aSearchResultSelection[0]);
 }
 
 // Test searching in document with mixed objects. We have 6 objects.
diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx
index efe322d54e76..86bae7d50447 100644
--- a/svx/qa/unit/customshapes.cxx
+++ b/svx/qa/unit/customshapes.cxx
@@ -406,10 +406,6 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, 
testTdf145111_Fontwork_rendering_font_siz
 
 CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf145111_anchor_in_Fontwork)
 {
-    // The tested positions depend on dpi.
-    if (!IsDefaultDPI())
-        return;
-
     // tdf#145004 In case ScaleX is true in property TextPath, 
SDRTEXTVERTADJUST is
     // evaluated and should shift the Fontwork text. That did not work for
     // 'Top-Left' and 'Bottom-Left'.
@@ -423,8 +419,7 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, 
testTdf145111_anchor_in_Fontwork)
         SdrObjCustomShape& rSdrCustomShape(
             
static_cast<SdrObjCustomShape&>(*SdrObject::getSdrObjectFromXShape(xShape)));
 
-        // Without the fix in place top was 2295, but should be 2916 for 96dpi.
-        // Was 2184, should be 2886 for 120dpi.
+        // Without the fix in place top was 2295, but should be 2900.
         tools::Rectangle aBoundRect(rSdrCustomShape.GetCurrentBoundRect());
         CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(2916), aBoundRect.Top(), 5);
     }
@@ -434,8 +429,7 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, 
testTdf145111_anchor_in_Fontwork)
         SdrObjCustomShape& rSdrCustomShape(
             
static_cast<SdrObjCustomShape&>(*SdrObject::getSdrObjectFromXShape(xShape)));
 
-        // Without the fix in place top was 10294, but should be 9519 for 
96dpi.
-        // Was 10184, should be 9481 for 120dpi.
+        // Without the fix in place top was 10294, but should be 9500.
         tools::Rectangle aBoundRect(rSdrCustomShape.GetCurrentBoundRect());
         CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(9519), aBoundRect.Top(), 5);
     }
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 0ffdb543fbd9..65b31c5909c6 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -3673,7 +3673,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf106234)
                 "type", "PortionType::Margin");
     // This was a justified line, without width
     assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/SwGluePortion",
-                "width", "7881");
+                "width", "7882");
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287b)
@@ -3686,7 +3686,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287b)
     assertXPath(
         pXmlDoc,
         
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabRight']",
-        "width", "17");
+        "width", "19");
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287c)
@@ -3819,7 +3819,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf122607)
     assertXPath(pXmlDoc,
                 
"/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/"
                 "fly/txt/SwParaPortion/SwLineLayout/child::*[1]",
-                "width", "428");
+                "width", "427");
     assertXPath(pXmlDoc,
                 
"/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/"
                 "fly/txt/SwParaPortion/SwLineLayout/child::*[1]",
diff --git a/toolkit/source/awt/vclxfont.cxx b/toolkit/source/awt/vclxfont.cxx
index 866a362e710f..f7338e79cfd0 100644
--- a/toolkit/source/awt/vclxfont.cxx
+++ b/toolkit/source/awt/vclxfont.cxx
@@ -156,7 +156,7 @@ sal_Int32 VCLXFont::getStringWidthArray( const OUString& 
str, css::uno::Sequence
         vcl::Font aOldFont = pOutDev->GetFont();
         pOutDev->SetFont( maFont );
         KernArray aDXA;
-        nRet = pOutDev->GetTextArray( str, &aDXA );
+        nRet = basegfx::fround(pOutDev->GetTextArray(str, &aDXA));
         rDXArray.realloc(aDXA.size());
         sal_Int32* pArray = rDXArray.getArray();
         for (size_t i = 0, nLen = aDXA.size(); i < nLen; ++i)
diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx
index daf70a1c589d..cfe5d2213d7d 100644
--- a/vcl/qa/cppunit/complextext.cxx
+++ b/vcl/qa/cppunit/complextext.cxx
@@ -79,7 +79,7 @@ void VclComplexTextTest::testArabic()
     std::vector<sal_Int32> aRefCharWidths {6,  9,  16, 16, 22, 22, 26, 29, 32, 
32,
                                       36, 40, 49, 53, 56, 63, 63, 66, 72, 72};
     KernArray aCharWidths;
-    tools::Long nTextWidth = pOutDev->GetTextArray(aOneTwoThree, &aCharWidths);
+    tools::Long nTextWidth = 
basegfx::fround<tools::Long>(pOutDev->GetTextArray(aOneTwoThree, &aCharWidths));
 
     CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
     // this sporadically returns 75 or 74 on some of the windows tinderboxes 
eg. tb73
diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx
index 45a1a7ce4e27..dfdc3156f838 100644
--- a/vcl/source/filter/wmf/emfwr.cxx
+++ b/vcl/source/filter/wmf/emfwr.cxx
@@ -880,7 +880,7 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, 
const OUString& rText, K
     }
     else
     {
-        nNormWidth = maVDev->GetTextArray( rText, &aOwnArray );
+        nNormWidth = basegfx::fround<sal_uInt32>(maVDev->GetTextArray(rText, 
&aOwnArray));
         pDX = aOwnArray;
     }
 
diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx
index 335773728b60..c35d7236c9d9 100644
--- a/vcl/source/filter/wmf/wmfwr.cxx
+++ b/vcl/source/filter/wmf/wmfwr.cxx
@@ -1198,7 +1198,7 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
                 pVirDev->SetFont( aSrcFont );
                 const sal_Int32 nLen = aTemp.getLength();
                 KernArray aDXAry;
-                const sal_Int32 nNormSize = pVirDev->GetTextArray( aTemp, nLen 
? &aDXAry : nullptr );
+                const sal_Int32 nNormSize = 
basegfx::fround(pVirDev->GetTextArray( aTemp, nLen ? &aDXAry : nullptr ));
                 if (nLen && nNormSize == 0)
                 {
                     OSL_FAIL("Impossible div by 0 action: 
MetaStretchTextAction!");
diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
index 0ee1c9ba5faf..ce681a2e9eea 100644
--- a/vcl/source/gdi/textlayout.cxx
+++ b/vcl/source/gdi/textlayout.cxx
@@ -166,7 +166,7 @@ namespace vcl
             return 0;
 
         // retrieve the character widths from the reference device
-        tools::Long nTextWidth = m_rReferenceDevice.GetTextArray( _rText, 
_pDXAry, _nStartIndex, _nLength );
+        tools::Long nTextWidth = 
basegfx::fround<tools::Long>(m_rReferenceDevice.GetTextArray( _rText, _pDXAry, 
_nStartIndex, _nLength ));
 #if OSL_DEBUG_LEVEL > 1
         if ( _pDXAry )
         {
diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx
index d7ddaf3ccd86..3359cc70c210 100644
--- a/vcl/source/outdev/map.cxx
+++ b/vcl/source/outdev/map.cxx
@@ -272,6 +272,19 @@ static tools::Long ImplPixelToLogic(tools::Long n, 
tools::Long nDPI, tools::Long
     return n;
 }
 
+static double ImplPixelToLogicDouble(double n, tools::Long nDPI, tools::Long 
nMapNum,
+                                     tools::Long nMapDenom)
+{
+    assert(nDPI > 0);
+    if (nMapNum == 0)
+        return 0;
+
+    n *= nMapDenom;
+    n /= nDPI;
+    n /= nMapNum;
+    return n;
+}
+
 tools::Long OutputDevice::ImplLogicXToDevicePixel( tools::Long nX ) const
 {
     if ( !mbMap )
@@ -314,6 +327,14 @@ tools::Long OutputDevice::ImplDevicePixelToLogicWidth( 
tools::Long nWidth ) cons
     return ImplPixelToLogic(nWidth, mnDPIX, maMapRes.mnMapScNumX, 
maMapRes.mnMapScDenomX);
 }
 
+SAL_DLLPRIVATE double OutputDevice::ImplDevicePixelToLogicWidthDouble(double 
nWidth) const
+{
+    if (!mbMap)
+        return nWidth;
+
+    return ImplPixelToLogicDouble(nWidth, mnDPIX, maMapRes.mnMapScNumX, 
maMapRes.mnMapScDenomX);
+}
+
 tools::Long OutputDevice::ImplDevicePixelToLogicHeight( tools::Long nHeight ) 
const
 {
     if ( !mbMap )
@@ -322,6 +343,14 @@ tools::Long OutputDevice::ImplDevicePixelToLogicHeight( 
tools::Long nHeight ) co
     return ImplPixelToLogic(nHeight, mnDPIY, maMapRes.mnMapScNumY, 
maMapRes.mnMapScDenomY);
 }
 
+double OutputDevice::ImplDevicePixelToLogicHeightDouble(double nHeight) const
+{
+    if (!mbMap)
+        return nHeight;
+
+    return ImplPixelToLogicDouble(nHeight, mnDPIY, maMapRes.mnMapScNumY, 
maMapRes.mnMapScDenomY);
+}
+
 Point OutputDevice::ImplLogicToDevicePixel( const Point& rLogicPt ) const
 {
     if ( !mbMap )
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index bbbb63f2326d..0ff3ac91f177 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -892,11 +892,15 @@ tools::Long OutputDevice::GetTextWidth( const OUString& 
rStr, sal_Int32 nIndex,
      vcl::text::TextLayoutCache const*const pLayoutCache,
      SalLayoutGlyphs const*const pSalLayoutCache) const
 {
+    double nWidth = GetTextWidthDouble(rStr, nIndex, nLen, pLayoutCache, 
pSalLayoutCache);
+    return basegfx::fround<tools::Long>(nWidth);
+}
 
-    tools::Long nWidth = GetTextArray( rStr, nullptr, nIndex,
-            nLen, false, pLayoutCache, pSalLayoutCache );
-
-    return nWidth;
+double OutputDevice::GetTextWidthDouble(const OUString& rStr, sal_Int32 
nIndex, sal_Int32 nLen,
+                                        vcl::text::TextLayoutCache const* 
const pLayoutCache,
+                                        SalLayoutGlyphs const* const 
pSalLayoutCache) const
+{
+    return GetTextArray(rStr, nullptr, nIndex, nLen, false, pLayoutCache, 
pSalLayoutCache);
 }
 
 tools::Long OutputDevice::GetTextHeight() const
@@ -912,6 +916,16 @@ tools::Long OutputDevice::GetTextHeight() const
     return nHeight;
 }
 
+double OutputDevice::GetTextHeightDouble() const
+{
+    if (!InitFont())
+        return 0;
+
+    tools::Long nHeight = mpFontInstance->mnLineHeight + mnEmphasisAscent + 
mnEmphasisDescent;
+
+    return ImplDevicePixelToLogicHeightDouble(nHeight);
+}
+
 float OutputDevice::approximate_char_width() const
 {
     //note pango uses "The quick brown fox jumps over the lazy dog." for 
english
@@ -960,7 +974,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, 
const OUString& rStr,
         mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, 
nIndex, nLen, flags );
 }
 
-tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* 
pKernArray,
+double OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernArray,
                                  sal_Int32 nIndex, sal_Int32 nLen, bool bCaret,
                                  vcl::text::TextLayoutCache const*const 
pLayoutCache,
                                  SalLayoutGlyphs const*const pSalLayoutCache) 
const
@@ -1048,7 +1062,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& 
rStr, KernArray* pKernAr
         if (mbMap)
         {
             for (int i = 0; i < nLen; ++i)
-                (*pDXAry)[i] = ImplDevicePixelToLogicWidth( (*pDXAry)[i] * 
nSubPixelFactor );
+                (*pDXAry)[i] = ImplDevicePixelToLogicWidthDouble((*pDXAry)[i] 
* nSubPixelFactor);
         }
         else if (nSubPixelFactor)
         {
@@ -1057,10 +1071,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& 
rStr, KernArray* pKernAr
         }
     }
 
-    if (mbMap)
-        nWidth = ImplDevicePixelToLogicWidth( nWidth );
-
-    return basegfx::fround<tools::Long>(nWidth);
+    return ImplDevicePixelToLogicWidthDouble(nWidth);
 #endif /* VCL_FLOAT_DEVICE_PIXEL */
 }
 
commit 15863b7d2a28e67f3c3adbafda77d4d864be05cf
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Apr 10 12:15:55 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:19 2024 +0500

    tdf#160622: Let SalLayout::GetBoundRect return basegfx::B2DRectangle
    
    This avoids premature rounding in TextLayouterDevice::getTextBoundRect.
    The box in D2DWriteTextOutRenderer::performRender needs to be expanded
    to allow room for the line width (which now will be guaranteed on all
    sides; previously, the rounding could happen to give no room on some
    side, even prior to commit 8962141a12c966b2d891829925e6203bf8d51852).
    Fixes some lines partially cut off in smaller text (or zoomed out).
    
    Change-Id: I07335136021f894cf045363b4d736bfab06c64d4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166236
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index ea9fed02a20f..e36abffe2e64 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -260,15 +260,9 @@ basegfx::B2DRange 
TextLayouterDevice::getTextBoundRect(const OUString& rText, sa
 
     if (nTextLength)
     {
-        ::tools::Rectangle aRect;
-
+        basegfx::B2DRange aRect;
         mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength);
-
-        // #i104432#, #i102556# take empty results into account
-        if (!aRect.IsEmpty())
-        {
-            return vcl::unotools::b2DRectangleFromRectangle(aRect);
-        }
+        return aRect;
     }
 
     return basegfx::B2DRange();
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 6b864213a66d..8bcf883c8fc9 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -54,6 +54,7 @@
 #include <vcl/settings.hxx>
 #include <vcl/vclreferencebase.hxx>
 
+#include <basegfx/range/b2drectangle.hxx>
 #include <basegfx/numeric/ftools.hxx>
 #include <basegfx/vector/b2enums.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
@@ -960,6 +961,11 @@ public:
                                                   sal_uLong nLayoutWidth = 0, 
KernArraySpan aDXArray = KernArraySpan(),
                                                   o3tl::span<const sal_Bool> 
pKashidaArray = {},
                                                   const SalLayoutGlyphs* 
pGlyphs = nullptr ) const;
+    bool                        GetTextBoundRect( basegfx::B2DRectangle& rRect,
+                                                  const OUString& rStr, 
sal_Int32 nBase = 0, sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
+                                                  sal_uLong nLayoutWidth = 0, 
KernArraySpan aDXArray = KernArraySpan(),
+                                                  o3tl::span<const sal_Bool> 
pKashidaArray = {},
+                                                  const SalLayoutGlyphs* 
pGlyphs = nullptr ) const;
 
     tools::Rectangle            ImplGetTextBoundRect( const SalLayout& ) const;
 
@@ -1627,6 +1633,7 @@ public:
     SAL_WARN_UNUSED_RESULT tools::Polygon PixelToLogic(const tools::Polygon& 
rDevicePoly) const;
     SAL_WARN_UNUSED_RESULT tools::PolyPolygon PixelToLogic(const 
tools::PolyPolygon& rDevicePolyPoly) const;
     SAL_WARN_UNUSED_RESULT basegfx::B2DPolyPolygon PixelToLogic(const 
basegfx::B2DPolyPolygon& rDevicePolyPoly) const;
+    SAL_WARN_UNUSED_RESULT basegfx::B2DRectangle PixelToLogic(const 
basegfx::B2DRectangle& rDeviceRect) const;
     SAL_WARN_UNUSED_RESULT vcl::Region PixelToLogic(const vcl::Region& 
rDeviceRegion) const;
     SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point& rDevicePt, const 
MapMode& rMapMode) const;
     SAL_WARN_UNUSED_RESULT Size PixelToLogic(const Size& rDeviceSize, const 
MapMode& rMapMode) const;
diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index 4705a44d9b92..887480ce3ee9 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drectangle.hxx>
 #include <i18nlangtag/languagetag.hxx>
 #include <tools/gen.hxx>
 #include <tools/degree.hxx>
@@ -103,7 +104,9 @@ public:
     virtual bool    GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, 
int& nStart,
                                  const LogicalFontInstance** ppGlyphFont = 
nullptr) const = 0;
     virtual bool GetOutline(basegfx::B2DPolyPolygonVector&) const;
-    bool GetBoundRect(tools::Rectangle&) const;
+    bool GetBoundRect(basegfx::B2DRectangle&) const;
+
+    static tools::Rectangle BoundRect2Rectangle(basegfx::B2DRectangle&);
 
     virtual SalLayoutGlyphs GetGlyphs() const;
 
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index d61c5c761f79..7a8706556129 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -41,6 +41,8 @@ protected:
     void checkRectPrimitive(Primitive2DSequence const & rPrimitive);
 
     Primitive2DSequence parseSvg(std::u16string_view aSource);
+    void assertXPathDouble(const xmlDocUniquePtr& pXmlDoc, const OString& 
rXPath,
+                           const OString& rAttribute, double nExpectedValue, 
double delta);
 };
 
 Primitive2DSequence Test::parseSvg(std::u16string_view aSource)
@@ -82,6 +84,13 @@ void Test::checkRectPrimitive(Primitive2DSequence const & 
rPrimitive)
 
 }
 
+void Test::assertXPathDouble(const xmlDocUniquePtr& pXmlDoc, const OString& 
rXPath,
+                             const OString& rAttribute, double nExpectedValue, 
double delta)
+{
+    auto sVal = getXPath(pXmlDoc, rXPath, rAttribute);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(nExpectedValue, sVal.toDouble(), delta);
+}
+
 bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const 
Primitive2DSequence& rB)
 {
     return std::equal(rA.begin(), rA.end(), rB.begin(), rB.end(),
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 84b625115648..c40a010173a7 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -2131,7 +2131,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const 
GenericSalLayout& layout, Colo
 
     preDraw();
     auto getBoundRect = [&layout]() {
-        tools::Rectangle rect;
+        basegfx::B2DRectangle rect;
         layout.GetBoundRect(rect);
         return rect;
     };
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index c8c2d6ca1093..e801ac3057ca 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -221,11 +221,10 @@ static double trimInsignificant(double n)
     return std::abs(n) >= 0x1p53 ? n : std::round(n * 1e5) / 1e5;
 }
 
-bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const
+bool SalLayout::GetBoundRect(basegfx::B2DRectangle& rRect) const
 {
     bool bRet = false;
-
-    basegfx::B2DRectangle aUnion;
+    rRect.reset();
     basegfx::B2DRectangle aRectangle;
 
     DevicePoint aPos;
@@ -241,28 +240,28 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) 
const
             {
                 
aRectangle.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos));
                 // merge rectangle
-                aUnion.expand(aRectangle);
+                rRect.expand(aRectangle);
             }
             bRet = true;
         }
     }
-    if (aUnion.isEmpty())
-    {
-        rRect = {};
-    }
-    else
-    {
-        double l = rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())),
-               t = rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())),
-               r = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())),
-               b = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY()));
-        assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && 
std::isfinite(b));
-        rRect = tools::Rectangle(l, t, r, b);
-    }
 
     return bRet;
 }
 
+tools::Rectangle SalLayout::BoundRect2Rectangle(basegfx::B2DRectangle& rRect)
+{
+    if (rRect.isEmpty())
+        return {};
+
+    double l = rtl::math::approxFloor(trimInsignificant(rRect.getMinX())),
+           t = rtl::math::approxFloor(trimInsignificant(rRect.getMinY())),
+           r = rtl::math::approxCeil(trimInsignificant(rRect.getMaxX())),
+           b = rtl::math::approxCeil(trimInsignificant(rRect.getMaxY()));
+    assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && 
std::isfinite(b));
+    return tools::Rectangle(l, t, r, b);
+}
+
 SalLayoutGlyphs SalLayout::GetGlyphs() const
 {
     return SalLayoutGlyphs(); // invalid
diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx
index 67414cb2976c..d7ddaf3ccd86 100644
--- a/vcl/source/outdev/map.cxx
+++ b/vcl/source/outdev/map.cxx
@@ -1230,6 +1230,14 @@ basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( 
const basegfx::B2DPolyPolygo
     return aTransformedPoly;
 }
 
+basegfx::B2DRectangle OutputDevice::PixelToLogic(const basegfx::B2DRectangle& 
rDeviceRect) const
+{
+    basegfx::B2DRectangle aTransformedRect = rDeviceRect;
+    const basegfx::B2DHomMatrix& rTransformationMatrix = 
GetInverseViewTransformation();
+    aTransformedRect.transform(rTransformationMatrix);
+    return aTransformedRect;
+}
+
 vcl::Region OutputDevice::PixelToLogic( const vcl::Region& rDeviceRegion ) 
const
 {
 
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 9e93a5775857..bbbb63f2326d 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -23,6 +23,7 @@
 #include <rtl/ustrbuf.hxx>
 #include <sal/log.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <comphelper/processfactory.hxx>
 #include <tools/lineend.hxx>
 #include <tools/debug.hxx>
@@ -233,7 +234,11 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& 
rSalLayout )
     tools::Rectangle aBoundRect;
     rSalLayout.DrawBase() = DevicePoint( 0, 0 );
     rSalLayout.DrawOffset() = Point( 0, 0 );
-    if (!rSalLayout.GetBoundRect(aBoundRect))
+    if (basegfx::B2DRectangle r; rSalLayout.GetBoundRect(r))
+    {
+        aBoundRect = SalLayout::BoundRect2Rectangle(r);
+    }
+    else
     {
         // guess vertical text extents if GetBoundRect failed
         tools::Long nRight = rSalLayout.GetTextWidth();
@@ -2326,9 +2331,22 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& 
rRect,
                                          sal_uLong nLayoutWidth, KernArraySpan 
pDXAry,
                                          o3tl::span<const sal_Bool> 
pKashidaAry,
                                          const SalLayoutGlyphs* pGlyphs ) const
+{
+    basegfx::B2DRectangle aRect;
+    bool bRet = GetTextBoundRect(aRect, rStr, nBase, nIndex, nLen, 
nLayoutWidth, pDXAry,
+                                 pKashidaAry, pGlyphs);
+    rRect = SalLayout::BoundRect2Rectangle(aRect);
+    return bRet;
+}
+
+bool OutputDevice::GetTextBoundRect(basegfx::B2DRectangle& rRect, const 
OUString& rStr,
+                                    sal_Int32 nBase, sal_Int32 nIndex, 
sal_Int32 nLen,
+                                    sal_uLong nLayoutWidth, KernArraySpan 
pDXAry,
+                                    o3tl::span<const sal_Bool> pKashidaAry,
+                                    const SalLayoutGlyphs* pGlyphs) const
 {
     bool bRet = false;
-    rRect.SetEmpty();
+    rRect.reset();
 
     std::unique_ptr<SalLayout> pSalLayout;
     const Point aPoint;
@@ -2352,18 +2370,22 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& 
rRect,
                             nullptr, pGlyphs);
     if( pSalLayout )
     {
-        tools::Rectangle aPixelRect;
+        basegfx::B2DRectangle aPixelRect;
         bRet = pSalLayout->GetBoundRect(aPixelRect);
 
         if( bRet )
         {
-            Point aRotatedOfs( mnTextOffX, mnTextOffY );
-            DevicePoint aPos = 
pSalLayout->GetDrawPosition(DevicePoint(nXOffset, 0));
-            aRotatedOfs -= Point(aPos.getX(), aPos.getY());
-            aPixelRect += aRotatedOfs;
+            basegfx::B2DPoint aPos = 
pSalLayout->GetDrawPosition(basegfx::B2DPoint(nXOffset, 0));
+            auto m = basegfx::utils::createTranslateB2DHomMatrix(mnTextOffX - 
aPos.getX(),
+                                                                 mnTextOffY - 
aPos.getY());
+            aPixelRect.transform(m);
             rRect = PixelToLogic( aPixelRect );
-            if( mbMap )
-                rRect += Point( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY );
+            if (mbMap)
+            {
+                m = 
basegfx::utils::createTranslateB2DHomMatrix(maMapRes.mnMapOfsX,
+                                                                
maMapRes.mnMapOfsY);
+                rRect.transform(m);
+            }
         }
     }
 
diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx 
b/vcl/win/gdi/DWriteTextRenderer.cxx
index 321587db8137..fb96cfa68659 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -238,8 +238,15 @@ bool 
D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
     if (!pFontFace)
         return false;
 
-    tools::Rectangle bounds;
-    bool succeeded = rLayout.GetBoundRect(bounds);
+    auto [succeeded, bounds] = [&rLayout]()
+    {
+        basegfx::B2DRectangle r;
+        bool result = rLayout.GetBoundRect(r);
+        if (result)
+            r.grow(1); // plus 1 pixel to the tight range
+        return std::make_pair(result, SalLayout::BoundRect2Rectangle(r));
+    }();
+
     if (succeeded)
     {
         hr = BindDC(hDC, bounds);   // Update the bounding rect.
commit a54c14ba6cee50e118578997ca3b03be07ea1206
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Apr 19 10:31:39 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:18 2024 +0500

    Add a unit test for commit 3f0220f18a66630e06e3c128980f21a5722f49ca
    
    (Handle empty range properly, 2024-04-18)
    
    Change-Id: Ifea60ace8ff864ef092e6a62177d5926ceb60de3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166278
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sw/qa/extras/ww8export/data/empty_group.docx 
b/sw/qa/extras/ww8export/data/empty_group.docx
new file mode 100644
index 000000000000..a3454746c5e0
Binary files /dev/null and b/sw/qa/extras/ww8export/data/empty_group.docx differ
diff --git a/sw/qa/extras/ww8export/ww8export4.cxx 
b/sw/qa/extras/ww8export/ww8export4.cxx
index efb198ebae00..b4116ff2bbac 100644
--- a/sw/qa/extras/ww8export/ww8export4.cxx
+++ b/sw/qa/extras/ww8export/ww8export4.cxx
@@ -19,8 +19,11 @@
 
 #include <comphelper/sequenceashashmap.hxx>
 #include <o3tl/string_view.hxx>
+#include <svx/svdpage.hxx>
 
 #include <docsh.hxx>
+#include <drawdoc.hxx>
+#include <IDocumentDrawModelAccess.hxx>
 #include <IDocumentSettingAccess.hxx>
 #include <unotxdoc.hxx>
 
@@ -78,6 +81,27 @@ DECLARE_WW8EXPORT_TEST(testTdf104704_mangledFooter, 
"tdf104704_mangledFooter.odt
     CPPUNIT_ASSERT_EQUAL(2, getPages());
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testEmptyGroup)
+{
+    // Given a document with an empty group
+    createSwDoc("empty_group.docx");
+
+    CPPUNIT_ASSERT_EQUAL(1, getPages());
+    CPPUNIT_ASSERT_EQUAL(1, getShapes());
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+    SdrPage* pPage = 
pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+    SdrObject* pObject = pPage->GetObj(0);
+
+    CPPUNIT_ASSERT_EQUAL(OUString("Empty group"), pObject->GetName());
+    CPPUNIT_ASSERT(pObject->IsGroupObject());
+    CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetSubList()->GetObjCount());
+
+    // it must not assert/crash on save
+    saveAndReload(OUString::createFromAscii(mpFilter));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d67d69b422837bd14b2d63d888ba3768969ea6af
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Apr 17 21:16:23 2024 +0100
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:18 2024 +0500

    Handle empty range properly
    
    Since commit 690526f95e3ee4fd25bb2c987e093543e4bc435b
    (Generalize basegfx::fround for templated return type, 2024-04-14),
    an assertion could fail for certain case, like
    
    include/o3tl/unit_conversion.hxx:75: sal_Int64 o3tl::detail::MulDiv(I,
    sal_Int64, sal_Int64) [I = long]: Assertion `isBetween(n,
    (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)'
    
    The problem was unchecked case of empty B2DRange.
    
    Change-Id: Ice9125ea557b73a7fabf64bc1ad9368f503ad525
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166101
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/filter/source/msfilter/eschesdo.cxx 
b/filter/source/msfilter/eschesdo.cxx
index ca0dc8a4a14d..2f8f84bb9dc4 100644
--- a/filter/source/msfilter/eschesdo.cxx
+++ b/filter/source/msfilter/eschesdo.cxx
@@ -1151,10 +1151,19 @@ void ImplEESdrObject::Init()
     {
         // if it's a group, the unrotated range is needed for that group
         const basegfx::B2DRange 
aUnrotatedRange(getUnrotatedGroupBoundRange(mXShape));
-        const Point 
aNewP(basegfx::fround<tools::Long>(aUnrotatedRange.getMinX()), 
basegfx::fround<tools::Long>(aUnrotatedRange.getMinY()));
-        const Size 
aNewS(basegfx::fround<tools::Long>(aUnrotatedRange.getWidth()), 
basegfx::fround<tools::Long>(aUnrotatedRange.getHeight()));
+        if (aUnrotatedRange.isEmpty())
+        {
+            SetRect(tools::Rectangle());
+        }
+        else
+        {
+            const Point 
aNewP(basegfx::fround<tools::Long>(aUnrotatedRange.getMinX()),
+                              
basegfx::fround<tools::Long>(aUnrotatedRange.getMinY()));
+            const Size 
aNewS(basegfx::fround<tools::Long>(aUnrotatedRange.getWidth()),
+                             
basegfx::fround<tools::Long>(aUnrotatedRange.getHeight()));
 
-        SetRect(ImplEESdrWriter::ImplMapPoint(aNewP), 
ImplEESdrWriter::ImplMapSize(aNewS));
+            SetRect(ImplEESdrWriter::ImplMapPoint(aNewP), 
ImplEESdrWriter::ImplMapSize(aNewS));
+        }
     }
     else
     {
commit 294483b2eee20b30053428110833aa0d1844bc53
Author:     Mike Kaganski <[email protected]>
AuthorDate: Tue Apr 16 23:10:45 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jun 1 14:56:18 2024 +0500

    Drop FRound, and use generalized basegfx::fround
    
    Change-Id: I7447e649dc3ef4e51242f69c7486a3e84e103d2e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166159
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/cui/source/dialogs/cuigrfflt.cxx b/cui/source/dialogs/cuigrfflt.cxx
index c67ee92d141c..0ffb50342936 100644
--- a/cui/source/dialogs/cuigrfflt.cxx
+++ b/cui/source/dialogs/cuigrfflt.cxx
@@ -192,8 +192,8 @@ Graphic GraphicFilterMosaic::GetFilteredGraphic( const 
Graphic& rGraphic,
     Graphic         aRet;
     tools::Long            nTileWidth = 
static_cast<tools::Long>(mxMtrWidth->get_value(FieldUnit::PIXEL));
     tools::Long            nTileHeight = 
static_cast<tools::Long>(mxMtrHeight->get_value(FieldUnit::PIXEL));
-    const Size      aSize( std::max( FRound( nTileWidth * fScaleX ), 
tools::Long(1) ),
-                           std::max( FRound( nTileHeight * fScaleY ), 
tools::Long(1) ) );
+    const Size      aSize( std::max( basegfx::fround<tools::Long>( nTileWidth 
* fScaleX ), tools::Long(1) ),
+                           std::max( basegfx::fround<tools::Long>( nTileHeight 
* fScaleY ), tools::Long(1) ) );
 
     if( rGraphic.IsAnimated() )
     {
@@ -270,7 +270,7 @@ GraphicFilterSolarize::GraphicFilterSolarize(weld::Window* 
pParent, const Graphi
     , mxMtrThreshold(m_xBuilder->weld_metric_spin_button("value", 
FieldUnit::PERCENT))
     , mxCbxInvert(m_xBuilder->weld_check_button("invert"))
 {
-    mxMtrThreshold->set_value(FRound(cGreyThreshold / 2.55), 
FieldUnit::PERCENT);
+    mxMtrThreshold->set_value(basegfx::fround(cGreyThreshold / 2.55), 
FieldUnit::PERCENT);
     mxMtrThreshold->connect_value_changed(LINK(this, GraphicFilterSolarize, 
EditModifyHdl));
 
     mxCbxInvert->set_active(bInvert);
@@ -290,7 +290,7 @@ IMPL_LINK_NOARG(GraphicFilterSolarize, EditModifyHdl, 
weld::MetricSpinButton&, v
 Graphic GraphicFilterSolarize::GetFilteredGraphic( const Graphic& rGraphic, 
double, double )
 {
     Graphic         aRet;
-    sal_uInt8       nGreyThreshold = 
static_cast<sal_uInt8>(FRound(mxMtrThreshold->get_value(FieldUnit::PERCENT) * 
2.55));
+    sal_uInt8       nGreyThreshold = 
basegfx::fround<sal_uInt8>(mxMtrThreshold->get_value(FieldUnit::PERCENT) * 
2.55);
 
     if( rGraphic.IsAnimated() )
     {
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index e4420dc27e71..ff444a6ce284 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2184,7 +2184,7 @@ void SVGActionWriter::ImplWriteShape( const 
SVGShapeDescriptor& rShape )
 
         for( size_t k = 0; k < rShape.maDashArray.size(); ++k )
         {
-            const sal_Int32 nDash = ImplMap( FRound( rShape.maDashArray[ k ] ) 
);
+            const sal_Int32 nDash = 
ImplMap(basegfx::fround(rShape.maDashArray[k]));
 
             if( k )
                 aDashArrayStr.append(",");
@@ -2546,8 +2546,8 @@ void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, 
const Point& rDestPt, con
     if (fScaleX != 1.0 || fScaleY != 1.0)
     {
         rMtf.Scale(fScaleX, fScaleY);
-        aSrcPt.setX(FRound(aSrcPt.X() * fScaleX));
-        aSrcPt.setY(FRound(aSrcPt.Y() * fScaleY));
+        aSrcPt.setX(basegfx::fround<tools::Long>(aSrcPt.X() * fScaleX));
+        aSrcPt.setY(basegfx::fround<tools::Long>(aSrcPt.Y() * fScaleY));
     }
 
     nMoveX = rDestPt.X() - aSrcPt.X();
@@ -2747,7 +2747,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, 
const OUString& rText,
                 const double fFactor = static_cast<double>(nWidth) / 
aNormSize.Width();
 
                 for( i = 0; i < ( nLen - 1 ); i++ )
-                    aTmpArray.set(i, FRound(aTmpArray[i] * fFactor));
+                    aTmpArray.set(i, basegfx::fround(aTmpArray[i] * fFactor));
             }
             else
             {
@@ -2811,11 +2811,11 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, 
const OUString& rText,
         return;
 
     tools::Polygon aPoly( 4 );
-    const tools::Long  nLineHeight = std::max<tools::Long>( FRound( 
aMetric.GetLineHeight() * 0.05 ), 1 );
+    const tools::Long  nLineHeight = std::max<tools::Long>( 
basegfx::fround<tools::Long>( aMetric.GetLineHeight() * 0.05 ), 1 );
 
     if( rFont.GetStrikeout() )
     {
-        const tools::Long nYLinePos = aBaseLinePos.Y() - FRound( 
aMetric.GetAscent() * 0.26 );
+        const tools::Long nYLinePos = aBaseLinePos.Y() - 
basegfx::fround<tools::Long>( aMetric.GetAscent() * 0.26 );
 
         aPoly[ 0 ].setX( aBaseLinePos.X() ); aPoly[ 0 ].setY( nYLinePos - ( 
nLineHeight >> 1 ) );
         aPoly[ 1 ].setX( aBaseLinePos.X() + aNormSize.Width() - 1 ); aPoly[ 1 
].setY( aPoly[ 0 ].Y() );
@@ -3323,8 +3323,8 @@ void SVGActionWriter::ImplWriteActions( const 
GDIMetaFile& rMtf,
                         // i.e. invisible line, because it makes it visible,
                         // resulting an extra line behind the normal shape line
                         if ( aNewLineColor.GetAlpha() > 0 )
-                            aNewLineColor.SetAlpha( 255 - 
sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
-                        aNewFillColor.SetAlpha( 255 - 
sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
+                            aNewLineColor.SetAlpha( 255 - 
basegfx::fround<sal_uInt8>( pA->GetTransparence() * 2.55 ) );
+                        aNewFillColor.SetAlpha( 255 - 
basegfx::fround<sal_uInt8>( pA->GetTransparence() * 2.55 ) );
 
                         maAttributeWriter.AddPaintAttr( aNewLineColor, 
aNewFillColor );
                         ImplWritePolyPolygon( rPolyPoly, false );
@@ -3435,7 +3435,7 @@ void SVGActionWriter::ImplWriteActions( const 
GDIMetaFile& rMtf,
 
                             mapCurShape->maShapePolyPoly = aShapePolyPoly;
                             mapCurShape->maShapeFillColor = 
aFill.getFillColor();
-                            mapCurShape->maShapeFillColor.SetAlpha( 255 - 
static_cast<sal_uInt8>(FRound( 255.0 * aFill.getTransparency() )) );
+                            mapCurShape->maShapeFillColor.SetAlpha( 255 - 
basegfx::fround<sal_uInt8>( 255.0 * aFill.getTransparency() ) );
 
                             if( bGradient )
                             {
@@ -3525,8 +3525,8 @@ void SVGActionWriter::ImplWriteActions( const 
GDIMetaFile& rMtf,
                     }
 
                     mapCurShape->maShapeLineColor = mpVDev->GetLineColor();
-                    mapCurShape->maShapeLineColor.SetAlpha( 255 - 
static_cast<sal_uInt8>(FRound( aStroke.getTransparency() * 255.0 )) );
-                    mapCurShape->mnStrokeWidth = FRound( 
aStroke.getStrokeWidth() );
+                    mapCurShape->maShapeLineColor.SetAlpha( 255 - 
basegfx::fround<sal_uInt8>( aStroke.getTransparency() * 255.0 ) );
+                    mapCurShape->mnStrokeWidth = 
basegfx::fround(aStroke.getStrokeWidth());
                     aStroke.getDashArray( mapCurShape->maDashArray );
 
                     // added support for LineJoin
diff --git a/include/basegfx/numeric/ftools.hxx 
b/include/basegfx/numeric/ftools.hxx
index 28efe2770b74..b286c847968c 100644
--- a/include/basegfx/numeric/ftools.hxx
+++ b/include/basegfx/numeric/ftools.hxx
@@ -35,41 +35,25 @@ namespace basegfx
 
         @return the nearest integer
     */
-    inline sal_Int32 fround32( double fVal )
+    template <class Int = sal_Int32>
+    inline std::enable_if_t<std::is_integral_v<Int>, Int> fround(double fVal)
     {
         if (fVal >= 0.0)
         {
-            if (fVal >= std::numeric_limits<sal_Int32>::max() - .5)
-                return std::numeric_limits<sal_Int32>::max();
-            return static_cast<sal_Int32>(fVal + .5);
+            if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 
0.5)
+                return std::numeric_limits<Int>::max();
+            return static_cast<Int>(fVal + .5);
         }
-        if (fVal <= std::numeric_limits<sal_Int32>::min() + .5)
-            return std::numeric_limits<sal_Int32>::min();
-        return static_cast<sal_Int32>(fVal - .5);
+        if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5)
+            return std::numeric_limits<Int>::min();
+        return static_cast<Int>(fVal - .5);
     }
 
     /** Round double to nearest integer
 
         @return the nearest 64 bit integer
     */
-    inline sal_Int64 fround64( double fVal )
-    {
-        return fVal > 0.0 ? static_cast<sal_Int64>( fVal + .5 ) : 
-static_cast<sal_Int64>( -fVal + .5 );
-    }
-
-    /** Round double to nearest integer
-
-        @return the nearest integer
-    */
-    template <class Int = sal_Int32>
-    inline std::enable_if_t<std::is_integral_v<Int> && std::is_signed_v<Int>, 
Int>
-    fround(double fVal)
-    {
-        if constexpr (sizeof(Int) == sizeof(sal_Int64))
-            return fround64(fVal);
-        else
-            return fround32(fVal);
-    }
+    inline sal_Int64 fround64(double fVal) { return fround<sal_Int64>(fVal); }
 
     /** Prune a small epsilon range around zero.
 
diff --git a/include/svx/svdtrans.hxx b/include/svx/svdtrans.hxx
index 0087f5407f81..88bbfc6fa1ed 100644
--- a/include/svx/svdtrans.hxx
+++ b/include/svx/svdtrans.hxx
@@ -94,27 +94,27 @@ inline void ResizePoint(Point& rPnt, const Point& rRef, 
const Fraction& xFract,
 {
     double nxFract = xFract.IsValid() ? static_cast<double>(xFract) : 1.0;
     double nyFract = yFract.IsValid() ? static_cast<double>(yFract) : 1.0;
-    rPnt.setX(rRef.X() + FRound( (rPnt.X() - rRef.X()) * nxFract ));
-    rPnt.setY(rRef.Y() + FRound( (rPnt.Y() - rRef.Y()) * nyFract ));
+    rPnt.setX(rRef.X() + basegfx::fround<tools::Long>((rPnt.X() - rRef.X()) * 
nxFract));
+    rPnt.setY(rRef.Y() + basegfx::fround<tools::Long>((rPnt.Y() - rRef.Y()) * 
nyFract));
 }
 
 inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs)
 {
     tools::Long dx=rPnt.X()-rRef.X();
     tools::Long dy=rPnt.Y()-rRef.Y();
-    rPnt.setX(FRound(rRef.X()+dx*cs+dy*sn));
-    rPnt.setY(FRound(rRef.Y()+dy*cs-dx*sn));
+    rPnt.setX(basegfx::fround<tools::Long>(rRef.X() + dx * cs + dy * sn));
+    rPnt.setY(basegfx::fround<tools::Long>(rRef.Y() + dy * cs - dx * sn));
 }
 
 inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear)
 {
     if (!bVShear) { // Horizontal
         if (rPnt.Y()!=rRef.Y()) { // else not needed
-            rPnt.AdjustX(-FRound((rPnt.Y()-rRef.Y())*tn));
+            rPnt.AdjustX(basegfx::fround<tools::Long>((rRef.Y() - rPnt.Y()) * 
tn));
         }
     } else { // or else vertical
         if (rPnt.X()!=rRef.X()) { // else not needed
-            rPnt.AdjustY(-FRound((rPnt.X()-rRef.X())*tn));
+            rPnt.AdjustY(basegfx::fround<tools::Long>((rRef.X() - rPnt.X()) * 
tn));
         }
     }
 }
diff --git a/include/tools/helpers.hxx b/include/tools/helpers.hxx
index 5f61ba80836c..d0fb08f70e5b 100644
--- a/include/tools/helpers.hxx
+++ b/include/tools/helpers.hxx
@@ -71,14 +71,6 @@ inline sal_uInt32 AlignedWidth4Bytes(sal_uInt32 nWidthBits)
     return (nWidthBits >> 5) << 2;
 }
 
-inline tools::Long FRound( double fVal )
-{
-    return fVal > 0.0
-        ? fVal == double(std::numeric_limits<tools::Long>::max())
-            ? std::numeric_limits<tools::Long>::max() : 
static_cast<tools::Long>( fVal + 0.5 )
-        :  static_cast<tools::Long>( fVal - 0.5 );
-}
-
 //valid range:  (-180,180]
 template <typename T>
 [[nodiscard]] inline typename std::enable_if<std::is_signed<T>::value, T>::type
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index 123b48fcd752..19dc78bc5d76 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -20,6 +20,9 @@
 #ifndef INCLUDED_VCL_BITMAP_HXX
 #define INCLUDED_VCL_BITMAP_HXX
 
+#include <sal/config.h>
+
+#include <basegfx/numeric/ftools.hxx>
 #include <tools/degree.hxx>
 #include <vcl/checksum.hxx>
 #include <vcl/dllapi.h>
@@ -32,7 +35,10 @@
 
 #include <memory>
 
-#define GAMMA( _def_cVal, _def_InvGamma )   
(static_cast<sal_uInt8>(MinMax(FRound(pow( 
_def_cVal/255.0,_def_InvGamma)*255.0),0,255)))
+inline sal_uInt8 GAMMA(double _def_cVal, double _def_InvGamma)
+{
+    return basegfx::fround<sal_uInt8>(pow(_def_cVal / 255.0, _def_InvGamma) * 
255.0);
+}
 
 class Color;
 
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 20da0fcac2bf..c4bd1b2f90b1 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -963,10 +963,10 @@ void ScDrawLayer::InitializeCellAnchoredObj(SdrObject* 
pObj, ScDrawObjData& rDat
                 
static_cast<SdrPathObj*>(pObj)->GetPathPoly().getB2DPolygon(0));
             const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0));
             const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1));
-            const Point aPointLT(FRound(std::min(aB2DPoint0.getX(), 
aB2DPoint1.getX())),
-                                 FRound(std::min(aB2DPoint0.getY(), 
aB2DPoint1.getY())));
-            const Point aPointRB(FRound(std::max(aB2DPoint0.getX(), 
aB2DPoint1.getX())),
-                                 FRound(std::max(aB2DPoint0.getY(), 
aB2DPoint1.getY())));
+            const Point 
aPointLT(basegfx::fround<tools::Long>(std::min(aB2DPoint0.getX(), 
aB2DPoint1.getX())),
+                                 
basegfx::fround<tools::Long>(std::min(aB2DPoint0.getY(), aB2DPoint1.getY())));
+            const Point 
aPointRB(basegfx::fround<tools::Long>(std::max(aB2DPoint0.getX(), 
aB2DPoint1.getX())),
+                                 
basegfx::fround<tools::Long>(std::max(aB2DPoint0.getY(), aB2DPoint1.getY())));
             const tools::Rectangle aObjRect(aPointLT, aPointRB);
             GetCellAnchorFromPosition(aObjRect, rNoRotatedAnchor, *pDoc, nTab1,
                                       false /*bHiddenAsZero*/);
diff --git a/sd/source/filter/html/htmlex.cxx b/sd/source/filter/html/htmlex.cxx
index aed0312bc812..7f41e2966a4d 100644
--- a/sd/source/filter/html/htmlex.cxx
+++ b/sd/source/filter/html/htmlex.cxx
@@ -2774,7 +2774,8 @@ OUString HtmlExport::CreateHTMLPolygonArea( const 
::basegfx::B2DPolyPolygon& rPo
         for ( sal_uInt32 nPoint = 0; nPoint < nNoOfPoints; nPoint++ )
         {
             const ::basegfx::B2DPoint aB2DPoint(aPolygon.getB2DPoint(nPoint));
-            Point aPnt(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
+            Point aPnt(basegfx::fround<tools::Long>(aB2DPoint.getX()),
+                       basegfx::fround<tools::Long>(aB2DPoint.getY()));
             // coordinates are relative to the physical page origin, not the
             // origin of ordinates
             aPnt.Move(aShift.Width(), aShift.Height());
diff --git a/sd/source/ui/app/optsitem.cxx b/sd/source/ui/app/optsitem.cxx
index fb9aac86d491..1736a20e0c6c 100644
--- a/sd/source/ui/app/optsitem.cxx
+++ b/sd/source/ui/app/optsitem.cxx
@@ -1042,13 +1042,13 @@ bool SdOptionsGrid::ReadData( const Any* pValues )
 
     if( pValues[2].hasValue() )
     {
-        const sal_uInt32 nDivX = FRound( *o3tl::doAccess<double>(pValues[ 2 ]) 
);
+        const sal_uInt32 nDivX = 
basegfx::fround<sal_uInt32>(*o3tl::doAccess<double>(pValues[2]));
         SetFieldDivisionX( SvxOptionsGrid::GetFieldDrawX() / ( nDivX + 1 ) );
     }
 
     if( pValues[3].hasValue() )
     {
-        const sal_uInt32 nDivY = FRound( *o3tl::doAccess<double>(pValues[ 3 ]) 
);
+        const sal_uInt32 nDivY = 
basegfx::fround<sal_uInt32>(*o3tl::doAccess<double>(pValues[3]));
         SetFieldDivisionY( SvxOptionsGrid::GetFieldDrawY() / ( nDivY + 1 ) );
     }
 
diff --git a/sd/source/ui/dlg/vectdlg.cxx b/sd/source/ui/dlg/vectdlg.cxx
index 4069aa225f44..ee407b7eb8ca 100644
--- a/sd/source/ui/dlg/vectdlg.cxx
+++ b/sd/source/ui/dlg/vectdlg.cxx
@@ -221,9 +221,9 @@ void SdVectorizeDlg::AddTile( BitmapReadAccess const * 
pRAcc, GDIMetaFile& rMtf,
         }
     }
 
-    const Color aColor( static_cast<sal_uInt8>(FRound( nSumR * fMult )),
-                        static_cast<sal_uInt8>(FRound( nSumG * fMult )),
-                        static_cast<sal_uInt8>(FRound( nSumB * fMult )) );
+    const Color aColor( basegfx::fround<sal_uInt8>( nSumR * fMult ),
+                        basegfx::fround<sal_uInt8>( nSumG * fMult ),
+                        basegfx::fround<sal_uInt8>( nSumB * fMult ) );
 
     ::tools::Rectangle   aRect( Point( nPosX, nPosY ), Size( nWidth + 1, 
nHeight + 1 ) );
     const Size& rMaxSize = rMtf.GetPrefSize();
diff --git a/sd/source/ui/func/fuoaprms.cxx b/sd/source/ui/func/fuoaprms.cxx
index 0feaabfb4736..893f833fcdf1 100644
--- a/sd/source/ui/func/fuoaprms.cxx
+++ b/sd/source/ui/func/fuoaprms.cxx
@@ -662,7 +662,8 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& 
rReq )
             const ::basegfx::B2DPolygon& 
aPolygon(rPolyPolygon.getB2DPolygon(nNoOfPolygons - 1));
             sal_uInt32 nPoints(aPolygon.count());
             const ::basegfx::B2DPoint 
aNewB2DCenter(aPolygon.getB2DPoint(nPoints - 1));
-            const Point aNewCenter(FRound(aNewB2DCenter.getX()), 
FRound(aNewB2DCenter.getY()));
+            const Point 
aNewCenter(basegfx::fround<::tools::Long>(aNewB2DCenter.getX()),
+                                   
basegfx::fround<::tools::Long>(aNewB2DCenter.getY()));
             Size aDistance(aNewCenter.X() - aCurCenter.X(), aNewCenter.Y() - 
aCurCenter.Y());
             pRunningObj->Move(aDistance);
 
diff --git a/sd/source/ui/view/drviews8.cxx b/sd/source/ui/view/drviews8.cxx
index 0f2907d424ba..15be1d1c95d0 100644
--- a/sd/source/ui/view/drviews8.cxx
+++ b/sd/source/ui/view/drviews8.cxx
@@ -74,13 +74,13 @@ void DrawViewShell::ScannerEvent()
 
                         if( fGrfWH < fWinWH )
                         {
-                            aBmpSize.setWidth( FRound( aPageSize.Height() * 
fGrfWH ) );
+                            aBmpSize.setWidth( basegfx::fround<::tools::Long>( 
aPageSize.Height() * fGrfWH ) );
                             aBmpSize.setHeight( aPageSize.Height() );
                         }
                         else if( fGrfWH > 0.F )
                         {
                             aBmpSize.setWidth( aPageSize.Width() );
-                            aBmpSize.setHeight( FRound( aPageSize.Width() / 
fGrfWH ) );
+                            aBmpSize.setHeight( 
basegfx::fround<::tools::Long>( aPageSize.Width() / fGrfWH ) );
                         }
                     }
 
diff --git a/sfx2/source/doc/objcont.cxx b/sfx2/source/doc/objcont.cxx
index a3b5226917d3..847d44d00820 100644
--- a/sfx2/source/doc/objcont.cxx
+++ b/sfx2/source/doc/objcont.cxx
@@ -171,13 +171,13 @@ bool SfxObjectShell::CreatePreview_Impl( bool 
bFullContent, VirtualDevice* pDevi
             double      fWH = static_cast< double >( aSizePix.Width() ) / 
aSizePix.Height();
             if ( fWH <= 1.0 )
             {
-                aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
+                aSizePix.setWidth(basegfx::fround<tools::Long>(nMaximumExtent 
* fWH));
                 aSizePix.setHeight( nMaximumExtent );
             }
             else
             {
                 aSizePix.setWidth( nMaximumExtent );
-                aSizePix.setHeight( FRound(  nMaximumExtent / fWH ) );
+                aSizePix.setHeight(basegfx::fround<tools::Long>(nMaximumExtent 
/ fWH));
             }
         }
         // do it 4x larger to be able to scale it down & get beautiful 
antialias
diff --git a/slideshow/source/engine/shapes/drawinglayeranimation.cxx 
b/slideshow/source/engine/shapes/drawinglayeranimation.cxx
index d0d3acb66369..ea765eea9649 100644
--- a/slideshow/source/engine/shapes/drawinglayeranimation.cxx
+++ b/slideshow/source/engine/shapes/drawinglayeranimation.cxx
@@ -422,7 +422,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes()
 
         const double fNumberSteps =
             (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
-        nLoopTime = FRound(fNumberSteps * mnFrequency);
+        nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
 
         // init loop
         ScrollTextAnimNode aInitNode(
@@ -451,7 +451,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes()
 
         const double fNumberSteps =
             (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
-        nLoopTime = FRound(fNumberSteps * mnFrequency);
+        nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
 
         if(0 == mnRepeat)
         {
@@ -501,7 +501,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes()
 
     const double fNumberSteps =
         (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
-    nLoopTime = FRound(fNumberSteps * mnFrequency);
+    nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency);
 
     // exit loop
     ScrollTextAnimNode aExitNode(
diff --git a/svx/source/customshapes/EnhancedCustomShape2d.cxx 
b/svx/source/customshapes/EnhancedCustomShape2d.cxx
index d93dbee142a3..4c5214bf8674 100644
--- a/svx/source/customshapes/EnhancedCustomShape2d.cxx
+++ b/svx/source/customshapes/EnhancedCustomShape2d.cxx
@@ -1171,9 +1171,9 @@ bool EnhancedCustomShape2d::GetHandlePosition( const 
sal_uInt32 nIndex, Point& r
                 double fY =-dx * sin( a );
                 rReturnPosition =
                     Point(
-                        FRound( fX + aReferencePoint.X() ),
+                        basegfx::fround<tools::Long>( fX + aReferencePoint.X() 
),
                         basegfx::fTools::equalZero(fXScale) ? 
aReferencePoint.Y() :
-                        FRound( ( fY * fYScale ) / fXScale + 
aReferencePoint.Y() ) );
+                        basegfx::fround<tools::Long>( ( fY * fYScale ) / 
fXScale + aReferencePoint.Y() ) );
             }
             else
             {
diff --git a/svx/source/dialog/_contdlg.cxx b/svx/source/dialog/_contdlg.cxx
index 3ae8cba852e0..02608859b380 100644
--- a/svx/source/dialog/_contdlg.cxx
+++ b/svx/source/dialog/_contdlg.cxx
@@ -135,12 +135,12 @@ tools::PolyPolygon SvxContourDlg::CreateAutoContour( 
const Graphic& rGraphic,
             if( fWH <= 1.0 )
             {
                 aSizePix.setHeight(512);
-                aSizePix.setWidth( FRound( ( aSizePix.Height() ) * fWH ) );
+                
aSizePix.setWidth(basegfx::fround<tools::Long>(aSizePix.Height() * fWH));
             }
             else
             {
                 aSizePix.setWidth(512);
-                aSizePix.setHeight( FRound( ( aSizePix.Width() ) / fWH ) );
+                
aSizePix.setHeight(basegfx::fround<tools::Long>(aSizePix.Width() / fWH));
             }
         }
 
diff --git a/svx/source/gallery2/galobj.cxx b/svx/source/gallery2/galobj.cxx
index 44362b9a78ec..80d49228e750 100644
--- a/svx/source/gallery2/galobj.cxx
+++ b/svx/source/gallery2/galobj.cxx
@@ -118,9 +118,9 @@ bool SgaObject::CreateThumb( const Graphic& rGraphic )
                     double  fFactorPix = static_cast< double >( 
aBmpSize.Width() ) / aBmpSize.Height();
 
                     if( fFactorPix > fFactorLog )
-                        aBmpSize.setWidth( FRound( aBmpSize.Height() * 
fFactorLog ) );
+                        aBmpSize.setWidth( basegfx::fround<tools::Long>( 
aBmpSize.Height() * fFactorLog ) );
                     else
-                        aBmpSize.setHeight( FRound( aBmpSize.Width() / 
fFactorLog ) );
+                        aBmpSize.setHeight( basegfx::fround<tools::Long>( 
aBmpSize.Width() / fFactorLog ) );
 
                     aBmpEx.Scale(aBmpSize, BmpScaleFlag::BestQuality);
                 }
diff --git a/svx/source/svdraw/gradtrns.cxx b/svx/source/svdraw/gradtrns.cxx
index d665cd48ce16..34c547bba8ed 100644
--- a/svx/source/svdraw/gradtrns.cxx
+++ b/svx/source/svdraw/gradtrns.cxx
@@ -235,7 +235,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 }
 
                 // to int and set
-                Degree10 nNewAngle( FRound(fNewFullAngle));
+                Degree10 nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle));
 
                 if(nNewAngle != rGOld.aGradient.GetAngle())
                 {
@@ -252,7 +252,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 const double fFullLen(aFullVec.getLength());
                 const double fOldLen(aOldVec.getLength());
                 const double fNewBorder((fFullLen * 100.0) / fOldLen);
-                sal_Int32 nNewBorder(100 - FRound(fNewBorder));
+                sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder));
 
                 // clip
                 if(nNewBorder < 0)
@@ -283,7 +283,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 const double fFullLen(aFullVec.getLength());
                 const double fOldLen(aOldVec.getLength());
                 const double fNewBorder((fFullLen * 100.0) / fOldLen);
-                sal_Int32 nNewBorder = 100 - FRound(fNewBorder);
+                sal_Int32 nNewBorder = 100 - basegfx::fround(fNewBorder);
 
                 // clip
                 if(nNewBorder < 0)
@@ -319,7 +319,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 }
 
                 // to int and set
-                const Degree10 nNewAngle(FRound(fNewFullAngle));
+                const Degree10 
nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle));
 
                 if(nNewAngle != rGOld.aGradient.GetAngle())
                 {
@@ -336,8 +336,8 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
             {
                 const basegfx::B2DPoint aTopLeft(aRange.getMinX(), 
aRange.getMinY());
                 const basegfx::B2DPoint aOffset(aEndPos - aTopLeft);
-                sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / 
aRange.getWidth()));
-                sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / 
aRange.getHeight()));
+                sal_Int32 nNewXOffset(basegfx::fround(aOffset.getX() * 100.0 / 
aRange.getWidth()));
+                sal_Int32 nNewYOffset(basegfx::fround(aOffset.getY() * 100.0 / 
aRange.getHeight()));
 
                 // clip
                 if(nNewXOffset < 0)
@@ -376,7 +376,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 const double fFullLen(aFullVec.getLength());
                 const double fOldLen(aOldVec.getLength());
                 const double fNewBorder((fFullLen * 100.0) / fOldLen);
-                sal_Int32 nNewBorder(100 - FRound(fNewBorder));
+                sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder));
 
                 // clip
                 if(nNewBorder < 0)
@@ -414,7 +414,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 }
 
                 // to int and set
-                const Degree10 nNewAngle(FRound(fNewFullAngle));
+                const Degree10 
nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle));
 
                 if(nNewAngle != rGOld.aGradient.GetAngle())
                 {
@@ -431,8 +431,8 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
             {
                 const basegfx::B2DPoint aTopLeft(aRange.getMinX(), 
aRange.getMinY());
                 const basegfx::B2DPoint aOffset(aEndPos - aTopLeft);
-                sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / 
aRange.getWidth()));
-                sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / 
aRange.getHeight()));
+                sal_Int32 nNewXOffset(basegfx::fround(aOffset.getX() * 100.0 / 
aRange.getWidth()));
+                sal_Int32 nNewYOffset(basegfx::fround(aOffset.getY() * 100.0 / 
aRange.getHeight()));
 
                 // clip
                 if(nNewXOffset < 0)
@@ -471,7 +471,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 const double fFullLen(aFullVec.getLength());
                 const double fOldLen(aOldVec.getLength());
                 const double fNewBorder((fFullLen * 100.0) / fOldLen);
-                sal_Int32 nNewBorder(100 - FRound(fNewBorder));
+                sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder));
 
                 // clip
                 if(nNewBorder < 0)
@@ -509,7 +509,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, 
GradTransGradient& r
                 }
 
                 // to int and set
-                const Degree10 nNewAngle(FRound(fNewFullAngle));
+                const Degree10 
nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle));
 
                 if(nNewAngle != rGOld.aGradient.GetAngle())
                 {
diff --git a/svx/source/svdraw/sdrpagewindow.cxx 
b/svx/source/svdraw/sdrpagewindow.cxx
index 01be77135674..86fbe967ccbc 100644
--- a/svx/source/svdraw/sdrpagewindow.cxx
+++ b/svx/source/svdraw/sdrpagewindow.cxx
@@ -231,6 +231,7 @@ void SdrPageWindow::PrepareRedraw(const vcl::Region& rReg)
 // clip test
 #ifdef CLIPPER_TEST
 #include <svx/svdopath.hxx>
+#include <basegfx/numeric/ftools.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <tools/helpers.hxx>
 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
@@ -262,8 +263,10 @@ namespace
             {
                 const basegfx::B2DPoint aBStart(aCandidate.getB2DPoint(a));
-e 
... etc. - the rest is truncated

Reply via email to