7#include <QtCore/QThreadStorage>
8#include <QtCore/QtEndian>
10#if QT_CONFIG(directwrite)
11# if QT_CONFIG(directwrite3)
109 const size_t fontDataSize = m_fontData.
size();
110 if (
Q_UNLIKELY(fontDataSize <
sizeof(OffsetSubTable)))
113 OffsetSubTable *offsetSubTable =
reinterpret_cast<OffsetSubTable *
>(m_fontData.
data());
114 TableDirectory *tableDirectory =
reinterpret_cast<TableDirectory *
>(offsetSubTable + 1);
116 const size_t tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
117 if (
Q_UNLIKELY(fontDataSize <
sizeof(OffsetSubTable) +
sizeof(TableDirectory) * tableCount))
120 TableDirectory *tableDirectoryEnd = tableDirectory + tableCount;
121 for (TableDirectory *
entry = tableDirectory;
entry < tableDirectoryEnd; ++
entry) {
133 TableDirectory *nameTableDirectoryEntry =
static_cast<TableDirectory *
>(directoryEntry);
134 if (nameTableDirectoryEntry ==
nullptr)
135 nameTableDirectoryEntry =
static_cast<TableDirectory *
>(tableDirectoryEntry(
"name"));
137 if (nameTableDirectoryEntry !=
nullptr) {
138 quint32 offset = qFromBigEndian<quint32>(nameTableDirectoryEntry->offset);
142 NameTable *nameTable =
reinterpret_cast<NameTable *
>(m_fontData.data() +
offset);
143 NameRecord *nameRecord =
reinterpret_cast<NameRecord *
>(nameTable + 1);
145 quint16 nameTableCount = qFromBigEndian<quint16>(nameTable->count);
149 for (
int i = 0;
i < nameTableCount; ++
i, ++nameRecord) {
150 if (qFromBigEndian<quint16>(nameRecord->nameID) == 1
151 && qFromBigEndian<quint16>(nameRecord->platformID) == 3
152 && qFromBigEndian<quint16>(nameRecord->languageID) == 0x0409) {
153 quint16 stringOffset = qFromBigEndian<quint16>(nameTable->stringOffset);
154 quint16 nameOffset = qFromBigEndian<quint16>(nameRecord->offset);
155 quint16 nameLength = qFromBigEndian<quint16>(nameRecord->length);
160 const void *
ptr =
reinterpret_cast<const quint8 *
>(nameTable)
167 name +=
QChar( qFromBigEndian<quint16>(*
s++));
178 TableDirectory *os2TableEntry =
static_cast<TableDirectory *
>(tableDirectoryEntry(
"OS/2"));
179 if (os2TableEntry !=
nullptr) {
180 const OS2Table *os2Table =
181 reinterpret_cast<const OS2Table *
>(m_fontData.constData()
182 + qFromBigEndian<quint32>(os2TableEntry->offset));
184 bool italic = qFromBigEndian<quint16>(os2Table->selection) & (1 << 0);
185 bool oblique = qFromBigEndian<quint16>(os2Table->selection) & (1 << 9);
200 TableDirectory *nameTableDirectoryEntry =
static_cast<TableDirectory *
>(tableDirectoryEntry(
"name"));
201 if (nameTableDirectoryEntry ==
nullptr)
204 QString oldFamilyName = familyName(nameTableDirectoryEntry);
207 const int requiredRecordCount = 5;
208 quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
210 int sizeOfHeader =
sizeof(NameTable) +
sizeof(NameRecord) * requiredRecordCount;
211 int newFamilyNameSize = newFamilyName.
size() * int(
sizeof(
quint16));
214 int regularStringSize = regularString.
size() * int(
sizeof(
quint16));
217 int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
222 NameTable *nameTable =
reinterpret_cast<NameTable *
>(newNameTable.
data());
223 nameTable->count = qbswap<quint16>(requiredRecordCount);
224 nameTable->stringOffset = qbswap<quint16>(sizeOfHeader);
226 NameRecord *nameRecord =
reinterpret_cast<NameRecord *
>(nameTable + 1);
227 for (
int i = 0;
i < requiredRecordCount; ++
i, nameRecord++) {
228 nameRecord->nameID = qbswap<quint16>(nameIds[
i]);
229 nameRecord->encodingID = qbswap<quint16>(1);
230 nameRecord->languageID = qbswap<quint16>(0x0409);
231 nameRecord->platformID = qbswap<quint16>(3);
232 nameRecord->length = qbswap<quint16>(newFamilyNameSize);
235 if (nameIds[
i] == 4) {
236 nameRecord->offset = qbswap<quint16>(newFamilyNameSize);
237 nameRecord->length = qbswap<quint16>(regularStringSize);
244 *stringStorage++ = qbswap<quint16>(
quint16(
ch.unicode()));
247 *stringStorage++ = qbswap<quint16>(
quint16(
ch.unicode()));
255 checkSum += qFromBigEndian<quint32>(*(
p++));
257 nameTableDirectoryEntry->checkSum = qbswap<quint32>(checkSum);
258 nameTableDirectoryEntry->offset = qbswap<quint32>(m_fontData.size());
259 nameTableDirectoryEntry->length = qbswap<quint32>(fullSize);
261 m_fontData.append(newNameTable);
263 return oldFamilyName;
266#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
269 class DirectWriteFontFileStream:
public IDWriteFontFileStream
271 Q_DISABLE_COPY(DirectWriteFontFileStream)
275 , m_referenceCount(0)
278 virtual ~DirectWriteFontFileStream()
282 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **
object)
override;
283 ULONG STDMETHODCALLTYPE AddRef()
override;
284 ULONG STDMETHODCALLTYPE
Release()
override;
286 HRESULT STDMETHODCALLTYPE ReadFileFragment(
const void **fragmentStart, UINT64 fileOffset,
287 UINT64 fragmentSize,
OUT void **fragmentContext)
override;
288 void STDMETHODCALLTYPE ReleaseFileFragment(
void *fragmentContext)
override;
289 HRESULT STDMETHODCALLTYPE GetFileSize(
OUT UINT64 *fileSize)
override;
290 HRESULT STDMETHODCALLTYPE GetLastWriteTime(
OUT UINT64 *lastWriteTime)
override;
294 ULONG m_referenceCount;
297 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid,
void **
object)
299 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
305 return E_NOINTERFACE;
309 ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
311 return InterlockedIncrement(&m_referenceCount);
314 ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release()
316 ULONG newCount = InterlockedDecrement(&m_referenceCount);
322 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
323 const void **fragmentStart,
326 OUT void **fragmentContext)
328 *fragmentContext = NULL;
329 if (fileOffset + fragmentSize <=
quint64(m_fontData.size())) {
330 *fragmentStart = m_fontData.data() + fileOffset;
333 *fragmentStart = NULL;
338 void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(
void *)
342 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
344 *fileSize = m_fontData.size();
348 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
354 class DirectWriteFontFileLoader:
public IDWriteFontFileLoader
357 DirectWriteFontFileLoader() : m_referenceCount(0) {}
358 virtual ~DirectWriteFontFileLoader()
368 inline void removeKey(
const void *
key)
370 m_fontDatas.remove(
key);
373 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **
object)
override;
374 ULONG STDMETHODCALLTYPE AddRef()
override;
375 ULONG STDMETHODCALLTYPE
Release()
override;
377 HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
void const *fontFileReferenceKey,
378 UINT32 fontFileReferenceKeySize,
379 OUT IDWriteFontFileStream **fontFileStream)
override;
382 ULONG m_referenceCount;
386 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(
const IID &iid,
389 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
395 return E_NOINTERFACE;
399 ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
401 return InterlockedIncrement(&m_referenceCount);
404 ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
406 ULONG newCount = InterlockedDecrement(&m_referenceCount);
412 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
413 void const *fontFileReferenceKey,
414 UINT32 fontFileReferenceKeySize,
415 IDWriteFontFileStream **fontFileStream)
419 if (fontFileReferenceKeySize !=
sizeof(
const void *)) {
420 qWarning(
"%s: Wrong key size", __FUNCTION__);
424 const void *
key = *
reinterpret_cast<void *
const *
>(fontFileReferenceKey);
425 *fontFileStream = NULL;
431 DirectWriteFontFileStream *
stream =
new DirectWriteFontFileStream(
fontData);
438 class CustomFontFileLoader
441 CustomFontFileLoader(IDWriteFactory *
factory)
443 m_directWriteFactory =
factory;
445 if (m_directWriteFactory) {
446 m_directWriteFactory->AddRef();
448 m_directWriteFontFileLoader =
new DirectWriteFontFileLoader();
449 m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
453 ~CustomFontFileLoader()
455 if (m_directWriteFactory !=
nullptr && m_directWriteFontFileLoader !=
nullptr)
456 m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
458 if (m_directWriteFactory !=
nullptr)
459 m_directWriteFactory->Release();
464 if (m_directWriteFontFileLoader !=
nullptr)
465 m_directWriteFontFileLoader->addKey(
key,
fontData);
468 void removeKey(
const void *
key)
470 if (m_directWriteFontFileLoader !=
nullptr)
471 m_directWriteFontFileLoader->removeKey(
key);
474 IDWriteFontFileLoader *
loader()
const
476 return m_directWriteFontFileLoader;
480 IDWriteFactory *m_directWriteFactory =
nullptr;
481 DirectWriteFontFileLoader *m_directWriteFontFileLoader =
nullptr;
493#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
494 if (directWriteGdiInterop)
495 directWriteGdiInterop->Release();
496 if (directWriteFactory)
497 directWriteFactory->Release();
516 if (!
data->hasLocalData())
519 if (!init(
data->localData()))
520 qCWarning(lcQpaFonts) <<
"Cannot initialize common font database data";
522 return data->localData();
527#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
528 if (!
d->directWriteFactory) {
529 createDirectWriteFactory(&
d->directWriteFactory);
530 if (!
d->directWriteFactory)
533 if (!
d->directWriteGdiInterop) {
534 const HRESULT hr =
d->directWriteFactory->GetGdiInterop(&
d->directWriteGdiInterop);
546#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
547void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **
factory)
550 IUnknown *
result =
nullptr;
552# if QT_CONFIG(directwrite3)
553 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &
result);
556 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &
result);
559 if (FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &
result))) {
577 memset(&lf, 0,
sizeof(LOGFONT));
582 lf.lfOrientation = 0;
584 lf.lfWeight = FW_DONTCARE;
588 lf.lfCharSet = DEFAULT_CHARSET;
590 int strat = OUT_DEFAULT_PRECIS;
592 strat = OUT_RASTER_PRECIS;
594 strat = OUT_DEVICE_PRECIS;
596 strat = OUT_OUTLINE_PRECIS;
598 strat = OUT_TT_ONLY_PRECIS;
601 lf.lfOutPrecision = strat;
603 int qual = DEFAULT_QUALITY;
606 qual = DRAFT_QUALITY;
608 qual = PROOF_QUALITY;
614 qual = NONANTIALIASED_QUALITY;
616 qual = ANTIALIASED_QUALITY;
621 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
623 int hint = FF_DONTCARE;
635 hint = FF_DECORATIVE;
644 lf.lfPitchAndFamily = DEFAULT_PITCH |
hint;
648 fam =
request.families.first();
654 memcpy(lf.lfFaceName, fam.
utf16(), fam.
size() *
sizeof(
wchar_t));
661 if (verticalDPI_In <= 0)
665 if (logFont.lfWeight != FW_DONTCARE)
667 const qreal logFontHeight =
qAbs(logFont.lfHeight);
678 static const auto stock_sysfont =
679 reinterpret_cast<HFONT
>(GetStockObject(DEFAULT_GUI_FONT));
680 return stock_sysfont;
686 NONCLIENTMETRICS ncm = {};
687 ncm.cbSize =
sizeof(ncm);
688 SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0,
defaultVerticalDPI());
694#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
695IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(
const QByteArray &
fontData)
const
698 if (fontEngineData->directWriteFactory ==
nullptr) {
699 qCWarning(lcQpaFonts) <<
"DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
703 CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory);
704 fontFileLoader.addKey(
this,
fontData);
706 IDWriteFontFile *fontFile =
nullptr;
707 const void *
key =
this;
709 HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&
key,
711 fontFileLoader.loader(),
714 qErrnoWarning(hres,
"%s: CreateCustomFontFileReference failed", __FUNCTION__);
718 BOOL isSupportedFontType;
719 DWRITE_FONT_FILE_TYPE fontFileType;
720 DWRITE_FONT_FACE_TYPE fontFaceType;
721 UINT32 numberOfFaces;
722 fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
723 if (!isSupportedFontType) {
729 IDWriteFontFace *directWriteFontFace =
nullptr;
730 hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
734 DWRITE_FONT_SIMULATIONS_NONE,
735 &directWriteFontFace);
737 qErrnoWarning(hres,
"%s: CreateFontFace failed", __FUNCTION__);
743 return directWriteFontFace;
758#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
760 if (fontEngineData->directWriteFactory ==
nullptr)
763 IDWriteFontFace *directWriteFontFace = createDirectWriteFace(
fontData);
774 directWriteFontFace->Release();
868 LANGID lid = GetUserDefaultLangID();
871 if ( lid == 0x0804 || lid == 0x1004)
909 if (fam ==
"MS Sans Serif"_L1) {
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QStringList families(WritingSystem writingSystem=Any)
Returns a sorted list of the available font families which support the writingSystem.
static bool hasFamily(const QString &family)
static QList< WritingSystem > writingSystems()
Returns a sorted list of the available writing systems.
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
void setOverline(bool)
If enable is true, sets overline on; otherwise sets overline off.
void setStrikeOut(bool)
If enable is true, sets strikeout on; otherwise sets strikeout off.
void setItalic(bool b)
Sets the style() of the font to QFont::StyleItalic if enable is true; otherwise the style is set to Q...
void setUnderline(bool)
If enable is true, sets underline on; otherwise sets underline off.
void setPointSizeF(qreal)
Sets the point size to pointSize.
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
void setWeight(Weight weight)
Sets the weight of the font to weight, using the scale defined by \l QFont::Weight enumeration.
const_iterator constEnd() const noexcept
const_iterator constFind(const T &value) const
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
void truncate(qsizetype pos)
Truncates the string at the given position index.
qsizetype size() const
Returns the number of characters in this string.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
QString & append(QChar c)
void updateFromOS2Table(QFontEngine *fontEngine)
QString changeFamilyName(const QString &newFamilyName)
FontTable * tableDirectoryEntry(const QByteArray &tagName)
QString familyName(FontTable *nameTableDirectory=nullptr)
static QFont systemDefaultFont()
QFontEngine * fontEngine(const QFontDef &fontDef, void *handle) override
Returns the font engine that can be used to render the font described by the font definition,...
static QFont LOGFONT_to_QFont(const LOGFONT &lf, int verticalDPI=0)
static QStringList extraTryFontsForFamily(const QString &family)
~QWindowsFontDatabaseBase() override
static HFONT systemFont()
static int defaultVerticalDPI()
static QSharedPointer< QWindowsFontEngineData > data()
QFontDef sanitizeRequest(QFontDef request) const
static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName)
QWindowsFontDatabaseBase()
static QString familyForStyleHint(QFont::StyleHint styleHint)
Static constant data shared by the font engines.
~QWindowsFontEngineData()
Windows font engine using Direct Write.
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
int qRound(qfloat16 d) noexcept
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format)
#define qCWarning(category,...)
#define qCDebug(category,...)
static ControlElement< T > * ptr(QWidget *widget)
constexpr T qAbs(const T &t)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLuint64 GLenum void * handle
GLint GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLenum GLsizeiptr const void * fontData
#define qPrintable(string)
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define CLEARTYPE_QUALITY
unsigned long long quint64
static const char * jp_tryFonts[]
static const char * other_tryFonts[]
QThreadStorage< QWindowsFontEngineDataPtr > FontEngineThreadLocalData
QSharedPointer< QWindowsFontEngineData > QWindowsFontEngineDataPtr
static const char * kr_tryFonts[]
static const char * ch_CN_tryFonts[]
static const char ** tryFonts
static const char * ch_TW_tryFonts[]
QItemEditorFactory * factory
QItemSelection * selection
[0]
QNetworkRequest request(url)