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()));
251 quint32 *tableEnd =
reinterpret_cast<quint32 *
>(newNameTable.data() + fullSize);
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()
364 if (!m_fontDatas.contains(
fontData.data()))
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;
387 ULONG m_referenceCount;
388 QHash<const void *, QByteArray> m_fontDatas;
391 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(
const IID &iid,
394 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
400 return E_NOINTERFACE;
404 ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
406 return InterlockedIncrement(&m_referenceCount);
409 ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
411 ULONG newCount = InterlockedDecrement(&m_referenceCount);
417 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
418 void const *fontFileReferenceKey,
419 UINT32 fontFileReferenceKeySize,
420 IDWriteFontFileStream **fontFileStream)
424 if (fontFileReferenceKeySize !=
sizeof(
const void *)) {
425 qWarning(
"%s: Wrong key size", __FUNCTION__);
429 const void *
key = *
reinterpret_cast<void *
const *
>(fontFileReferenceKey);
430 *fontFileStream = NULL;
436 DirectWriteFontFileStream *
stream =
new DirectWriteFontFileStream(
fontData);
445class QCustomFontFileLoader
448 QCustomFontFileLoader(IDWriteFactory *
factory)
450 m_directWriteFactory =
factory;
452 if (m_directWriteFactory) {
453 m_directWriteFactory->AddRef();
455 m_directWriteFontFileLoader =
new DirectWriteFontFileLoader();
456 m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
460 ~QCustomFontFileLoader()
464 if (m_directWriteFactory !=
nullptr && m_directWriteFontFileLoader !=
nullptr)
465 m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
467 if (m_directWriteFactory !=
nullptr)
468 m_directWriteFactory->Release();
473 if (m_directWriteFontFileLoader !=
nullptr)
474 m_directWriteFontFileLoader->addKey(
fontData);
477 void removeKey(
const void *
key)
479 if (m_directWriteFontFileLoader !=
nullptr)
480 m_directWriteFontFileLoader->removeKey(
key);
483 IDWriteFontFileLoader *loader()
const
485 return m_directWriteFontFileLoader;
490 if (m_directWriteFontFileLoader !=
nullptr)
491 m_directWriteFontFileLoader->clear();
495 IDWriteFactory *m_directWriteFactory =
nullptr;
496 DirectWriteFontFileLoader *m_directWriteFontFileLoader =
nullptr;
508#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
509 if (directWriteGdiInterop)
510 directWriteGdiInterop->Release();
511 if (directWriteFactory)
512 directWriteFactory->Release();
531 if (!
data->hasLocalData())
534 if (!init(
data->localData()))
535 qCWarning(lcQpaFonts) <<
"Cannot initialize common font database data";
537 return data->localData();
540bool QWindowsFontDatabaseBase::init(QSharedPointer<QWindowsFontEngineData>
d)
542#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
543 if (!
d->directWriteFactory) {
544 createDirectWriteFactory(&
d->directWriteFactory);
545 if (!
d->directWriteFactory)
548 if (!
d->directWriteGdiInterop) {
549 const HRESULT hr =
d->directWriteFactory->GetGdiInterop(&
d->directWriteGdiInterop);
561#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
562void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **
factory)
565 IUnknown *
result =
nullptr;
567# if QT_CONFIG(directwrite3)
568 qCDebug(lcQpaFonts) <<
"Trying to create IDWriteFactory6";
569 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory6), &
result);
572 qCDebug(lcQpaFonts) <<
"Trying to create IDWriteFactory5";
573 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory5), &
result);
577 qCDebug(lcQpaFonts) <<
"Trying to create IDWriteFactory3";
578 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &
result);
583 qCDebug(lcQpaFonts) <<
"Trying to create IDWriteFactory2";
584 DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &
result);
588 qCDebug(lcQpaFonts) <<
"Trying to create plain IDWriteFactory";
589 if (FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &
result))) {
607 memset(&lf, 0,
sizeof(LOGFONT));
612 lf.lfOrientation = 0;
614 lf.lfWeight = FW_DONTCARE;
618 lf.lfCharSet = DEFAULT_CHARSET;
620 int strat = OUT_DEFAULT_PRECIS;
622 strat = OUT_RASTER_PRECIS;
624 strat = OUT_DEVICE_PRECIS;
626 strat = OUT_OUTLINE_PRECIS;
628 strat = OUT_TT_ONLY_PRECIS;
631 lf.lfOutPrecision = strat;
633 int qual = DEFAULT_QUALITY;
636 qual = DRAFT_QUALITY;
638 qual = PROOF_QUALITY;
644 qual = NONANTIALIASED_QUALITY;
646 qual = ANTIALIASED_QUALITY;
651 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
653 int hint = FF_DONTCARE;
665 hint = FF_DECORATIVE;
674 lf.lfPitchAndFamily = DEFAULT_PITCH |
hint;
678 fam =
request.families.first();
681 fam.truncate(LF_FACESIZE - 1);
684 memcpy(lf.lfFaceName, fam.utf16(), fam.size() *
sizeof(
wchar_t));
691 if (verticalDPI_In <= 0)
694 qFont.setItalic(logFont.lfItalic);
695 if (logFont.lfWeight != FW_DONTCARE)
697 const qreal logFontHeight =
qAbs(logFont.lfHeight);
698 qFont.setPointSizeF(logFontHeight * 72.0 /
qreal(verticalDPI_In));
699 qFont.setUnderline(logFont.lfUnderline);
700 qFont.setOverline(
false);
701 qFont.setStrikeOut(logFont.lfStrikeOut);
708 static const auto stock_sysfont =
709 reinterpret_cast<HFONT
>(GetStockObject(DEFAULT_GUI_FONT));
710 return stock_sysfont;
716 NONCLIENTMETRICS ncm = {};
717 ncm.cbSize =
sizeof(ncm);
718 SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0,
defaultVerticalDPI());
726#if QT_CONFIG(directwrite)
727 m_fontFileLoader.reset(
nullptr);
731#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
732IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(
const QByteArray &
fontData)
734 QList<IDWriteFontFace *> faces = createDirectWriteFaces(
fontData,
false);
737 return faces.isEmpty() ?
nullptr : faces.first();
740QList<IDWriteFontFace *> QWindowsFontDatabaseBase::createDirectWriteFaces(
const QByteArray &
fontData,
741 bool queryVariations)
const
743 QList<IDWriteFontFace *>
ret;
744 QSharedPointer<QWindowsFontEngineData> fontEngineData =
data();
745 if (fontEngineData->directWriteFactory ==
nullptr) {
746 qCWarning(lcQpaFonts) <<
"DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
750 if (m_fontFileLoader ==
nullptr)
751 m_fontFileLoader.reset(
new QCustomFontFileLoader(fontEngineData->directWriteFactory));
755 IDWriteFontFile *fontFile =
nullptr;
758 HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&
key,
760 m_fontFileLoader->loader(),
763 qErrnoWarning(hres,
"%s: CreateCustomFontFileReference failed", __FUNCTION__);
767 BOOL isSupportedFontType;
768 DWRITE_FONT_FILE_TYPE fontFileType;
769 DWRITE_FONT_FACE_TYPE fontFaceType;
770 UINT32 numberOfFaces;
771 fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
772 if (!isSupportedFontType) {
777#if QT_CONFIG(directwrite3)
778 IDWriteFactory5 *factory5 =
nullptr;
779 if (queryVariations && SUCCEEDED(fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory5),
780 reinterpret_cast<void **
>(&factory5)))) {
782 IDWriteFontSetBuilder1 *builder;
783 if (SUCCEEDED(factory5->CreateFontSetBuilder(&builder))) {
784 if (SUCCEEDED(builder->AddFontFile(fontFile))) {
785 IDWriteFontSet *fontSet;
786 if (SUCCEEDED(builder->CreateFontSet(&fontSet))) {
787 int count = fontSet->GetFontCount();
788 qCDebug(lcQpaFonts) <<
"Found" <<
count <<
"variations in font file";
790 IDWriteFontFaceReference *
ref;
791 if (SUCCEEDED(fontSet->GetFontFaceReference(
i, &
ref))) {
792 IDWriteFontFace3 *
face;
793 if (SUCCEEDED(
ref->CreateFontFace(&
face))) {
814 IDWriteFontFace *directWriteFontFace =
nullptr;
815 hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
819 DWRITE_FONT_SIMULATIONS_NONE,
820 &directWriteFontFace);
822 qErrnoWarning(hres,
"%s: CreateFontFace failed", __FUNCTION__);
826 ret.append(directWriteFontFace);
847#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
848 QSharedPointer<QWindowsFontEngineData> fontEngineData =
data();
849 if (fontEngineData->directWriteFactory ==
nullptr)
852 IDWriteFontFace * directWriteFontFace = createDirectWriteFace(
fontData);
853 if (directWriteFontFace ==
nullptr)
866 directWriteFontFace->Release();
960 LANGID lid = GetUserDefaultLangID();
963 if ( lid == 0x0804 || lid == 0x1004)
1001 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 ...
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
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...
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
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()
void invalidate() override
This function is called whenever the font database is invalidated.
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.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
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)