[Libreoffice-commits] core.git: vcl/inc vcl/source vcl/win

Khaled Hosny khaledhosny at eglug.org
Tue Nov 15 11:31:12 UTC 2016


 vcl/inc/CommonSalLayout.hxx        |    1 +
 vcl/source/gdi/CommonSalLayout.cxx |   33 +++++++++++++++++++++++++++++++++
 vcl/win/gdi/winlayout.cxx          |   16 +++++++++++-----
 3 files changed, 45 insertions(+), 5 deletions(-)

New commits:
commit a5750d92b2136d60d698b41ef5760f2efac0ffce
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Mon Nov 14 00:52:14 2016 +0200

    tdf#103725: Fix horizontal scaling on Windows
    
    * Create IDWriteFont from LOGFONT instead of HDC, as it seems the later
      will discard the font width. Without font width, GDI/DirectWrite will
      not scale the font horizontally.
      Does not seem to work with all Windows versions (at least not
      Windows 10 Anniversary Update), seems like this undocumented behaviour
      have been dropped :(
    * Adjusting font width on Windows during layout, see the inline comment.
    
    
    Change-Id: I19b788460b6b6ca2c83d75bbf09a0601a250c289
    Reviewed-on: https://gerrit.libreoffice.org/30847
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
    Tested-by: Khaled Hosny <khaledhosny at eglug.org>

diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index 825f772..5d54cb8 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -45,6 +45,7 @@ class CommonSalLayout : public GenericSalLayout
 #ifdef _WIN32
     HDC                     mhDC;
     HFONT                   mhFont;
+    double                  mnAveWidthFactor;
 #elif defined(MACOSX) || defined(IOS)
     const CoreTextStyle&    mrCoreTextStyle;
 #else
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 1031b9c..9ad1967 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -95,7 +95,15 @@ void CommonSalLayout::getScale(double* nXScale, double* nYScale)
     unsigned int nUPEM = hb_face_get_upem(pHbFace);
 
     double nHeight(mrFontSelData.mnHeight);
+#if defined(_WIN32)
+    // On Windows, mnWidth is relative to average char width not font height,
+    // and wee need to keep it that way for GDI to correctly scale the glyphs.
+    // Here we compensate for this so that HarfBuzz gives us the correct glyph
+    // positions.
+    double nWidth(mrFontSelData.mnWidth ? mrFontSelData.mnWidth * mnAveWidthFactor : nHeight);
+#else
     double nWidth(mrFontSelData.mnWidth ? mrFontSelData.mnWidth : nHeight);
+#endif
 
     if (nYScale)
         *nYScale = nHeight / nUPEM;
@@ -173,6 +181,7 @@ CommonSalLayout::CommonSalLayout(HDC hDC, WinFontInstance& rWinFontInstance, con
 :   mrFontSelData(rWinFontInstance.maFontSelData)
 ,   mhDC(hDC)
 ,   mhFont(static_cast<HFONT>(GetCurrentObject(hDC, OBJ_FONT)))
+,   mnAveWidthFactor(1.0f)
 {
     mpHbFont = rWinFontFace.GetHbFont();
     if (!mpHbFont)
@@ -182,6 +191,30 @@ CommonSalLayout::CommonSalLayout(HDC hDC, WinFontInstance& rWinFontInstance, con
         mpHbFont = createHbFont(pHbFace);
         rWinFontFace.SetHbFont(mpHbFont);
     }
+
+    // Calculate the mnAveWidthFactor, see the comment where it is used.
+    if (mrFontSelData.mnWidth)
+    {
+        double nUPEM = hb_face_get_upem(hb_font_get_face(mpHbFont));
+
+        LOGFONTW aLogFont;
+        GetObjectW(mhFont, sizeof(LOGFONTW), &aLogFont);
+
+        // Set the height (font size) to EM to minimize rounding errors.
+        aLogFont.lfHeight = -nUPEM;
+        // Set width to the default to get the original value in the metrics.
+        aLogFont.lfWidth = 0;
+
+        // Get the font metrics.
+        HFONT hNewFont = CreateFontIndirectW(&aLogFont);
+        HFONT hOldFont = static_cast<HFONT>(SelectObject(hDC, hNewFont));
+        TEXTMETRICW aFontMetric;
+        GetTextMetricsW(hDC, &aFontMetric);
+        SelectObject(hDC, hOldFont);
+        DeleteObject(hNewFont);
+
+        mnAveWidthFactor = nUPEM / aFontMetric.tmAveCharWidth;
+    }
 }
 
 #elif defined(MACOSX) || defined(IOS)
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index b7882e3..335bb8c 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -3599,9 +3599,19 @@ std::vector<Rectangle> D2DWriteTextOutRenderer::GetGlyphInkBoxes(uint16_t * pGid
 bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** ppFontFace, float * lfSize) const
 {
     bool succeeded = false;
+    IDWriteFont* pFont;
+
+    LOGFONTW aLogFont;
+    HFONT hFont = static_cast<HFONT>(::GetCurrentObject(hDC, OBJ_FONT));
+    GetObjectW(hFont, sizeof(LOGFONTW), &aLogFont);
     try
     {
-        succeeded = SUCCEEDED(mpGdiInterop->CreateFontFaceFromHdc(hDC, ppFontFace));
+        succeeded = SUCCEEDED(mpGdiInterop->CreateFontFromLOGFONT(&aLogFont, &pFont));
+        if (succeeded)
+        {
+            succeeded = SUCCEEDED(pFont->CreateFontFace(ppFontFace));
+            pFont->Release();
+        }
     }
     catch (const std::exception& e)
     {
@@ -3611,10 +3621,6 @@ bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** p
 
     if (succeeded)
     {
-        LOGFONTW aLogFont;
-        HFONT hFont = static_cast<HFONT>(::GetCurrentObject(hDC, OBJ_FONT));
-
-        GetObjectW(hFont, sizeof(LOGFONTW), &aLogFont);
         float dpix, dpiy;
         mpRT->GetDpi(&dpix, &dpiy);
         *lfSize = aLogFont.lfHeight * 96.0f / dpiy;


More information about the Libreoffice-commits mailing list