Changeset 222 for trunk/src/gui/text/qfontdatabase_pm.cpp
- Timestamp:
- Oct 14, 2009, 2:32:13 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/text/qfontdatabase_pm.cpp
r220 r222 46 46 #include "qfontengine_pm_p.h" 47 47 48 #include <ft2build.h> 49 #include FT_FREETYPE_H 50 #include FT_TYPES_H 51 #include FT_TRUETYPE_TABLES_H 52 48 53 QT_BEGIN_NAMESPACE 49 54 … … 66 71 const QString foundryName; 67 72 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) 83 122 continue; 84 123 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) 150 131 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 } 171 219 } 172 220 … … 181 229 #ifdef QFONTDATABASE_DEBUG 182 230 // print the database 231 qDebug("initializeDb:"); 183 232 for (int f = 0; f < db->count; f++) { 184 233 QtFontFamily *family = db->families[f]; 185 234 qDebug(" %s: %p", qPrintable(family->name), family); 186 235 populateDatabase(family->name); 187 188 236 #if 1 189 237 qDebug(" scripts supported:"); … … 193 241 for (int fd = 0; fd < family->count; fd++) { 194 242 QtFontFoundry *foundry = family->foundries[fd]; 195 qDebug(" %s", qPrintable(foundry->name)); 243 qDebug(" %s", foundry->name.isEmpty() ? "(empty foundry)" : 244 qPrintable(foundry->name)); 196 245 for (int s = 0; s < foundry->count; s++) { 197 246 QtFontStyle *style = foundry->styles[s]; 198 247 qDebug(" style: style=%d weight=%d smooth=%d", style->key.style, 199 248 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); 204 258 } 205 259 } … … 220 274 } 221 275 276 static const char *styleHint(const QFontDef &request) 277 { 278 const char *stylehint = 0; 279 switch (request.styleHint) { 280 case QFont::SansSerif: 281 stylehint = "Helvetica"; 282 break; 283 case QFont::Serif: 284 stylehint = "Roman"; 285 break; 286 case QFont::TypeWriter: 287 stylehint = "Courier"; 288 break; 289 default: 290 if (request.fixedPitch) 291 stylehint = "Courier"; 292 else 293 stylehint = "Helvetica"; 294 break; 295 } 296 return stylehint; 297 } 298 299 static QFontDef fontDescToFontDef(const QFontDef &req, const QtFontDesc &desc) 300 { 301 static LONG dpi = -1; 302 if (dpi == -1) { 303 // PM cannot change resolutions on the fly so cache it 304 int hps = qt_display_ps(); 305 DevQueryCaps(GpiQueryDevice(hps), CAPS_HORIZONTAL_FONT_RES, 1, &dpi); 306 } 307 308 QFontDef fontDef; 309 310 fontDef.family = desc.family->name; 311 312 if (desc.size->pixelSize == SMOOTH_SCALABLE) { 313 // scalable font matched, calculate the missing size (points or pixels) 314 fontDef.pointSize = req.pointSize; 315 fontDef.pixelSize = req.pixelSize; 316 if (req.pointSize < 0) { 317 fontDef.pointSize = req.pixelSize * 72. / dpi; 318 } else if (req.pixelSize == -1) { 319 fontDef.pixelSize = qRound(req.pointSize * dpi / 72.); 320 } 321 } else { 322 // non-scalable font matched, calculate both point and pixel size 323 fontDef.pixelSize = desc.size->pixelSize; 324 fontDef.pointSize = desc.size->pixelSize * 72. / dpi; 325 } 326 327 fontDef.styleStrategy = req.styleStrategy; 328 fontDef.styleHint = req.styleHint; 329 330 fontDef.weight = desc.style->key.weight; 331 fontDef.fixedPitch = desc.family->fixedPitch; 332 fontDef.style = desc.style->key.style; 333 fontDef.stretch = desc.style->key.stretch; 334 335 return fontDef; 336 } 337 338 static QFontEngine *loadEngine(const QFontDef &req, const QtFontDesc &desc) 339 { 340 QFontEngineFT *fe = new QFontEnginePMFT(fontDescToFontDef(req, desc)); 341 Q_ASSERT(fe); 342 if (fe) { 343 QFontEngine::FaceId faceId; 344 faceId.filename = desc.size->fileName; 345 faceId.index = desc.size->fileIndex; 346 fe->init(faceId, desc.style->antialiased); 347 if (fe->invalid()) { 348 FM_DEBUG(" --> invalid!\n"); 349 delete fe; 350 fe = 0; 351 } 352 } 353 return fe; 354 } 355 222 356 static QFontEngine *loadPM(const QFontPrivate *d, int script, const QFontDef &req) 223 357 { 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 } 227 396 return fe; 228 397 }
Note:
See TracChangeset
for help on using the changeset viewer.