diff options
author | Eike Rathke <erack@erack.de> | 2011-09-09 18:19:43 +0200 |
---|---|---|
committer | Eike Rathke <erack@erack.de> | 2011-09-09 18:28:20 +0200 |
commit | 052f181dad89ad34d90513bc9dcd3e3239727933 (patch) | |
tree | 1157c86ef42326e155da194abbd996bb7fa41fc5 | |
parent | d3794d2d8ab2ee3f8118d61538bb753335b37f23 (diff) |
Use new line heights only if SAL_USE_NEW_LINEHEIGHT=1
Commit 3364fefe1e2dec522211040f2f9ea37bf5cd7466 introduced a new (and
font technically correct) handling of interline spacing that affects
line heights in all applications. Activate that only if
SAL_USE_NEW_LINEHEIGHT=1 is set in the environment, else use the old
handling until all quirks are sorted out.
-rw-r--r-- | vcl/unx/generic/glyphs/gcach_ftyp.cxx | 88 |
1 files changed, 81 insertions, 7 deletions
diff --git a/vcl/unx/generic/glyphs/gcach_ftyp.cxx b/vcl/unx/generic/glyphs/gcach_ftyp.cxx index 5610b014af84..ffa4aa33b642 100644 --- a/vcl/unx/generic/glyphs/gcach_ftyp.cxx +++ b/vcl/unx/generic/glyphs/gcach_ftyp.cxx @@ -951,6 +951,18 @@ int ServerFont::GetEmUnits() const void ServerFont::FetchFontMetric( ImplFontMetricData& rTo, long& rFactor ) const { + const int UNDETERMINED = 0xFEED; + static int nUseNewLineHeight = UNDETERMINED; + if (nUseNewLineHeight == UNDETERMINED) + { + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex()); + if (nUseNewLineHeight == UNDETERMINED) + { + const char* pEnv = getenv( "SAL_USE_NEW_LINEHEIGHT"); + nUseNewLineHeight = (pEnv ? atoi(pEnv) : 0); + } + } + static_cast<ImplFontAttributes&>(rTo) = mpFontInfo->GetFontAttributes(); rTo.mbScalableFont = true; @@ -977,8 +989,15 @@ void ServerFont::FetchFontMetric( ImplFontMetricData& rTo, long& rFactor ) const const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics; rTo.mnAscent = (+rMetrics.ascender + 32) >> 6; rTo.mnDescent = (-rMetrics.descender + 32) >> 6; - rTo.mnExtLeading = ((rMetrics.height + 32) >> 6) - (rTo.mnAscent + rTo.mnDescent); - rTo.mnIntLeading = (rTo.mnAscent + rTo.mnDescent) - ((maFaceFT->units_per_EM + 32) >> 6); + if (nUseNewLineHeight) + { + rTo.mnExtLeading = ((rMetrics.height + 32) >> 6) - (rTo.mnAscent + rTo.mnDescent); + rTo.mnIntLeading = (rTo.mnAscent + rTo.mnDescent) - ((maFaceFT->units_per_EM + 32) >> 6); + } + else + { + rTo.mnIntLeading = ((rMetrics.height + 32) >> 6) - (rTo.mnAscent + rTo.mnDescent); + } rTo.mnSlant = 0; const TT_OS2* pOS2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 ); @@ -1014,12 +1033,67 @@ void ServerFont::FetchFontMetric( ImplFontMetricData& rTo, long& rFactor ) const } const double fScale = (double)GetFontSelData().mnHeight / maFaceFT->units_per_EM; - if( pOS2->sTypoAscender || pOS2->sTypoDescender ) + if (nUseNewLineHeight) + { + if( pOS2->sTypoAscender || pOS2->sTypoDescender ) + { + rTo.mnAscent = (long)( pOS2->sTypoAscender * fScale + 0.5 ); + rTo.mnDescent = (long)( -pOS2->sTypoDescender * fScale + 0.5 ); + rTo.mnExtLeading = (long)( pOS2->sTypoLineGap * fScale + 0.5 ); + rTo.mnIntLeading = (long)( (pOS2->sTypoAscender - pOS2->sTypoDescender - maFaceFT->units_per_EM) * fScale + 0.5 ); + } + } + else { - rTo.mnAscent = (long)( pOS2->sTypoAscender * fScale + 0.5 ); - rTo.mnDescent = (long)( -pOS2->sTypoDescender * fScale + 0.5 ); - rTo.mnExtLeading = (long)( pOS2->sTypoLineGap * fScale + 0.5 ); - rTo.mnIntLeading = (long)( (pOS2->sTypoAscender - pOS2->sTypoDescender - maFaceFT->units_per_EM) * fScale + 0.5 ); + // #108862# sanity check, some fonts treat descent as signed !!! + int nDescent = pOS2->usWinDescent; + if( nDescent > 5*maFaceFT->units_per_EM ) + nDescent = (short)pOS2->usWinDescent; // interpret it as signed! + + if( pOS2->usWinAscent || pOS2->usWinDescent ) // #i30551# + { + rTo.mnAscent = (long)( +pOS2->usWinAscent * fScale + 0.5 ); + rTo.mnDescent = (long)( +nDescent * fScale + 0.5 ); + rTo.mnIntLeading = (long)( (+pOS2->usWinAscent + pOS2->usWinDescent - maFaceFT->units_per_EM) * fScale + 0.5 ); + } + rTo.mnExtLeading = 0; + const TT_HoriHeader* pHHEA = (const TT_HoriHeader*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_hhea ); + if( (pHHEA != NULL) && (pOS2->usWinAscent || pOS2->usWinDescent) ) + { + int nExtLeading = pHHEA->Line_Gap; + nExtLeading -= (pOS2->usWinAscent + pOS2->usWinDescent); + nExtLeading += (pHHEA->Ascender - pHHEA->Descender); + if( nExtLeading > 0 ) + rTo.mnExtLeading = (long)(nExtLeading * fScale + 0.5); + } + + // Check for CJK capabilities of the current font + // #107888# workaround for Asian... + // TODO: remove when ExtLeading fully implemented + sal_Bool bCJKCapable = ((pOS2->ulUnicodeRange2 & 0x2DF00000) != 0); + + if ( bCJKCapable && (pOS2->usWinAscent || pOS2->usWinDescent) ) + { + rTo.mnIntLeading += rTo.mnExtLeading; + + // #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 = rTo.mnExtLeading / 2; + const long nOtherHalfTmpExtLeading = rTo.mnExtLeading - nHalfTmpExtLeading; + + // #110641# external leading for Asian fonts. + // The factor 0.3 has been verified during experiments. + const long nCJKExtLeading = (long)(0.30 * (rTo.mnAscent + rTo.mnDescent)); + + if ( nCJKExtLeading > rTo.mnExtLeading ) + rTo.mnExtLeading = nCJKExtLeading - rTo.mnExtLeading; + else + rTo.mnExtLeading = 0; + + rTo.mnAscent += nHalfTmpExtLeading; + rTo.mnDescent += nOtherHalfTmpExtLeading; + } } } |