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/winlayout.hxx                      |    2 
 vcl/qa/cppunit/cjktext.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                           |   15 ++---
 vcl/skia/win/gdiimpl.cxx                       |   33 +++++++-----
 vcl/skia/x11/textrender.cxx                    |   10 +--
 vcl/source/font/LogicalFontInstance.cxx        |   36 +------------
 vcl/source/font/fontcache.cxx                  |    4 -
 vcl/source/gdi/CommonSalLayout.cxx             |    6 +-
 vcl/source/gdi/pdfbuildin_fonts.cxx            |    5 +
 vcl/source/gdi/pdfwriter_impl.cxx              |   29 +---------
 vcl/source/gdi/sallayout.cxx                   |   37 ++++---------
 vcl/source/outdev/font.cxx                     |    6 +-
 vcl/unx/generic/glyphs/freetype_glyphcache.cxx |   38 ++++++++++++++
 vcl/unx/generic/glyphs/glyphcache.cxx          |    8 ++
 vcl/win/gdi/salfont.cxx                        |   53 +++++++++++++++++++
 vcl/win/gdi/winlayout.cxx                      |   14 ++++-
 vcl/workben/listglyphs.cxx                     |    2 
 29 files changed, 237 insertions(+), 188 deletions(-)

New commits:
commit 0aa53d7f7d4aa31cd79ed27dfd20be5b13dd0815
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:21 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:21 2024 +0500

    Revert "Optimize trigonometry a bit"
    
    This reverts commit dc7d9bfbfb7b46d9ac2e3bb72669da1130259f93.

diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 84b625115648..7a240600be98 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -2099,8 +2099,8 @@ bool SkiaSalGraphicsImpl::implDrawGradient(const 
basegfx::B2DPolyPolygon& rPolyP
 }
 
 static double toRadian(Degree10 degree10th) { return toRadians(3600_deg10 - 
degree10th); }
-static auto toCos(Degree10 degree10th) { return 
SkScalarCos(toRadian(degree10th)); }
-static auto toSin(Degree10 degree10th) { return 
SkScalarSin(toRadian(degree10th)); }
+static double toCos(Degree10 degree10th) { return 
SkScalarCos(toRadian(degree10th)); }
+static double toSin(Degree10 degree10th) { return 
SkScalarSin(toRadian(degree10th)); }
 
 void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, 
Color textColor,
                                             const SkFont& font, const SkFont& 
verticalFont)
@@ -2115,16 +2115,15 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const 
GenericSalLayout& layout, Colo
     DevicePoint aPos;
     const GlyphItem* pGlyph;
     int nStart = 0;
-    auto cos = toCos(layout.GetOrientation());
-    auto sin = toSin(layout.GetOrientation());
     while (layout.GetNextGlyph(&pGlyph, aPos, nStart))
     {
         glyphIds.push_back(pGlyph->glyphId());
-        verticals.emplace_back(pGlyph->IsVertical());
-        auto cos1 = pGlyph->IsVertical() ? sin : cos; // cos (x - 90) = sin (x)
-        auto sin1 = pGlyph->IsVertical() ? -cos : sin; // sin (x - 90) = -cos 
(x)
-        SkRSXform form = SkRSXform::Make(cos1, sin1, aPos.getX(), aPos.getY());
+        Degree10 angle = layout.GetOrientation();
+        if (pGlyph->IsVertical())
+            angle += 900_deg10;
+        SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), 
aPos.getX(), aPos.getY());
         glyphForms.emplace_back(std::move(form));
+        verticals.emplace_back(pGlyph->IsVertical());
     }
     if (glyphIds.empty())
         return;
commit b05c43c694435cc4a27c7bfcf103c1d3d8cfcc31
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:21 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:21 2024 +0500

    Revert "Simplify a bit"
    
    This reverts commit 401ed53c66085d2442c361c43fe0180e115d6b11.

diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index 04dad0123573..d063b440cf31 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -216,22 +216,20 @@ catch (const sal::systools::ComError& e)
 bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout)
 {
     assert(dynamic_cast<const SkiaWinFontInstance*>(&rLayout.GetFont()));
-    const SkiaWinFontInstance& rWinFont
-        = static_cast<const SkiaWinFontInstance&>(rLayout.GetFont());
-    const vcl::font::FontSelectPattern& rFSD = rWinFont.GetFontSelectPattern();
-    if (rFSD.mnHeight == 0)
-        return false;
-    const HFONT hLayoutFont = rWinFont.GetHFONT();
+    const SkiaWinFontInstance* pWinFont
+        = static_cast<const SkiaWinFontInstance*>(&rLayout.GetFont());
+    const HFONT hLayoutFont = pWinFont->GetHFONT();
+    double hScale = pWinFont->getHScale();
     LOGFONTW logFont;
     if (GetObjectW(hLayoutFont, sizeof(logFont), &logFont) == 0)
     {
         assert(false);
         return false;
     }
-    sk_sp<SkTypeface> typeface = rWinFont.GetSkiaTypeface();
+    sk_sp<SkTypeface> typeface = pWinFont->GetSkiaTypeface();
     if (!typeface)
     {
-        typeface = createDirectWriteTypeface(&rWinFont);
+        typeface = createDirectWriteTypeface(pWinFont);
         bool dwrite = true;
         if (!typeface) // fall back to GDI text rendering
         {
@@ -252,7 +250,7 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const 
GenericSalLayout& rLayout)
                 return false;
         }
         // Cache the typeface.
-        const_cast<SkiaWinFontInstance&>(rWinFont).SetSkiaTypeface(typeface, 
dwrite);
+        const_cast<SkiaWinFontInstance*>(pWinFont)->SetSkiaTypeface(typeface, 
dwrite);
     }
 
     SkFont font(typeface);
@@ -269,14 +267,21 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const 
GenericSalLayout& rLayout)
     font.setEdging(logFont.lfQuality == NONANTIALIASED_QUALITY ? 
SkFont::Edging::kAlias
                                                                : 
ePreferredAliasing);
 
-    double nHeight = rFSD.mnHeight;
-    double nWidth = rFSD.mnWidth ? rFSD.mnWidth * 
rWinFont.GetAverageWidthFactor() : nHeight;
+    const vcl::font::FontSelectPattern& rFSD = 
pWinFont->GetFontSelectPattern();
+    int nHeight = rFSD.mnHeight;
+    int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
+    if (nWidth == 0 || nHeight == 0)
+        return false;
     font.setSize(nHeight);
-    font.setScaleX(nWidth / nHeight);
+    font.setScaleX(hScale);
 
+    // Unlike with Freetype-based font handling, use height even in vertical 
mode,
+    // additionally multiply it by horizontal scale to get the proper
+    // size and then scale the width back, otherwise the height would
+    // not be correct. I don't know why this is inconsistent.
     SkFont verticalFont(font);
