Qt 4.8
qfontdatabase_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qt_windows.h"
43 #include <qmath.h>
44 #include <private/qapplication_p.h>
45 #include "qfont_p.h"
46 #include "qfontengine_p.h"
47 #include "qpaintdevice.h"
48 #include <private/qsystemlibrary_p.h>
49 #include "qabstractfileengine.h"
50 #include "qendian.h"
51 
52 #if !defined(QT_NO_DIRECTWRITE)
53 # include "qsettings.h"
55 #endif
56 
57 #ifdef Q_OS_WINCE
58 # include <QTemporaryFile>
59 #endif
60 
62 
63 extern HDC shared_dc(); // common dc for all fonts
64 
65 #ifdef MAKE_TAG
66 #undef MAKE_TAG
67 #endif
68 // GetFontData expects the tags in little endian ;(
69 #define MAKE_TAG(ch1, ch2, ch3, ch4) (\
70  (((quint32)(ch4)) << 24) | \
71  (((quint32)(ch3)) << 16) | \
72  (((quint32)(ch2)) << 8) | \
73  ((quint32)(ch1)) \
74  )
75 
76 static HFONT stock_sysfont = 0;
77 
78 static bool localizedName(const QString &name)
79 {
80  const QChar *c = name.unicode();
81  for(int i = 0; i < name.length(); ++i) {
82  if(c[i].unicode() >= 0x100)
83  return true;
84  }
85  return false;
86 }
87 
88 static inline quint16 getUShort(const unsigned char *p)
89 {
90  quint16 val;
91  val = *p++ << 8;
92  val |= *p;
93 
94  return val;
95 }
96 
97 static QString getEnglishName(const uchar *table, quint32 bytes)
98 {
99  QString i18n_name;
100  enum {
101  NameRecordSize = 12,
102  FamilyId = 1,
103  MS_LangIdEnglish = 0x009
104  };
105 
106  // get the name table
107  quint16 count;
108  quint16 string_offset;
109  const unsigned char *names;
110 
111  int microsoft_id = -1;
112  int apple_id = -1;
113  int unicode_id = -1;
114 
115  if(getUShort(table) != 0)
116  goto error;
117 
118  count = getUShort(table+2);
119  string_offset = getUShort(table+4);
120  names = table + 6;
121 
122  if(string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
123  goto error;
124 
125  for(int i = 0; i < count; ++i) {
126  // search for the correct name entry
127 
128  quint16 platform_id = getUShort(names + i*NameRecordSize);
129  quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
130  quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
131  quint16 name_id = getUShort(names + 6 + i*NameRecordSize);
132 
133  if(name_id != FamilyId)
134  continue;
135 
136  enum {
137  PlatformId_Unicode = 0,
138  PlatformId_Apple = 1,
139  PlatformId_Microsoft = 3
140  };
141 
142  quint16 length = getUShort(names + 8 + i*NameRecordSize);
143  quint16 offset = getUShort(names + 10 + i*NameRecordSize);
144  if(DWORD(string_offset + offset + length) >= bytes)
145  continue;
146 
147  if ((platform_id == PlatformId_Microsoft
148  && (encoding_id == 0 || encoding_id == 1))
149  && (language_id & 0x3ff) == MS_LangIdEnglish
150  && microsoft_id == -1)
151  microsoft_id = i;
152  // not sure if encoding id 4 for Unicode is utf16 or ucs4...
153  else if(platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1)
154  unicode_id = i;
155  else if(platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0)
156  apple_id = i;
157  }
158  {
159  bool unicode = false;
160  int id = -1;
161  if(microsoft_id != -1) {
162  id = microsoft_id;
163  unicode = true;
164  } else if(apple_id != -1) {
165  id = apple_id;
166  unicode = false;
167  } else if (unicode_id != -1) {
168  id = unicode_id;
169  unicode = true;
170  }
171  if(id != -1) {
172  quint16 length = getUShort(names + 8 + id*NameRecordSize);
173  quint16 offset = getUShort(names + 10 + id*NameRecordSize);
174  if(unicode) {
175  // utf16
176 
177  length /= 2;
178  i18n_name.resize(length);
179  QChar *uc = (QChar *) i18n_name.unicode();
180  const unsigned char *string = table + string_offset + offset;
181  for(int i = 0; i < length; ++i)
182  uc[i] = getUShort(string + 2*i);
183  } else {
184  // Apple Roman
185 
186  i18n_name.resize(length);
187  QChar *uc = (QChar *) i18n_name.unicode();
188  const unsigned char *string = table + string_offset + offset;
189  for(int i = 0; i < length; ++i)
190  uc[i] = QLatin1Char(string[i]);
191  }
192  }
193  }
194  error:
195  //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
196  return i18n_name;
197 }
198 
199 static QString getEnglishName(const QString &familyName)
200 {
201  QString i18n_name;
202 
203  HDC hdc = GetDC( 0 );
204  LOGFONT lf;
205  memset(&lf, 0, sizeof(LOGFONT));
206  memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
207  lf.lfCharSet = DEFAULT_CHARSET;
208  HFONT hfont = CreateFontIndirect(&lf);
209 
210  if(!hfont) {
211  ReleaseDC(0, hdc);
212  return QString();
213  }
214 
215  HGDIOBJ oldobj = SelectObject( hdc, hfont );
216 
217  const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
218 
219  // get the name table
220  unsigned char *table = 0;
221 
222  DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 );
223  if ( bytes == GDI_ERROR ) {
224  // ### Unused variable
225  /* int err = GetLastError(); */
226  goto error;
227  }
228 
229  table = new unsigned char[bytes];
230  GetFontData(hdc, name_tag, 0, table, bytes);
231  if ( bytes == GDI_ERROR )
232  goto error;
233 
234  i18n_name = getEnglishName(table, bytes);
235 error:
236  delete [] table;
237  SelectObject( hdc, oldobj );
238  DeleteObject( hfont );
239  ReleaseDC( 0, hdc );
240 
241  //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
242  return i18n_name;
243 }
244 
245 extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp
246 
247 static
248 void addFontToDatabase(QString familyName, const QString &scriptName,
249  TEXTMETRIC *textmetric,
250  const FONTSIGNATURE *signature,
251  int type)
252 {
253  const int script = -1;
254  const QString foundryName;
255  Q_UNUSED(script);
256 
257  bool italic = false;
258  int weight;
259  bool fixed;
260  bool ttf;
261  bool scalable;
262  int size;
263 
264 // QString escript = QString::fromWCharArray(f->elfScript);
265 // qDebug("script=%s", escript.latin1());
266 
267  NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
268  fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
269  ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
270  scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
271  size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
272  italic = tm->tmItalic;
273  weight = tm->tmWeight;
274 
275  // the "@family" fonts are just the same as "family". Ignore them.
276  if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) {
277  QtFontStyle::Key styleKey;
278  styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
279  styleKey.weight = weightFromInteger(weight);
280 
281  QtFontFamily *family = privateDb()->family(familyName, true);
282 
283  if(ttf && localizedName(familyName) && family->english_name.isEmpty())
284  family->english_name = getEnglishName(familyName);
285 
286  QtFontFoundry *foundry = family->foundry(foundryName, true);
287  QtFontStyle *style = foundry->style(styleKey, QString(), true);
288  style->smoothScalable = scalable;
289  style->pixelSize( size, TRUE);
290 
291  // add fonts windows can generate for us:
292  if (styleKey.weight <= QFont::DemiBold) {
293  QtFontStyle::Key key(styleKey);
294  key.weight = QFont::Bold;
295  QtFontStyle *style = foundry->style(key, QString(), true);
296  style->smoothScalable = scalable;
297  style->pixelSize( size, TRUE);
298  }
299  if (styleKey.style != QFont::StyleItalic) {
300  QtFontStyle::Key key(styleKey);
302  QtFontStyle *style = foundry->style(key, QString(), true);
303  style->smoothScalable = scalable;
304  style->pixelSize( size, TRUE);
305  }
306  if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) {
307  QtFontStyle::Key key(styleKey);
308  key.weight = QFont::Bold;
310  QtFontStyle *style = foundry->style(key, QString(), true);
311  style->smoothScalable = scalable;
312  style->pixelSize( size, TRUE);
313  }
314 
315  family->fixedPitch = fixed;
316 
317  if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) {
318  quint32 unicodeRange[4] = {
319  signature->fsUsb[0], signature->fsUsb[1],
320  signature->fsUsb[2], signature->fsUsb[3]
321  };
322 #ifdef Q_WS_WINCE
323  if (signature->fsUsb[0] == 0) {
324  // If the unicode ranges bit mask is zero then
325  // EnumFontFamiliesEx failed to determine it properly.
326  // In this case we just pretend that the font supports all languages.
327  unicodeRange[0] = 0xbfffffff; // second most significant bit must be zero
328  unicodeRange[1] = 0xffffffff;
329  unicodeRange[2] = 0xffffffff;
330  unicodeRange[3] = 0xffffffff;
331  }
332 #endif
333  quint32 codePageRange[2] = {
334  signature->fsCsb[0], signature->fsCsb[1]
335  };
337 
338  for (int i = 0; i < systems.count(); ++i) {
339  QFontDatabase::WritingSystem writingSystem = systems.at(i);
340 
341  // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
342  // the symbol for Baht, and Windows thus reports that it supports the Thai script.
343  // Since it's the default UI font on this platform, most widgets will be unable to
344  // display Thai text by default. As a temporary work around, we special case Segoe UI
345  // and remove the Thai script from its list of supported writing systems.
346  if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI"))
347  family->writingSystems[writingSystem] = QtFontFamily::Supported;
348  }
349  } else if (!family->writingSystemCheck) {
350  //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1());
351  if (scriptName == QLatin1String("Western")
352  || scriptName == QLatin1String("Baltic")
353  || scriptName == QLatin1String("Central European")
354  || scriptName == QLatin1String("Turkish")
355  || scriptName == QLatin1String("Vietnamese"))
357  else if (scriptName == QLatin1String("Thai"))
359  else if (scriptName == QLatin1String("Symbol")
360  || scriptName == QLatin1String("Other"))
362  else if (scriptName == QLatin1String("OEM/Dos"))
364  else if (scriptName == QLatin1String("CHINESE_GB2312"))
366  else if (scriptName == QLatin1String("CHINESE_BIG5"))
368  else if (scriptName == QLatin1String("Cyrillic"))
370  else if (scriptName == QLatin1String("Hangul"))
372  else if (scriptName == QLatin1String("Hebrew"))
374  else if (scriptName == QLatin1String("Greek"))
376  else if (scriptName == QLatin1String("Japanese"))
378  else if (scriptName == QLatin1String("Arabic"))
380  }
381  }
382 }
383 
384 static
385 int CALLBACK
386 storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/)
387 {
388  QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
389  QString script = QString::fromWCharArray(f->elfScript);
390 
391  FONTSIGNATURE signature = textmetric->ntmFontSig;
392 
393  // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
394  // identical to a TEXTMETRIC except for the last four members, which we don't use
395  // anyway
396  addFontToDatabase(familyName, script, (TEXTMETRIC *)textmetric, &signature, type);
397  // keep on enumerating
398  return 1;
399 }
400 
401 static
402 void populate_database(const QString& fam)
403 {
404  QFontDatabasePrivate *d = privateDb();
405  if (!d)
406  return;
407 
408  QtFontFamily *family = 0;
409  if(!fam.isEmpty()) {
410  family = d->family(fam);
411  if(family && family->loaded)
412  return;
413  } else if (d->count) {
414  return;
415  }
416 
417  HDC dummy = GetDC(0);
418 
419  LOGFONT lf;
420  lf.lfCharSet = DEFAULT_CHARSET;
421  if (fam.isNull()) {
422  lf.lfFaceName[0] = 0;
423  } else {
424  memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
425  }
426  lf.lfPitchAndFamily = 0;
427 
428  EnumFontFamiliesEx(dummy, &lf,
429  (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0);
430 
431  ReleaseDC(0, dummy);
432 
433  for (int i = 0; i < d->applicationFonts.count(); ++i) {
435  if (!fnt.memoryFont)
436  continue;
437  for (int j = 0; j < fnt.families.count(); ++j) {
438  const QString familyName = fnt.families.at(j);
439  HDC hdc = GetDC(0);
440  LOGFONT lf;
441  memset(&lf, 0, sizeof(LOGFONT));
442  memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
443  lf.lfCharSet = DEFAULT_CHARSET;
444  HFONT hfont = CreateFontIndirect(&lf);
445  HGDIOBJ oldobj = SelectObject(hdc, hfont);
446 
447  TEXTMETRIC textMetrics;
448  GetTextMetrics(hdc, &textMetrics);
449 
450  addFontToDatabase(familyName, QString(),
451  &textMetrics,
452  &fnt.signatures.at(j),
453  TRUETYPE_FONTTYPE);
454 
455  SelectObject(hdc, oldobj);
456  DeleteObject(hfont);
457  ReleaseDC(0, hdc);
458  }
459  }
460 
461  if(!fam.isEmpty()) {
462  family = d->family(fam);
463  if(family) {
464  if(!family->writingSystemCheck) {
465  }
466  family->loaded = true;
467  }
468  }
469 }
470 
471 static void initializeDb()
472 {
473  QFontDatabasePrivate *db = privateDb();
474  if (!db || db->count)
475  return;
476 
478 
479 #ifdef QFONTDATABASE_DEBUG
480  // print the database
481  for (int f = 0; f < db->count; f++) {
482  QtFontFamily *family = db->families[f];
483  qDebug(" %s: %p", qPrintable(family->name), family);
484  populate_database(family->name);
485 
486 #if 0
487  qDebug(" scripts supported:");
488  for (int i = 0; i < QUnicodeTables::ScriptCount; i++)
489  if(family->writingSystems[i] & QtFontFamily::Supported)
490  qDebug(" %d", i);
491  for (int fd = 0; fd < family->count; fd++) {
492  QtFontFoundry *foundry = family->foundries[fd];
493  qDebug(" %s", foundry->name.latin1());
494  for (int s = 0; s < foundry->count; s++) {
495  QtFontStyle *style = foundry->styles[s];
496  qDebug(" style: style=%d weight=%d smooth=%d", style->key.style,
497  style->key.weight, style->smoothScalable );
498  if(!style->smoothScalable) {
499  for(int i = 0; i < style->count; ++i) {
500  qDebug(" %d", style->pixelSizes[i].pixelSize);
501  }
502  }
503  }
504  }
505 #endif
506  }
507 #endif // QFONTDATABASE_DEBUG
508 
509 }
510 
511 static inline void load(const QString &family = QString(), int = -1)
512 {
513  populate_database(family);
514 }
515 
516 
517 
518 
519 
520 // --------------------------------------------------------------------------------------
521 // font loader
522 // --------------------------------------------------------------------------------------
523 
524 
525 
526 static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, HDC fontHdc, int dpi)
527 {
528  fe->fontDef = request; // most settings are equal
529 
530  HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fontHdc) ? fontHdc : shared_dc();
531  SelectObject(dc, fe->hfont);
532  wchar_t n[64];
533  GetTextFace(dc, 64, n);
535  fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
536  if (fe->fontDef.pointSize < 0) {
537  fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi;
538  } else if (fe->fontDef.pixelSize == -1) {
539  fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.);
540  }
541 }
542 
543 #if !defined(QT_NO_DIRECTWRITE)
544 static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request,
545  int dpi, IDWriteFont *font)
546 {
547  fe->fontDef = request;
548 
549  IDWriteFontFamily *fontFamily = NULL;
550  HRESULT hr = font->GetFontFamily(&fontFamily);
551 
552  IDWriteLocalizedStrings *familyNames = NULL;
553  if (SUCCEEDED(hr))
554  hr = fontFamily->GetFamilyNames(&familyNames);
555 
556  UINT32 index = 0;
557  BOOL exists = false;
558 
559  wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
560 
561  if (SUCCEEDED(hr)) {
562  int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);
563 
564  if (defaultLocaleSuccess)
565  hr = familyNames->FindLocaleName(localeName, &index, &exists);
566 
567  if (SUCCEEDED(hr) && !exists)
568  hr = familyNames->FindLocaleName(L"en-us", &index, &exists);
569  }
570 
571  if (!exists)
572  index = 0;
573 
574  UINT32 length = 0;
575  if (SUCCEEDED(hr))
576  hr = familyNames->GetStringLength(index, &length);
577 
578  wchar_t *name = new (std::nothrow) wchar_t[length+1];
579  if (name == NULL)
580  hr = E_OUTOFMEMORY;
581 
582  // Get the family name.
583  if (SUCCEEDED(hr))
584  hr = familyNames->GetString(index, name, length + 1);
585 
586  if (SUCCEEDED(hr))
588 
589  delete[] name;
590  if (familyNames != NULL)
591  familyNames->Release();
592 
593  if (FAILED(hr))
594  qErrnoWarning(hr, "initFontInfo: Failed to get family name");
595 
596  if (fe->fontDef.pointSize < 0)
597  fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi;
598  else if (fe->fontDef.pixelSize == -1)
599  fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.);
600 }
601 #endif
602 
603 static const char *other_tryFonts[] = {
604  "Arial",
605  "MS UI Gothic",
606  "Gulim",
607  "SimSun",
608  "PMingLiU",
609  "Arial Unicode MS",
610  0
611 };
612 
613 static const char *jp_tryFonts [] = {
614  "MS UI Gothic",
615  "Arial",
616  "Gulim",
617  "SimSun",
618  "PMingLiU",
619  "Arial Unicode MS",
620  0
621 };
622 
623 static const char *ch_CN_tryFonts [] = {
624  "SimSun",
625  "Arial",
626  "PMingLiU",
627  "Gulim",
628  "MS UI Gothic",
629  "Arial Unicode MS",
630  0
631 };
632 
633 static const char *ch_TW_tryFonts [] = {
634  "PMingLiU",
635  "Arial",
636  "SimSun",
637  "Gulim",
638  "MS UI Gothic",
639  "Arial Unicode MS",
640  0
641 };
642 
643 static const char *kr_tryFonts[] = {
644  "Gulim",
645  "Arial",
646  "PMingLiU",
647  "SimSun",
648  "MS UI Gothic",
649  "Arial Unicode MS",
650  0
651 };
652 
653 static const char **tryFonts = 0;
654 
655 #if !defined(QT_NO_DIRECTWRITE)
656 static QString fontNameSubstitute(const QString &familyName)
657 {
658  QLatin1String key("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"
659  "FontSubstitutes");
660  return QSettings(key, QSettings::NativeFormat).value(familyName, familyName).toString();
661 }
662 #endif
663 
664 static inline HFONT systemFont()
665 {
666  if (stock_sysfont == 0)
667  stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT);
668  return stock_sysfont;
669 }
670 
671 #if !defined(DEFAULT_GUI_FONT)
672 #define DEFAULT_GUI_FONT 17
673 #endif
674 
675 static QFontEngine *loadEngine(int script, const QFontDef &request,
676  HDC fontHdc, int dpi, bool rawMode,
677  const QtFontDesc *desc,
678  const QStringList &family_list)
679 {
680  LOGFONT lf;
681  memset(&lf, 0, sizeof(LOGFONT));
682 
683  bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc;
684 
685  HDC hdc = shared_dc();
686  QString font_name = desc != 0 ? desc->family->name : request.family;
687 
688  if (useDevice) {
689  hdc = fontHdc;
690  font_name = request.family;
691  }
692 
693  bool stockFont = false;
694  bool preferClearTypeAA = false;
695 
696  HFONT hfont = 0;
697 
698 
699 #if !defined(QT_NO_DIRECTWRITE)
700  bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
702  IDWriteFont *directWriteFont = 0;
703 #else
704  bool useDirectWrite = false;
705 #endif
706 
707  if (rawMode) { // will choose a stock font
708  int f, deffnt = SYSTEM_FONT;
709  QString fam = desc != 0 ? desc->family->name.toLower() : request.family.toLower();
710  if (fam == QLatin1String("default"))
711  f = deffnt;
712  else if (fam == QLatin1String("system"))
713  f = SYSTEM_FONT;
714 #ifndef Q_WS_WINCE
715  else if (fam == QLatin1String("system_fixed"))
716  f = SYSTEM_FIXED_FONT;
717  else if (fam == QLatin1String("ansi_fixed"))
718  f = ANSI_FIXED_FONT;
719  else if (fam == QLatin1String("ansi_var"))
720  f = ANSI_VAR_FONT;
721  else if (fam == QLatin1String("device_default"))
722  f = DEVICE_DEFAULT_FONT;
723  else if (fam == QLatin1String("oem_fixed"))
724  f = OEM_FIXED_FONT;
725 #endif
726  else if (fam[0] == QLatin1Char('#'))
727  f = fam.right(fam.length()-1).toInt();
728  else
729  f = deffnt;
730  hfont = (HFONT)GetStockObject(f);
731  if (!hfont) {
732  qErrnoWarning("QFontEngine::loadEngine: GetStockObject failed");
733  hfont = systemFont();
734  }
735  stockFont = true;
736  } else {
737 
738  int hint = FF_DONTCARE;
739  switch (request.styleHint) {
740  case QFont::Helvetica:
741  hint = FF_SWISS;
742  break;
743  case QFont::Times:
744  hint = FF_ROMAN;
745  break;
746  case QFont::Courier:
747  hint = FF_MODERN;
748  break;
749  case QFont::OldEnglish:
750  hint = FF_DECORATIVE;
751  break;
752  case QFont::System:
753  hint = FF_MODERN;
754  break;
755  default:
756  break;
757  }
758 
759  lf.lfHeight = -qRound(request.pixelSize);
760  lf.lfWidth = 0;
761  lf.lfEscapement = 0;
762  lf.lfOrientation = 0;
763  if (desc == 0 || desc->style->key.weight == 50)
764  lf.lfWeight = FW_DONTCARE;
765  else
766  lf.lfWeight = (desc->style->key.weight*900)/99;
767  lf.lfItalic = (desc != 0 && desc->style->key.style != QFont::StyleNormal);
768  lf.lfCharSet = DEFAULT_CHARSET;
769 
770  int strat = OUT_DEFAULT_PRECIS;
771  if (request.styleStrategy & QFont::PreferBitmap) {
772  strat = OUT_RASTER_PRECIS;
773 #ifndef Q_WS_WINCE
774  } else if (request.styleStrategy & QFont::PreferDevice) {
775  strat = OUT_DEVICE_PRECIS;
776  } else if (request.styleStrategy & QFont::PreferOutline) {
777  strat = OUT_OUTLINE_PRECIS;
778  } else if (request.styleStrategy & QFont::ForceOutline) {
779  strat = OUT_TT_ONLY_PRECIS;
780 #endif
781  }
782 
783  lf.lfOutPrecision = strat;
784 
785  int qual = DEFAULT_QUALITY;
786 
787  if (request.styleStrategy & QFont::PreferMatch)
788  qual = DRAFT_QUALITY;
789 #ifndef Q_WS_WINCE
790  else if (request.styleStrategy & QFont::PreferQuality)
791  qual = PROOF_QUALITY;
792 #endif
793 
794  if (request.styleStrategy & QFont::PreferAntialias) {
796  qual = CLEARTYPE_QUALITY;
797  preferClearTypeAA = true;
798  } else {
799  qual = ANTIALIASED_QUALITY;
800  }
801  } else if (request.styleStrategy & QFont::NoAntialias) {
802  qual = NONANTIALIASED_QUALITY;
803  }
804 
805  lf.lfQuality = qual;
806 
807  lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
808  lf.lfPitchAndFamily = DEFAULT_PITCH | hint;
809 
810  QString fam = font_name;
811 
812  if(fam.isEmpty())
813  fam = QLatin1String("MS Sans Serif");
814 
815  if ((fam == QLatin1String("MS Sans Serif"))
816  && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
817  fam = QLatin1String("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
818  }
819  if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
820  fam = QLatin1String("Courier New");
821 
822  memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
823 
824  hfont = CreateFontIndirect(&lf);
825  if (!hfont)
826  qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed");
827 
828  stockFont = (hfont == 0);
829  bool ttf = false;
830  int avWidth = 0;
831  BOOL res;
832  HGDIOBJ oldObj = SelectObject(hdc, hfont);
833 
834  TEXTMETRIC tm;
835  res = GetTextMetrics(hdc, &tm);
836  avWidth = tm.tmAveCharWidth;
837  ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
838  SelectObject(hdc, oldObj);
839 
840  if (!ttf || !useDirectWrite) {
841  useDirectWrite = false;
842 
843  if (hfont && (!ttf || request.stretch != 100)) {
844  DeleteObject(hfont);
845  if (!res)
846  qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed");
847  lf.lfWidth = avWidth * request.stretch/100;
848  hfont = CreateFontIndirect(&lf);
849  if (!hfont)
850  qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed");
851  }
852 
853 #ifndef Q_WS_WINCE
854  if (hfont == 0) {
855  hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
856  stockFont = true;
857  }
858 #else
859  if (hfont == 0) {
860  hfont = (HFONT)GetStockObject(SYSTEM_FONT);
861  stockFont = true;
862  }
863 #endif
864 
865  }
866 
867 #if !defined(QT_NO_DIRECTWRITE)
868  else {
869  // Default to false for DirectWrite (and re-enable once/if everything
870  // turns out okay)
871  useDirectWrite = false;
872 
873  QFontDatabasePrivate *db = privateDb();
874  if (db->directWriteFactory == 0) {
875  HRESULT hr = DWriteCreateFactory(
876  DWRITE_FACTORY_TYPE_SHARED,
877  __uuidof(IDWriteFactory),
878  reinterpret_cast<IUnknown **>(&db->directWriteFactory)
879  );
880  if (FAILED(hr)) {
881  qErrnoWarning("QFontEngine::loadEngine: DWriteCreateFactory failed");
882  } else {
883  hr = db->directWriteFactory->GetGdiInterop(&db->directWriteGdiInterop);
884  if (FAILED(hr))
885  qErrnoWarning("QFontEngine::loadEngine: GetGdiInterop failed");
886  }
887  }
888 
889  if (db->directWriteGdiInterop != 0) {
890  QString nameSubstitute = fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName));
891  memcpy(lf.lfFaceName, nameSubstitute.utf16(),
892  sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
893 
894  HRESULT hr = db->directWriteGdiInterop->CreateFontFromLOGFONT(
895  &lf,
896  &directWriteFont);
897  if (FAILED(hr)) {
898 #ifndef QT_NO_DEBUG
899  qErrnoWarning("QFontEngine::loadEngine: CreateFontFromLOGFONT failed "
900  "for %ls (0x%lx)",
901  lf.lfFaceName, hr);
902 #endif
903  } else {
904  DeleteObject(hfont);
905  useDirectWrite = true;
906  }
907  }
908  }
909 #endif
910 
911  }
912 
913  QFontEngine *fe = 0;
914  if (!useDirectWrite) {
915  QFontEngineWin *few = new QFontEngineWin(font_name, hfont, stockFont, lf);
916  if (preferClearTypeAA)
918 
919  // Also check for OpenType tables when using complex scripts
920  // ### TODO: This only works for scripts that require OpenType. More generally
921  // for scripts that do not require OpenType we should just look at the list of
922  // supported writing systems in the font's OS/2 table.
923  if (scriptRequiresOpenType(script)) {
924  HB_Face hbFace = few->harfbuzzFace();
925  if (!hbFace || !hbFace->supported_scripts[script]) {
926  FM_DEBUG(" OpenType support missing for script\n");
927  delete few;
928  return 0;
929  }
930  }
931 
932  initFontInfo(few, request, fontHdc, dpi);
933  fe = few;
934  }
935 
936 #if !defined(QT_NO_DIRECTWRITE)
937  else {
938  QFontDatabasePrivate *db = privateDb();
939 
940  IDWriteFontFace *directWriteFontFace = NULL;
941  HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace);
942  if (SUCCEEDED(hr)) {
944  directWriteFontFace,
945  request.pixelSize);
946 
947  initFontInfo(fedw, request, dpi, directWriteFont);
948 
949  fe = fedw;
950  } else {
951  qErrnoWarning(hr, "QFontEngine::loadEngine: CreateFontFace failed");
952  }
953  }
954 
955  if (directWriteFont != 0)
956  directWriteFont->Release();
957 #endif
958 
959  if(script == QUnicodeTables::Common
960  && !(request.styleStrategy & QFont::NoFontMerging)
961  && desc != 0
963  if(!tryFonts) {
964  LANGID lid = GetUserDefaultLangID();
965  switch( lid&0xff ) {
966  case LANG_CHINESE: // Chinese (Taiwan)
967  if ( lid == 0x0804 ) // Taiwan
968  tryFonts = ch_TW_tryFonts;
969  else
970  tryFonts = ch_CN_tryFonts;
971  break;
972  case LANG_JAPANESE:
973  tryFonts = jp_tryFonts;
974  break;
975  case LANG_KOREAN:
976  tryFonts = kr_tryFonts;
977  break;
978  default:
979  tryFonts = other_tryFonts;
980  break;
981  }
982  }
984  QStringList list = family_list;
985  const char **tf = tryFonts;
986  while(tf && *tf) {
987  if(fm.contains(QLatin1String(*tf)))
988  list << QLatin1String(*tf);
989  ++tf;
990  }
991  QFontEngine *mfe = new QFontEngineMultiWin(fe, list);
992  mfe->fontDef = fe->fontDef;
993  fe = mfe;
994  }
995  return fe;
996 }
997 
999 {
1000  // From qfont.cpp
1001  extern int qt_defaultDpi();
1002 
1005  if (fe != 0)
1006  return fe;
1007  else
1008  return loadEngine(QUnicodeTables::Common, request, 0, qt_defaultDpi(), false, 0,
1009  QStringList());
1010 }
1011 
1012 const char *styleHint(const QFontDef &request)
1013 {
1014  const char *stylehint = 0;
1015  switch (request.styleHint) {
1016  case QFont::SansSerif:
1017  stylehint = "Arial";
1018  break;
1019  case QFont::Serif:
1020  stylehint = "Times New Roman";
1021  break;
1022  case QFont::TypeWriter:
1023  stylehint = "Courier New";
1024  break;
1025  default:
1026  if (request.fixedPitch)
1027  stylehint = "Courier New";
1028  break;
1029  }
1030  return stylehint;
1031 }
1032 
1033 static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &req)
1034 {
1035  // list of families to try
1036  QStringList family_list = familyList(req);
1037 
1038  const char *stylehint = styleHint(d->request);
1039  if (stylehint)
1040  family_list << QLatin1String(stylehint);
1041 
1042  // append the default fallback font for the specified script
1043  // family_list << ... ; ###########
1044 
1045  // add the default family
1046  QString defaultFamily = QApplication::font().family();
1047  if (! family_list.contains(defaultFamily))
1048  family_list << defaultFamily;
1049 
1050  // add QFont::defaultFamily() to the list, for compatibility with
1051  // previous versions
1052  family_list << QApplication::font().defaultFamily();
1053 
1054  // null family means find the first font matching the specified script
1055  family_list << QString();
1056 
1057  QtFontDesc desc;
1058  QFontEngine *fe = 0;
1059  QList<int> blacklistedFamilies;
1060 
1061  while (!fe) {
1062  for (int i = 0; i < family_list.size(); ++i) {
1063  QString family, foundry;
1064  parseFontName(family_list.at(i), foundry, family);
1065  FM_DEBUG("loadWin: >>>>>>>>>>>>>>trying to match '%s'", family.toLatin1().data());
1066  QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies);
1067  if (desc.family)
1068  break;
1069  }
1070  if (!desc.family)
1071  break;
1072  fe = loadEngine(script, req, d->hdc, d->dpi, d->rawMode, &desc, family_list);
1073  if (!fe)
1074  blacklistedFamilies.append(desc.familyIndex);
1075  }
1076  return fe;
1077 }
1078 
1079 void QFontDatabase::load(const QFontPrivate *d, int script)
1080 {
1081  // sanity checks
1082  if (!qApp)
1083  qWarning("QFontDatabase::load: Must construct QApplication first");
1084  Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
1085 
1086  // normalize the request to get better caching
1087  QFontDef req = d->request;
1088  if (req.pixelSize <= 0)
1089  req.pixelSize = floor((100.0 * req.pointSize * d->dpi) / 72. + 0.5) / 100;
1090  if (req.pixelSize < 1)
1091  req.pixelSize = 1;
1092  if (req.weight == 0)
1093  req.weight = QFont::Normal;
1094  if (req.stretch == 0)
1095  req.stretch = 100;
1096 
1097  QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
1098  if (!d->engineData)
1099  getEngineData(d, key);
1100 
1101  // the cached engineData could have already loaded the engine we want
1102  if (d->engineData->engines[script])
1103  return;
1104 
1106 
1107  // set it to the actual pointsize, so QFontInfo will do the right thing
1108  if (req.pointSize < 0)
1109  req.pointSize = req.pixelSize*72./d->dpi;
1110 
1111  if (!fe) {
1112  if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
1113  fe = new QTestFontEngine(req.pixelSize);
1114  fe->fontDef = req;
1115  } else {
1116  QMutexLocker locker(fontDatabaseMutex());
1117  if (!privateDb()->count)
1118  initializeDb();
1119  fe = loadWin(d, script, req);
1120  }
1121  if (!fe) {
1122  fe = new QFontEngineBox(req.pixelSize);
1123  fe->fontDef = QFontDef();
1124  }
1125  }
1126  d->engineData->engines[script] = fe;
1127  fe->ref.ref();
1128  QFontCache::instance()->insertEngine(key, fe);
1129 }
1130 
1131 #if !defined(FR_PRIVATE)
1132 #define FR_PRIVATE 0x10
1133 #endif
1134 
1135 typedef int (WINAPI *PtrAddFontResourceExW)(LPCWSTR, DWORD, PVOID);
1136 typedef HANDLE (WINAPI *PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
1137 typedef BOOL (WINAPI *PtrRemoveFontResourceExW)(LPCWSTR, DWORD, PVOID);
1138 typedef BOOL (WINAPI *PtrRemoveFontMemResourceEx)(HANDLE);
1139 
1141 {
1142  QList<quint32> offsets;
1143  const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
1144  if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
1145  if (headerTag != MAKE_TAG(0, 1, 0, 0)
1146  && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
1147  && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
1148  && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
1149  return offsets;
1150  offsets << 0;
1151  return offsets;
1152  }
1153  const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
1154  for (uint i = 0; i < numFonts; ++i) {
1155  offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
1156  }
1157  return offsets;
1158 }
1159 
1160 static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
1161 {
1162  const quint16 numTables = qFromBigEndian<quint16>(data + 4);
1163  for (uint i = 0; i < numTables; ++i) {
1164  const quint32 offset = 12 + 16 * i;
1165  if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
1166  *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
1167  *length = qFromBigEndian<quint32>(data + offset + 12);
1168  return;
1169  }
1170  }
1171  *table = 0;
1172  *length = 0;
1173  return;
1174 }
1175 
1177 {
1178  const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
1179 
1180  QList<quint32> offsets = getTrueTypeFontOffsets(data);
1181  if (offsets.isEmpty())
1182  return;
1183 
1184  for (int i = 0; i < offsets.count(); ++i) {
1185  const uchar *font = data + offsets.at(i);
1186  const uchar *table;
1187  quint32 length;
1188  getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
1189  if (!table)
1190  continue;
1191  QString name = getEnglishName(table, length);
1192  if (name.isEmpty())
1193  continue;
1194 
1195  appFont->families << name;
1196  FONTSIGNATURE signature;
1197  getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
1198  if (table && length >= 86) {
1199  // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec
1200  signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
1201  signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46);
1202  signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50);
1203  signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54);
1204 
1205  signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
1206  signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
1207  } else {
1208  memset(&signature, 0, sizeof(signature));
1209  }
1210  appFont->signatures << signature;
1211  }
1212 }
1213 
1215 {
1216  if(!fnt->data.isEmpty()) {
1217 #ifndef Q_OS_WINCE
1219  "AddFontMemResourceEx");
1220  if (!ptrAddFontMemResourceEx)
1221  return;
1222 #endif
1223  getFamiliesAndSignatures(fnt->data, fnt);
1224  if (fnt->families.isEmpty())
1225  return;
1226 
1227 #ifdef Q_OS_WINCE
1228  HANDLE handle = 0;
1229 
1230  {
1231 #ifdef QT_NO_TEMPORARYFILE
1232  wchar_t lpBuffer[MAX_PATH];
1233  GetTempPath(MAX_PATH, lpBuffer);
1234  QString s = QString::fromWCharArray(lpBuffer);
1235  QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf"));
1236  if (!tempfile.open(QIODevice::ReadWrite))
1237 #else
1238  QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf"));
1239  if (!tempfile.open())
1240 #endif // QT_NO_TEMPORARYFILE
1241  return;
1242  if (tempfile.write(fnt->data) == -1)
1243  return;
1244 
1245 #ifndef QT_NO_TEMPORARYFILE
1246  tempfile.setAutoRemove(false);
1247 #endif
1248  fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath();
1249  }
1250 
1251  if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) {
1252  QFile(fnt->fileName).remove();
1253  return;
1254  }
1255 #else
1256  DWORD dummy = 0;
1257  HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0,
1258  &dummy);
1259  if (handle == 0)
1260  return;
1261 #endif // Q_OS_WINCE
1262 
1263  fnt->handle = handle;
1264  fnt->data = QByteArray();
1265  fnt->memoryFont = true;
1266  } else {
1267  QFile f(fnt->fileName);
1268  if (!f.open(QIODevice::ReadOnly))
1269  return;
1270  QByteArray data = f.readAll();
1271  f.close();
1272  getFamiliesAndSignatures(data, fnt);
1273 
1274 #ifdef Q_OS_WINCE
1275  QFileInfo fileinfo(fnt->fileName);
1276  fnt->fileName = fileinfo.absoluteFilePath();
1277  if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0)
1278  return;
1279 #else
1281  "AddFontResourceExW");
1282  if (!ptrAddFontResourceExW
1283  || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0)
1284  return;
1285 #endif // Q_OS_WINCE
1286 
1287  fnt->memoryFont = false;
1288  }
1289 }
1290 
1291 bool QFontDatabase::removeApplicationFont(int handle)
1292 {
1293  QMutexLocker locker(fontDatabaseMutex());
1294 
1295  QFontDatabasePrivate *db = privateDb();
1296  if (handle < 0 || handle >= db->applicationFonts.count())
1297  return false;
1298 
1301  if (font.memoryFont) {
1302 #ifdef Q_OS_WINCE
1303  bool removeSucceeded = RemoveFontResource((LPCWSTR)font.fileName.utf16());
1304  QFile tempfile(font.fileName);
1305  tempfile.remove();
1306  if (!removeSucceeded)
1307  return false;
1308 #else
1310  "RemoveFontMemResourceEx");
1311  if (!ptrRemoveFontMemResourceEx
1313  return false;
1314 #endif // Q_OS_WINCE
1315  } else {
1316 #ifdef Q_OS_WINCE
1317  if (!RemoveFontResource((LPCWSTR)font.fileName.utf16()))
1318  return false;
1319 #else
1321  "RemoveFontResourceExW");
1322  if (!ptrRemoveFontResourceExW
1323  || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0))
1324  return false;
1325 #endif // Q_OS_WINCE
1326  }
1327 
1328  db->invalidate();
1329  return true;
1330 }
1331 
1333 {
1334  QMutexLocker locker(fontDatabaseMutex());
1335 
1336  QFontDatabasePrivate *db = privateDb();
1337  for (int i = 0; i < db->applicationFonts.count(); ++i)
1338  if (!removeApplicationFont(i))
1339  return false;
1340  return true;
1341 }
1342 
1344 {
1345  return true;
1346 }
1347 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
QAtomicInt ref
uint fixedPitch
Definition: qfont_p.h:96
static bool removeAllApplicationFonts()
Removes all application-local fonts previously added using addApplicationFont() and addApplicationFon...
double d
Definition: qnumeric_p.h:62
QString fileName() const
Returns the name set by setFileName() or to the QFile constructors.
Definition: qfile.cpp:470
static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, HDC fontHdc, int dpi)
QFont font(const QString &family, const QString &style, int pointSize) const
Returns a QFont object that has family family, style style and point size pointSize.
int type
Definition: qmetatype.cpp:239
unsigned short pixelSize
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QtFontStyle * style(const QtFontStyle::Key &, const QString &=QString(), bool=false)
int(WINAPI * PtrAddFontResourceExW)(LPCWSTR, DWORD, PVOID)
static PtrAddFontMemResourceEx ptrAddFontMemResourceEx
qreal pointSize
Definition: qfont_p.h:89
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
signed int count
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
QtFontStyle ** styles
#define error(msg)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
The QTemporaryFile class is an I/O device that operates on temporary files.
static const char * ch_TW_tryFonts[]
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
void insertEngine(const Key &key, QFontEngine *engine)
Definition: qfont.cpp:3073
static bool match(const uchar *found, const char *target, uint len)
QtFontStyle * style
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QString absoluteFilePath() const
Returns an absolute path including the file name.
Definition: qfileinfo.cpp:534
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
Weight
Qt uses a weighting scale from 0 to 99 similar to, but not the same as, the scales used in Windows or...
Definition: qfont.h:103
friend struct QFontDef
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
bool ref()
Atomically increments the value of this QAtomicInt.
static const WinVersion WindowsVersion
the version of the Windows operating system on which the application is run (Windows only) ...
Definition: qglobal.h:1613
The QString class provides a Unicode character string.
Definition: qstring.h:83
static const char * ch_CN_tryFonts[]
static void load(const QFontPrivate *d, int script)
Loads a QFontEngine for the specified script that matches the QFontDef request member variable...
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define ANSI_VAR_FONT
static void parseFontName(const QString &name, QString &foundry, QString &family)
This makes sense of the font family name:
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
static QList< quint32 > getTrueTypeFontOffsets(const uchar *fontData)
static const char * kr_tryFonts[]
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
static QFontEngine * loadWin(const QFontPrivate *d, int script, const QFontDef &req)
static QFontCache * instance()
Definition: qfont.cpp:2919
static QFont font()
Returns the default application font.
static QString getEnglishName(const uchar *table, quint32 bytes)
uint rawMode
Definition: qfont_p.h:187
#define MAKE_TAG(ch1, ch2, ch3, ch4)
HDC shared_dc()
Q_CORE_EXPORT void qDebug(const char *,...)
static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define SMOOTH_SCALABLE
The QFontDatabase class provides information about the fonts available in the underlying window syste...
Definition: qfontdatabase.h:66
static QStringList familyList(const QFontDef &req)
QStringList families(WritingSystem writingSystem=Any) const
Returns a sorted list of the available font families which support the writingSystem.
static const char * jp_tryFonts[]
static HFONT stock_sysfont
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QtFontFamily ** families
#define qApp
QTextStream & fixed(QTextStream &stream)
Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation) on stream and returns stream...
QFontDef request
Definition: qfont_p.h:178
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static int toInt(const QByteArray &str)
Definition: generator.cpp:167
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
const char * styleHint(const QFontDef &request)
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
BOOL(WINAPI * PtrRemoveFontMemResourceEx)(HANDLE)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
static bool supportsThreadedFontRendering()
Returns true if font rendering is supported outside the GUI thread, false otherwise.
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
BOOL(WINAPI * PtrRemoveFontResourceExW)(LPCWSTR, DWORD, PVOID)
uint weight
Definition: qfont_p.h:95
bool qt_enable_test_font
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
QString right(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n rightmost characters of the string.
Definition: qstring.cpp:3682
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
void * HANDLE
Definition: qnamespace.h:1671
static void populate_database(const QString &fam)
QtFontFoundry ** foundries
#define FM_DEBUG
static bool removeApplicationFont(int id)
Removes the previously loaded application font identified by id.
Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4)
qreal pixelSize
Definition: qfont_p.h:90
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QtFontFamily * family(const QString &f, bool=false)
static quint16 getUShort(const unsigned char *p)
quint16 qFromBigEndian< quint16 >(const uchar *src)
Definition: qendian.h:249
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
void resize(int size)
Sets the size of the string to size characters.
Definition: qstring.cpp:1353
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
static void load(const QString &family=QString(), int=-1)
static void addFontToDatabase(QString familyName, const QString &scriptName, TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, int type)
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
static QString fontNameSubstitute(const QString &familyName)
long HRESULT
#define FR_PRIVATE
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
void * resolve(const char *symbol)
#define CLEARTYPE_QUALITY
Definition: qt_windows.h:139
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
static bool scriptRequiresOpenType(int script)
unsigned char writingSystems[QFontDatabase::WritingSystemsCount]
QtFontSize * pixelSize(unsigned short size, bool=false)
static QFontEngine * loadEngine(int script, const QFontDef &request, HDC fontHdc, int dpi, bool rawMode, const QtFontDesc *desc, const QStringList &family_list)
QString family() const
Returns the requested font family name, i.e.
Definition: qfont.cpp:906
Q_GUI_EXPORT int qt_defaultDpi()
Definition: qfont.cpp:240
uint style
Definition: qfont_p.h:97
static QString appFont
QVector< FONTSIGNATURE > signatures
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
QFont::Weight weightFromInteger(int weight)
unsigned int quint32
Definition: qglobal.h:938
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static HFONT systemFont()
uint stretch
Definition: qfont_p.h:98
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
QtFontFamily * family
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
quint16 index
static int CALLBACK storeFont(ENUMLOGFONTEX *f, NEWTEXTMETRICEX *textmetric, int type, LPARAM)
QString defaultFamily() const
Returns the family name that corresponds to the current style hint.
Definition: qfont_mac.cpp:134
static void initializeDb()
static const char * other_tryFonts[]
int screen
Definition: qfont_p.h:181
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QFontEngine * findEngine(const Key &key)
Definition: qfont.cpp:3054
QString english_name
static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont)
QFontDef fontDef
QVector< ApplicationFont > applicationFonts
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
QtFontFoundry * foundry(const QString &f, bool=false)
QString family
Definition: qfont_p.h:82
IDWriteGdiInterop * directWriteGdiInterop
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
static const char ** tryFonts
QFontEngineData * engineData
Definition: qfont_p.h:179
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
uint hintingPreference
Definition: qfont_p.h:101
#define qPrintable(string)
Definition: qglobal.h:1750
uint styleHint
Definition: qfont_p.h:93
IDWriteFactory * directWriteFactory
uint styleStrategy
Definition: qfont_p.h:92
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
HANDLE(WINAPI * PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *)
QtFontSize * pixelSizes
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
QFontEngine * qt_load_font_engine_win(const QFontDef &request)
static bool localizedName(const QString &name)
QList< QFontDatabase::WritingSystem > qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2])
static PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954
HB_Face harfbuzzFace() const