diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 194c5f3..855d2ee 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -969,7 +969,7 @@ resolveTable: // Check that none of the latin1 range are in the unicode table bool unicodeTableHasLatin1 = false; for (int uc=0x00; uc<0x100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getCMapGlyphIndex(selectedTable, uc) != 0) { unicodeTableHasLatin1 = true; break; } @@ -979,7 +979,7 @@ resolveTable: bool unicodeTableHasSymbols = false; if (!unicodeTableHasLatin1) { for (int uc=0xf000; uc<0xf100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getCMapGlyphIndex(selectedTable, uc) != 0) { unicodeTableHasSymbols = true; break; } @@ -997,7 +997,7 @@ resolveTable: return table + unicode_table; } -quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) +quint32 QFontEngine::getCMapGlyphIndex(const uchar *cmap, uint unicode) { unsigned short format = qFromBigEndian(cmap); if (format == 0) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index e645caf..872e60a 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -225,7 +225,7 @@ public: QFontEngineGlyphCache *glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); - static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); + static quint32 getCMapGlyphIndex(const uchar *cmap, uint unicode); QAtomicInt ref; QFontDef fontDef; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index a805612..1d9b9e6 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -193,13 +193,15 @@ void QFontEngineWin::getCMap() ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE); HDC hdc = shared_dc(); SelectObject(hdc, hfont); - bool symb = false; - if (ttf) { - cmapTable = getSfntTable(qbswap(MAKE_TAG('c', 'm', 'a', 'p'))); - int size = 0; - cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), - cmapTable.size(), &symb, &size); - } + bool symb = false; + + // Need to retrieve cmap table for OpenType PS as well as TTF fonts - these share the sfnt format. (QTBUG 10089). + // This should fail safely if the font doesn't have a cmap. + cmapTable = getSfntTable(qbswap(MAKE_TAG('c', 'm', 'a', 'p'))); + int size = 0; + cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), + cmapTable.size(), &symb, &size); + if (!cmap) { ttf = false; symb = false; @@ -244,17 +246,17 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout #if defined(Q_WS_WINCE) { #else - if (symbol) { + if (symbol && cmap) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getCMapGlyphIndex(cmap, uc); if (!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getCMapGlyphIndex(cmap, uc + 0xf000); } - } else if (ttf) { + } else if (cmap) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc)); + glyphs->glyphs[glyph_pos] = getCMapGlyphIndex(cmap, QChar::mirroredChar(uc)); } } else { #endif @@ -277,17 +279,17 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout #if defined(Q_WS_WINCE) { #else - if (symbol) { + if (symbol && cmap) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[i] = getCMapGlyphIndex(cmap, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getCMapGlyphIndex(cmap, uc + 0xf000); } - } else if (ttf) { + } else if (cmap) { for (; i < numChars; ++i, ++glyph_pos) { unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getCMapGlyphIndex(cmap, uc); } } else { #endif @@ -394,7 +396,7 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph return true; } -inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width) +inline void calculateSfntGlyphWidth(HDC hdc, UINT glyph, int &width) { #if defined(Q_WS_WINCE) GetCharWidth32(hdc, glyph, glyph, &width); @@ -408,7 +410,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla { HGDIOBJ oldFont = 0; HDC hdc = shared_dc(); - if (ttf && (flags & QTextEngine::DesignMetrics)) { + if (cmap && (flags & QTextEngine::DesignMetrics)) { for(int i = 0; i < glyphs->numGlyphs; i++) { unsigned int glyph = glyphs->glyphs[i]; if(int(glyph) >= designAdvancesSize) { @@ -424,7 +426,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla oldFont = selectDesignFont(); int width = 0; - calculateTTFGlyphWidth(hdc, glyph, width); + calculateSfntGlyphWidth(hdc, glyph, width); designAdvances[glyph] = QFixed(width) / designToDevice; } glyphs->advances_x[i] = designAdvances[glyph]; @@ -452,7 +454,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla if (!oldFont) oldFont = SelectObject(hdc, hfont); - if (!ttf) { + if (!cmap) { QChar ch[2] = { ushort(glyph), 0 }; int chrLen = 1; if (glyph > 0xffff) { @@ -464,7 +466,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); width = size.cx; } else { - calculateTTFGlyphWidth(hdc, glyph, width); + calculateSfntGlyphWidth(hdc, glyph, width); } glyphs->advances_x[i] = width; // if glyph's within cache range, store it for later @@ -487,7 +489,7 @@ glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs) for (int i = 0; i < glyphs.numGlyphs; ++i) w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -tm.tmAscent, w, tm.tmHeight, w, 0); + return glyph_metrics_t(0, -ascent(), w, tm.tmHeight, w, 0); } #ifndef Q_WS_WINCE @@ -522,7 +524,7 @@ bool QFontEngineWin::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph } uint format = GGO_METRICS; - if (ttf) + if (cmap) format |= GGO_GLYPH_INDEX; res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat); @@ -560,7 +562,7 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) GetCharABCWidthsFloat(hdc, ch, ch, &abc); int width = qRound(abc.abcfB); - return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t); + return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -ascent(), width, tm.tmHeight, width, 0).transformed(t); } return glyphMetrics; @@ -590,7 +592,7 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) } SelectObject(hdc, oldFont); - return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t); + return glyph_metrics_t(0, -ascent(), width, tm.tmHeight, advance, 0).transformed(t); #endif } @@ -611,7 +613,6 @@ QFixed QFontEngineWin::leading() const return tm.tmExternalLeading; } - QFixed QFontEngineWin::xHeight() const { if(x_height >= 0) @@ -794,19 +795,19 @@ bool QFontEngineWin::canRender(const QChar *string, int len) if (symbol) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(string, i, len); - if (getTrueTypeGlyphIndex(cmap, uc) == 0) { + if (getCMapGlyphIndex(cmap, uc) == 0) { if (uc < 0x100) { - if (getTrueTypeGlyphIndex(cmap, uc + 0xf000) == 0) + if (getCMapGlyphIndex(cmap, uc + 0xf000) == 0) return false; } else { return false; } } } - } else if (ttf) { + } else if (cmap) { for (int i = 0; i < len; ++i) { unsigned int uc = getChar(string, i, len); - if (getTrueTypeGlyphIndex(cmap, uc) == 0) + if (getCMapGlyphIndex(cmap, uc) == 0) return false; } } else { @@ -836,7 +837,7 @@ static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) { #endif static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, - QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1) + QPainterPath *path, bool cmap, glyph_metrics_t *metric = 0, qreal scale = 1) { #if defined(Q_WS_WINCE) Q_UNUSED(glyph); @@ -849,7 +850,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, mat.eM21.fract = mat.eM12.fract = 0; uint glyphFormat = GGO_NATIVE; - if (ttf) + if (cmap) glyphFormat |= GGO_GLYPH_INDEX; GLYPHMETRICS gMetric; @@ -957,7 +958,7 @@ void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in HGDIOBJ oldfont = SelectObject(hdc, hf); for(int i = 0; i < nglyphs; ++i) { - if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0, + if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, cmap, /*metric*/0, qreal(fontDef.pixelSize) / unitsPerEm)) { // Some windows fonts, like "Modern", are vector stroke // fonts, which are reported as TMPF_VECTOR but do not @@ -1001,7 +1002,7 @@ int QFontEngineWin::synthesized() const { if(synthesized_flags == -1) { synthesized_flags = 0; - if(ttf) { + if(cmap) { const DWORD HEAD = MAKE_TAG('h', 'e', 'a', 'd'); HDC hdc = shared_dc(); SelectObject(hdc, hfont); @@ -1010,7 +1011,7 @@ int QFontEngineWin::synthesized() const USHORT macStyle = getUShort(data); if (tm.tmItalic && !(macStyle & 2)) synthesized_flags = SynthesizedItalic; - if (fontDef.stretch != 100 && ttf) + if (fontDef.stretch != 100) synthesized_flags |= SynthesizedStretch; if (tm.tmWeight >= 500 && !(macStyle & 1)) synthesized_flags |= SynthesizedBold; @@ -1069,14 +1070,14 @@ void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m QFixedPoint p; p.x = 0; p.y = 0; - addGlyphToPath(glyph, p, hdc, path, ttf, metrics); + addGlyphToPath(glyph, p, hdc, path, cmap, metrics); DeleteObject(SelectObject(hdc, oldfont)); } bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) const { - if (!ttf) - return false; + // Need to retrieve tables for OpenType as well as TTF fonts - these share the sfnt format. (QTBUG 10089) + // This should fail safely if the font isn't hin sfnt format. HDC hdc = shared_dc(); SelectObject(hdc, hfont); DWORD t = qbswap(tag); @@ -1109,7 +1110,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin bool has_transformation = t.type() > QTransform::TxTranslate; #ifndef Q_WS_WINCE - unsigned int options = ttf ? ETO_GLYPH_INDEX : 0; + unsigned int options = cmap ? ETO_GLYPH_INDEX : 0; XFORM xform; if (has_transformation) { @@ -1127,7 +1128,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin SetWorldTransform(hdc, &xform); HGDIOBJ old_font = SelectObject(hdc, font); - int ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); + int ggo_options = GGO_METRICS | (cmap ? GGO_GLYPH_INDEX : 0); GLYPHMETRICS tgm; MAT2 mat; memset(&mat, 0, sizeof(mat));