📄 qfontengine_qpf.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qfontengine_qpf_p.h"#include "private/qpaintengine_raster_p.h"#include <QtCore/qlibraryinfo.h>#include <QtCore/qfileinfo.h>#include <QtCore/qfile.h>#include <QtCore/qdir.h>#include <QtCore/qbuffer.h>#if !defined(QT_NO_FREETYPE)#include "private/qfontengine_ft_p.h"#include "qopentype_p.h"#endif// for mmap#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <fcntl.h>#include <errno.h>#ifndef QT_NO_QWS_QPF#include "qpfutil.cpp"#if defined(Q_WS_QWS)#include "private/qwscommand_qws_p.h"#include "qwsdisplay_qws.h"#include "qabstractfontengine_p.h"#endif#include "qplatformdefs.h"#ifdef QT_LSB#include <dlfcn.h># ifdef QT_NO_MREMAP# undef QT_NO_MREMAP# endif# define MREMAP_MAYMOVE 1# define RTLD_DEFAULT ((void *) 0)// LSB doesn't standardize mremap - resolve it dynamically at runtimestatic void *mremap (void *__addr, size_t __old_len, size_t __new_len, int __flags){ typedef void *(*RemapAddress)(void*, size_t, size_t, int, ...); static RemapAddress remapAddr = 0; if (!remapAddr) { *(void **)(&remapAddr) = ::dlsym(RTLD_DEFAULT, "mremap"); if (!remapAddr) qFatal("Unable to call mremap"); } return remapAddr(__addr, __old_len, __new_len, __flags);}#endif//#define DEBUG_HEADER//#define DEBUG_FONTENGINE#if defined(DEBUG_HEADER)# define DEBUG_VERIFY qDebug#else# define DEBUG_VERIFY if (0) qDebug#endif#define READ_VERIFY(type, variable) \ if (tagPtr + sizeof(type) > endPtr) { \ DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \ return 0; \ } \ variable = qFromBigEndian<type>(tagPtr); \ DEBUG_VERIFY() << "read value" << variable << "of type " #type; \ tagPtr += sizeof(type)template <typename T>T readValue(const uchar *&data){ T value = qFromBigEndian<T>(data); data += sizeof(T); return value;}#define VERIFY(condition) \ if (!(condition)) { \ DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \ return 0; \ }#define VERIFY_TAG(condition) \ if (!(condition)) { \ DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \ return 0; \ }static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr){ quint16 tag, length; READ_VERIFY(quint16, tag); READ_VERIFY(quint16, length); if (tag == QFontEngineQPF::Tag_EndOfHeader) return endPtr; if (tag < QFontEngineQPF::NumTags) { switch (tagTypes[tag]) { case QFontEngineQPF::BitFieldType: case QFontEngineQPF::StringType: // can't do anything... break; case QFontEngineQPF::UInt32Type: VERIFY_TAG(length == sizeof(quint32)); break; case QFontEngineQPF::FixedType: VERIFY_TAG(length == sizeof(quint32)); break; case QFontEngineQPF::UInt8Type: VERIFY_TAG(length == sizeof(quint8)); break; }#if defined(DEBUG_HEADER) if (length == 1) qDebug() << "tag data" << hex << *tagPtr; else if (length == 4) qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3];#endif } return tagPtr + length;}const QFontEngineQPF::Glyph *QFontEngineQPF::findGlyph(glyph_t g) const{ if (!g || g >= glyphMapEntries) return 0; const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); quint32 glyphPos = qFromBigEndian<quint32>(gmapPtr[g]); if (glyphPos > glyphDataSize) { if (glyphPos == 0xffffffff) return 0;#if defined(DEBUG_FONTENGINE) qDebug() << "glyph" << g << "outside of glyphData, remapping font file";#endif#ifndef QT_NO_FREETYPE const_cast<QFontEngineQPF *>(this)->remapFontData();#endif if (glyphPos > glyphDataSize) return 0; } return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos);}bool QFontEngineQPF::verifyHeader(const uchar *data, int size){ VERIFY(size >= int(sizeof(Header))); const Header *header = reinterpret_cast<const Header *>(data); if (header->magic[0] != 'Q' || header->magic[1] != 'P' || header->magic[2] != 'F' || header->magic[3] != '2') return false; VERIFY(header->majorVersion <= CurrentMajorVersion); const quint16 dataSize = qFromBigEndian<quint16>(header->dataSize); VERIFY(size >= int(sizeof(Header)) + dataSize); const uchar *tagPtr = data + sizeof(Header); const uchar *tagEndPtr = tagPtr + dataSize; while (tagPtr < tagEndPtr - 3) { tagPtr = verifyTag(tagPtr, tagEndPtr); VERIFY(tagPtr); } VERIFY(tagPtr <= tagEndPtr); return true;}QVariant QFontEngineQPF::extractHeaderField(const uchar *data, HeaderTag requestedTag){ const Header *header = reinterpret_cast<const Header *>(data); const uchar *tagPtr = data + sizeof(Header); const uchar *endPtr = tagPtr + qFromBigEndian<quint16>(header->dataSize); while (tagPtr < endPtr - 3) { quint16 tag = readValue<quint16>(tagPtr); quint16 length = readValue<quint16>(tagPtr); if (tag == requestedTag) { switch (tagTypes[requestedTag]) { case StringType: return QVariant(QString::fromUtf8(reinterpret_cast<const char *>(tagPtr), length)); case UInt32Type: return QVariant(readValue<quint32>(tagPtr)); case UInt8Type: return QVariant(uint(*tagPtr)); case FixedType: return QVariant(QFixed::fromFixed(readValue<quint32>(tagPtr)).toReal()); case BitFieldType: return QVariant(QByteArray(reinterpret_cast<const char *>(tagPtr), length)); } return QVariant(); } else if (tag == Tag_EndOfHeader) { break; } tagPtr += length; } return QVariant();}#endif // QT_NO_QWS_QPFQString qws_fontCacheDir(){ static QString dir; if (!dir.isEmpty()) return dir;#if defined(Q_WS_QWS) extern QString qws_dataDir(); dir = qws_dataDir();#else dir = QDir::tempPath();#endif dir.append(QLatin1String("/fonts/")); QDir qd(dir); if (!qd.exists() && !qd.mkpath(dir)) dir = QDir::tempPath(); return dir;}#ifndef QT_NO_QWS_QPFQList<QByteArray> QFontEngineQPF::cleanUpAfterClientCrash(const QList<int> &crashedClientIds){ QList<QByteArray> removedFonts; QDir dir(qws_fontCacheDir(), QLatin1String("*.qsf")); for (int i = 0; i < int(dir.count()); ++i) { const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i])); int fd = ::open(fileName.constData(), O_RDONLY); if (fd >= 0) { void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0); if (header && header != MAP_FAILED) { quint32 lockValue = reinterpret_cast<QFontEngineQPF::Header *>(header)->lock; if (lockValue && crashedClientIds.contains(lockValue)) { removedFonts.append(fileName); QFile::remove(QFile::decodeName(fileName)); } ::munmap(header, sizeof(QFontEngineQPF::Header)); } ::close(fd); } } if (!removedFonts.isEmpty()) qDebug() << "list of corrupted and removed fonts:" << removedFonts; return removedFonts;}static inline unsigned int getChar(const QChar *str, int &i, const int len){ unsigned int uc = str[i].unicode(); if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { uint low = str[i+1].unicode(); if (low >= 0xdc00 && low < 0xe000) { uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; ++i; } } return uc;}QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEngine *fontEngine) : fd(fileDescriptor), renderingFontEngine(fontEngine){ fontData = 0; dataSize = 0; fontDef = def; cache_cost = 100; freetype = 0; _openType = 0; externalCMap = 0; cmapOffset = 0; cmapSize = 0; glyphMapOffset = 0; glyphMapEntries = 0; glyphDataOffset = 0; glyphDataSize = 0; kerning_pairs_loaded = false; readOnly = true;#if defined(DEBUG_FONTENGINE) qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ")";#endif if (fd < 0) { if (!renderingFontEngine) return; fileName = fontDef.family.toLower() + QLatin1String("_") + QString::number(fontDef.pixelSize) + QLatin1String("_") + QString::number(fontDef.weight) + (fontDef.style != QFont::StyleNormal ? QLatin1String("_italic") : QLatin1String("")) + QLatin1String(".qsf"); fileName.replace(QLatin1Char(' '), QLatin1Char('_')); fileName.prepend(qws_fontCacheDir()); const QByteArray encodedName = QFile::encodeName(fileName); if (::access(encodedName, F_OK) == 0) {#if defined(DEBUG_FONTENGINE) qDebug() << "found existing qpf:" << fileName;#endif if (::access(encodedName, W_OK | R_OK) == 0) fd = ::open(encodedName, O_RDWR); else if (::access(encodedName, R_OK) == 0) fd = ::open(encodedName, O_RDONLY); } else {#if defined(DEBUG_FONTENGINE) qDebug() << "creating qpf on the fly:" << fileName;#endif if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) { fd = ::open(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644); QBuffer buffer; buffer.open(QIODevice::ReadWrite); QPFGenerator generator(&buffer, renderingFontEngine); generator.generate(); buffer.close(); const QByteArray &data = buffer.data(); ::write(fd, data.constData(), data.size()); } } } QT_STATBUF st; if (QT_FSTAT(fd, &st)) {#if defined(DEBUG_FONTENGINE) qDebug() << "stat failed!";#endif return; } dataSize = st.st_size; fontData = (const uchar *)::mmap(0, st.st_size, PROT_READ | (renderingFontEngine ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -