From 992f1b36dc7c246bb978c9c60b11369e3d1cce9d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 17 Sep 2009 13:21:14 +0200 Subject: Fix glyph selection in symbol fonts that contain unicode cmap table Some symbol fonts will contain a unicode cmap table in addition to the microsoft symbol cmap table that maps the symbol range (private range 0xf000 - 0xf100) into the correct glyphs. This is essentially a broken unicode table, and we should not prefer it if these conditions are true. In the strict cases where these conditions apply, we fall back to the symbol table instead. Task-number: QT-2354 Done-with: Lars Reviewed by: Lars --- src/gui/text/qfontengine.cpp | 77 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 8dd01d7..e5a88fc 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -946,48 +946,60 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy if (maps + 8 * numTables > endPtr) return 0; + enum { + Invalid, + Symbol, + AppleRoman, + Unicode11, + Unicode, + MicrosoftUnicode, + MicrosoftUnicodeExtended + }; + + int symbolTable = -1; int tableToUse = -1; - int score = 0; + int score = Invalid; for (int n = 0; n < numTables; ++n) { const quint16 platformId = qFromBigEndian(maps + 8 * n); const quint16 platformSpecificId = qFromBigEndian(maps + 8 * n + 2); switch (platformId) { case 0: // Unicode - if (score < 4 && + if (score < Unicode && (platformSpecificId == 0 || platformSpecificId == 2 || platformSpecificId == 3)) { tableToUse = n; - score = 4; - } else if (score < 3 && platformSpecificId == 1) { + score = Unicode; + } else if (score < Unicode11 && platformSpecificId == 1) { tableToUse = n; - score = 3; + score = Unicode11; } break; case 1: // Apple - if (score < 2 && platformSpecificId == 0) { // Apple Roman + if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman tableToUse = n; - score = 2; + score = AppleRoman; } break; case 3: // Microsoft switch (platformSpecificId) { case 0: - if (score < 1) { + symbolTable = n; + if (score < Symbol) { tableToUse = n; - score = 1; + score = Symbol; } break; case 1: - if (score < 5) { + if (score < MicrosoftUnicode) { tableToUse = n; - score = 5; + score = MicrosoftUnicode; } break; case 0xa: - if (score < 6) { + if (score < MicrosoftUnicodeExtended) { tableToUse = n; - score = 6; + score = MicrosoftUnicodeExtended; } break; default: @@ -999,7 +1011,9 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy } if(tableToUse < 0) return 0; - *isSymbolFont = (score == 1); + +resolveTable: + *isSymbolFont = (score == Symbol); unsigned int unicode_table = qFromBigEndian(maps + 8*tableToUse + 4); @@ -1019,6 +1033,41 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy if (table + unicode_table + length > endPtr) return 0; *cmapSize = length; + + // To support symbol fonts that contain a unicode table for the symbol area + // we check the cmap tables and fall back to symbol font unless that would + // involve losing information from the unicode table + if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) { + const uchar *selectedTable = table + unicode_table; + + // 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) { + unicodeTableHasLatin1 = true; + break; + } + } + + // Check that at least one symbol char is in the unicode table + bool unicodeTableHasSymbols = false; + if (!unicodeTableHasLatin1) { + for (int uc=0xf000; uc<0xf100; ++uc) { + if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + unicodeTableHasSymbols = true; + break; + } + } + } + + // Fall back to symbol table + if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) { + tableToUse = symbolTable; + score = Symbol; + goto resolveTable; + } + } + return table + unicode_table; } -- cgit v0.12