void QFontEngineWin::getCMap() { ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE); HDC hdc = shared_dc(); SelectObject(hdc, hfont); bool symb = false; if (ttf) { cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p'))); int size = 0; cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symb, &size); } if (!cmap) { ttf = false; symb = false; } symbol = symb; designToDevice = 1; _faceId.index = 0; if(cmap) { OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight); unitsPerEm = otm->otmEMSquare; x_height = (int)otm->otmsXHeight; loadKerningPairs(designToDevice); _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1(); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; free(otm); } else { unitsPerEm = tm.tmHeight; } }
const unsigned char *QFontEngineS60Extensions::cmap() const { if (!m_cmap) { m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); int size = 0; m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size); } return m_cmap; }
const uchar *QSymbianTypeFaceExtras::cmap() const { if (m_cmapTable.isNull()) { const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); int size = 0; const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *> (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size); m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size); } return reinterpret_cast<const uchar *>(m_cmapTable.constData()); }
bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const { if (flags & QTextEngine::GlyphIndicesOnly) { if (!cmap) { cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); int size = 0; cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &size); if (!cmap) return false; } if (symbolCMap) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); glyphs->glyph = getTrueTypeGlyphIndex(cmap, uc); if(!glyphs->glyph && uc < 0x100) glyphs->glyph = getTrueTypeGlyphIndex(cmap, uc + 0xf000); glyphs++; } } else { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(str, i, len); glyphs->glyph = getTrueTypeGlyphIndex(cmap, uc); glyphs++; } } *nglyphs = len; return true; } if (!multiEngine) return false; const bool kashidaRequest = (len == 1 && *str == QChar(0x640)); if (kashidaRequest && kashidaGlyph.glyph != 0) { *glyphs = kashidaGlyph; *nglyphs = 1; return true; } bool result = multiEngine->stringToCMap(str, len, glyphs, nglyphs, flags); if (result && kashidaRequest) { kashidaGlyph = *glyphs; } return result; }
QFixed QSymbianTypeFaceExtras::unitsPerEm() const { if (m_unitsPerEm.value() != 0) return m_unitsPerEm; const QByteArray head = getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); const int unitsPerEmOffset = 18; if (head.size() > unitsPerEmOffset + sizeof(quint16)) { const uchar* tableData = reinterpret_cast<const uchar*>(head.constData()); const uchar* unitsPerEm = tableData + unitsPerEmOffset; m_unitsPerEm = qFromBigEndian<quint16>(unitsPerEm); } else { // Bitmap font? Corrupt font? // We return -1 and let the QFontEngineS60 return the pixel size. m_unitsPerEm = -1; } return m_unitsPerEm; }
void QWindowsFontEngine::getCMap() { ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable(); cffTable = hasCFFTable(); HDC hdc = m_fontEngineData->hdc; SelectObject(hdc, hfont); bool symb = false; if (ttf) { cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symb, &cmapSize); } if (!cmap) { ttf = false; symb = false; } symbol = symb; designToDevice = 1; _faceId.index = 0; if(cmap) { OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); unitsPerEm = int(otm->otmEMSquare); const QFixed unitsPerEmF(unitsPerEm); designToDevice = unitsPerEmF / QFixed::fromReal(fontDef.pixelSize); x_height = int(otm->otmsXHeight); loadKerningPairs(designToDevice); _faceId.filename = QFile::encodeName(stringFromOutLineTextMetric(otm, otm->otmpFullName)); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; free(otm); } else { unitsPerEm = tm.tmHeight; } }
QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEngine *fontEngine) : fd(fileDescriptor), renderingFontEngine(fontEngine) { fontData = 0; dataSize = 0; fontDef = def; cache_cost = 100; freetype = 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); if (!fontData || fontData == (const uchar *)MAP_FAILED) { #if defined(DEBUG_FONTENGINE) perror("mmap failed"); #endif fontData = 0; return; } if (!verifyHeader(fontData, st.st_size)) { #if defined(DEBUG_FONTENGINE) qDebug() << "verifyHeader failed!"; #endif return; } const Header *header = reinterpret_cast<const Header *>(fontData); readOnly = (header->lock == 0xffffffff); const uchar *data = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize); const uchar *endPtr = fontData + dataSize; while (data <= endPtr - 8) { quint16 blockTag = readValue<quint16>(data); data += 2; // skip padding quint32 blockSize = readValue<quint32>(data); if (blockTag == CMapBlock) { cmapOffset = data - fontData; cmapSize = blockSize; } else if (blockTag == GMapBlock) { glyphMapOffset = data - fontData; glyphMapEntries = blockSize / 4; } else if (blockTag == GlyphBlock) { glyphDataOffset = data - fontData; glyphDataSize = blockSize; } data += blockSize; } face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString()); face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt(); #if !defined(QT_NO_FREETYPE) freetype = QFreetypeFace::getFace(face_id); if (!freetype) { QString newPath = #ifndef QT_NO_SETTINGS QLibraryInfo::location(QLibraryInfo::LibrariesPath) + #endif QLatin1String("/fonts/") + QFileInfo(QFile::decodeName(face_id.filename)).fileName(); face_id.filename = QFile::encodeName(newPath); freetype = QFreetypeFace::getFace(face_id); } if (freetype) { const quint32 qpfTtfRevision = extractHeaderField(fontData, Tag_FontRevision).toUInt(); uchar data[4]; uint length = 4; bool ok = freetype->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'), data, &length); if (!ok || length != 4 || qFromBigEndian<quint32>(data) != qpfTtfRevision) { freetype->release(face_id); freetype = 0; } } if (!cmapOffset && freetype) { freetypeCMapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); externalCMap = reinterpret_cast<const uchar *>(freetypeCMapTable.constData()); cmapSize = freetypeCMapTable.size(); } #endif // get the real cmap if (cmapOffset) { int tableSize = cmapSize; const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize); if (cmapPtr) cmapOffset = cmapPtr - fontData; else cmapOffset = 0; } else if (externalCMap) { int tableSize = cmapSize; externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize); } // verify all the positions in the glyphMap if (glyphMapOffset) { const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); for (uint i = 0; i < glyphMapEntries; ++i) { quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]); if (glyphDataPos == 0xffffffff) continue; if (glyphDataPos >= glyphDataSize) { // error glyphMapOffset = 0; glyphMapEntries = 0; break; } } } #if defined(DEBUG_FONTENGINE) if (!isValid()) qDebug() << "fontData" << fontData << "dataSize" << dataSize << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset << "fd" << fd << "glyphDataSize" << glyphDataSize; #endif #if defined(Q_WS_QWS) if (isValid() && renderingFontEngine) qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName)); #endif }