-    verticalFont.setSize(nWidth);
-    verticalFont.setScaleX(nHeight / nWidth);
+    verticalFont.setSize(nHeight * hScale);
+    verticalFont.setScaleX(1.0 / hScale);
 
     assert(dynamic_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl()));
     SkiaSalGraphicsImpl* impl = 
static_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl());
diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx
index c598146be376..fed5daa8a117 100644
--- a/vcl/skia/x11/textrender.cxx
+++ b/vcl/skia/x11/textrender.cxx
@@ -35,10 +35,10 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& 
rLayout, const SalGr
     const FreetypeFontInstance& rInstance = 
static_cast<FreetypeFontInstance&>(rLayout.GetFont());
     const FreetypeFont& rFont = rInstance.GetFreetypeFont();
     const vcl::font::FontSelectPattern& rFSD = 
rInstance.GetFontSelectPattern();
-    if (rFSD.mnHeight == 0)
+    int nHeight = rFSD.mnHeight;
+    int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
+    if (nWidth == 0 || nHeight == 0)
         return;
-    double nHeight = rFSD.mnHeight;
-    double nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;
 
     if (!fontManager)
     {
@@ -49,7 +49,7 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& 
rLayout, const SalGr
         = SkFontMgr_createTypefaceFromFcPattern(fontManager, 
rFont.GetFontOptions()->GetPattern());
     SkFont font(typeface);
     font.setSize(nHeight);
-    font.setScaleX(nWidth / nHeight);
+    font.setScaleX(1.0 * nWidth / nHeight);
     if (rInstance.NeedsArtificialItalic())
         font.setSkewX(-1.0 * ARTIFICIAL_ITALIC_SKEW);
     if (rInstance.NeedsArtificialBold())
@@ -76,7 +76,7 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& 
rLayout, const SalGr
     // Vertical font, use width as "height".
     SkFont verticalFont(font);
     verticalFont.setSize(nWidth);
-    verticalFont.setScaleX(nHeight / nWidth);
+    verticalFont.setScaleX(1.0 * nHeight / nWidth);
 
     assert(dynamic_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl()));
     SkiaSalGraphicsImpl* impl = 
static_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl());
commit cd894eb00babba247ec63d8a3cba4da42d0cc3c4
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:21 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:21 2024 +0500

    Revert "tdf#115321: Fix PDF position of emphasis mark in vertical text"
    
    This reverts commit 2b1e0c071dc186cd29ee2653166fdb9aa98bca2e.

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 40b6b9456266..6ea5c67f12a3 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6982,20 +6982,11 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, 
const OUString& rText, bool
     writeBuffer( aLine.getStr(), aLine.getLength() );
 
     Point aOffset(0,0);
-    Point aOffsetVert(0,0);
 
     if ( nEmphMark & FontEmphasisMark::PosBelow )
-    {
         aOffset.AdjustY(GetFontInstance()->mxFontMetric->GetDescent() + 
aEmphasisMark.GetYOffset() );
-        aOffsetVert = aOffset;
-    }
     else
-    {
         aOffset.AdjustY( -(GetFontInstance()->mxFontMetric->GetAscent() + 
aEmphasisMark.GetYOffset()) );
-        // Todo: use ideographic em-box or ideographic character face 
information.
-        aOffsetVert.AdjustY(-(GetFontInstance()->mxFontMetric->GetAscent() +
-                    GetFontInstance()->mxFontMetric->GetDescent() + 
aEmphasisMark.GetYOffset()));
-    }
 
     tools::Long nEmphWidth2 = aEmphasisMark.GetWidth() / 2;
     tools::Long nEmphHeight2 = nEmphHeight / 2;
@@ -7006,27 +6997,13 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, 
const OUString& rText, bool
     else if ( eAlign == ALIGN_TOP )
         aOffset.AdjustY(GetFontInstance()->mxFontMetric->GetAscent() );
 
-    tools::Rectangle aRectangle;
     nIndex = 0;
-    while (rLayout.GetNextGlyph(&pGlyph, aPos, nIndex, &pGlyphFont))
+    while (rLayout.GetNextGlyph(&pGlyph, aPos, nIndex))
     {
-        if (!pGlyph->GetGlyphBoundRect(pGlyphFont, aRectangle))
-            continue;
-
         if (!pGlyph->IsSpacing())
         {
-            DevicePoint aAdjOffset;
-            if (pGlyph->IsVertical())
-            {
-                aAdjOffset = DevicePoint(aOffsetVert.X(), aOffsetVert.Y());
-                aAdjOffset.adjustX((-pGlyph->origWidth() + 
aEmphasisMark.GetWidth()) / 2);
-            }
-            else
-            {
-                aAdjOffset = DevicePoint(aOffset.X(), aOffset.Y());
-                aAdjOffset.adjustX(aRectangle.Left() + (aRectangle.GetWidth() 
- aEmphasisMark.GetWidth()) / 2 );
-            }
-
+            DevicePoint aAdjOffset(aOffset.X(), aOffset.Y());
+            aAdjOffset.adjustX((pGlyph->newWidth() - aEmphasisMark.GetWidth()) 
/ 2);
             aAdjOffset = aRotScale.transform( aAdjOffset );
 
             aAdjOffset -= DevicePoint(nEmphWidth2, nEmphHeight2);
commit 43f4826ac4064e36685aec9424f6c9636c73573a
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:20 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:20 2024 +0500

    Revert "vcl: Use HarfBuzz to get glyph bounding rectangle"
    
    This reverts commit cbb9d93f5396ee0842cf48fdefc98d5db6eb27c4.

diff --git a/vcl/inc/font/LogicalFontInstance.hxx 
b/vcl/inc/font/LogicalFontInstance.hxx
index 518716b5c7df..c9e837d540f1 100644
--- a/vcl/inc/font/LogicalFontInstance.hxx
+++ b/vcl/inc/font/LogicalFontInstance.hxx
@@ -120,6 +120,8 @@ protected:
     explicit LogicalFontInstance(const vcl::font::PhysicalFontFace&,
                                  const vcl::font::FontSelectPattern&);
 
+    virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) 
const = 0;
+
     hb_font_t* InitHbFont();
     virtual void ImplInitHbFont(hb_font_t*) {}
 
diff --git a/vcl/inc/pdf/pdfbuildin_fonts.hxx b/vcl/inc/pdf/pdfbuildin_fonts.hxx
index a0c2fc06287d..8cb34e74922b 100644
--- a/vcl/inc/pdf/pdfbuildin_fonts.hxx
+++ b/vcl/inc/pdf/pdfbuildin_fonts.hxx
@@ -49,6 +49,8 @@ struct BuildinFont
 
 class BuildinFontInstance final : public LogicalFontInstance
 {
+    bool ImplGetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& rRect, bool) 
const override;
+
 public:
     BuildinFontInstance(const vcl::font::PhysicalFontFace&, const 
vcl::font::FontSelectPattern&);
 
diff --git a/vcl/inc/qt5/QtFont.hxx b/vcl/inc/qt5/QtFont.hxx
index 7d0b338c939d..e19d6de21aa2 100644
--- a/vcl/inc/qt5/QtFont.hxx
+++ b/vcl/inc/qt5/QtFont.hxx
@@ -33,6 +33,7 @@ class QtFont final : public QFont, public LogicalFontInstance
     QtFontFace::CreateFontInstance(const vcl::font::FontSelectPattern&) const;
 
     bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const 
override;
+    bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const 
override;
 
     explicit QtFont(const vcl::font::PhysicalFontFace&, const 
vcl::font::FontSelectPattern&);
 };
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index a255e9dc330d..6d1668c1f913 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -103,6 +103,8 @@ public:
 private:
     explicit CoreTextFont(const CoreTextFontFace&, const 
vcl::font::FontSelectPattern&);
 
