summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Hosny <khaled@libreoffice.org>2023-07-16 07:37:55 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2024-04-08 02:24:05 +0500
commitcbb9d93f5396ee0842cf48fdefc98d5db6eb27c4 (patch)
tree2bc7c8679124f3f953e7c5b035980e120853be27
parent2b1e0c071dc186cd29ee2653166fdb9aa98bca2e (diff)
vcl: Use HarfBuzz to get glyph bounding rectangle
For consistent cross-platform results that also matches our glyph advances since platform functions might be using hints which we don’t use. Change-Id: I4aebd3e7c5f460dff584f5eba74f7a11bab0f9b1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154388 Tested-by: Jenkins Reviewed-by: خالد حسني <khaled@libreoffice.org>
-rw-r--r--vcl/inc/font/LogicalFontInstance.hxx2
-rw-r--r--vcl/inc/pdf/pdfbuildin_fonts.hxx2
-rw-r--r--vcl/inc/qt5/QtFont.hxx1
-rw-r--r--vcl/inc/quartz/salgdi.h2
-rw-r--r--vcl/inc/unx/freetype_glyphcache.hxx2
-rw-r--r--vcl/inc/unx/glyphcache.hxx1
-rw-r--r--vcl/inc/win/winlayout.hxx1
-rw-r--r--vcl/qa/cppunit/cjktext.cxx2
-rw-r--r--vcl/qa/cppunit/fontmocks.hxx3
-rw-r--r--vcl/qa/cppunit/logicalfontinstance.cxx9
-rw-r--r--vcl/qt5/QtFont.cxx7
-rw-r--r--vcl/quartz/ctfonts.cxx21
-rw-r--r--vcl/source/font/LogicalFontInstance.cxx33
-rw-r--r--vcl/source/gdi/pdfbuildin_fonts.cxx5
-rw-r--r--vcl/unx/generic/glyphs/freetype_glyphcache.cxx38
-rw-r--r--vcl/unx/generic/glyphs/glyphcache.cxx8
-rw-r--r--vcl/win/gdi/salfont.cxx53
17 files changed, 38 insertions, 152 deletions
diff --git a/vcl/inc/font/LogicalFontInstance.hxx b/vcl/inc/font/LogicalFontInstance.hxx
index c9e837d540f1..518716b5c7df 100644
--- a/vcl/inc/font/LogicalFontInstance.hxx
+++ b/vcl/inc/font/LogicalFontInstance.hxx
@@ -120,8 +120,6 @@ 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 8cb34e74922b..a0c2fc06287d 100644
--- a/vcl/inc/pdf/pdfbuildin_fonts.hxx
+++ b/vcl/inc/pdf/pdfbuildin_fonts.hxx
@@ -49,8 +49,6 @@ 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 e19d6de21aa2..7d0b338c939d 100644
--- a/vcl/inc/qt5/QtFont.hxx
+++ b/vcl/inc/qt5/QtFont.hxx
@@ -33,7 +33,6 @@ 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 6d1668c1f913..a255e9dc330d 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -103,8 +103,6 @@ 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 c80642b6126c..9c61e0ff60d1 100644
--- a/vcl/inc/unx/freetype_glyphcache.hxx
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
@@ -107,8 +107,6 @@ 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 9de7bd59fe6c..4d21d34d05ea 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -123,7 +123,6 @@ 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 fb8e5a1c6e43..18de0e684b1c 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -60,7 +60,6 @@ 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 af63b29959fd..cd9bd2c165fd 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, 1);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(width36, width36Rotated, 2);
font = baseFont;
font.SetFontSize(Size(0, 72));
diff --git a/vcl/qa/cppunit/fontmocks.hxx b/vcl/qa/cppunit/fontmocks.hxx
index 7e33ce8e7e13..8eac463c143f 100644
--- a/vcl/qa/cppunit/fontmocks.hxx
+++ b/vcl/qa/cppunit/fontmocks.hxx
@@ -30,9 +30,6 @@ 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 2a7a5c83ac27..12ee95762eef 100644
--- a/vcl/qa/cppunit/logicalfontinstance.cxx
+++ b/vcl/qa/cppunit/logicalfontinstance.cxx
@@ -50,13 +50,14 @@ 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_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_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/qt5/QtFont.cxx b/vcl/qt5/QtFont.cxx
index 384f56774ffd..e3a6c0b0a9d7 100644
--- a/vcl/qt5/QtFont.cxx
+++ b/vcl/qt5/QtFont.cxx
@@ -187,11 +187,4 @@ 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 38112a7deb50..1cafd270552d 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -89,27 +89,6 @@ 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 6c7a7e2bde09..6c6c95bbb6a1 100644
--- a/vcl/source/font/LogicalFontInstance.cxx
+++ b/vcl/source/font/LogicalFontInstance.cxx
@@ -172,7 +172,38 @@ bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& r
if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect))
return true;
- bool res = ImplGetGlyphBoundRect(nID, rRect, bVertical);
+ 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;
+ }
+
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 e387f78638d3..7f80bfdd030d 100644
--- a/vcl/source/gdi/pdfbuildin_fonts.cxx
+++ b/vcl/source/gdi/pdfbuildin_fonts.cxx
@@ -738,11 +738,6 @@ 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 64fcb6bfc2bf..bed24e081ee5 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -564,44 +564,6 @@ 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 39b10c78e123..ac3c5e15ab73 100644
--- a/vcl/unx/generic/glyphs/glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/glyphcache.cxx
@@ -75,14 +75,6 @@ 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 196932982c28..d5f41e2e8819 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -1156,59 +1156,6 @@ 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();