X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiFontLoader.cpp;h=ff3fe53675c1bdaf1b0a2f632d72b0278afab574;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=df6e7543e7badf622de8008138295ccd26308552;hpb=e5cb4fc10f104eea433a08087c7d91b97c74dc7c;p=lyx.git diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index df6e7543e7..ff3fe53675 100644 --- a/src/frontends/qt4/GuiFontLoader.cpp +++ b/src/frontends/qt4/GuiFontLoader.cpp @@ -1,5 +1,5 @@ /** - * \file GuiFontLoader.cpp + * \file FontLoader.cpp * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * @@ -11,128 +11,128 @@ #include -#include "GuiFontLoader.h" +#include "FontLoader.h" + +#include "FontInfo.h" +#include "GuiFontMetrics.h" #include "qt_helpers.h" -#include "debug.h" #include "LyXRC.h" #include "support/convert.h" +#include "support/debug.h" #include "support/filetools.h" #include "support/lstrings.h" #include "support/Systemcall.h" #include "support/Package.h" #include "support/os.h" -#include - #include #include -using lyx::support::contains; -using lyx::support::package; -using lyx::support::addPath; -using lyx::support::addName; - -using std::endl; -using std::make_pair; +#include "support/lassert.h" -using std::pair; -using std::vector; -using std::string; +using namespace std; +using namespace lyx::support; -#if QT_VERSION >= 0x040200 -string const math_fonts[] = {"cmex10", "cmmi10", "cmr10", "cmsy10", +QString const math_fonts[] = {"cmex10", "cmmi10", "cmr10", "cmsy10", "eufm10", "msam10", "msbm10", "wasy10", "esint10"}; int const num_math_fonts = sizeof(math_fonts) / sizeof(*math_fonts); -#endif - namespace lyx { -namespace frontend { -namespace { - -struct symbol_font { - Font::FONT_FAMILY lyx_family; - string family; - string xlfd; -}; +extern docstring const stateText(FontInfo const & f); -symbol_font symbol_fonts[] = { - { Font::SYMBOL_FAMILY, - "symbol", - "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific" }, - - { Font::CMR_FAMILY, - "cmr10", - "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*" }, +namespace frontend { - { Font::CMSY_FAMILY, - "cmsy10", - "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*" }, +/** + * Matches Fonts against + * actual QFont instances, and also caches metrics. + */ +class GuiFontInfo +{ +public: + GuiFontInfo(FontInfo const & f); - { Font::CMM_FAMILY, - "cmmi10", - "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*" }, + /// The font instance + QFont font; + /// Metrics on the font + GuiFontMetrics metrics; +}; - { Font::CMEX_FAMILY, - "cmex10", - "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*" }, +namespace { - { Font::MSA_FAMILY, - "msam10", - "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*" }, +struct SymbolFont { + FontFamily lyx_family; + QString family; + QString xlfd; +}; - { Font::MSB_FAMILY, - "msbm10", - "-*-msbm10-*-*-*-*-*-*-*-*-*-*-*-*" }, +SymbolFont symbol_fonts[] = { + { SYMBOL_FAMILY,"symbol", "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific"}, + { CMR_FAMILY, "cmr10", "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*" }, + { CMSY_FAMILY, "cmsy10", "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*" }, + { CMM_FAMILY, "cmmi10", "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*" }, + { CMEX_FAMILY, "cmex10", "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*" }, + { MSA_FAMILY, "msam10", "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*" }, + { MSB_FAMILY, "msbm10", "-*-msbm10-*-*-*-*-*-*-*-*-*-*-*-*" }, + { EUFRAK_FAMILY,"eufm10", "-*-eufm10-medium-*-*-*-*-*-*-*-*-*-*-*" }, + { WASY_FAMILY, "wasy10", "-*-wasy10-medium-*-*-*-*-*-*-*-*-*-*-*" }, + { ESINT_FAMILY, "esint10","-*-esint10-medium-*-*-*-*-*-*-*-*-*-*-*" } +}; - { Font::EUFRAK_FAMILY, - "eufm10", - "-*-eufm10-medium-*-*-*-*-*-*-*-*-*-*-*" }, +size_t const nr_symbol_fonts = sizeof(symbol_fonts) / sizeof(symbol_fonts[0]); - { Font::WASY_FAMILY, - "wasy10", - "-*-wasy10-medium-*-*-*-*-*-*-*-*-*-*-*" }, +/// BUTT ugly ! +static GuiFontInfo * fontinfo_[NUM_FAMILIES][2][4][10]; - { Font::ESINT_FAMILY, - "esint10", - "-*-esint10-medium-*-*-*-*-*-*-*-*-*-*-*" } -}; -size_t const nr_symbol_fonts = sizeof(symbol_fonts) / sizeof(symbol_font); +/// Get font info (font + metrics) for the given LyX font. +// if not cached, create it. +GuiFontInfo & fontinfo(FontInfo const & f) +{ + LASSERT(f.family() < NUM_FAMILIES, /**/); + LASSERT(f.series() < 2, /**/); + LASSERT(f.realShape() < 4, /**/); + LASSERT(f.size() < 10, /**/); + // fi is a reference to the pointer type (GuiFontInfo *) in the + // fontinfo_ table. + GuiFontInfo * & fi = + fontinfo_[f.family()][f.series()][f.realShape()][f.size()]; + if (!fi) + fi = new GuiFontInfo(f); + return *fi; +} -string getRawName(string const & family) +QString rawName(QString const & family) { for (size_t i = 0; i < nr_symbol_fonts; ++i) if (family == symbol_fonts[i].family) return symbol_fonts[i].xlfd; - LYXERR(Debug::FONT) << "BUG: family not found !" << endl; - return string(); + LYXERR(Debug::FONT, "BUG: family not found !"); + return QString(); } -string const symbolFamily(Font::FONT_FAMILY family) +QString symbolFamily(FontFamily family) { for (size_t i = 0; i < nr_symbol_fonts; ++i) { if (family == symbol_fonts[i].lyx_family) return symbol_fonts[i].family; } - return string(); + return QString(); } -bool isSymbolFamily(Font::FONT_FAMILY family) +bool isSymbolFamily(FontFamily family) { - return family >= Font::SYMBOL_FAMILY && - family <= Font::ESINT_FAMILY; + return family >= SYMBOL_FAMILY && family <= ESINT_FAMILY; } -bool isChosenFont(QFont & font, string const & family) +static bool isChosenFont(QFont & font, QString const & family) { // QFontInfo won't find a font that has only a few glyphs at unusual // positions, e.g. the original esint10 font. @@ -140,10 +140,10 @@ bool isChosenFont(QFont & font, string const & family) // positions. QFontInfo fi(font); - LYXERR(Debug::FONT) << "got: " << fromqstr(fi.family()) << endl; + LYXERR(Debug::FONT, "got: " << fi.family()); - if (contains(fromqstr(fi.family()), family)) { - LYXERR(Debug::FONT) << " got it "; + if (fi.family().contains(family)) { + LYXERR(Debug::FONT, " got it "); return true; } @@ -151,67 +151,65 @@ bool isChosenFont(QFont & font, string const & family) } -pair const getSymbolFont(string const & family) +QFont symbolFont(QString const & family, bool * ok) { - LYXERR(Debug::FONT) << "Looking for font family " - << family << " ... "; - string upper = family; - upper[0] = toupper(family[0]); + LYXERR(Debug::FONT, "Looking for font family " << family << " ... "); + QString upper = family; + upper[0] = family[0].toUpper(); QFont font; font.setKerning(false); - font.setFamily(toqstr(family)); + font.setFamily(family); if (isChosenFont(font, family)) { - LYXERR(Debug::FONT) << "normal!" << endl; - return make_pair(font, true); + LYXERR(Debug::FONT, "normal!"); + *ok = true; + return font; } - LYXERR(Debug::FONT) << "Trying " << upper << " ... "; - font.setFamily(toqstr(upper)); + LYXERR(Debug::FONT, "Trying " << upper << " ... "); + font.setFamily(upper); if (isChosenFont(font, upper)) { - LYXERR(Debug::FONT) << "upper!" << endl; - return make_pair(font, true); + LYXERR(Debug::FONT, "upper!"); + *ok = true; + return font; } // A simple setFamily() fails on Qt 2 - string const rawName = getRawName(family); - LYXERR(Debug::FONT) << "Trying " << rawName << " ... "; - font.setRawName(toqstr(rawName)); + QString const raw = rawName(family); + LYXERR(Debug::FONT, "Trying " << raw << " ... "); + font.setRawName(raw); if (isChosenFont(font, family)) { - LYXERR(Debug::FONT) << "raw version!" << endl; - return make_pair(font, true); + LYXERR(Debug::FONT, "raw version!"); + *ok = true; + return font; } - LYXERR(Debug::FONT) << " FAILED :-(" << endl; - return make_pair(font, false); + LYXERR(Debug::FONT, " FAILED :-("); + *ok = false; + return font; } } // namespace anon -GuiFontLoader::GuiFontLoader() +FontLoader::FontLoader() { -#if QT_VERSION >= 0x040200 - string const fonts_dir = - addPath(package().system_support().absFilename(), "fonts"); + QString const fonts_dir = + toqstr(addPath(package().system_support().absFilename(), "fonts")); for (int i = 0 ; i < num_math_fonts; ++i) { - string const font_file = lyx::support::os::external_path( - addName(fonts_dir, math_fonts[i] + ".ttf")); - int fontID = QFontDatabase::addApplicationFont(toqstr(font_file)); - - LYXERR(Debug::FONT) << "Adding font " << font_file - << static_cast - (fontID < 0 ? " FAIL" : " OK") - << endl; + QString const font_file = fonts_dir + '/' + math_fonts[i] + ".ttf"; + int fontID = QFontDatabase::addApplicationFont(font_file); + + LYXERR(Debug::FONT, "Adding font " << font_file + << (fontID < 0 ? " FAIL" : " OK")); } -#endif - for (int i1 = 0; i1 < Font::NUM_FAMILIES; ++i1) + for (int i1 = 0; i1 < NUM_FAMILIES; ++i1) for (int i2 = 0; i2 < 2; ++i2) for (int i3 = 0; i3 < 4; ++i3) for (int i4 = 0; i4 < 10; ++i4) @@ -219,53 +217,67 @@ GuiFontLoader::GuiFontLoader() } -void GuiFontLoader::update() +void FontLoader::update() { - for (int i1 = 0; i1 < Font::NUM_FAMILIES; ++i1) { + for (int i1 = 0; i1 < NUM_FAMILIES; ++i1) for (int i2 = 0; i2 < 2; ++i2) for (int i3 = 0; i3 < 4; ++i3) for (int i4 = 0; i4 < 10; ++i4) { delete fontinfo_[i1][i2][i3][i4]; fontinfo_[i1][i2][i3][i4] = 0; } - } } +FontLoader::~FontLoader() +{ + update(); +} + ///////////////////////////////////////////////// -QLFontInfo::QLFontInfo(Font const & f) +static QString makeFontName(QString const & family, QString const & foundry) +{ + QString res = family; + if (!foundry.isEmpty()) + res += " [" + foundry + ']'; + return res; +} + + +GuiFontInfo::GuiFontInfo(FontInfo const & f) + : metrics(QFont()) { font.setKerning(false); - string const pat = symbolFamily(f.family()); - if (!pat.empty()) { - bool tmp; - boost::tie(font, tmp) = getSymbolFont(pat); + QString const pat = symbolFamily(f.family()); + if (!pat.isEmpty()) { + bool ok; + font = symbolFont(pat, &ok); } else { switch (f.family()) { - case Font::ROMAN_FAMILY: { - QString family = toqstr(makeFontName(lyxrc.roman_font_name, - lyxrc.roman_font_foundry)); + case ROMAN_FAMILY: { + QString family = makeFontName(toqstr(lyxrc.roman_font_name), + toqstr(lyxrc.roman_font_foundry)); font.setFamily(family); #ifdef Q_WS_MACX #if QT_VERSION >= 0x040300 - // Workaround for a Qt bug, see http://bugzilla.lyx.org/show_bug.cgi?id=3684 + // Workaround for a Qt bug, see http://www.lyx.org/trac/ticket/3684 // It is reported to Trolltech at 02/06/07 against 4.3 final. // FIXME: Add an upper version limit as soon as the bug is fixed in Qt. if (family == "Times" && !font.exactMatch()) - font.setFamily(QString::fromLatin1("Times New Roman")); + font.setFamily("Times New Roman"); #endif #endif break; } - case Font::SANS_FAMILY: - font.setFamily(toqstr(makeFontName(lyxrc.sans_font_name, - lyxrc.sans_font_foundry))); + case SANS_FAMILY: + font.setFamily(makeFontName(toqstr(lyxrc.sans_font_name), + toqstr(lyxrc.sans_font_foundry))); break; - case Font::TYPEWRITER_FAMILY: - font.setFamily(toqstr(makeFontName(lyxrc.typewriter_font_name, - lyxrc.typewriter_font_foundry))); + case TYPEWRITER_FAMILY: + font.setFamily(makeFontName(toqstr(lyxrc.typewriter_font_name), + toqstr(lyxrc.typewriter_font_foundry))); break; default: break; @@ -273,10 +285,10 @@ QLFontInfo::QLFontInfo(Font const & f) } switch (f.series()) { - case Font::MEDIUM_SERIES: + case MEDIUM_SERIES: font.setWeight(QFont::Normal); break; - case Font::BOLD_SERIES: + case BOLD_SERIES: font.setWeight(QFont::Bold); break; default: @@ -284,72 +296,87 @@ QLFontInfo::QLFontInfo(Font const & f) } switch (f.realShape()) { - case Font::ITALIC_SHAPE: - case Font::SLANTED_SHAPE: + case ITALIC_SHAPE: + case SLANTED_SHAPE: font.setItalic(true); break; default: break; } - LYXERR(Debug::FONT) << "Font '" << to_utf8(f.stateText(0)) - << "' matched by\n" << fromqstr(font.family()) << endl; + LYXERR(Debug::FONT, "Font '" << stateText(f) + << "' matched by\n" << font.family()); // Is this an exact match? if (font.exactMatch()) - LYXERR(Debug::FONT) << "This font is an exact match" << endl; + LYXERR(Debug::FONT, "This font is an exact match"); else - LYXERR(Debug::FONT) << "This font is NOT an exact match" - << endl; + LYXERR(Debug::FONT, "This font is NOT an exact match"); - LYXERR(Debug::FONT) << "XFLD: " << fromqstr(font.rawName()) << endl; + LYXERR(Debug::FONT, "XFLD: " << font.rawName()); font.setPointSizeF(convert(lyxrc.font_sizes[f.size()]) * lyxrc.zoom / 100.0); - LYXERR(Debug::FONT) << "The font has size: " - << font.pointSizeF() << endl; + LYXERR(Debug::FONT, "The font has size: " << font.pointSizeF()); - if (f.realShape() != Font::SMALLCAPS_SHAPE) { - metrics.reset(new GuiFontMetrics(font)); - } - else { + if (f.realShape() != SMALLCAPS_SHAPE) { + metrics = GuiFontMetrics(font); + } else { // handle small caps ourselves ... - Font smallfont = f; - smallfont.decSize().decSize().setShape(Font::UP_SHAPE); + FontInfo smallfont = f; + smallfont.decSize().decSize().setShape(UP_SHAPE); QFont font2(font); font2.setKerning(false); font2.setPointSizeF(convert(lyxrc.font_sizes[smallfont.size()]) * lyxrc.zoom / 100.0); - metrics.reset(new GuiFontMetrics(font, font2)); + metrics = GuiFontMetrics(font, font2); } - } -bool GuiFontLoader::available(Font const & f) +bool FontLoader::available(FontInfo const & f) { - static vector cache_set(Font::NUM_FAMILIES, false); - static vector cache(Font::NUM_FAMILIES, false); + static vector cache_set(NUM_FAMILIES, false); + static vector cache(NUM_FAMILIES, false); - Font::FONT_FAMILY family = f.family(); + FontFamily family = f.family(); if (cache_set[family]) return cache[family]; cache_set[family] = true; - string const pat = symbolFamily(family); - if (pat.empty()) + QString const pat = symbolFamily(family); + if (pat.isEmpty()) // We don't care about non-symbol fonts return false; - pair tmp = getSymbolFont(pat); - if (!tmp.second) + bool ok; + symbolFont(pat, &ok); + if (!ok) return false; cache[family] = true; return true; } + +FontMetrics const & FontLoader::metrics(FontInfo const & f) +{ + return fontinfo(f).metrics; +} + + +GuiFontMetrics const & getFontMetrics(FontInfo const & f) +{ + return fontinfo(f).metrics; +} + + +QFont const & getFont(FontInfo const & f) +{ + return fontinfo(f).font; +} + } // namespace frontend } // namespace lyx