+    bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const 
override;
+
     CTFontRef mpCTFont;
 };
 
diff --git a/vcl/inc/unx/freetype_glyphcache.hxx 
b/vcl/inc/unx/freetype_glyphcache.hxx
index 9c61e0ff60d1..c80642b6126c 100644
--- a/vcl/inc/unx/freetype_glyphcache.hxx
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
@@ -107,6 +107,8 @@ class SAL_DLLPUBLIC_RTTI FreetypeFontInstance final : 
public LogicalFontInstance
 
     std::unique_ptr<FreetypeFont> mxFreetypeFont;
 
+    virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) 
const override;
+
     explicit FreetypeFontInstance(const vcl::font::PhysicalFontFace& rPFF, 
const vcl::font::FontSelectPattern& rFSP);
 
 public:
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
index 4d21d34d05ea..9de7bd59fe6c 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -123,6 +123,7 @@ public:
 
     void                    GetFontMetric(ImplFontMetricDataRef const &) const;
 
+    bool                    GetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, 
bool) const;
     bool                    GetGlyphOutline(sal_GlyphId, 
basegfx::B2DPolyPolygon&, bool) const;
     bool                    GetAntialiasAdvice() const;
 
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 18de0e684b1c..fb8e5a1c6e43 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -60,6 +60,7 @@ private:
     explicit WinFontInstance(const WinFontFace&, const 
vcl::font::FontSelectPattern&);
 
     virtual void ImplInitHbFont(hb_font_t*) override;
+    bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const 
override;
 
     WinSalGraphics *m_pGraphics;
     HFONT m_hFont;
diff --git a/vcl/qa/cppunit/cjktext.cxx b/vcl/qa/cppunit/cjktext.cxx
index cd9bd2c165fd..af63b29959fd 100644
--- a/vcl/qa/cppunit/cjktext.cxx
+++ b/vcl/qa/cppunit/cjktext.cxx
@@ -178,7 +178,7 @@ void VclCjkTextTest::testVerticalText()
     tools::Long height36Rotated = getCharacterRightSideHeight(device, 
Point(99, 35));
     CPPUNIT_ASSERT_DOUBLES_EQUAL(height36, height36Rotated, 1);
     tools::Long width36Rotated = getCharacterTopWidth(device, Point(25, 0));
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36Rotated, 2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36Rotated, 1);
 
     font = baseFont;
     font.SetFontSize(Size(0, 72));
diff --git a/vcl/qa/cppunit/fontmocks.hxx b/vcl/qa/cppunit/fontmocks.hxx
index 8eac463c143f..7e33ce8e7e13 100644
--- a/vcl/qa/cppunit/fontmocks.hxx
+++ b/vcl/qa/cppunit/fontmocks.hxx
@@ -30,6 +30,9 @@ public:
     {
         return true;
     }
+
+protected:
+    bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const 
override { return true; }
 };
 
 class TestFontFace : public vcl::font::PhysicalFontFace
diff --git a/vcl/qa/cppunit/logicalfontinstance.cxx 
b/vcl/qa/cppunit/logicalfontinstance.cxx
index 12ee95762eef..2a7a5c83ac27 100644
--- a/vcl/qa/cppunit/logicalfontinstance.cxx
+++ b/vcl/qa/cppunit/logicalfontinstance.cxx
@@ -50,14 +50,13 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
 
     const tools::Long nExpectedX = 7;
     const tools::Long nExpectedY = -80;
-    const tools::Long nExpectedWidth = 51;
-    const tools::Long nExpectedHeight = 83;
 
     CPPUNIT_ASSERT_EQUAL_MESSAGE("x of glyph is wrong", nExpectedX, 
aBoundRect.getX());
     CPPUNIT_ASSERT_EQUAL_MESSAGE("y of glyph is wrong", nExpectedY, 
aBoundRect.getY());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("height of glyph of wrong", nExpectedWidth, 
aBoundRect.GetWidth());
-    CPPUNIT_ASSERT_EQUAL_MESSAGE("width of glyph of wrong", nExpectedHeight,
-                                 aBoundRect.GetHeight());
+    CPPUNIT_ASSERT_MESSAGE("height of glyph of wrong",
+                           aBoundRect.GetWidth() == 50 || 
aBoundRect.GetWidth() == 51);
+    CPPUNIT_ASSERT_MESSAGE("width of glyph of wrong",
+                           aBoundRect.GetHeight() == 82 || 
aBoundRect.GetHeight() == 83);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VclLogicalFontInstanceTest);
diff --git a/vcl/qt5/QtFont.cxx b/vcl/qt5/QtFont.cxx
index e3a6c0b0a9d7..384f56774ffd 100644
--- a/vcl/qt5/QtFont.cxx
+++ b/vcl/qt5/QtFont.cxx
@@ -187,4 +187,11 @@ bool QtFont::GetGlyphOutline(sal_GlyphId nId, 
basegfx::B2DPolyPolygon& rB2DPolyP
     return true;
 }
 
+bool QtFont::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, 
bool) const
+{
+    QRawFont aRawFont(QRawFont::fromFont(*this));
+    rRect = toRectangle(aRawFont.boundingRect(nId).toAlignedRect());
+    return true;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx
index 1cafd270552d..38112a7deb50 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -89,6 +89,27 @@ void CoreTextFont::GetFontMetric( ImplFontMetricDataRef 
const & rxFontMetric )
     rxFontMetric->SetMinKashida(GetKashidaWidth());
 }
 
