From 641b3461dd57b73807f7f55fa2d9b08fb777ed20 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Thu, 15 Dec 2016 17:17:17 +0200 Subject: tdf#104533: Fix font metrics for non-SFNT fonts They can still be used with the old layout engine, so fallback to old code when we encounter one of them. Not needed on master as the old layout engine is gone there. Change-Id: Ibe3e4772cb519843eeb44cfc7efd912ae9737b69 Reviewed-on: https://gerrit.libreoffice.org/32049 Tested-by: Jenkins Reviewed-by: Khaled Hosny --- vcl/win/gdi/salfont.cxx | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'vcl') diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 10ec674c9f07..fd207a5db7bf 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -1252,14 +1252,17 @@ void WinSalGraphics::GetFontMetric( ImplFontMetricDataRef& rxFontMetric, int nFa // get the font metric OUTLINETEXTMETRICW aOutlineMetric; - const bool bOK = GetOutlineTextMetricsW(getHDC(), sizeof(OUTLINETEXTMETRICW), &aOutlineMetric); + TEXTMETRICW aWinMetric; + bool bOK = GetOutlineTextMetricsW(getHDC(), sizeof(OUTLINETEXTMETRICW), &aOutlineMetric); + if (bOK) + aWinMetric = aOutlineMetric.otmTextMetrics; + else + bOK = GetTextMetricsW(getHDC(), &aWinMetric); // restore the HDC to the font in the base level SelectFont( getHDC(), hOldFont ); if( !bOK ) return; - TEXTMETRICW aWinMetric = aOutlineMetric.otmTextMetrics; - // device independent font attributes rxFontMetric->SetFamilyType(ImplFamilyToSal( aWinMetric.tmPitchAndFamily )); rxFontMetric->SetSymbolFlag(aWinMetric.tmCharSet == SYMBOL_CHARSET); @@ -1290,9 +1293,42 @@ void WinSalGraphics::GetFontMetric( ImplFontMetricDataRef& rxFontMetric, int nFa // transformation dependent font metrics rxFontMetric->SetWidth( static_cast( mfFontScale[nFallbackLevel] * aWinMetric.tmAveCharWidth ) ); - const std::vector rHhea(aHheaRawData.get(), aHheaRawData.get() + aHheaRawData.size()); - const std::vector rOS2(aOS2RawData.get(), aOS2RawData.get() + aOS2RawData.size()); - rxFontMetric->ImplCalcLineSpacing(rHhea, rOS2, aOutlineMetric.otmEMSquare); + if (aHheaRawData.size() > 0 || aOS2RawData.size() > 0) + { + const std::vector rHhea(aHheaRawData.get(), aHheaRawData.get() + aHheaRawData.size()); + const std::vector rOS2(aOS2RawData.get(), aOS2RawData.get() + aOS2RawData.size()); + rxFontMetric->ImplCalcLineSpacing(rHhea, rOS2, aOutlineMetric.otmEMSquare); + } + else + { + // Falback to GDI code, can only happen with non-SFNT fonts + rxFontMetric->SetInternalLeading( static_cast( mfFontScale[nFallbackLevel] * aWinMetric.tmInternalLeading ) ); + rxFontMetric->SetExternalLeading( static_cast( mfFontScale[nFallbackLevel] * aWinMetric.tmExternalLeading ) ); + rxFontMetric->SetAscent( static_cast( mfFontScale[nFallbackLevel] * aWinMetric.tmAscent ) ); + rxFontMetric->SetDescent( static_cast( mfFontScale[nFallbackLevel] * aWinMetric.tmDescent ) ); + // #107888# improved metric compatibility for Asian fonts... + // TODO: assess workaround below for CWS >= extleading + // TODO: evaluate use of aWinMetric.sTypo* members for CJK + if( mpWinFontData[nFallbackLevel] && mpWinFontData[nFallbackLevel]->SupportsCJK() ) + { + rxFontMetric->SetInternalLeading( rxFontMetric->GetInternalLeading() + rxFontMetric->GetExternalLeading() ); + + // #109280# The line height for Asian fonts is too small. + // Therefore we add half of the external leading to the + // ascent, the other half is added to the descent. + const long nHalfTmpExtLeading = rxFontMetric->GetExternalLeading() / 2; + const long nOtherHalfTmpExtLeading = rxFontMetric->GetExternalLeading() - nHalfTmpExtLeading; + + // #110641# external leading for Asian fonts. + // The factor 0.3 has been confirmed with experiments. + long nCJKExtLeading = static_cast(0.30 * (rxFontMetric->GetAscent() + rxFontMetric->GetDescent())); + nCJKExtLeading -= rxFontMetric->GetExternalLeading(); + rxFontMetric->SetExternalLeading( (nCJKExtLeading > 0) ? nCJKExtLeading : 0 ); + + rxFontMetric->SetAscent( rxFontMetric->GetAscent() + nHalfTmpExtLeading ); + rxFontMetric->SetDescent( rxFontMetric->GetDescent() + nOtherHalfTmpExtLeading ); + } + } rxFontMetric->SetMinKashida( GetMinKashidaWidth() ); } -- cgit