Blob Blame History Raw
From 39387fda8c027722d7db2a1320a2bebf95efb641 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Wed, 9 Mar 2011 14:22:04 +0000
Subject: [PATCH] Resolves: rhbz#682621 better resizing of overtall glyphsubs

---
 vcl/inc/vcl/outdev.hxx     |    5 +++
 vcl/source/gdi/outdev3.cxx |   70 ++++++++++++++++++++++++++++++++++---------
 2 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/vcl/inc/vcl/outdev.hxx b/vcl/inc/vcl/outdev.hxx
index 251b2e8..859020f 100644
--- a/vcl/inc/vcl/outdev.hxx
+++ b/vcl/inc/vcl/outdev.hxx
@@ -276,6 +276,8 @@ enum OutDevViewType { OUTDEV_VIEWTYPE_DONTKNOW, OUTDEV_VIEWTYPE_PRINTPREVIEW, OU
 
 class VirtualDevice;
 class Printer;
+class ImplFontSelectData;
+class ImplFontMetricData;
 
 const char* ImplDbgCheckOutputDevice( const void* pObj );
 
@@ -563,6 +565,9 @@ public:
     // Helper for line geometry paint with support for graphic expansion (pattern and fat_to_area)
     void impPaintLineGeometryWithEvtlExpand(const LineInfo& rInfo, basegfx::B2DPolyPolygon aLinePolyPolygon);
 
+    SAL_DLLPRIVATE void forceFallbackFontToFit(SalLayout &rFallback, ImplFontEntry &rFallbackFont,
+        ImplFontSelectData &rFontSelData, int nFallbackLevel,
+        ImplLayoutArgs& rLayoutArgs, const ImplFontMetricData& rOrigMetric) const;
 protected:
                         OutputDevice();
 
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 84a7b5d..7a439f2 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -6023,6 +6023,58 @@
     return pSalLayout;
 }
 
+void OutputDevice::forceFallbackFontToFit(SalLayout &rFallback, ImplFontEntry &rFallbackFont,
+    ImplFontSelectData &rFontSelData, int nFallbackLevel,
+    ImplLayoutArgs& rLayoutArgs, const ImplFontMetricData& rOrigMetric) const
+{
+    Rectangle aBoundRect;
+    bool bHaveBounding = false;
+    Rectangle aRectangle;
+
+    rFallback.AdjustLayout( rLayoutArgs );
+
+    //All we care about here is getting the vertical bounds of this text and
+    //make sure it will fit inside the available space
+    Point aPos;
+    for( int nStart = 0;;)
+    {
+        sal_GlyphId nLGlyph;
+        if( !rFallback.GetNextGlyphs( 1, &nLGlyph, aPos, nStart ) )
+            break;
+
+        int nFontTag = nFallbackLevel << GF_FONTSHIFT;
+        nLGlyph |= nFontTag;
+
+        // get bounding rectangle of individual glyph
+        if( mpGraphics->GetGlyphBoundRect( nLGlyph, aRectangle ) )
+        {
+            // merge rectangle
+            aRectangle += aPos;
+            aBoundRect.Union( aRectangle );
+            bHaveBounding = true;
+        }
+    }
+
+    //Shrink it down if it won't fit
+    if (bHaveBounding)
+    {
+        long  nGlyphsAscent = -aBoundRect.Top();
+        float fScaleTop = nGlyphsAscent > rOrigMetric.mnAscent ?
+            rOrigMetric.mnAscent/(float)nGlyphsAscent : 1;
+        long  nGlyphsDescent = aBoundRect.Bottom();
+        float fScaleBottom = nGlyphsDescent > rOrigMetric.mnDescent ?
+            rOrigMetric.mnDescent/(float)nGlyphsDescent : 1;
+        float fScale = fScaleBottom < fScaleTop ? fScaleBottom : fScaleTop;
+        if (fScale < 1)
+        {
+            long nOrigHeight = rFontSelData.mnHeight;
+            rFontSelData.mnHeight *= fScale;
+            rFallbackFont.mnSetFontFlags = mpGraphics->SetFont( &rFontSelData, nFallbackLevel );
+            rFontSelData.mnHeight = nOrigHeight;
+        }
+    }
+}
+
 // -----------------------------------------------------------------------
 
 SalLayout* OutputDevice::ImplGlyphFallbackLayout( SalLayout* pSalLayout, ImplLayoutArgs& rLayoutArgs ) const
@@ -6102,22 +6154,7 @@
         }
 #endif
 
-        ImplFontMetricData aSubstituteMetric(aFontSelData);
         pFallbackFont->mnSetFontFlags = mpGraphics->SetFont( &aFontSelData, nFallbackLevel );
-        mpGraphics->GetFontMetric(&aSubstituteMetric, nFallbackLevel);
-
-        long nOriginalHeight = aOrigMetric.mnAscent + aOrigMetric.mnDescent;
-        long nSubstituteHeight = aSubstituteMetric.mnAscent + aSubstituteMetric.mnDescent;
-        //Too tall, shrink it a bit. Need a better calculation to include extra
-        //factors and any extra wriggle room we might have available ?
-        if (nSubstituteHeight > nOriginalHeight)
-        {
-            float fScale = nOriginalHeight/(float)nSubstituteHeight;
-            long nOrigHeight = aFontSelData.mnHeight;
-            aFontSelData.mnHeight *= fScale;
-            pFallbackFont->mnSetFontFlags = mpGraphics->SetFont( &aFontSelData, nFallbackLevel );
-            aFontSelData.mnHeight = nOrigHeight;
-        }
 
         // create and add glyph fallback layout to multilayout
         rLayoutArgs.ResetPos();
@@ -6126,6 +6163,9 @@
         {
             if( pFallback->LayoutText( rLayoutArgs ) )
             {
+                forceFallbackFontToFit(*pFallback, *pFallbackFont, aFontSelData,
+                    nFallbackLevel, rLayoutArgs, aOrigMetric);
+
                 if( !pMultiSalLayout )
                     pMultiSalLayout = new MultiSalLayout( *pSalLayout );
                 pMultiSalLayout->AddFallback( *pFallback,