+bool CoreTextFont::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& 
rRect, bool bVertical) const
+{
+    CGGlyph nCGGlyph = nId;
+
+    SAL_WNODEPRECATED_DECLARATIONS_PUSH //TODO: 10.11 kCTFontDefaultOrientation
+    const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation; // 
TODO: horz/vert
+    SAL_WNODEPRECATED_DECLARATIONS_POP
+    CGRect aCGRect = CTFontGetBoundingRectsForGlyphs(mpCTFont, 
aFontOrientation, &nCGGlyph, nullptr, 1);
+
+    // Apply font rotation to non-vertical glyphs.
+    if (mfFontRotation && !bVertical)
+        aCGRect = CGRectApplyAffineTransform(aCGRect, 
CGAffineTransformMakeRotation(mfFontRotation));
+
+    tools::Long xMin = floor(aCGRect.origin.x);
+    tools::Long yMin = floor(aCGRect.origin.y);
+    tools::Long xMax = ceil(aCGRect.origin.x + aCGRect.size.width);
+    tools::Long yMax = ceil(aCGRect.origin.y + aCGRect.size.height);
+    rRect = tools::Rectangle(xMin, -yMax, xMax, -yMin);
+    return true;
+}
+
 namespace {
 
 // callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline()
diff --git a/vcl/source/font/LogicalFontInstance.cxx 
b/vcl/source/font/LogicalFontInstance.cxx
index 6c6c95bbb6a1..6c7a7e2bde09 100644
--- a/vcl/source/font/LogicalFontInstance.cxx
+++ b/vcl/source/font/LogicalFontInstance.cxx
@@ -172,38 +172,7 @@ bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId 
nID, tools::Rectangle& r
     if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect))
         return true;
 
-    auto* pHbFont = const_cast<LogicalFontInstance*>(this)->GetHbFont();
-    hb_glyph_extents_t aExtents;
-    bool res = hb_font_get_glyph_extents(pHbFont, nID, &aExtents);
-
-    if (res)
-    {
-        double nXScale = 0, nYScale = 0;
-        GetScale(&nXScale, &nYScale);
-
-        double fMinX = aExtents.x_bearing;
-        double fMinY = aExtents.y_bearing;
-        double fMaxX = aExtents.x_bearing + aExtents.width;
-        double fMaxY = aExtents.y_bearing + aExtents.height;
-
-        tools::Rectangle aRect(std::floor(fMinX * nXScale), -std::ceil(fMinY * 
nYScale),
-                               std::ceil(fMaxX * nXScale), -std::floor(fMaxY * 
nYScale));
-        if (mnOrientation && !bVertical)
-        {
-            // Apply font rotation.
-            const double fRad = toRadians(mnOrientation);
-            const double fCos = cos(fRad);
-            const double fSin = sin(fRad);
-
-            rRect.SetLeft(fCos * aRect.Left() + fSin * aRect.Top());
-            rRect.SetTop(-fSin * aRect.Left() - fCos * aRect.Top());
-            rRect.SetRight(fCos * aRect.Right() + fSin * aRect.Bottom());
-            rRect.SetBottom(-fSin * aRect.Right() - fCos * aRect.Bottom());
-        }
-        else
-            rRect = aRect;
-    }
-
+    bool res = ImplGetGlyphBoundRect(nID, rRect, bVertical);
     if (mpFontCache && res)
         mpFontCache->CacheGlyphBoundRect(this, nID, rRect);
     return res;
diff --git a/vcl/source/gdi/pdfbuildin_fonts.cxx 
b/vcl/source/gdi/pdfbuildin_fonts.cxx
index 7f80bfdd030d..e387f78638d3 100644
--- a/vcl/source/gdi/pdfbuildin_fonts.cxx
+++ b/vcl/source/gdi/pdfbuildin_fonts.cxx
@@ -738,6 +738,11 @@ BuildinFontInstance::BuildinFontInstance(const 
vcl::font::PhysicalFontFace& rFon
 {
 }
 
+bool BuildinFontInstance::ImplGetGlyphBoundRect(sal_GlyphId, 
tools::Rectangle&, bool) const
+{
+    return false;
+}
+
 bool BuildinFontInstance::GetGlyphOutline(sal_GlyphId, 
basegfx::B2DPolyPolygon&, bool) const
 {
     return false;
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx 
b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
index bed24e081ee5..64fcb6bfc2bf 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -564,6 +564,44 @@ void FreetypeFont::ApplyGlyphTransform(bool bVertical, 
FT_Glyph pGlyphFT ) const
     }
 }
 
+bool FreetypeFont::GetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& rRect, 
bool bVertical) const
+{
+    FT_Activate_Size( maSizeFT );
+
+    FT_Error rc = FT_Load_Glyph(maFaceFT, nID, mnLoadFlags);
+
+    if (rc != FT_Err_Ok)
+        return false;
+
+    if (mrFontInstance.NeedsArtificialBold())
+        FT_GlyphSlot_Embolden(maFaceFT->glyph);
+
+    FT_Glyph pGlyphFT;
+    rc = FT_Get_Glyph(maFaceFT->glyph, &pGlyphFT);
+    if (rc != FT_Err_Ok)
+        return false;
+
+    ApplyGlyphTransform(bVertical, pGlyphFT);
+
+    FT_BBox aBbox;
+    FT_Glyph_Get_CBox( pGlyphFT, FT_GLYPH_BBOX_PIXELS, &aBbox );
+    FT_Done_Glyph( pGlyphFT );
+
+    tools::Rectangle aRect(aBbox.xMin, -aBbox.yMax, aBbox.xMax, -aBbox.yMin);
+    if (mnCos != 0x10000 && mnSin != 0)
+    {
+        const double nCos = mnCos / 65536.0;
+        const double nSin = mnSin / 65536.0;
+        rRect.SetLeft(  nCos*aRect.Left() + nSin*aRect.Top() );
+        rRect.SetTop( -nSin*aRect.Left() - nCos*aRect.Top() );
+        rRect.SetRight(  nCos*aRect.Right() + nSin*aRect.Bottom() );
+        rRect.SetBottom( -nSin*aRect.Right() - nCos*aRect.Bottom() );
+    }
+    else
+        rRect = aRect;
+    return true;
+}
+
 bool FreetypeFont::GetAntialiasAdvice() const
 {
     // TODO: also use GASP info
diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx 
b/vcl/unx/generic/glyphs/glyphcache.cxx
index ac3c5e15ab73..39b10c78e123 100644
--- a/vcl/unx/generic/glyphs/glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/glyphcache.cxx
@@ -75,6 +75,14 @@ FreetypeFontInstance::~FreetypeFontInstance()
 {
 }
 
+bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, 
tools::Rectangle& rRect, bool bVertical) const
+{
+    assert(mxFreetypeFont);
+    if (!mxFreetypeFont)
+        return false;
+    return mxFreetypeFont->GetGlyphBoundRect(nId, rRect, bVertical);
+}
+
 bool FreetypeFontInstance::GetGlyphOutline(sal_GlyphId nId, 
basegfx::B2DPolyPolygon& rPoly, bool bVertical) const
 {
     assert(mxFreetypeFont);
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index d5f41e2e8819..196932982c28 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -1156,6 +1156,59 @@ void WinSalGraphics::ClearDevFontCache()
     ImplReleaseTempFonts(*GetSalData(), false);
 }
 
