LibreOffice Module vcl (master)  1
fontmetric.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <i18nlangtag/mslangid.hxx>
23 #include <officecfg/Office/Common.hxx>
24 #include <unotools/configmgr.hxx>
25 #include <vcl/metric.hxx>
26 #include <vcl/outdev.hxx>
27 #include <sal/log.hxx>
28 
31 #include <fontinstance.hxx>
32 #include <impfontmetricdata.hxx>
33 #include <sft.hxx>
34 
35 #include <com/sun/star/uno/Sequence.hxx>
36 #include <comphelper/sequence.hxx>
37 #include <hb-ot.h>
38 
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::rtl;
42 using namespace ::utl;
43 
45 : mnAscent( 0 ),
46  mnDescent( 0 ),
47  mnIntLeading( 0 ),
48  mnExtLeading( 0 ),
49  mnLineHeight( 0 ),
50  mnSlant( 0 ),
51  mnBulletOffset( 0 ),
52  mnHangingBaseline( 0 ),
53  mbFullstopCentered( false )
54 {}
55 
56 FontMetric::FontMetric( const FontMetric& rFontMetric ) = default;
57 
59  : FontMetric()
60 {
62  SetStyleName(rFace.GetStyleName());
63  SetCharSet(rFace.GetCharSet());
64  SetFamily(rFace.GetFamilyType());
65  SetPitch(rFace.GetPitch());
66  SetWeight(rFace.GetWeight());
67  SetItalic(rFace.GetItalic());
68  SetAlignment(TextAlign::ALIGN_TOP);
69  SetWidthType(rFace.GetWidthType());
70  SetQuality(rFace.GetQuality() );
71 }
72 
74 {
75 }
76 
77 FontMetric& FontMetric::operator=(const FontMetric& rFontMetric) = default;
78 
79 FontMetric& FontMetric::operator=(FontMetric&& rFontMetric) = default;
80 
81 bool FontMetric::EqualNoBase( const FontMetric& r ) const
82 {
84  return false;
85  if( mnAscent != r.mnAscent )
86  return false;
87  if( mnDescent != r.mnDescent )
88  return false;
89  if( mnIntLeading != r.mnIntLeading )
90  return false;
91  if( mnExtLeading != r.mnExtLeading )
92  return false;
93  if( mnSlant != r.mnSlant )
94  return false;
95 
96  return true;
97 }
98 
99 bool FontMetric::operator==( const FontMetric& r ) const
100 {
101  if( Font::operator!=(r) )
102  return false;
103  return EqualNoBase(r);
104 }
105 
107 {
108  if( !Font::EqualIgnoreColor(r) )
109  return false;
110  return EqualNoBase(r);
111 }
112 
114 {
115  size_t hash = 0;
117  o3tl::hash_combine( hash, mnAscent );
118  o3tl::hash_combine( hash, mnDescent );
121  o3tl::hash_combine( hash, mnSlant );
122  return hash;
123 }
124 
126 {
127  size_t hash = GetHashValueNoBase();
128  o3tl::hash_combine( hash, Font::GetHashValue());
129  return hash;
130 }
131 
133 {
134  size_t hash = GetHashValueNoBase();
135  o3tl::hash_combine( hash, Font::GetHashValueIgnoreColor());
136  return hash;
137 }
138 
140  : FontAttributes( rFontSelData )
141  , mnHeight ( rFontSelData.mnHeight )
142  , mnWidth ( rFontSelData.mnWidth )
143  , mnOrientation( static_cast<short>(rFontSelData.mnOrientation) )
144  , mnAscent( 0 )
145  , mnDescent( 0 )
146  , mnIntLeading( 0 )
147  , mnExtLeading( 0 )
148  , mnSlant( 0 )
149  , mnMinKashida( 0 )
150  , mbFullstopCentered( false )
151  , mnBulletOffset( 0 )
152  , mnUnderlineSize( 0 )
153  , mnUnderlineOffset( 0 )
154  , mnBUnderlineSize( 0 )
155  , mnBUnderlineOffset( 0 )
156  , mnDUnderlineSize( 0 )
157  , mnDUnderlineOffset1( 0 )
158  , mnDUnderlineOffset2( 0 )
159  , mnWUnderlineSize( 0 )
160  , mnWUnderlineOffset( 0 )
161  , mnAboveUnderlineSize( 0 )
162  , mnAboveUnderlineOffset( 0 )
163  , mnAboveBUnderlineSize( 0 )
164  , mnAboveBUnderlineOffset( 0 )
165  , mnAboveDUnderlineSize( 0 )
166  , mnAboveDUnderlineOffset1( 0 )
167  , mnAboveDUnderlineOffset2( 0 )
168  , mnAboveWUnderlineSize( 0 )
169  , mnAboveWUnderlineOffset( 0 )
170  , mnStrikeoutSize( 0 )
171  , mnStrikeoutOffset( 0 )
172  , mnBStrikeoutSize( 0 )
173  , mnBStrikeoutOffset( 0 )
174  , mnDStrikeoutSize( 0 )
175  , mnDStrikeoutOffset1( 0 )
176  , mnDStrikeoutOffset2( 0 )
177 {
178  // initialize the used font name
179  sal_Int32 nTokenPos = 0;
180  SetFamilyName( OUString(GetNextFontToken( rFontSelData.GetFamilyName(), nTokenPos )) );
181  SetStyleName( rFontSelData.GetStyleName() );
182 }
183 
185 {
186  tools::Long nDescent = mnDescent;
187  if ( nDescent <= 0 )
188  {
189  nDescent = mnAscent / 10;
190  if ( !nDescent )
191  nDescent = 1;
192  }
193 
194  // #i55341# for some fonts it is not a good idea to calculate
195  // their text line metrics from the real font descent
196  // => work around this problem just for these fonts
197  if( 3*nDescent > mnAscent )
198  nDescent = mnAscent / 3;
199 
200  tools::Long nLineHeight = ((nDescent*25)+50) / 100;
201  if ( !nLineHeight )
202  nLineHeight = 1;
203  tools::Long nLineHeight2 = nLineHeight / 2;
204  if ( !nLineHeight2 )
205  nLineHeight2 = 1;
206 
207  tools::Long nBLineHeight = ((nDescent*50)+50) / 100;
208  if ( nBLineHeight == nLineHeight )
209  nBLineHeight++;
210  tools::Long nBLineHeight2 = nBLineHeight/2;
211  if ( !nBLineHeight2 )
212  nBLineHeight2 = 1;
213 
214  tools::Long n2LineHeight = ((nDescent*16)+50) / 100;
215  if ( !n2LineHeight )
216  n2LineHeight = 1;
217  tools::Long n2LineDY = n2LineHeight;
218  /* #117909#
219  * add some pixels to minimum double line distance on higher resolution devices
220  */
221  tools::Long nMin2LineDY = 1 + pDev->GetDPIY()/150;
222  if ( n2LineDY < nMin2LineDY )
223  n2LineDY = nMin2LineDY;
224  tools::Long n2LineDY2 = n2LineDY/2;
225  if ( !n2LineDY2 )
226  n2LineDY2 = 1;
227 
228  const vcl::Font& rFont ( pDev->GetFont() );
229  bool bCJKVertical = MsLangId::isCJK(rFont.GetLanguage()) && rFont.IsVertical();
230  tools::Long nUnderlineOffset = bCJKVertical ? mnDescent : (mnDescent/2 + 1);
231  tools::Long nStrikeoutOffset = rFont.IsVertical() ? -((mnAscent - mnDescent) / 2) : -((mnAscent - mnIntLeading) / 3);
232 
233  mnUnderlineSize = nLineHeight;
234  mnUnderlineOffset = nUnderlineOffset - nLineHeight2;
235 
236  mnBUnderlineSize = nBLineHeight;
237  mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2;
238 
239  mnDUnderlineSize = n2LineHeight;
240  mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight;
241  mnDUnderlineOffset2 = mnDUnderlineOffset1 + n2LineDY + n2LineHeight;
242 
243  tools::Long nWCalcSize = mnDescent;
244  if ( nWCalcSize < 6 )
245  {
246  if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
247  mnWUnderlineSize = nWCalcSize;
248  else
249  mnWUnderlineSize = 3;
250  }
251  else
252  mnWUnderlineSize = ((nWCalcSize*50)+50) / 100;
253 
254 
255  // Don't assume that wavelines are never placed below the descent, because for most fonts the waveline
256  // is drawn into the text
257  mnWUnderlineOffset = nUnderlineOffset;
258 
259  mnStrikeoutSize = nLineHeight;
260  mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2;
261 
262  mnBStrikeoutSize = nBLineHeight;
263  mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2;
264 
265  mnDStrikeoutSize = n2LineHeight;
266  mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight;
267  mnDStrikeoutOffset2 = mnDStrikeoutOffset1 + n2LineDY + n2LineHeight;
268 
269  mnBulletOffset = ( pDev->GetTextWidth( OUString( u' ' ) ) - pDev->GetTextWidth( OUString( u'\x00b7' ) ) ) >> 1 ;
270 
271 }
272 
273 
275 {
276  tools::Long nIntLeading = mnIntLeading;
277  // TODO: assess usage of nLeading below (changed in extleading CWS)
278  // if no leading is available, we assume 15% of the ascent
279  if ( nIntLeading <= 0 )
280  {
281  nIntLeading = mnAscent*15/100;
282  if ( !nIntLeading )
283  nIntLeading = 1;
284  }
285 
286  tools::Long nLineHeight = ((nIntLeading*25)+50) / 100;
287  if ( !nLineHeight )
288  nLineHeight = 1;
289 
290  tools::Long nBLineHeight = ((nIntLeading*50)+50) / 100;
291  if ( nBLineHeight == nLineHeight )
292  nBLineHeight++;
293 
294  tools::Long n2LineHeight = ((nIntLeading*16)+50) / 100;
295  if ( !n2LineHeight )
296  n2LineHeight = 1;
297 
298  tools::Long nCeiling = -mnAscent;
299 
300  mnAboveUnderlineSize = nLineHeight;
301  mnAboveUnderlineOffset = nCeiling + (nIntLeading - nLineHeight + 1) / 2;
302 
303  mnAboveBUnderlineSize = nBLineHeight;
304  mnAboveBUnderlineOffset = nCeiling + (nIntLeading - nBLineHeight + 1) / 2;
305 
306  mnAboveDUnderlineSize = n2LineHeight;
307  mnAboveDUnderlineOffset1 = nCeiling + (nIntLeading - 3*n2LineHeight + 1) / 2;
308  mnAboveDUnderlineOffset2 = nCeiling + (nIntLeading + n2LineHeight + 1) / 2;
309 
310  tools::Long nWCalcSize = nIntLeading;
311  if ( nWCalcSize < 6 )
312  {
313  if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
314  mnAboveWUnderlineSize = nWCalcSize;
315  else
317  }
318  else
319  mnAboveWUnderlineSize = ((nWCalcSize*50)+50) / 100;
320 
321  mnAboveWUnderlineOffset = nCeiling + (nIntLeading + 1) / 2;
322 }
323 
325 {
326  const vcl::Font& rFont ( pDev->GetFont() );
327  bool bCentered = true;
328  if (MsLangId::isCJK(rFont.GetLanguage()))
329  {
330  tools::Rectangle aRect;
331  pDev->GetTextBoundRect( aRect, u"\x3001" ); // Fullwidth fullstop
332  const auto nH = rFont.GetFontSize().Height();
333  const auto nB = aRect.Left();
334  // Use 18.75% as a threshold to define a centered fullwidth fullstop.
335  // In general, nB/nH < 5% for most Japanese fonts.
336  bCentered = nB > (((nH >> 1)+nH)>>3);
337  }
338  SetFullstopCenteredFlag( bCentered );
339 }
340 
342 {
344  return false;
345 
346  OUString aFontIdentifier(
347  GetFamilyName() + ","
348  + OUString::number(rInfo.ascender) + "," + OUString::number(rInfo.descender) + ","
349  + OUString::number(rInfo.typoAscender) + "," + OUString::number(rInfo.typoDescender) + ","
350  + OUString::number(rInfo.winAscent) + "," + OUString::number(rInfo.winDescent));
351 
352  css::uno::Sequence<OUString> rWinMetricFontList(
353  officecfg::Office::Common::Misc::FontsUseWinMetrics::get());
354  if (comphelper::findValue(rWinMetricFontList, aFontIdentifier) != -1)
355  {
356  SAL_INFO("vcl.gdi.fontmetric", "Using win metrics for: " << aFontIdentifier);
357  return true;
358  }
359  return false;
360 }
361 
362 /*
363  * Calculate line spacing:
364  *
365  * - hhea metrics should be used, since hhea is a mandatory font table and
366  * should always be present.
367  * - But if OS/2 is present, it should be used since it is mandatory in
368  * Windows.
369  * OS/2 has Typo and Win metrics, but the later was meant to control
370  * text clipping not line spacing and can be ridiculously large.
371  * Unfortunately many Windows application incorrectly use the Win metrics
372  * (thanks to GDI’s TEXTMETRIC) and old fonts might be designed with this
373  * in mind, so OpenType introduced a flag for fonts to indicate that they
374  * really want to use Typo metrics. So for best backward compatibility:
375  * - Use Win metrics if available.
376  * - Unless USE_TYPO_METRICS flag is set, in which case use Typo metrics.
377 */
379 {
381 
382  hb_font_t* pHbFont = pFontInstance->GetHbFont();
383  hb_face_t* pHbFace = hb_font_get_face(pHbFont);
384 
385  hb_blob_t* pHhea = hb_face_reference_table(pHbFace, HB_TAG('h', 'h', 'e', 'a'));
386  hb_blob_t* pOS2 = hb_face_reference_table(pHbFace, HB_TAG('O', 'S', '/', '2'));
387 
388  vcl::TTGlobalFontInfo rInfo = {};
389  GetTTFontMetrics(reinterpret_cast<const uint8_t*>(hb_blob_get_data(pHhea, nullptr)), hb_blob_get_length(pHhea),
390  reinterpret_cast<const uint8_t*>(hb_blob_get_data(pOS2, nullptr)), hb_blob_get_length(pOS2),
391  &rInfo);
392 
393  hb_blob_destroy(pHhea);
394  hb_blob_destroy(pOS2);
395 
396  double nUPEM = hb_face_get_upem(pHbFace);
397  double fScale = mnHeight / nUPEM;
398  double fAscent = 0, fDescent = 0, fExtLeading = 0;
399 
400  // Try hhea table first.
401  // tdf#107605: Some fonts have weird values here, so check that ascender is
402  // +ve and descender is -ve as they normally should.
403  if (rInfo.ascender >= 0 && rInfo.descender <= 0)
404  {
405  fAscent = rInfo.ascender * fScale;
406  fDescent = -rInfo.descender * fScale;
407  fExtLeading = rInfo.linegap * fScale;
408  }
409 
410  // But if OS/2 is present, prefer it.
411  if (rInfo.winAscent || rInfo.winDescent ||
412  rInfo.typoAscender || rInfo.typoDescender)
413  {
414  if (ShouldUseWinMetrics(rInfo) || (fAscent == 0.0 && fDescent == 0.0))
415  {
416  fAscent = rInfo.winAscent * fScale;
417  fDescent = rInfo.winDescent * fScale;
418  fExtLeading = 0;
419  }
420 
421  const uint16_t kUseTypoMetricsMask = 1 << 7;
422  if (rInfo.fsSelection & kUseTypoMetricsMask &&
423  rInfo.typoAscender >= 0 && rInfo.typoDescender <= 0)
424  {
425  fAscent = rInfo.typoAscender * fScale;
426  fDescent = -rInfo.typoDescender * fScale;
427  fExtLeading = rInfo.typoLineGap * fScale;
428  }
429  }
430 
431  mnAscent = round(fAscent);
432  mnDescent = round(fDescent);
433  mnExtLeading = round(fExtLeading);
434 
435  if (mnAscent || mnDescent)
437 
438  SAL_INFO("vcl.gdi.fontmetric", GetFamilyName()
439  << ": fsSelection: " << rInfo.fsSelection
440  << ", typoAscender: " << rInfo.typoAscender
441  << ", typoDescender: " << rInfo.typoDescender
442  << ", typoLineGap: " << rInfo.typoLineGap
443  << ", winAscent: " << rInfo.winAscent
444  << ", winDescent: " << rInfo.winDescent
445  << ", ascender: " << rInfo.ascender
446  << ", descender: " << rInfo.descender
447  << ", linegap: " << rInfo.linegap
448  );
449 }
450 
452 {
453  hb_font_t* pHbFont = pFontInstance->GetHbFont();
454  hb_face_t* pHbFace = hb_font_get_face(pHbFont);
455  double nUPEM = hb_face_get_upem(pHbFace);
456  double fScale = mnHeight / nUPEM;
457  hb_position_t nBaseline = 0;
458 
459  if (hb_ot_layout_get_baseline(pHbFont,
460  HB_OT_LAYOUT_BASELINE_TAG_HANGING,
461  HB_DIRECTION_INVALID,
462  HB_SCRIPT_UNKNOWN,
463  HB_TAG_NONE,
464  &nBaseline))
465  {
466  mnHangingBaseline = nBaseline * fScale;
467  }
468  else
469  {
470  mnHangingBaseline = 0;
471  }
472 }
473 
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetFamily(FontFamily)
Definition: font/font.cxx:154
tools::Long mnAscent
Definition: metric.hxx:81
int winDescent
descender metric for Windows
Definition: sft.hxx:170
double mnHeight
tools::Long mnDStrikeoutOffset2
const OUString & GetStyleName() const
bool operator==(const FontMetric &rMetric) const
Definition: fontmetric.cxx:99
sal_uInt16 fsSelection
OS/2 fsSelection.
Definition: sft.hxx:174
tools::Long mnAboveWUnderlineSize
tools::Long mnAboveDUnderlineSize
tools::Long mnExtLeading
Definition: metric.hxx:84
constexpr tools::Long Left() const
bool ShouldUseWinMetrics(const vcl::TTGlobalFontInfo &rInfo) const
Definition: fontmetric.cxx:341
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
long Long
std::u16string_view GetNextFontToken(std::u16string_view rTokenStr, sal_Int32 &rIndex)
size_t GetHashValueNoBase() const
Definition: fontmetric.cxx:113
void SetWeight(FontWeight)
Definition: font/font.cxx:249
tools::Long mnBUnderlineOffset
tools::Long mnAboveWUnderlineOffset
hb_font_t * GetHbFont()
~FontMetric() override
Definition: fontmetric.cxx:73
tools::Long mnDUnderlineOffset1
void SetCharSet(rtl_TextEncoding)
Definition: font/font.cxx:160
void ImplInitAboveTextLineSize()
Definition: fontmetric.cxx:274
void ImplCalcLineSpacing(LogicalFontInstance *pFontInstance)
Definition: fontmetric.cxx:378
bool mbFullstopCentered
Definition: metric.hxx:90
void ImplInitTextLineSize(const OutputDevice *pDev)
Definition: fontmetric.cxx:184
void SetQuality(int)
Definition: font/font.cxx:911
tools::Long mnDStrikeoutOffset1
tools::Long mnSlant
Definition: metric.hxx:86
tools::Long mnWUnderlineOffset
tools::Long mnAboveUnderlineSize
const vcl::Font & GetFont() const
Definition: outdev.hxx:540
static bool IsFuzzing()
tools::Long mnAboveUnderlineOffset
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, o3tl::span< const sal_Int32 > pDXArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
Return the exact bounding rectangle of rStr.
Definition: text.cxx:2377
int winAscent
ascender metric for Windows
Definition: sft.hxx:169
FontItalic GetItalic() const
rtl_TextEncoding GetCharSet() const
void GetTTFontMetrics(const uint8_t *pHhea, size_t nHhea, const uint8_t *pOs2, size_t nOs2, TTGlobalFontInfo *info)
Returns fonts metrics.
Definition: sft.cxx:2119
tools::Long mnAboveDUnderlineOffset1
void SetPitch(FontPitch ePitch)
Definition: font/font.cxx:220
FontFamily GetFamilyType() const
static bool isCJK(LanguageType nLang)
tools::Long mnIntLeading
Definition: metric.hxx:83
size_t GetHashValueIgnoreColor() const
Definition: fontmetric.cxx:132
size_t GetHashValue() const
Definition: fontmetric.cxx:125
void SetFamilyName(const OUString &rFamilyName)
Definition: font/font.cxx:136
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
Definition: text.cxx:884
int typoAscender
OS/2 portable typographic ascender.
Definition: sft.hxx:166
FontWeight GetWeight() const
int ascender
typographic ascent.
Definition: sft.hxx:162
ImplFontMetricData(const vcl::font::FontSelectPattern &)
Definition: fontmetric.cxx:139
int descender
typographic descent.
Definition: sft.hxx:163
void ImplInitFlags(const OutputDevice *pDev)
Definition: fontmetric.cxx:324
void SetFamilyName(const OUString &sFamilyName)
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:175
tools::Long mnAboveBUnderlineOffset
float u
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
int GetQuality() const
void SetWidthType(FontWidth)
Definition: font/font.cxx:255
int typoLineGap
OS/2 portable typographic line gap.
Definition: sft.hxx:168
tools::Long mnDUnderlineOffset2
bool EqualIgnoreColor(const FontMetric &) const
Definition: fontmetric.cxx:106
abstract base class for physical font faces
void SetAlignment(TextAlign)
Definition: font/font.cxx:130
FontMetric & operator=(const FontMetric &rMetric)
void SetStyleName(const OUString &rStyleName)
Definition: font/font.cxx:142
tools::Long mnAboveDUnderlineOffset2
#define SAL_INFO(area, stream)
Sun Font Tools.
double mnWidth
void SetStyleName(const OUString &sStyleName)
int linegap
typographic line gap. Negative values are treated as zero in Win 3.1, System 6 and System 7...
Definition: sft.hxx:164
tools::Long mnAboveBUnderlineSize
void SetItalic(FontItalic)
Definition: font/font.cxx:261
tools::Long mnBStrikeoutOffset
FontWidth GetWidthType() const
FontPitch GetPitch() const
bool EqualNoBase(const FontMetric &) const
Definition: fontmetric.cxx:81
const OUString & GetFamilyName() const
tools::Long mnDescent
Definition: metric.hxx:82
SAL_DLLPRIVATE sal_Int32 GetDPIY() const
Get the output device's DPI y-axis value.
Definition: outdev.hxx:398
int typoDescender
OS/2 portable typographic descender.
Definition: sft.hxx:167
void ImplInitBaselines(LogicalFontInstance *pFontInstance)
Definition: fontmetric.cxx:451
Return value of GetTTGlobalFontInfo()
Definition: sft.hxx:147
void SetFullstopCenteredFlag(bool bFullstopCentered)
bool m_bDetectedRangeSegmentation false