Changeset 500 for trunk/src/gui/text
- Timestamp:
- Feb 2, 2010, 10:46:30 PM (15 years ago)
- Location:
- trunk/src/gui/text
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/text/qfontdatabase.cpp
r318 r500 582 582 : count(0), families(0), reregisterAppFonts(false) 583 583 #if defined(Q_WS_QWS) 584 , stream(0) 584 , stream(0) 585 #endif 586 #if defined(Q_WS_PM) 587 , valid(false) 585 588 #endif 586 589 { } … … 634 637 QStringList fallbackFamilies; 635 638 #endif 639 640 641 642 636 643 }; 637 644 … … 640 647 QFontCache::instance()->clear(); 641 648 free(); 649 650 651 642 652 emit static_cast<QApplication *>(QApplication::instance())->fontDatabaseChanged(); 643 653 } -
trunk/src/gui/text/qfontdatabase_pm.cpp
r423 r500 61 61 QT_BEGIN_NAMESPACE 62 62 63 64 63 65 struct FaceData 64 66 { 67 65 68 int index; 66 69 QString familyName; … … 120 123 typedef QHash<QString, FileData> FontFileHash; 121 124 static FontFileHash knownFontFiles; 122 static bool knownFontFilesInitialized = false;123 125 124 126 static bool lookupFamilyName(FT_Face ftface, QString &familyName) … … 287 289 } 288 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 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 289 407 static void populateDatabase(const QString& fam) 290 408 { … … 313 431 fontCache.beginGroup(QLatin1String("Qt/Fonts/Cache 1.0")); 314 432 315 if (!knownFontFilesInitialized) { 316 // get the initial list of know font files from the cache (necessary to 317 // detect deleted font files) 318 knownFontFilesInitialized = true; 433 if (!db->valid) { 434 // Obtain the initial list of known font files from the font cache in 435 // the registry. This list is used as an in-process cache which speeds 436 // speed up populating by eliminating the need to access the registry 437 // each time an unknown family is requested. This list is also necessary 438 // to detect deleted font files. 439 FD_DEBUG("populateDatabase: INVALID, getting font list from the cache"); 440 db->valid = true; 441 knownFontFiles.clear(); 319 442 QStringList files = fontCache.childGroups(); 320 443 foreach(QString file, files) { … … 333 456 QList<QFileInfo> fontFiles; 334 457 458 335 459 ULONG bufSize = 0; 336 460 BOOL ok = PrfQueryProfileSize(HINI_USERPROFILE, "PM_Fonts", 0, &bufSize); … … 360 484 file.append(".PFB"); 361 485 } 362 QFileInfo fileInfo(QFile::decodeName(file)); 363 QString fileName = fileInfo.canonicalFilePath().toLower(); 364 if (!fileName.isEmpty()) { // file may have been deleted 365 fileInfo.setFile(fileName); 366 // check the in-process file name cache 367 FileData &cached = knownFontFiles[fileName]; 368 if (cached.fileInfo.filePath().isEmpty() || 369 cached.fileInfo.lastModified() != fileInfo.lastModified() || 370 cached.fileInfo.size() != fileInfo.size()) { 371 // no cache entry or outdated, process it 372 cached.fileInfo = fileInfo; 373 cached.seen = true; 374 fontFiles << fileInfo; 375 FD_DEBUG("populateDatabase: NEW/UPDATED font file %s", 376 qPrintable(fileName)); 377 } else { 378 // just set the 'seen' flag and skip this font 379 // (it's already in the database) 380 knownFontFiles[fileName].seen = true; 381 FD_DEBUG("populateDatabase: UNCHANGED font file %s", 382 qPrintable(fileName)); 383 } 384 } 486 fontFiles << QFileInfo(QFile::decodeName(file)); 385 487 } 386 488 } … … 392 494 } 393 495 394 extern FT_Library qt_getFreetype(); // qfontengine_ft.cpp 496 // add the application-defined fonts (only file-based) 497 foreach(const QFontDatabasePrivate::ApplicationFont &font, db->applicationFonts) { 498 if (!font.fileName.startsWith(QLatin1String(":qmemoryfonts/"))) 499 fontFiles << QFileInfo(font.fileName); 500 } 501 502 // go through each font file and check if we have a valid cahce for it 503 for (QList<QFileInfo>::iterator it = fontFiles.begin(); it != fontFiles.end();) { 504 QFileInfo fileInfo = *it; 505 QString fileName = fileInfo.canonicalFilePath().toLower(); 506 if (!fileName.isEmpty()) { // file may have been deleted 507 fileInfo.setFile(fileName); 508 // check the in-process file name cache 509 FileData &cached = knownFontFiles[fileName]; 510 if (cached.fileInfo.filePath().isEmpty() || 511 cached.fileInfo.lastModified() != fileInfo.lastModified() || 512 cached.fileInfo.size() != fileInfo.size()) { 513 // no cache entry or outdated 514 FD_DEBUG("populateDatabase: NEW/UPDATED font file %s", 515 qPrintable(fileName)); 516 cached.fileInfo = fileInfo; 517 cached.seen = true; 518 // keep it in the list for further inspection 519 ++it; 520 continue; 521 } else { 522 // just set the 'seen' flag and skip this font 523 // (it's already in the database) 524 FD_DEBUG("populateDatabase: UNCHANGED font file %s", 525 qPrintable(fileName)); 526 cached.seen = true; 527 } 528 } 529 // remove from the list, nothing to do with it 530 it = fontFiles.erase(it); 531 } 532 395 533 FT_Library lib = qt_getFreetype(); 396 534 397 // go through each font file and get available faces 535 QList<FaceData> foundFaces; 536 537 // go through each new/outdated font file and get available faces 398 538 foreach(const QFileInfo &fileInfo, fontFiles) { 399 QString fileKey = fileInfo. absoluteFilePath().toLower();539 QString fileKey = fileInfo.FilePath().toLower(); 400 540 QByteArray file = QFile::encodeName(fileKey); 401 541 … … 411 551 fontCache.value(QLatin1String("Size")).toUInt() != fileInfo.size()) { 412 552 // the cache is outdated or doesn't exist, query the font file 413 414 FT_Long numFaces = 0; 415 FT_Face face; 416 417 FT_Error rc = FT_New_Face(lib, file, -1, &face); 418 if (rc == 0) { 419 numFaces = face->num_faces; 420 FT_Done_Face(face); 421 } else { 422 // invalid/unsupported font file, numFaces is left 0 so that 423 // only DateTime and Size will be cached indicating that this 424 // file is not recognized 425 } 426 427 FD_DEBUG("populateDatabase: Font file %s: FT error %d, has %ld faces", 428 file.constData(), (int) rc, numFaces); 429 430 // go throuhg each face 431 for (FT_Long idx = 0; idx < numFaces; ++idx) { 432 rc = FT_New_Face(lib, file, idx, &face); 433 if (rc != 0) 434 continue; 435 436 FaceData cached; 437 438 cached.index = idx; 439 440 if (!lookupFamilyName(face, cached.familyName)) 441 cached.familyName = QString::fromLocal8Bit(face->family_name); 442 443 // familyName may contain extra spaces (at least this is true for 444 // TNR.PFB that is reported as "Times New Roman ". Trim them. 445 cached.familyName = cached.familyName.trimmed(); 446 447 cached.styleKey.style = face->style_flags & FT_STYLE_FLAG_ITALIC ? 448 QFont::StyleItalic : QFont::StyleNormal; 449 450 TT_OS2 *os2_table = 0; 451 if (face->face_flags & FT_FACE_FLAG_SFNT) { 452 os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); 453 } 454 if (os2_table) { 455 // map weight and width values 456 if (os2_table->usWeightClass < 400) 457 cached.styleKey.weight = QFont::Light; 458 else if (os2_table->usWeightClass < 600) 459 cached.styleKey.weight = QFont::Normal; 460 else if (os2_table->usWeightClass < 700) 461 cached.styleKey.weight = QFont::DemiBold; 462 else if (os2_table->usWeightClass < 800) 463 cached.styleKey.weight = QFont::Bold; 464 else 465 cached.styleKey.weight = QFont::Black; 466 467 switch (os2_table->usWidthClass) { 468 case 1: cached.styleKey.stretch = QFont::UltraCondensed; break; 469 case 2: cached.styleKey.stretch = QFont::ExtraCondensed; break; 470 case 3: cached.styleKey.stretch = QFont::Condensed; break; 471 case 4: cached.styleKey.stretch = QFont::SemiCondensed; break; 472 case 5: cached.styleKey.stretch = QFont::Unstretched; break; 473 case 6: cached.styleKey.stretch = QFont::SemiExpanded; break; 474 case 7: cached.styleKey.stretch = QFont::Expanded; break; 475 case 8: cached.styleKey.stretch = QFont::ExtraExpanded; break; 476 case 9: cached.styleKey.stretch = QFont::UltraExpanded; break; 477 default: cached.styleKey.stretch = QFont::Unstretched; break; 478 } 479 480 quint32 unicodeRange[4] = { 481 os2_table->ulUnicodeRange1, os2_table->ulUnicodeRange2, 482 os2_table->ulUnicodeRange3, os2_table->ulUnicodeRange4 483 }; 484 quint32 codePageRange[2] = { 485 os2_table->ulCodePageRange1, os2_table->ulCodePageRange2 486 }; 487 cached.systems = 488 determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); 489 } else { 490 // we've only got simple weight information and no stretch 491 cached.styleKey.weight = face->style_flags & FT_STYLE_FLAG_BOLD ? 492 QFont::Bold : QFont::Normal; 493 cached.styleKey.stretch = QFont::Unstretched; 494 } 495 496 cached.fixedPitch = face->face_flags & FT_FACE_FLAG_FIXED_WIDTH; 497 498 cached.smoothScalable = face->face_flags & FT_FACE_FLAG_SCALABLE; 499 500 // the font may both be scalable and contain fixed size bitmaps 501 if (face->face_flags & FT_FACE_FLAG_FIXED_SIZES) { 502 for (FT_Int i = 0; i < face->num_fixed_sizes; ++i) { 503 cached.pixelSizes << face->available_sizes[i].height; 504 } 505 } 506 507 cachedFaces << cached; 508 509 FT_Done_Face(face); 510 } 553 cachedFaces = readFreeTypeFont(lib, file); 511 554 512 555 // store the data into the cache 513 556 fontCache.setValue(QLatin1String("DateTime"), fileInfo.lastModified()); 514 557 fontCache.setValue(QLatin1String("Size"), fileInfo.size()); 558 559 560 561 515 562 foreach(FaceData cached, cachedFaces) { 516 563 QByteArray rawData; … … 525 572 } else { 526 573 // take the face data from the cache 527 528 574 QStringList faces = fontCache.childGroups(); 529 575 … … 534 580 bool ok = false; 535 581 FaceData cached; 582 536 583 cached.index = face.toInt(&ok); 537 584 if (!ok || cached.index < 0) // not a valid index … … 549 596 } 550 597 598 599 551 600 fontCache.endGroup(); 552 553 // go throuhg each cached face and add it to the database 554 foreach(FaceData cached, cachedFaces) { 555 556 QtFontFamily *family = privateDb()->family(cached.familyName, true); 557 558 // @todo is it possible that the same family is both fixed and not? 559 Q_ASSERT(!family->fixedPitch || cached.fixedPitch); 560 family->fixedPitch = cached.fixedPitch; 561 562 if (cached.systems.isEmpty()) { 563 // it was hard or impossible to determine the actual writing system 564 // of the font (as in case of OS/2 bitmap and PFB fonts for which it is 565 // usually simply reported that they support standard/system codepages). 566 // Pretend that we support all writing systems to not miss the one. 567 // 568 // @todo find a proper way to detect actual supported scripts to make 569 // sure these fonts are not matched for scripts they don't support. 570 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws) 571 family->writingSystems[ws] = QtFontFamily::Supported; 572 } else { 573 for (int i = 0; i < cached.systems.count(); ++i) 574 family->writingSystems[cached.systems.at(i)] = QtFontFamily::Supported; 575 } 576 577 QtFontFoundry *foundry = family->foundry(foundryName, true); 578 QtFontStyle *style = foundry->style(cached.styleKey, true); 579 580 // so far, all recognized fonts are antialiased 581 style->antialiased = true; 582 583 if (cached.smoothScalable && !style->smoothScalable) { 584 // add new scalable style only if it hasn't been already added -- 585 // the first one of two duplicate (in Qt terms) non-bitmap font 586 // styles wins. 587 style->smoothScalable = true; 588 QtFontSize *size = 589 style->pixelSize(SMOOTH_SCALABLE, true); 590 size->fileName = file; 591 size->fileIndex = cached.index; 592 size->systems = cached.systems; 593 } 594 595 foreach(unsigned short pixelSize, cached.pixelSizes) { 596 QtFontSize *size = style->pixelSize(pixelSize, true); 597 // the first bitmap style with a given pixel and point size wins 598 if (!size->fileName.isEmpty()) 599 continue; 600 size->fileName = file; 601 size->fileIndex = cached.index; 602 size->systems = cached.systems; 603 } 601 } 602 603 // get available faces of the application-defined fonts (memory-based) 604 foreach(const QFontDatabasePrivate::ApplicationFont &font, db->applicationFonts) { 605 if (font.fileName.startsWith(QLatin1String(":qmemoryfonts/"))) { 606 QList<FaceData> faces = readFreeTypeFont(lib, font.fileName.toLatin1(), 607 &font.data); 608 foundFaces << faces; 609 } 610 } 611 612 // go throuhg each found face and add it to the database 613 foreach(const FaceData &face, foundFaces) { 614 615 QtFontFamily *family = privateDb()->family(face.familyName, true); 616 617 // @todo is it possible that the same family is both fixed and not? 618 Q_ASSERT(!family->fixedPitch || face.fixedPitch); 619 family->fixedPitch = face.fixedPitch; 620 621 if (face.systems.isEmpty()) { 622 // it was hard or impossible to determine the actual writing system 623 // of the font (as in case of OS/2 bitmap and PFB fonts for which it is 624 // usually simply reported that they support standard/system codepages). 625 // Pretend that we support all writing systems to not miss the one. 626 // 627 // @todo find a proper way to detect actual supported scripts to make 628 // sure these fonts are not matched for scripts they don't support. 629 for (int ws = 0; ws < QFontDatabase::WritingSystemsCount; ++ws) 630 family->writingSystems[ws] = QtFontFamily::Supported; 631 } else { 632 for (int i = 0; i < face.systems.count(); ++i) 633 family->writingSystems[face.systems.at(i)] = QtFontFamily::Supported; 634 } 635 636 QtFontFoundry *foundry = family->foundry(foundryName, true); 637 QtFontStyle *style = foundry->style(face.styleKey, true); 638 639 // so far, all recognized fonts are antialiased 640 style->antialiased = true; 641 642 if (face.smoothScalable && !style->smoothScalable) { 643 // add new scalable style only if it hasn't been already added -- 644 // the first one of two duplicate (in Qt terms) non-bitmap font 645 // styles wins. 646 style->smoothScalable = true; 647 QtFontSize *size = 648 style->pixelSize(SMOOTH_SCALABLE, true); 649 size->fileName = face.file; 650 size->fileIndex = face.index; 651 size->systems = face.systems; 652 } 653 654 foreach(unsigned short pixelSize, face.pixelSizes) { 655 QtFontSize *size = style->pixelSize(pixelSize, true); 656 // the first bitmap style with a given pixel and point size wins 657 if (!size->fileName.isEmpty()) 658 continue; 659 size->fileName = face.file; 660 size->fileIndex = face.index; 661 size->systems = face.systems; 604 662 } 605 663 } … … 683 741 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) 684 742 { 685 // @todo implement 743 Q_ASSERT(fnt); 744 if (!fnt) 745 return; 746 747 QByteArray file = 748 QFile::encodeName(QDir::current().absoluteFilePath(fnt->fileName)); 749 750 FT_Library lib = qt_getFreetype(); 751 QList<FaceData> faces = readFreeTypeFont(lib, file, &fnt->data); 752 753 QStringList families; 754 755 foreach(const FaceData &face, faces) 756 if (!families.contains(face.familyName)) 757 families << face.familyName; 758 759 fnt->families = families; 686 760 } 687 761 … … 896 970 bool QFontDatabase::removeApplicationFont(int handle) 897 971 { 898 // @todo implement 972 // nothing special to do here; just empty the given ApplicationFont entry 973 974 QMutexLocker locker(fontDatabaseMutex()); 975 976 QFontDatabasePrivate *db = privateDb(); 977 if (handle < 0 || handle >= db->applicationFonts.count()) 978 return false; 979 980 db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); 981 982 db->invalidate(); 983 return true; 984 } 985 986 bool QFontDatabase::removeAllApplicationFonts() 987 { 988 // nothing special to do here; just empty all ApplicationFont entries 989 990 QMutexLocker locker(fontDatabaseMutex()); 991 992 QFontDatabasePrivate *db = privateDb(); 993 if (db->applicationFonts.isEmpty()) 994 return false; 995 996 db->applicationFonts.clear(); 997 db->invalidate(); 998 return true; 999 } 1000 1001 bool QFontDatabase::supportsThreadedFontRendering() 1002 { 1003 // qt_getFreetype() returns a global static FT_Library object but 1004 // FreeType2 docs say that each thread should use its own FT_Library 1005 // object. For this reason, we return false here to prevent apps from 1006 // rendering fonts on threads other than the main GUI thread. 899 1007 return false; 900 1008 } 901 1009 902 bool QFontDatabase::removeAllApplicationFonts()903 {904 // @todo implement905 return false;906 }907 908 bool QFontDatabase::supportsThreadedFontRendering()909 {910 // @todo implement911 return false;912 }913 914 1010 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.