+bool WinFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& 
rRect, bool bIsVertical) const
+{
+    assert(m_pGraphics);
+    HDC hDC = m_pGraphics->getHDC();
+    const HFONT hOrigFont = static_cast<HFONT>(GetCurrentObject(hDC, 
OBJ_FONT));
+    const HFONT hFont = GetHFONT();
+    if (hFont != hOrigFont)
+        SelectObject(hDC, hFont);
+
+    const ::comphelper::ScopeGuard aFontRestoreScopeGuard([hFont, hOrigFont, 
hDC]()
+        { if (hFont != hOrigFont) SelectObject(hDC, hOrigFont); });
+    const float fFontScale = GetScale();
+
+    // use unity matrix
+    MAT2 aMat;
+    const vcl::font::FontSelectPattern& rFSD = GetFontSelectPattern();
+
+    // Use identity matrix for fonts requested in horizontal
+    // writing (LTR or RTL), or rotated glyphs in vertical writing.
+    if (!rFSD.mbVertical || !bIsVertical)
+    {
+        aMat.eM11 = aMat.eM22 = FixedFromDouble(1.0);
+        aMat.eM12 = aMat.eM21 = FixedFromDouble(0.0);
+    }
+    else
+    {
+        constexpr double nCos = 0.0;
+        constexpr double nSin = 1.0;
+        aMat.eM11 = FixedFromDouble(nCos);
+        aMat.eM12 = FixedFromDouble(nSin);
+        aMat.eM21 = FixedFromDouble(-nSin);
+        aMat.eM22 = FixedFromDouble(nCos);
+    }
+
+    UINT nGGOFlags = GGO_METRICS;
+    nGGOFlags |= GGO_GLYPH_INDEX;
+
+    GLYPHMETRICS aGM;
+    aGM.gmptGlyphOrigin.x = aGM.gmptGlyphOrigin.y = 0;
+    aGM.gmBlackBoxX = aGM.gmBlackBoxY = 0;
+    DWORD nSize = ::GetGlyphOutlineW(hDC, nId, nGGOFlags, &aGM, 0, nullptr, 
&aMat);
+    if (nSize == GDI_ERROR)
+        return false;
+
+    rRect = tools::Rectangle( Point( +aGM.gmptGlyphOrigin.x, 
-aGM.gmptGlyphOrigin.y ),
+        Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) );
+    rRect.SetLeft(static_cast<int>( fFontScale * rRect.Left() ));
+    rRect.SetRight(static_cast<int>( fFontScale * rRect.Right() ) + 1);
+    rRect.SetTop(static_cast<int>( fFontScale * rRect.Top() ));
+    rRect.SetBottom(static_cast<int>( fFontScale * rRect.Bottom() ) + 1);
+    return true;
+}
+
 bool WinFontInstance::GetGlyphOutline(sal_GlyphId nId, 
basegfx::B2DPolyPolygon& rB2DPolyPoly, bool) const
 {
     rB2DPolyPoly.clear();
commit 30a3ab3b8cb08abee71c0ca855b4c805d9e4772c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:20 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:20 2024 +0500

    Revert "tdf#160430: Fix glyph bounds calculation, and use 
basegfx::B2DRectangle"
    
    This reverts commit aa5514cce0ab4e12bbf7f20a7d4dbf16b89ae58c.

diff --git a/vcl/inc/font/LogicalFontInstance.hxx 
b/vcl/inc/font/LogicalFontInstance.hxx
index e8124eac7eca..518716b5c7df 100644
--- a/vcl/inc/font/LogicalFontInstance.hxx
+++ b/vcl/inc/font/LogicalFontInstance.hxx
@@ -22,7 +22,6 @@
 #include <sal/config.h>
 
 #include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <basegfx/range/b2drectangle.hxx>
 #include <o3tl/hash_combine.hxx>
 #include <rtl/ref.hxx>
 #include <salhelper/simplereferenceobject.hxx>
@@ -102,7 +101,7 @@ public: // TODO: make data members private
     vcl::font::PhysicalFontFace* GetFontFace() { return m_pFontFace.get(); }
     const ImplFontCache* GetFontCache() const { return mpFontCache; }
 
-    bool GetGlyphBoundRect(sal_GlyphId, basegfx::B2DRectangle&, bool) const;
+    bool GetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const;
     virtual bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) 
const = 0;
     bool GetGlyphOutlineUntransformed(sal_GlyphId, basegfx::B2DPolyPolygon&) 
const;
 
diff --git a/vcl/inc/impfontcache.hxx b/vcl/inc/impfontcache.hxx
index 4d197003b279..5ea19b05d9a5 100644
--- a/vcl/inc/impfontcache.hxx
+++ b/vcl/inc/impfontcache.hxx
@@ -21,10 +21,10 @@
 
 #include <sal/config.h>
 
-#include <basegfx/range/b2drectangle.hxx>
 #include <rtl/ref.hxx>
 #include <o3tl/lru_map.hxx>
 #include <o3tl/hash_combine.hxx>
+#include <tools/gen.hxx>
 
 #include "font/FontSelectPattern.hxx"
 #include "glyphid.hxx"
@@ -59,7 +59,7 @@ struct GlyphBoundRectCacheHash
     }
 };
 
-typedef o3tl::lru_map<GlyphBoundRectCacheKey, basegfx::B2DRectangle,
+typedef o3tl::lru_map<GlyphBoundRectCacheKey, tools::Rectangle,
                       GlyphBoundRectCacheHash> GlyphBoundRectCache;
 
 class ImplFontCache
@@ -86,8 +86,8 @@ public:
                             LogicalFontInstance* pLogicalFont,
                             int nFallbackLevel, OUString& rMissingCodes );
 
-    bool GetCachedGlyphBoundRect(const LogicalFontInstance*, sal_GlyphId, 
basegfx::B2DRectangle&);
-    void CacheGlyphBoundRect(const LogicalFontInstance*, sal_GlyphId, 
basegfx::B2DRectangle&);
+    bool GetCachedGlyphBoundRect(const LogicalFontInstance *, sal_GlyphId, 
tools::Rectangle &);
+    void CacheGlyphBoundRect(const LogicalFontInstance *, sal_GlyphId, 
tools::Rectangle &);
 
     void                Invalidate();
 };
diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx
index a3f1b8a7a7a6..87f966bd1676 100644
--- a/vcl/inc/impglyphitem.hxx
+++ b/vcl/inc/impglyphitem.hxx
@@ -20,8 +20,8 @@
 #ifndef INCLUDED_VCL_IMPGLYPHITEM_HXX
 #define INCLUDED_VCL_IMPGLYPHITEM_HXX
 
-#include <basegfx/range/b2drectangle.hxx>
 #include <o3tl/typed_flags_set.hxx>
+#include <tools/gen.hxx>
 #include <vcl/dllapi.h>
 #include <vcl/outdev.hxx>
 #include <vector>
@@ -87,7 +87,7 @@ public:
         return bool(m_nFlags & GlyphItemFlags::IS_SAFE_TO_INSERT_KASHIDA);
     }
 
