Changeset 222


Ignore:
Timestamp:
Oct 14, 2009, 2:32:13 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Changed to using the Freetype2 library for populating the fonts. Implemented font matching against populated fonts.

Location:
trunk/src/gui/text
Files:
4 edited

Legend:

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

    r220 r222  
    5454#include <locale.h>
    5555#endif
    56 #ifdef Q_WS_PM
    57 #include "qt_os2.h"
    58 #endif
    5956
    6057#include <stdlib.h>
     
    148145                                uint yres = 0, uint avgwidth = 0, bool add = false);
    149146#endif // Q_WS_X11
    150 #ifdef Q_WS_QWS
     147#if
    151148    QByteArray fileName;
    152149    int fileIndex;
    153 #endif
    154 #ifdef Q_WS_PM
    155     unsigned short pointSize; // in deca-points
    156     LONG lMatch;
    157150#endif
    158151};
     
    219212        weightName = setwidthName = 0;
    220213#endif // Q_WS_X11
    221 #if defined(Q_WS_PM)
    222         faceName[0] = 0;
    223 #endif
    224214    }
    225215
     
    234224            free(pixelSizes[count].encodings);
    235225#endif
    236 #ifdef Q_WS_QWS
     226#if
    237227            pixelSizes[count].fileName.~QByteArray();
    238228#endif
     
    252242    const char *setwidthName;
    253243#endif // Q_WS_X11
    254 #ifdef Q_WS_QWS
     244#if
    255245    bool antialiased;
    256246#endif
    257 #ifdef Q_WS_PM
    258     CHAR faceName[FACESIZE];
    259 #endif
    260 
    261 #ifdef Q_WS_PM
    262     QtFontSize *pixelSize(unsigned short size, bool = false,
    263                           unsigned short pointSize = 0);
    264 #else
     247
    265248    QtFontSize *pixelSize(unsigned short size, bool = false);
    266 #endif
    267249};
    268250
     
    280262}
    281263
    282 #ifdef Q_WS_PM
    283 QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add,
    284                                    unsigned short pointSize)
    285 #else
    286264QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
    287 #endif
    288265{
    289266    for (int i = 0; i < count; i++) {
    290 #ifdef Q_WS_PM
    291         if (pixelSizes[i].pixelSize == size &&
    292         (size == SMOOTH_SCALABLE || !pointSize ||
    293          pixelSizes[i].pointSize == pointSize))
    294         return pixelSizes + i;
    295 #else
    296267        if (pixelSizes[i].pixelSize == size)
    297268            return pixelSizes + i;
    298 #endif
    299269    }
    300270    if (!add)
     
    310280    pixelSizes[count].encodings = 0;
    311281#endif
    312 #ifdef Q_WS_QWS
     282#if
    313283    new (&pixelSizes[count].fileName) QByteArray;
    314284    pixelSizes[count].fileIndex = 0;
    315 #endif
    316 #ifdef Q_WS_PM
    317     pixelSizes[count].pointSize = pointSize;
    318     pixelSizes[count].lMatch = 0;
    319285#endif
    320286    return pixelSizes + (count++);
     
    401367    {
    402368        memset(writingSystems, 0, sizeof(writingSystems));
    403 #ifdef Q_WS_PM
    404         // the concept of writing systems isn't used, let's support just Any
    405         writingSystems[QFontDatabase::Any] = Supported;
    406 #endif
    407369    }
    408370    ~QtFontFamily() {
  • trunk/src/gui/text/qfontdatabase_pm.cpp

    r220 r222  
    4646#include "qfontengine_pm_p.h"
    4747
     48
     49
     50
     51
     52
    4853QT_BEGIN_NAMESPACE
    4954
     
    6671    const QString foundryName;
    6772
    68     int hps = qt_display_ps();
    69 
    70     LONG cFonts = 0;
    71     cFonts = GpiQueryFonts(hps, QF_PUBLIC, NULL, &cFonts, 0, NULL);
    72     PFONTMETRICS afm = new FONTMETRICS[cFonts];
    73     GpiQueryFonts(hps, QF_PUBLIC, NULL, &cFonts, sizeof(FONTMETRICS), afm);
    74 
    75     LONG info[2];
    76     DevQueryCaps(GpiQueryDevice(hps), CAPS_HORIZONTAL_FONT_RES, 2, info);
    77     LONG xRes = info[0], yRes = info[1];
    78 
    79     for (PFONTMETRICS fm = afm ; cFonts ; cFonts--, fm++) {
    80         // ignore the default (lMatch = 0) GPI font, since it is always
    81         // present with non-zero lMatch in the list
    82         if (!fm->lMatch)
     73    QList<QByteArray> fontFiles;
     74
     75    ULONG bufSize = 0;
     76    BOOL ok = PrfQueryProfileSize(HINI_USERPROFILE, "PM_Fonts", 0, &bufSize);
     77    Q_ASSERT(ok);
     78    if (ok) {
     79        char *buffer = new char[bufSize + 1 /*terminating NULL*/];
     80        Q_ASSERT(buffer);
     81        if (buffer) {
     82            ULONG bufLen = PrfQueryProfileString(HINI_USERPROFILE, "PM_Fonts", 0, 0,
     83                                                 buffer, bufSize);
     84            if (bufLen) {
     85                char *key = buffer;
     86                while (*key) {
     87                    ULONG keySize = 0;
     88                    ok = PrfQueryProfileSize(HINI_USERPROFILE, "PM_Fonts", key,
     89                                             &keySize);
     90                    if (ok) {
     91                        QByteArray file(keySize, 0);
     92                        ULONG keyLen =
     93                            PrfQueryProfileString(HINI_USERPROFILE, "PM_Fonts", key, 0,
     94                                                  file.data(), file.size());
     95                        file.truncate(keyLen - 1 /*terminating NULL*/);
     96                        if (!file.isEmpty()) {
     97                            // FreeType doesn't understand .OFM but understands .PFB
     98                            if (file.toUpper().endsWith(".OFM")) {
     99                                file.chop(4);
     100                                file.append(".PFB");
     101                            }
     102                            fontFiles << file;
     103                        }
     104                    }
     105                    key += strlen(key) + 1;
     106                }
     107            }
     108            delete buffer;
     109        }
     110    }
     111
     112    extern FT_Library qt_getFreetype(); // qfontengine_ft.cpp
     113    FT_Library lib = qt_getFreetype();
     114
     115    foreach(const QByteArray &file, fontFiles) {
     116        FT_Face face;
     117        FT_Error rc = FT_New_Face(lib, file, -1, &face);
     118
     119        FD_DEBUG("populateDatabase: Font file %s: FT error %d, has %ld faces",
     120                 file.constData(), (int) rc, rc ? -1 : face->num_faces);
     121        if (rc != 0)
    83122            continue;
    84123
    85         QString familyName = QString::fromLocal8Bit(fm->szFamilyname);
    86         bool italic = fm->fsSelection & FM_SEL_ITALIC;
    87         bool fixed = fm->fsType & FM_TYPE_FIXED;
    88         bool scalable = fm->fsDefn & FM_DEFN_OUTLINE;
    89         USHORT weight = fm->usWeightClass;
    90         USHORT width = fm->usWidthClass;
    91 
    92         // ignore bitmap fonts that do not match the current device resolution
    93         if (!scalable && (fm->sXDeviceRes != xRes || fm->sYDeviceRes != yRes))
    94             continue;
    95 
    96         // the "@family" fonts are just the same as "family". Ignore them.
    97         if (familyName[0] == '@')
    98             continue;
    99 
    100         QtFontStyle::Key styleKey;
    101         styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
    102 
    103         if (weight < 4)
    104             styleKey.weight = QFont::Light;
    105         else if (weight < 6)
    106             styleKey.weight = QFont::Normal;
    107         else if (weight < 7)
    108             styleKey.weight = QFont::DemiBold;
    109         else if (weight < 8)
    110             styleKey.weight = QFont::Bold;
    111         else
    112             styleKey.weight = QFont::Black;
    113 
    114         switch (width) {
    115             case 1: styleKey.stretch = QFont::UltraCondensed; break;
    116             case 2: styleKey.stretch = QFont::ExtraCondensed; break;
    117             case 3: styleKey.stretch = QFont::Condensed; break;
    118             case 4: styleKey.stretch = QFont::SemiCondensed; break;
    119             case 5: styleKey.stretch = QFont::Unstretched; break;
    120             case 6: styleKey.stretch = QFont::SemiExpanded; break;
    121             case 7: styleKey.stretch = QFont::Expanded; break;
    122             case 8: styleKey.stretch = QFont::ExtraExpanded; break;
    123             case 9: styleKey.stretch = QFont::UltraExpanded; break;
    124             default: styleKey.stretch = QFont::Unstretched; break;
    125         }
    126 
    127         // @todo why?
    128         familyName.replace('-', ' ');
    129 
    130         QtFontFamily *family = privateDb()->family(familyName, true);
    131         // @todo is it possible that the same family is both fixed and not?
    132         family->fixedPitch = fixed;
    133 
    134         QtFontFoundry *foundry = family->foundry(foundryName, true);
    135         QtFontStyle *style = foundry->style(styleKey, true);
    136 
    137         // add new scalable style only if it hasn't been already added --
    138         // the first one of two duplicate (in Qt terms) non-bitmap font
    139         // styles wins.
    140         if (scalable && style->smoothScalable)
    141             continue;
    142 
    143         if (style->faceName[0]) {
    144             // if a duplicate (having the same style in Qt terms) bitmap
    145             // font is encountered but it has the different facename, ignore
    146             // it (we have only one facename field per style -- it should be
    147             // the same for all sizes otherwise we will not be able to create
    148             // a font with some sizes later).
    149             if (strcmp(style->faceName, fm->szFacename))
     124        FT_Long numFaces = face->num_faces;
     125        FT_Done_Face(face);
     126
     127        // go throuhg each face
     128        for (FT_Long idx = 0; idx < numFaces; ++idx) {
     129            rc = FT_New_Face(lib, file, idx, &face);
     130            if (rc != 0)
    150131                continue;
    151         } else {
    152             strcpy(style->faceName, fm->szFacename);
    153         }
    154 
    155         if (scalable) {
    156             style->smoothScalable = TRUE;
    157             QtFontSize *size =
    158                 style->pixelSize(SMOOTH_SCALABLE, TRUE, fm->sNominalPointSize);
    159             size->lMatch = fm->lMatch;
    160         } else {
    161             QtFontSize *size =
    162                 style->pixelSize(fm->lEmHeight, TRUE, fm->sNominalPointSize);
    163             // the first bitmap style with a given pixel and point size wins
    164             if (size->lMatch)
    165                 continue;
    166             size->lMatch = fm->lMatch;
    167         }
    168     }
    169 
    170     delete[] afm;
     132
     133            QString familyName = QString::fromLatin1(face->family_name);
     134
     135            QtFontStyle::Key styleKey;
     136
     137            styleKey.style = face->style_flags & FT_STYLE_FLAG_ITALIC ?
     138                QFont::StyleItalic : QFont::StyleNormal;
     139
     140            TT_OS2 *os2_table = 0;
     141            if (face->face_flags & FT_FACE_FLAG_SFNT) {
     142                os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
     143            }
     144            if (os2_table) {
     145                // map weight and width values
     146                if (os2_table->usWeightClass < 400)
     147                    styleKey.weight = QFont::Light;
     148                else if (os2_table->usWeightClass < 600)
     149                    styleKey.weight = QFont::Normal;
     150                else if (os2_table->usWeightClass < 700)
     151                    styleKey.weight = QFont::DemiBold;
     152                else if (os2_table->usWeightClass < 800)
     153                    styleKey.weight = QFont::Bold;
     154                else
     155                    styleKey.weight = QFont::Black;
     156
     157                switch (os2_table->usWidthClass) {
     158                    case 1: styleKey.stretch = QFont::UltraCondensed; break;
     159                    case 2: styleKey.stretch = QFont::ExtraCondensed; break;
     160                    case 3: styleKey.stretch = QFont::Condensed; break;
     161                    case 4: styleKey.stretch = QFont::SemiCondensed; break;
     162                    case 5: styleKey.stretch = QFont::Unstretched; break;
     163                    case 6: styleKey.stretch = QFont::SemiExpanded; break;
     164                    case 7: styleKey.stretch = QFont::Expanded; break;
     165                    case 8: styleKey.stretch = QFont::ExtraExpanded; break;
     166                    case 9: styleKey.stretch = QFont::UltraExpanded; break;
     167                    default: styleKey.stretch = QFont::Unstretched; break;
     168                }
     169            } else {
     170                // we've only got simple weight information and no stretch
     171                styleKey.weight = face->style_flags & FT_STYLE_FLAG_BOLD ?
     172                    QFont::Bold : QFont::Normal;
     173                styleKey.stretch = QFont::Unstretched;
     174            }
     175
     176            QtFontFamily *family = privateDb()->family(familyName, true);
     177
     178            // @todo is it possible that the same family is both fixed and not?
     179            Q_ASSERT(!family->fixedPitch || face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
     180            family->fixedPitch = face->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
     181
     182            // writing systems aren't used ATM, let's support just Any
     183            family->writingSystems[QFontDatabase::Any] = QtFontFamily::Supported;
     184
     185            QtFontFoundry *foundry = family->foundry(foundryName, true);
     186            QtFontStyle *style = foundry->style(styleKey, true);
     187
     188            // so far, all recognized fonts are antialiased
     189            style->antialiased = true;
     190
     191            if ((face->face_flags & FT_FACE_FLAG_SCALABLE) &&
     192                !style->smoothScalable) {
     193                // add new scalable style only if it hasn't been already added --
     194                // the first one of two duplicate (in Qt terms) non-bitmap font
     195                // styles wins.
     196                style->smoothScalable = true;
     197                QtFontSize *size =
     198                    style->pixelSize(SMOOTH_SCALABLE, true);
     199                size->fileName = file;
     200                size->fileIndex = idx;
     201            }
     202
     203            // the font may both be scalable and contain fixed size bitmaps
     204            if (face->face_flags & FT_FACE_FLAG_FIXED_SIZES) {
     205                for (FT_Int i = 0; i < face->num_fixed_sizes; ++i) {
     206                    QtFontSize *size =
     207                        style->pixelSize(face->available_sizes[i].height, true);
     208                    // the first bitmap style with a given pixel and point size wins
     209                    if (!size->fileName.isEmpty())
     210                        continue;
     211                    size->fileName = file;
     212                    size->fileIndex = idx;
     213                }
     214            }
     215
     216            FT_Done_Face(face);
     217        }
     218    }
    171219}
    172220
     
    181229#ifdef QFONTDATABASE_DEBUG
    182230    // print the database
     231
    183232    for (int f = 0; f < db->count; f++) {
    184233        QtFontFamily *family = db->families[f];
    185234        qDebug("    %s: %p", qPrintable(family->name), family);
    186235        populateDatabase(family->name);
    187 
    188236#if 1
    189237        qDebug("        scripts supported:");
     
    193241        for (int fd = 0; fd < family->count; fd++) {
    194242            QtFontFoundry *foundry = family->foundries[fd];
    195             qDebug("        %s", qPrintable(foundry->name));
     243            qDebug("        %s", foundry->name.isEmpty() ? "(empty foundry)" :
     244                   qPrintable(foundry->name));
    196245            for (int s = 0; s < foundry->count; s++) {
    197246                QtFontStyle *style = foundry->styles[s];
    198247                qDebug("            style: style=%d weight=%d smooth=%d",  style->key.style,
    199248                       style->key.weight, style->smoothScalable);
    200                 if(!style->smoothScalable) {
    201                     for(int i = 0; i < style->count; ++i) {
    202                         qDebug("                %d", style->pixelSizes[i].pixelSize);
    203                     }
     249                for(int i = 0; i < style->count; ++i) {
     250                    if (style->pixelSizes[i].pixelSize == SMOOTH_SCALABLE)
     251                        qDebug("                smooth %s:%d",
     252                               style->pixelSizes[i].fileName.constData(),
     253                               style->pixelSizes[i].fileIndex);
     254                    else
     255                        qDebug("                %d px %s:%d", style->pixelSizes[i].pixelSize,
     256                               style->pixelSizes[i].fileName.constData(),
     257                               style->pixelSizes[i].fileIndex);
    204258                }
    205259            }
     
    220274}
    221275
     276
     277
     278
     279
     280
     281
     282
     283
     284
     285
     286
     287
     288
     289
     290
     291
     292
     293
     294
     295
     296
     297
     298
     299
     300
     301
     302
     303
     304
     305
     306
     307
     308
     309
     310
     311
     312
     313
     314
     315
     316
     317
     318
     319
     320
     321
     322
     323
     324
     325
     326
     327
     328
     329
     330
     331
     332
     333
     334
     335
     336
     337
     338
     339
     340
     341
     342
     343
     344
     345
     346
     347
     348
     349
     350
     351
     352
     353
     354
     355
    222356static QFontEngine *loadPM(const QFontPrivate *d, int script, const QFontDef &req)
    223357{
    224     // @todo initializeDb() and stuff, get the engine
    225     QFontDef fd = req;
    226     QFontEngine *fe = new QFontEnginePMFT(fd);
     358    // list of families to try
     359    QStringList families = familyList(req);
     360
     361    const char *stylehint = styleHint(d->request);
     362    if (stylehint)
     363        families << QLatin1String(stylehint);
     364
     365    // add the default family
     366    QString defaultFamily = QApplication::font().family();
     367    if (! families.contains(defaultFamily))
     368        families << defaultFamily;
     369
     370    // add QFont::defaultFamily() to the list, for compatibility with
     371    // previous versions
     372    families << QApplication::font().defaultFamily();
     373
     374    // null family means find the first font matching the specified script
     375    families << QString();
     376
     377    QtFontDesc desc;
     378    QFontEngine *fe = 0;
     379    QList<int> blacklistedFamilies;
     380
     381    while (!fe) {
     382        for (int i = 0; i < families.size(); ++i) {
     383            QString family, foundry;
     384            parseFontName(families.at(i), foundry, family);
     385            FM_DEBUG("loadPM: >>>>>>>>>>>>>> trying to match '%s'", qPrintable(family));
     386            QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies);
     387            if (desc.family)
     388                break;
     389        }
     390        if (!desc.family)
     391            break;
     392        fe = loadEngine(req, desc);
     393        if (!fe)
     394            blacklistedFamilies.append(desc.familyIndex);
     395    }
    227396    return fe;
    228397}
  • trunk/src/gui/text/qfontengine_pm.cpp

    r219 r222  
    5858    : QFontEngineFT(fd)
    5959{
    60     QFontEngine::FaceId face_id;
    61     // @todo temporary:
    62     ULONG bootDrive = 0;
    63     DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&bootDrive,
    64                     sizeof(bootDrive));
    65     QByteArray font(1, bootDrive + 'A' - 1);
    66     font += ":\\PSFONTS\\HELV.PFB";
    67 
    68     face_id.filename = font;
    69     face_id.index = 0;
    70 
    71     init(face_id, true /*antialias*/);
    7260}
    7361
  • trunk/src/gui/text/qfontengine_pm_p.h

    r125 r222  
    6868#ifndef QT_NO_FREETYPE
    6969
    70 class QFreetypeFace;
    71 
    7270class Q_GUI_EXPORT QFontEnginePMFT : public QFontEngineFT
    7371{
Note: See TracChangeset for help on using the changeset viewer.