Ignore:
Timestamp:
Dec 2, 2009, 2:27:41 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Improved font handling (patch by komh):

  • Read national face names from font files instead of always taking the Latin name.
  • Use the PM_AssociateFont registry key to select a fallback font for missing glyphs (important on DBCS systems).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/text/qfontdatabase_pm.cpp

    r319 r371  
    4242****************************************************************************/
    4343
     44#include "qfontengine_pm_p.h"
     45
    4446#include "qabstractfileengine.h"
    45 
    46 #include "qfontengine_pm_p.h"
    47 
    4847#include "qsettings.h"
    4948#include "qfileinfo.h"
    5049#include "qdatetime.h"
    5150#include "qhash.h"
     51#include "qtextcodec.h"
    5252
    5353#include <ft2build.h>
     
    5656#include FT_TRUETYPE_TABLES_H
    5757#include FT_LCD_FILTER_H
     58#include FT_SFNT_NAMES_H
     59#include FT_TRUETYPE_IDS_H
    5860
    5961QT_BEGIN_NAMESPACE
     
    119121static FontFileHash knownFontFiles;
    120122static bool knownFontFilesInitialized = false;
     123
     124static bool lookupFamilyName(FT_Face ftface, QString &familyName)
     125{
     126    FT_UInt     nNameCount;
     127    FT_UInt     i;
     128    FT_SfntName sfntName;
     129    FT_UInt     found, best;
     130
     131    nNameCount = FT_Get_Sfnt_Name_Count(ftface);
     132
     133    if (nNameCount == 0)
     134        return false;
     135
     136#ifndef QT_NO_TEXTCODEC
     137    QTextCodec *codec = QTextCodec::codecForName("UTF-16BE");
     138
     139    // find a unicode name at first
     140    if (codec) {
     141        found = (FT_UInt)-1;
     142        best  = (FT_UInt)-1;
     143
     144        // try to find the unicode name matching to the locale
     145        for (i = 0; found == (FT_UInt)-1 && i < nNameCount; i++) {
     146            FT_Get_Sfnt_Name(ftface, i, &sfntName);
     147
     148            if (sfntName.name_id     == TT_NAME_ID_FONT_FAMILY &&
     149                sfntName.platform_id == TT_PLATFORM_MICROSOFT &&
     150                sfntName.encoding_id == TT_MS_ID_UNICODE_CS) {
     151                if (best == (FT_UInt)-1 || sfntName.language_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)
     152                    best = i;
     153
     154                QLocale sysLocale = QLocale::system();
     155                switch (sfntName.language_id) {
     156                    case TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA :
     157                        if (sysLocale.language() == QLocale::Korean)
     158                            found = i;
     159                        break;
     160
     161                    case TT_MS_LANGID_JAPANESE_JAPAN :
     162                        if (sysLocale.language() == QLocale::Japanese)
     163                            found = i;
     164                        break;
     165
     166                    case TT_MS_LANGID_CHINESE_PRC :
     167                        if (sysLocale.country() == QLocale::China &&
     168                            sysLocale.language() == QLocale::Chinese)
     169                            found = i;
     170                        break;
     171
     172                    case TT_MS_LANGID_CHINESE_TAIWAN :
     173                        if (sysLocale.country() == QLocale::Taiwan &&
     174                            sysLocale.language() == QLocale::Chinese)
     175                            found = i;
     176                        break;
     177                }
     178            }
     179        }
     180
     181        if (found == (FT_UInt)-1)
     182            found = best;
     183
     184        if (found != (FT_UInt)-1) {
     185            FT_Get_Sfnt_Name(ftface, found, &sfntName);
     186
     187            familyName = codec->toUnicode((const char *)sfntName.string, sfntName.string_len);
     188
     189            return true;
     190        }
     191    }
     192#endif
     193
     194    found = (FT_UInt)-1;
     195    best  = (FT_UInt)-1;
     196
     197    // unicode name is not available, try the NLS encoded name
     198    for (i = 0; found == (FT_UInt)-1 && i < nNameCount; i++) {
     199        FT_Get_Sfnt_Name(ftface, i, &sfntName);
     200
     201        if (sfntName.name_id     == TT_NAME_ID_FONT_FAMILY &&
     202            sfntName.platform_id == TT_PLATFORM_MICROSOFT) {
     203            if (best == (FT_UInt)-1)
     204                best = i;
     205
     206            QLocale sysLocale = QLocale::system();
     207            switch (sfntName.encoding_id) {
     208                case TT_MS_ID_WANSUNG :
     209                    if (sysLocale.language() == QLocale::Korean)
     210                        found = i;
     211                    break;
     212
     213                case TT_MS_ID_SJIS :
     214                    if (sysLocale.language() == QLocale::Japanese)
     215                        found = i;
     216                    break;
     217
     218                case TT_MS_ID_BIG_5 :
     219                    if (sysLocale.country() == QLocale::Taiwan &&
     220                        sysLocale.language() == QLocale::Chinese)
     221                        found = i;
     222                    break;
     223
     224                case TT_MS_ID_GB2312 :
     225                    if (sysLocale.country() == QLocale::China &&
     226                        sysLocale.language() == QLocale::Chinese)
     227                        found = i;
     228                    break;
     229
     230                case TT_MS_ID_SYMBOL_CS :
     231                    found = i;
     232                    break;
     233            }
     234        }
     235    }
     236
     237    if (found == (FT_UInt)-1)
     238        found = best;
     239
     240    if (found != (FT_UInt)-1)
     241    {
     242        char   *name;
     243        FT_UInt name_len = 0;
     244
     245        FT_Get_Sfnt_Name(ftface, found, &sfntName);
     246
     247        name = (char *)alloca(sfntName.string_len);
     248
     249        for (FT_UInt j = 0; j < sfntName.string_len; j++)
     250            if (sfntName.string[j])
     251                name[name_len++] = sfntName.string[j];
     252
     253#ifndef QT_NO_TEXTCODEC
     254        switch (sfntName.encoding_id) {
     255            case TT_MS_ID_WANSUNG :
     256                codec = QTextCodec::codecForName("cp949");
     257                break;
     258
     259            case TT_MS_ID_SJIS :
     260                codec = QTextCodec::codecForName("SJIS");
     261                break;
     262
     263            case TT_MS_ID_BIG_5 :
     264                codec = QTextCodec::codecForName("Big5");
     265                break;
     266
     267            case TT_MS_ID_GB2312 :
     268                codec = QTextCodec::codecForName("GB2312");
     269                break;
     270
     271            case TT_MS_ID_SYMBOL_CS :
     272            default :
     273                codec = NULL;
     274                break;
     275        }
     276
     277        if (codec)
     278            familyName = codec->toUnicode(name, name_len);
     279        else
     280#endif
     281            familyName = QString::fromLocal8Bit(name, name_len);
     282
     283        return true;
     284    }
     285
     286    return false;
     287}
    121288
    122289static void populateDatabase(const QString& fam)
     
    270437
    271438                cached.index = idx;
    272                 cached.familyName = QString::fromLatin1(face->family_name);
     439
     440                if (!lookupFamilyName(face, cached.familyName))
     441                    cached.familyName = QString::fromLocal8Bit(face->family_name);
    273442
    274443                // familyName may contain extra spaces (at least this is true for
Note: See TracChangeset for help on using the changeset viewer.