-    inline bool GetGlyphBoundRect(const LogicalFontInstance*, 
basegfx::B2DRectangle&) const;
+    inline bool GetGlyphBoundRect(const LogicalFontInstance*, 
tools::Rectangle&) const;
     inline bool GetGlyphOutline(const LogicalFontInstance*, 
basegfx::B2DPolyPolygon&) const;
     inline void dropGlyph();
 
@@ -117,7 +117,7 @@ public:
 };
 
 bool GlyphItem::GetGlyphBoundRect(const LogicalFontInstance* pFontInstance,
-                                  basegfx::B2DRectangle& rRect) const
+                                  tools::Rectangle& rRect) const
 {
     return pFontInstance->GetGlyphBoundRect(m_aGlyphId, rRect, IsVertical());
 }
diff --git a/vcl/qa/cppunit/logicalfontinstance.cxx 
b/vcl/qa/cppunit/logicalfontinstance.cxx
index 1eaf0ebd28db..12ee95762eef 100644
--- a/vcl/qa/cppunit/logicalfontinstance.cxx
+++ b/vcl/qa/cppunit/logicalfontinstance.cxx
@@ -39,46 +39,25 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
 {
     ScopedVclPtr<VirtualDevice> device = 
VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
     device->SetOutputSizePixel(Size(1000, 1000));
-    vcl::Font font("Liberation Sans", Size(0, 110));
-    device->SetFont(font);
+    device->SetFont(vcl::Font("Liberation Sans", Size(0, 110)));
 
     const LogicalFontInstance* pFontInstance = device->GetFontInstance();
 
-    basegfx::B2DRectangle aBoundRect;
+    tools::Rectangle aBoundRect;
     const auto LATIN_SMALL_LETTER_B = 0x0062;
     
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B),
 aBoundRect,
                                      false);
 
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(7.1, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getHeight(), 0.05);
+    const tools::Long nExpectedX = 7;
+    const tools::Long nExpectedY = -80;
+    const tools::Long nExpectedWidth = 51;
+    const tools::Long nExpectedHeight = 83;
 
-    font.SetOrientation(900_deg10);
-    device->SetFont(font);
-
-    pFontInstance = device->GetFontInstance();
-
-    
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B),
 aBoundRect,
-                                     false);
-
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-56.6, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getHeight(), 0.05);
-
-    font.SetOrientation(450_deg10);
-    device->SetFont(font);
-
-    pFontInstance = device->GetFontInstance();
-
-    
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B),
 aBoundRect,
-                                     false);
-
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-51.3, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-96.4, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getHeight(), 0.05);
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("x of glyph is wrong", nExpectedX, 
aBoundRect.getX());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("y of glyph is wrong", nExpectedY, 
aBoundRect.getY());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("height of glyph of wrong", nExpectedWidth, 
aBoundRect.GetWidth());
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("width of glyph of wrong", nExpectedHeight,
+                                 aBoundRect.GetHeight());
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VclLogicalFontInstanceTest);
diff --git a/vcl/source/font/LogicalFontInstance.cxx 
b/vcl/source/font/LogicalFontInstance.cxx
index 6524422397f0..6c6c95bbb6a1 100644
--- a/vcl/source/font/LogicalFontInstance.cxx
+++ b/vcl/source/font/LogicalFontInstance.cxx
@@ -26,8 +26,6 @@
 #include <font/LogicalFontInstance.hxx>
 #include <impfontcache.hxx>
 
-#include <basegfx/matrix/b2dhommatrixtools.hxx>
-
 LogicalFontInstance::LogicalFontInstance(const vcl::font::PhysicalFontFace& 
rFontFace,
                                          const vcl::font::FontSelectPattern& 
rFontSelData)
     : mxFontMetric(new ImplFontMetricData(rFontSelData))
@@ -168,39 +166,47 @@ void 
LogicalFontInstance::IgnoreFallbackForUnicode(sal_UCS4 cChar, FontWeight eW
         maUnicodeFallbackList.erase(it);
 }
 
-bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId nID, 
basegfx::B2DRectangle& rRect,
+bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& 
rRect,
                                             bool bVertical) const
 {
-    // TODO/FIXME: bVertical handling here is highly suspicious. When it's 
true, it may
-    // return different rectangle, depending on if this glyph was cached 
already or not.
-
     if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect))
         return true;
 
     auto* pHbFont = const_cast<LogicalFontInstance*>(this)->GetHbFont();
     hb_glyph_extents_t aExtents;
-    if (!hb_font_get_glyph_extents(pHbFont, nID, &aExtents))
-        return false;
+    bool res = hb_font_get_glyph_extents(pHbFont, nID, &aExtents);
 
-    double nXScale = 0, nYScale = 0;
-    GetScale(&nXScale, &nYScale);
+    if (res)
+    {
+        double nXScale = 0, nYScale = 0;
+        GetScale(&nXScale, &nYScale);
 
-    double fMinX = aExtents.x_bearing * nXScale;
-    double fMinY = -aExtents.y_bearing * nYScale;
-    double fMaxX = (aExtents.x_bearing + aExtents.width) * nXScale;
-    double fMaxY = -(aExtents.y_bearing + aExtents.height) * nYScale;
-    rRect = basegfx::B2DRectangle(fMinX, fMinY, fMaxX, fMaxY);
+        double fMinX = aExtents.x_bearing;
+        double fMinY = aExtents.y_bearing;
+        double fMaxX = aExtents.x_bearing + aExtents.width;
+        double fMaxY = aExtents.y_bearing + aExtents.height;
 
-    if (mnOrientation && !bVertical)
-    {
-        // Apply font rotation.
-        
rRect.transform(basegfx::utils::createRotateB2DHomMatrix(-toRadians(mnOrientation)));
+        tools::Rectangle aRect(std::floor(fMinX * nXScale), -std::ceil(fMinY * 
nYScale),
+                               std::ceil(fMaxX * nXScale), -std::floor(fMaxY * 
nYScale));
+        if (mnOrientation && !bVertical)
+        {
+            // Apply font rotation.
+            const double fRad = toRadians(mnOrientation);
+            const double fCos = cos(fRad);
+            const double fSin = sin(fRad);
+
+            rRect.SetLeft(fCos * aRect.Left() + fSin * aRect.Top());
+            rRect.SetTop(-fSin * aRect.Left() - fCos * aRect.Top());
+            rRect.SetRight(fCos * aRect.Right() + fSin * aRect.Bottom());
+            rRect.SetBottom(-fSin * aRect.Right() - fCos * aRect.Bottom());
+        }
+        else
+            rRect = aRect;
     }
 
-    if (mpFontCache)
+    if (mpFontCache && res)
         mpFontCache->CacheGlyphBoundRect(this, nID, rRect);
-
-    return true;
+    return res;
 }
 
 sal_GlyphId LogicalFontInstance::GetGlyphIndex(uint32_t nUnicode, uint32_t 
nVariationSelector) const
diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx
index a167f741de15..58b68baa9fe3 100644
--- a/vcl/source/font/fontcache.cxx
+++ b/vcl/source/font/fontcache.cxx
@@ -248,7 +248,7 @@ void ImplFontCache::Invalidate()
     m_aBoundRectCache.clear();
 }
 
