44 #if !defined(QT_NO_RAWFONT) 46 #include <private/qsystemlibrary_p.h> 48 #if !defined(QT_NO_DIRECTWRITE) 65 for (
int i = 0; i < int(
sizeof(T)); ++i)
66 littleEndian |=
data[i] << ((
sizeof(T) - i - 1) * 8);
71 BigEndian<T> &operator=(
const T &t)
73 for (
int i = 0; i < int(
sizeof(T)); ++i)
74 data[i] = ((t >> (
sizeof(T) - i - 1) * 8) & 0xff);
86 BigEndian<quint16> count;
87 BigEndian<quint16> stringOffset;
92 BigEndian<quint16> platformID;
93 BigEndian<quint16> encodingID;
94 BigEndian<quint16> languageID;
95 BigEndian<quint16> nameID;
96 BigEndian<quint16> length;
97 BigEndian<quint16> offset;
100 struct OffsetSubTable
102 BigEndian<quint32> scalerType;
103 BigEndian<quint16> numTables;
104 BigEndian<quint16> searchRange;
105 BigEndian<quint16> entrySelector;
106 BigEndian<quint16> rangeShift;
109 struct TableDirectory
111 BigEndian<quint32> identifier;
112 BigEndian<quint32> checkSum;
113 BigEndian<quint32> offset;
114 BigEndian<quint32> length;
119 BigEndian<quint16> version;
120 BigEndian<qint16> avgCharWidth;
121 BigEndian<quint16> weightClass;
122 BigEndian<quint16> widthClass;
123 BigEndian<quint16>
type;
124 BigEndian<qint16> subscriptXSize;
125 BigEndian<qint16> subscriptYSize;
126 BigEndian<qint16> subscriptXOffset;
127 BigEndian<qint16> subscriptYOffset;
128 BigEndian<qint16> superscriptXSize;
129 BigEndian<qint16> superscriptYSize;
130 BigEndian<qint16> superscriptXOffset;
131 BigEndian<qint16> superscriptYOffset;
132 BigEndian<qint16> strikeOutSize;
133 BigEndian<qint16> strikeOutPosition;
134 BigEndian<qint16> familyClass;
136 BigEndian<quint32> unicodeRanges[4];
138 BigEndian<quint16> selection;
139 BigEndian<quint16> firstCharIndex;
140 BigEndian<quint16> lastCharIndex;
141 BigEndian<qint16> typoAscender;
142 BigEndian<qint16> typoDescender;
143 BigEndian<qint16> typoLineGap;
144 BigEndian<quint16> winAscent;
145 BigEndian<quint16> winDescent;
146 BigEndian<quint32> codepageRanges[2];
147 BigEndian<qint16> height;
148 BigEndian<qint16> capHeight;
149 BigEndian<quint16> defaultChar;
150 BigEndian<quint16> breakChar;
151 BigEndian<quint16> maxContext;
159 EmbeddedFont(
const QByteArray &fontData) : m_fontData(fontData) {}
163 TableDirectory *tableDirectoryEntry(
const QByteArray &tagName);
164 QString familyName(TableDirectory *nameTableDirectory = 0);
170 TableDirectory *EmbeddedFont::tableDirectoryEntry(
const QByteArray &tagName)
174 const BigEndian<quint32> *tagIdPtr =
175 reinterpret_cast<const BigEndian<quint32> *
>(tagName.
constData());
178 OffsetSubTable *offsetSubTable =
reinterpret_cast<OffsetSubTable *
>(m_fontData.data());
179 TableDirectory *tableDirectory =
reinterpret_cast<TableDirectory *
>(offsetSubTable + 1);
181 TableDirectory *nameTableDirectoryEntry = 0;
182 for (
int i=0; i<offsetSubTable->numTables; ++i, ++tableDirectory) {
183 if (tableDirectory->identifier == tagId) {
184 nameTableDirectoryEntry = tableDirectory;
189 return nameTableDirectoryEntry;
192 QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
196 if (nameTableDirectoryEntry == 0)
197 nameTableDirectoryEntry = tableDirectoryEntry(
"name");
199 if (nameTableDirectoryEntry != 0) {
200 NameTable *nameTable =
reinterpret_cast<NameTable *
>(m_fontData.data()
201 + nameTableDirectoryEntry->offset);
202 NameRecord *nameRecord =
reinterpret_cast<NameRecord *
>(nameTable + 1);
203 for (
int i=0; i<nameTable->count; ++i, ++nameRecord) {
204 if (nameRecord->nameID == 1
205 && nameRecord->platformID == 3
206 && nameRecord->languageID == 0x0409) {
207 const void *
ptr =
reinterpret_cast<const quint8 *
>(nameTable)
208 + nameTable->stringOffset
209 + nameRecord->offset;
211 const BigEndian<quint16> *s = reinterpret_cast<
const BigEndian<quint16> *>(ptr);
212 const BigEndian<quint16> *e = s + nameRecord->length /
sizeof(
quint16);
223 QString EmbeddedFont::changeFamilyName(
const QString &newFamilyName)
225 TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry(
"name");
226 if (nameTableDirectoryEntry == 0)
229 QString oldFamilyName = familyName(nameTableDirectoryEntry);
232 const int requiredRecordCount = 5;
233 quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
235 int sizeOfHeader =
sizeof(NameTable) +
sizeof(NameRecord) * requiredRecordCount;
236 int newFamilyNameSize = newFamilyName.
size() *
sizeof(
quint16);
239 int regularStringSize = regularString.
size() *
sizeof(
quint16);
242 int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
247 NameTable *nameTable =
reinterpret_cast<NameTable *
>(newNameTable.data());
248 nameTable->count = requiredRecordCount;
249 nameTable->stringOffset = sizeOfHeader;
251 NameRecord *nameRecord =
reinterpret_cast<NameRecord *
>(nameTable + 1);
252 for (
int i=0; i<requiredRecordCount; ++i, nameRecord++) {
253 nameRecord->nameID = nameIds[i];
254 nameRecord->encodingID = 1;
255 nameRecord->languageID = 0x0409;
256 nameRecord->platformID = 3;
257 nameRecord->length = newFamilyNameSize;
260 if (nameIds[i] == 4) {
261 nameRecord->offset = newFamilyNameSize;
262 nameRecord->length = regularStringSize;
267 BigEndian<quint16> *stringStorage =
reinterpret_cast<BigEndian<quint16> *
>(nameRecord);
269 for (
int i=0; i<newFamilyName.
size(); ++i)
270 stringStorage[i] = sourceString[i];
271 stringStorage += newFamilyName.
size();
273 sourceString = regularString.
utf16();
274 for (
int i=0; i<regularString.
size(); ++i)
275 stringStorage[i] = sourceString[i];
279 quint32 *tableEnd =
reinterpret_cast<quint32 *
>(newNameTable.data() + fullSize);
285 nameTableDirectoryEntry->checkSum = checkSum;
286 nameTableDirectoryEntry->offset = m_fontData.size();
287 nameTableDirectoryEntry->length = fullSize;
289 m_fontData.append(newNameTable);
291 return oldFamilyName;
294 #if !defined(QT_NO_DIRECTWRITE) 296 class DirectWriteFontFileStream:
public IDWriteFontFileStream
299 DirectWriteFontFileStream(
const QByteArray &fontData)
300 : m_fontData(fontData)
301 , m_referenceCount(0)
305 ~DirectWriteFontFileStream()
309 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **
object);
310 ULONG STDMETHODCALLTYPE AddRef();
311 ULONG STDMETHODCALLTYPE
Release();
313 HRESULT STDMETHODCALLTYPE ReadFileFragment(
const void **fragmentStart, UINT64 fileOffset,
314 UINT64 fragmentSize, OUT
void **fragmentContext);
315 void STDMETHODCALLTYPE ReleaseFileFragment(
void *fragmentContext);
316 HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize);
317 HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime);
321 ULONG m_referenceCount;
324 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid,
void **
object)
326 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
332 return E_NOINTERFACE;
336 ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
338 return InterlockedIncrement(&m_referenceCount);
343 ULONG newCount = InterlockedDecrement(&m_referenceCount);
349 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
350 const void **fragmentStart,
353 OUT
void **fragmentContext)
355 *fragmentContext = NULL;
356 if (fragmentSize + fileOffset <= m_fontData.size()) {
357 *fragmentStart = m_fontData.data() + fileOffset;
360 *fragmentStart = NULL;
365 void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(
void *)
369 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
371 *fileSize = m_fontData.size();
375 HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
381 class DirectWriteFontFileLoader:
public IDWriteFontFileLoader
384 DirectWriteFontFileLoader() : m_referenceCount(0) {}
386 ~DirectWriteFontFileLoader()
392 Q_ASSERT(!m_fontDatas.contains(key));
393 m_fontDatas.insert(key, fontData);
396 inline void removeKey(
const void *key)
398 m_fontDatas.remove(key);
401 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **
object);
402 ULONG STDMETHODCALLTYPE AddRef();
403 ULONG STDMETHODCALLTYPE
Release();
405 HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
void const *fontFileReferenceKey,
406 UINT32 fontFileReferenceKeySize,
407 OUT IDWriteFontFileStream **fontFileStream);
410 ULONG m_referenceCount;
414 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(
const IID &iid,
417 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
423 return E_NOINTERFACE;
427 ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
429 return InterlockedIncrement(&m_referenceCount);
434 ULONG newCount = InterlockedDecrement(&m_referenceCount);
440 HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
441 void const *fontFileReferenceKey,
442 UINT32 fontFileReferenceKeySize,
443 IDWriteFontFileStream **fontFileStream)
447 if (fontFileReferenceKeySize !=
sizeof(
const void *)) {
448 qWarning(
"DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size");
452 const void *key = *
reinterpret_cast<void *
const *
>(fontFileReferenceKey);
453 *fontFileStream = NULL;
454 if (!m_fontDatas.contains(key))
458 DirectWriteFontFileStream *
stream =
new DirectWriteFontFileStream(fontData);
465 class CustomFontFileLoader
468 CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0)
470 HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
471 __uuidof(IDWriteFactory),
472 reinterpret_cast<IUnknown **>(&m_directWriteFactory));
474 qErrnoWarning(hres,
"CustomFontFileLoader::CustomFontFileLoader: " 475 "DWriteCreateFactory failed.");
477 m_directWriteFontFileLoader =
new DirectWriteFontFileLoader();
478 m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
482 ~CustomFontFileLoader()
484 if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0)
485 m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
487 if (m_directWriteFactory != 0)
488 m_directWriteFactory->Release();
493 if (m_directWriteFontFileLoader != 0)
494 m_directWriteFontFileLoader->addKey(key, fontData);
497 void removeKey(
const void *key)
499 if (m_directWriteFontFileLoader != 0)
500 m_directWriteFontFileLoader->removeKey(key);
503 IDWriteFontFileLoader *loader()
const 505 return m_directWriteFontFileLoader;
509 IDWriteFactory *m_directWriteFactory;
510 DirectWriteFontFileLoader *m_directWriteFontFileLoader;
530 static bool triedResolve =
false;
544 if (fontHandle != NULL) {
545 if (ptrRemoveFontMemResourceEx)
555 EmbeddedFont font(fontData);
557 #if !defined(QT_NO_DIRECTWRITE) 571 QString actualFontName = font.changeFamilyName(uniqueFamilyName);
572 if (actualFontName.
isEmpty()) {
573 qWarning(
"QRawFont::platformLoadFromData: Can't change family name of font");
579 if (ptrAddFontMemResourceEx && ptrRemoveFontMemResourceEx) {
584 if (count == 0 && fontHandle != NULL) {
590 if (fontHandle == NULL) {
591 qWarning(
"QRawFont::platformLoadFromData: AddFontMemResourceEx failed");
594 request.
family = uniqueFamilyName;
600 if (request.
family != fontEngine->fontDef.family) {
601 qWarning(
"QRawFont::platformLoadFromData: Failed to load font. " 602 "Got fallback instead: %s",
qPrintable(fontEngine->fontDef.family));
603 if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
607 Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0);
610 static_cast<QFontEngineWin *
>(fontEngine)->uniqueFamilyName = uniqueFamilyName;
611 fontEngine->fontDef.family = actualFontName;
612 fontEngine->ref.ref();
616 #if !defined(QT_NO_DIRECTWRITE) 618 CustomFontFileLoader fontFileLoader;
619 fontFileLoader.addKey(
this, fontData);
621 IDWriteFactory *factory = NULL;
622 HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
623 __uuidof(IDWriteFactory),
624 reinterpret_cast<IUnknown **>(&factory));
626 qErrnoWarning(hres,
"QRawFont::platformLoadFromData: DWriteCreateFactory failed");
633 hres = factory->CreateCustomFontFileReference(&key,
sizeof(
void *),
634 fontFileLoader.loader(), &
fontFile);
637 "CreateCustomFontFileReference failed");
642 BOOL isSupportedFontType;
643 DWRITE_FONT_FILE_TYPE fontFileType;
644 DWRITE_FONT_FACE_TYPE fontFaceType;
645 UINT32 numberOfFaces;
646 fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
647 if (!isSupportedFontType) {
653 IDWriteFontFace *directWriteFontFace = NULL;
654 hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE,
655 &directWriteFontFace);
657 qErrnoWarning(hres,
"QRawFont::platformLoadFromData: CreateFontFace failed");
668 fontEngine->fontDef.family = font.familyName();
669 fontEngine->ref.ref();
671 directWriteFontFace->Release();
677 if (fontEngine != 0) {
678 TableDirectory *os2TableEntry = font.tableDirectoryEntry(
"OS/2");
679 if (os2TableEntry != 0) {
680 const OS2Table *os2Table =
681 reinterpret_cast<const OS2Table *
>(fontData.
constData()
682 + os2TableEntry->offset);
684 bool italic = os2Table->selection & 1;
685 bool oblique = os2Table->selection & 128;
701 #endif // QT_NO_RAWFONT static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
HintingPreference
This enum describes the different levels of hinting that can be applied to glyphs to improve legibili...
#define QT_END_NAMESPACE
This macro expands to.
static void resolveGdi32()
static PtrAddFontMemResourceEx ptrAddFontMemResourceEx
QFontEngine * qt_load_font_engine_win(const QFontDef &request)
The QByteArray class provides an array of bytes.
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...
The QString class provides a Unicode character string.
The QHash class is a template class that provides a hash-table-based dictionary.
bool load(bool onlySystemDirectory=true)
The QChar class provides a 16-bit Unicode character.
static void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format)
#define QT_BEGIN_NAMESPACE
This macro expands to.
QFont::Weight weightFromInteger(int weight)
static float pixelSize(const QFontDef &request, int dpi)
static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **freetype, int *synth)
int size() const
Returns the number of characters in this string.
void platformLoadFromData(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
const T * ptr(const T &t)
BOOL(WINAPI * PtrRemoveFontMemResourceEx)(HANDLE)
const char * constData() const
Returns a pointer to the data stored in the byte array.
void * resolve(const char *symbol)
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
int size() const
Returns the number of bytes in this byte array.
#define qPrintable(string)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
HANDLE(WINAPI * PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *)
static PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
void qErrnoWarning(const char *msg,...)