X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiFontLoader.cpp;h=ff3fe53675c1bdaf1b0a2f632d72b0278afab574;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=b7ede4c3ddffc0a14985e4df344599957ac9ac02;hpb=fe2085b0e1ce78d457b440384451bdeee2372a47;p=lyx.git diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index b7ede4c3dd..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,110 +11,112 @@ #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 namespace std; +using namespace lyx::support; -#if QT_VERSION >= 0x040200 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 { + +extern docstring const stateText(FontInfo const & f); + namespace frontend { +/** + * Matches Fonts against + * actual QFont instances, and also caches metrics. + */ +class GuiFontInfo +{ +public: + GuiFontInfo(FontInfo const & f); + + /// The font instance + QFont font; + /// Metrics on the font + GuiFontMetrics metrics; +}; + namespace { struct SymbolFont { - Font::FONT_FAMILY lyx_family; + FontFamily lyx_family; QString family; QString xlfd; }; SymbolFont symbol_fonts[] = { - { Font::SYMBOL_FAMILY, - "symbol", - "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific" }, - - { Font::CMR_FAMILY, - "cmr10", - "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*" }, - - { Font::CMSY_FAMILY, - "cmsy10", - "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*" }, - - { Font::CMM_FAMILY, - "cmmi10", - "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*" }, - - { Font::CMEX_FAMILY, - "cmex10", - "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*" }, - - { Font::MSA_FAMILY, - "msam10", - "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*" }, - - { Font::MSB_FAMILY, - "msbm10", - "-*-msbm10-*-*-*-*-*-*-*-*-*-*-*-*" }, + { 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(SymbolFont); +/// 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; +} -QString getRawName(QString 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; + LYXERR(Debug::FONT, "BUG: family not found !"); return QString(); } -QString 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) @@ -124,10 +126,9 @@ QString const symbolFamily(Font::FONT_FAMILY family) } -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; } @@ -139,10 +140,10 @@ static bool isChosenFont(QFont & font, QString const & family) // positions. QFontInfo fi(font); - LYXERR(Debug::FONT) << "got: " << fromqstr(fi.family()) << endl; + LYXERR(Debug::FONT, "got: " << fi.family()); if (fi.family().contains(family)) { - LYXERR(Debug::FONT) << " got it "; + LYXERR(Debug::FONT, " got it "); return true; } @@ -150,10 +151,9 @@ static bool isChosenFont(QFont & font, QString const & family) } -static pair const getSymbolFont(QString const & family) +QFont symbolFont(QString const & family, bool * ok) { - LYXERR(Debug::FONT) << "Looking for font family " - << fromqstr(family) << " ... "; + LYXERR(Debug::FONT, "Looking for font family " << family << " ... "); QString upper = family; upper[0] = family[0].toUpper(); @@ -162,39 +162,42 @@ static pair const getSymbolFont(QString const & 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 " << fromqstr(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 - QString const rawName = getRawName(family); - LYXERR(Debug::FONT) << "Trying " << fromqstr(rawName) << " ... "; - font.setRawName(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 QString const fonts_dir = toqstr(addPath(package().system_support().absFilename(), "fonts")); @@ -202,14 +205,11 @@ GuiFontLoader::GuiFontLoader() QString const font_file = fonts_dir + '/' + math_fonts[i] + ".ttf"; int fontID = QFontDatabase::addApplicationFont(font_file); - LYXERR(Debug::FONT) << "Adding font " << fromqstr(font_file) - << static_cast - (fontID < 0 ? " FAIL" : " OK") - << endl; + 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) @@ -217,19 +217,23 @@ 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(); +} + ///////////////////////////////////////////////// @@ -242,22 +246,23 @@ static QString makeFontName(QString const & family, QString const & foundry) } -GuiFontInfo::GuiFontInfo(Font const & f) +GuiFontInfo::GuiFontInfo(FontInfo const & f) + : metrics(QFont()) { font.setKerning(false); QString const pat = symbolFamily(f.family()); if (!pat.isEmpty()) { - bool tmp; - boost::tie(font, tmp) = getSymbolFont(pat); + bool ok; + font = symbolFont(pat, &ok); } else { switch (f.family()) { - case Font::ROMAN_FAMILY: { + 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()) @@ -266,11 +271,11 @@ GuiFontInfo::GuiFontInfo(Font const & f) #endif break; } - case Font::SANS_FAMILY: + case SANS_FAMILY: font.setFamily(makeFontName(toqstr(lyxrc.sans_font_name), toqstr(lyxrc.sans_font_foundry))); break; - case Font::TYPEWRITER_FAMILY: + case TYPEWRITER_FAMILY: font.setFamily(makeFontName(toqstr(lyxrc.typewriter_font_name), toqstr(lyxrc.typewriter_font_foundry))); break; @@ -280,10 +285,10 @@ GuiFontInfo::GuiFontInfo(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: @@ -291,56 +296,52 @@ GuiFontInfo::GuiFontInfo(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; @@ -350,13 +351,32 @@ bool GuiFontLoader::available(Font const & f) // 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