-bool ImplFontCache::GetCachedGlyphBoundRect(const LogicalFontInstance *pFont, 
sal_GlyphId nID, basegfx::B2DRectangle &rRect)
+bool ImplFontCache::GetCachedGlyphBoundRect(const LogicalFontInstance *pFont, 
sal_GlyphId nID, tools::Rectangle &rRect)
 {
     if (!pFont->GetFontCache())
         return false;
@@ -265,7 +265,7 @@ bool ImplFontCache::GetCachedGlyphBoundRect(const 
LogicalFontInstance *pFont, sa
     return false;
 }
 
-void ImplFontCache::CacheGlyphBoundRect(const LogicalFontInstance *pFont, 
sal_GlyphId nID, basegfx::B2DRectangle &rRect)
+void ImplFontCache::CacheGlyphBoundRect(const LogicalFontInstance *pFont, 
sal_GlyphId nID, tools::Rectangle &rRect)
 {
     if (!pFont->GetFontCache())
         return;
diff --git a/vcl/source/gdi/CommonSalLayout.cxx 
b/vcl/source/gdi/CommonSalLayout.cxx
index 5167921bd7ed..be301edcd365 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -561,12 +561,12 @@ bool 
GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay
                     {
                         // We need glyph's advance, top bearing, and height to
                         // correct y offset.
-                        basegfx::B2DRectangle aRect;
+                        tools::Rectangle aRect;
                         // Get cached bound rect value for the font,
                         GetFont().GetGlyphBoundRect(nGlyphIndex, aRect, true);
 
-                        nXOffset = -(aRect.getMinX() / nXScale  + ( 
pHbPositions[i].y_advance
-                                    + ( aRect.getHeight() / nXScale ) ) / 2.0 
);
+                        nXOffset = -(aRect.Top() / nXScale  + ( 
pHbPositions[i].y_advance
+                                    + ( aRect.GetHeight() / nXScale ) ) / 2 );
                     }
 
                 }
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 8dd72a469de1..40b6b9456266 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -7006,7 +7006,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const 
OUString& rText, bool
     else if ( eAlign == ALIGN_TOP )
         aOffset.AdjustY(GetFontInstance()->mxFontMetric->GetAscent() );
 
-    basegfx::B2DRectangle aRectangle;
+    tools::Rectangle aRectangle;
     nIndex = 0;
     while (rLayout.GetNextGlyph(&pGlyph, aPos, nIndex, &pGlyphFont))
     {
@@ -7023,8 +7023,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const 
OUString& rText, bool
             }
             else
             {
-                aAdjOffset = basegfx::B2DPoint(aOffset.X(), aOffset.Y());
-                aAdjOffset.adjustX(aRectangle.getMinX() + 
(aRectangle.getWidth() - aEmphasisMark.GetWidth()) / 2 );
+                aAdjOffset = DevicePoint(aOffset.X(), aOffset.Y());
+                aAdjOffset.adjustX(aRectangle.Left() + (aRectangle.GetWidth() 
- aEmphasisMark.GetWidth()) / 2 );
             }
 
             aAdjOffset = aRotScale.transform( aAdjOffset );
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 7397748ecd72..ed368f04022e 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -33,7 +33,6 @@
 #include <sallayout.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <rtl/math.hxx>
 
 #include <i18nlangtag/lang.h>
 
@@ -215,15 +214,12 @@ bool SalLayout::GetOutline(basegfx::B2DPolyPolygonVector& 
rVector) const
     return (bAllOk && bOneOk);
 }
 
-// No need to expand to the next pixel, when the character only covers its 
tiny fraction
-static double trimInsignificant(double n) { return std::round(n * 1e5) / 1e5; }
-
 bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const
 {
     bool bRet = false;
+    rRect.SetEmpty();
 
-    basegfx::B2DRectangle aUnion;
-    basegfx::B2DRectangle aRectangle;
+    tools::Rectangle aRectangle;
 
     DevicePoint aPos;
     const GlyphItem* pGlyph;
@@ -234,19 +230,22 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) 
const
         // get bounding rectangle of individual glyph
         if (pGlyph->GetGlyphBoundRect(pGlyphFont, aRectangle))
         {
-            if (!aRectangle.isEmpty())
+            if (!aRectangle.IsEmpty())
             {
-                
aRectangle.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos));
+                aRectangle.AdjustLeft(std::floor(aPos.getX()));
+                aRectangle.AdjustRight(std::ceil(aPos.getX()));
+                aRectangle.AdjustTop(std::floor(aPos.getY()));
+                aRectangle.AdjustBottom(std::ceil(aPos.getY()));
+
                 // merge rectangle
-                aUnion.expand(aRectangle);
+                if (rRect.IsEmpty())
+                    rRect = aRectangle;
+                else
+                    rRect.Union(aRectangle);
             }
             bRet = true;
         }
     }
-    rRect = 
tools::Rectangle(rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())),
-                             
rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())),
-                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())),
-                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY())));
 
     return bRet;
 }
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index fee8021b43a9..3bfbb8f6d8ce 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -950,8 +950,8 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& 
rSalLayout )
     tools::Long nEmphasisHeight2 = nEmphasisHeight / 2;
     aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 );
 
-    basegfx::B2DPoint aOutPoint;
-    basegfx::B2DRectangle aRectangle;
+    DevicePoint aOutPoint;
+    tools::Rectangle aRectangle;
     const GlyphItem* pGlyph;
     const LogicalFontInstance* pGlyphFont;
     int nStart = 0;
@@ -971,7 +971,7 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& 
rSalLayout )
             else
             {
                 aAdjPoint = aOffset;
-                aAdjPoint.AdjustX(aRectangle.getMinX() + 
(aRectangle.getWidth() - aEmphasisMark.GetWidth()) / 2 );
+                aAdjPoint.AdjustX(aRectangle.Left() + (aRectangle.GetWidth() - 
aEmphasisMark.GetWidth()) / 2 );
             }
 
             if ( mpFontInstance->mnOrientation )
diff --git a/vcl/workben/listglyphs.cxx b/vcl/workben/listglyphs.cxx
index 341006d433dd..def2ff818122 100644
--- a/vcl/workben/listglyphs.cxx
+++ b/vcl/workben/listglyphs.cxx
@@ -120,7 +120,7 @@ int ListGlyphs::Main()
              nChar = pCharMap->GetNextChar(nChar))
         {
             auto nGlyphIndex = pFontInstance->GetGlyphIndex(nChar);
-            basegfx::B2DRectangle aGlyphBounds;
+            tools::Rectangle aGlyphBounds;
             pFontInstance->GetGlyphBoundRect(nGlyphIndex, aGlyphBounds, false);
             std::cout << "Codepoint: " << pFontFace->GetGlyphName(nGlyphIndex)
                       << "; glyph bounds: " << aGlyphBounds << "
";
commit 9599b7d969cfe534c17d2249fd8f718dbb39867a
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:20 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:20 2024 +0500

    Revert "tdf#160436: fix glyph bounds calculation for vertical glyphs"
    
    This reverts commit a2c412dbc17b5c9a7b12639390b58b73cc858e49.

diff --git a/vcl/qa/cppunit/logicalfontinstance.cxx 
b/vcl/qa/cppunit/logicalfontinstance.cxx
index 77de9b9b4e3f..1eaf0ebd28db 100644
--- a/vcl/qa/cppunit/logicalfontinstance.cxx
+++ b/vcl/qa/cppunit/logicalfontinstance.cxx
@@ -46,7 +46,6 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
 
     basegfx::B2DRectangle aBoundRect;
     const auto LATIN_SMALL_LETTER_B = 0x0062;
-    const auto SECTION_SIGN = 0x00A7; // UTR#50: Vertical_Orientation (vo) 
property value U
     
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B),
 aBoundRect,
                                      false);
 
@@ -55,14 +54,6 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
     CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getWidth(), 0.05);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getHeight(), 0.05);
 
-    // tdf#160436: test vertically oriented glyphs
-    
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), 
aBoundRect, true);
-
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-55.0, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(88.9, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(48.8, aBoundRect.getHeight(), 0.05);
-
     font.SetOrientation(900_deg10);
     device->SetFont(font);
 
@@ -76,14 +67,6 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
     CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getWidth(), 0.05);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getHeight(), 0.05);
 
-    // tdf#160436: test vertically oriented glyphs
-    
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), 
aBoundRect, true);
-
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-55.0, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-9.2, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(48.8, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(88.9, aBoundRect.getHeight(), 0.05);
-
     font.SetOrientation(450_deg10);
     device->SetFont(font);
 
@@ -96,14 +79,6 @@ void VclLogicalFontInstanceTest::testglyphboundrect()
     CPPUNIT_ASSERT_DOUBLES_EQUAL(-96.4, aBoundRect.getMinY(), 0.05);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getWidth(), 0.05);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getHeight(), 0.05);
-
-    // tdf#160436: test vertically oriented glyphs
-    
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), 
aBoundRect, true);
-
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-95.3, aBoundRect.getMinX(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(-45.4, aBoundRect.getMinY(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(97.4, aBoundRect.getWidth(), 0.05);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(97.4, aBoundRect.getHeight(), 0.05);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VclLogicalFontInstanceTest);
diff --git a/vcl/source/font/LogicalFontInstance.cxx 
b/vcl/source/font/LogicalFontInstance.cxx
index 9d893b85aa70..6524422397f0 100644
--- a/vcl/source/font/LogicalFontInstance.cxx
+++ b/vcl/source/font/LogicalFontInstance.cxx
@@ -171,8 +171,8 @@ void LogicalFontInstance::IgnoreFallbackForUnicode(sal_UCS4 
cChar, FontWeight eW
 bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId nID, 
basegfx::B2DRectangle& rRect,
                                             bool bVertical) const
 {
-    // TODO: find out if it's possible for the same glyph in the same font to 
be used both
-    // normally and vertically; if yes, then these two variants must be cached 
separately
+    // TODO/FIXME: bVertical handling here is highly suspicious. When it's 
true, it may
+    // return different rectangle, depending on if this glyph was cached 
already or not.
 
     if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect))
         return true;
@@ -191,13 +191,10 @@ bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId 
nID, basegfx::B2DRectang
     double fMaxY = -(aExtents.y_bearing + aExtents.height) * nYScale;
     rRect = basegfx::B2DRectangle(fMinX, fMinY, fMaxX, fMaxY);
 
-    auto orientation = mnOrientation;
-    if (bVertical)
-        orientation += 900_deg10;
-    if (orientation)
+    if (mnOrientation && !bVertical)
     {
         // Apply font rotation.
-        
rRect.transform(basegfx::utils::createRotateB2DHomMatrix(-toRadians(orientation)));
+        
rRect.transform(basegfx::utils::createRotateB2DHomMatrix(-toRadians(mnOrientation)));
     }
 
     if (mpFontCache)
commit 6d49cae9c32f485ddb071f12e3ad98612251c4ef
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:20 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:20 2024 +0500

    Revert "Fix UB after 8962141a12c966b2d891829925e6203bf8d51852"
    
    This reverts commit 49e6927e3bd44021796b97d1ebb7886923f6cbcc.

diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index c8c2d6ca1093..7397748ecd72 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -216,10 +216,7 @@ bool SalLayout::GetOutline(basegfx::B2DPolyPolygonVector& 
rVector) const
 }
 
 // No need to expand to the next pixel, when the character only covers its 
tiny fraction
-static double trimInsignificant(double n)
-{
-    return std::abs(n) >= 0x1p53 ? n : std::round(n * 1e5) / 1e5;
-}
+static double trimInsignificant(double n) { return std::round(n * 1e5) / 1e5; }
 
 bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const
 {
@@ -246,19 +243,10 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) 
const
             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);
-    }
+    rRect = 
tools::Rectangle(rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())),
+                             
rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())),
+                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())),
+                             
rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY())));
 
     return bRet;
 }
commit a65735a23ac3cde6fbfc7b9b38dd03318a5a97ee
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 20:55:19 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 9 20:55:19 2024 +0500

    Revert "Simplify and drop unused method"
    
    This reverts commit ee5584b926cd10ea600a3514242148db5a0a6f18.

diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 0f253230c1b4..18de0e684b1c 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -36,6 +36,7 @@ class WinFontInstance : public LogicalFontInstance
 public:
     ~WinFontInstance() override;
 
+    bool hasHScale() const;
     float getHScale() const;
 
     void SetGraphics(WinSalGraphics*);
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 3865f2ebed66..371bdeb9642e 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -147,12 +147,22 @@ WinFontInstance::~WinFontInstance()
         ::DeleteFont(m_hFont);
 }
 
+bool WinFontInstance::hasHScale() const
+{
+    const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
+    int nHeight(rPattern.mnHeight);
+    int nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : 
nHeight);
+    return nWidth != nHeight;
+}
+
 float WinFontInstance::getHScale() const
 {
     const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
-    if (!rPattern.mnHeight || !rPattern.mnWidth)
+    int nHeight(rPattern.mnHeight);
+    if (!nHeight)
         return 1.0;
-    return rPattern.mnWidth * GetAverageWidthFactor() / rPattern.mnHeight;
+    float nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() 
: nHeight);
+    return nWidth / nHeight;
 }
 
 void WinFontInstance::ImplInitHbFont(hb_font_t* /*pHbFont*/)

Reply via email to