X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiFontLoader.cpp;h=ff3fe53675c1bdaf1b0a2f632d72b0278afab574;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=f5cc8c9a5a593f2ad6291273d86e2966a6c25290;hpb=8c5f097b5d59cc157b39a08fa5d3f5fa82cf1e4f;p=lyx.git diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index f5cc8c9a5a..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,122 +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 "LyXRC.h" #include "support/convert.h" +#include "support/debug.h" #include "support/filetools.h" #include "support/lstrings.h" -#include "support/systemcall.h" - -#include +#include "support/Systemcall.h" +#include "support/Package.h" +#include "support/os.h" -#include +#include +#include -#ifdef Q_WS_X11 -#include -//#include -#include -#endif +#include "support/lassert.h" -using lyx::support::contains; +using namespace std; +using namespace lyx::support; -using std::endl; -using std::make_pair; +QString const math_fonts[] = {"cmex10", "cmmi10", "cmr10", "cmsy10", + "eufm10", "msam10", "msbm10", "wasy10", "esint10"}; +int const num_math_fonts = sizeof(math_fonts) / sizeof(*math_fonts); -using std::pair; -using std::vector; -using std::string; +namespace lyx { +extern docstring const stateText(FontInfo const & f); -namespace lyx { namespace frontend { -namespace { +/** + * Matches Fonts against + * actual QFont instances, and also caches metrics. + */ +class GuiFontInfo +{ +public: + GuiFontInfo(FontInfo const & f); -struct symbol_font { - LyXFont::FONT_FAMILY lyx_family; - string family; - string xlfd; + /// The font instance + QFont font; + /// Metrics on the font + GuiFontMetrics metrics; }; -symbol_font symbol_fonts[] = { - { LyXFont::SYMBOL_FAMILY, - "symbol", - "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific" }, - - { LyXFont::CMR_FAMILY, - "cmr10", - "-*-cmr10-medium-*-*-*-*-*-*-*-*-*-*-*" }, - - { LyXFont::CMSY_FAMILY, - "cmsy10", - "-*-cmsy10-*-*-*-*-*-*-*-*-*-*-*-*" }, - - { LyXFont::CMM_FAMILY, - "cmmi10", - "-*-cmmi10-medium-*-*-*-*-*-*-*-*-*-*-*" }, - - { LyXFont::CMEX_FAMILY, - "cmex10", - "-*-cmex10-*-*-*-*-*-*-*-*-*-*-*-*" }, +namespace { - { LyXFont::MSA_FAMILY, - "msam10", - "-*-msam10-*-*-*-*-*-*-*-*-*-*-*-*" }, +struct SymbolFont { + FontFamily lyx_family; + QString family; + QString xlfd; +}; - { LyXFont::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-*-*-*-*-*-*-*-*-*-*-*" } +}; - { LyXFont::EUFRAK_FAMILY, - "eufm10", - "-*-eufm10-medium-*-*-*-*-*-*-*-*-*-*-*" }, +size_t const nr_symbol_fonts = sizeof(symbol_fonts) / sizeof(symbol_fonts[0]); - { LyXFont::WASY_FAMILY, - "wasy10", - "-*-wasy10-medium-*-*-*-*-*-*-*-*-*-*-*" }, +/// BUTT ugly ! +static GuiFontInfo * fontinfo_[NUM_FAMILIES][2][4][10]; - { LyXFont::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(LyXFont::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(LyXFont::FONT_FAMILY family) +bool isSymbolFamily(FontFamily family) { - return family >= LyXFont::SYMBOL_FAMILY && - family <= LyXFont::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. @@ -134,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; } @@ -145,51 +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() { - for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1) + QString const fonts_dir = + toqstr(addPath(package().system_support().absFilename(), "fonts")); + + for (int i = 0 ; i < num_math_fonts; ++i) { + 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")); + } + + 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) @@ -197,9 +217,9 @@ GuiFontLoader::GuiFontLoader() } -void GuiFontLoader::update() +void FontLoader::update() { - for (int i1 = 0; i1 < LyXFont::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) { @@ -209,29 +229,55 @@ void GuiFontLoader::update() } +FontLoader::~FontLoader() +{ + update(); +} + ///////////////////////////////////////////////// -QLFontInfo::QLFontInfo(LyXFont 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 LyXFont::ROMAN_FAMILY: - font.setFamily(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://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("Times New Roman"); +#endif +#endif break; - case LyXFont::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 LyXFont::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; @@ -239,10 +285,10 @@ QLFontInfo::QLFontInfo(LyXFont const & f) } switch (f.series()) { - case LyXFont::MEDIUM_SERIES: + case MEDIUM_SERIES: font.setWeight(QFont::Normal); break; - case LyXFont::BOLD_SERIES: + case BOLD_SERIES: font.setWeight(QFont::Bold); break; default: @@ -250,72 +296,87 @@ QLFontInfo::QLFontInfo(LyXFont const & f) } switch (f.realShape()) { - case LyXFont::ITALIC_SHAPE: - case LyXFont::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() != LyXFont::SMALLCAPS_SHAPE) { - metrics.reset(new GuiFontMetrics(font)); - } - else { + if (f.realShape() != SMALLCAPS_SHAPE) { + metrics = GuiFontMetrics(font); + } else { // handle small caps ourselves ... - LyXFont smallfont = f; - smallfont.decSize().decSize().setShape(LyXFont::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(LyXFont const & f) +bool FontLoader::available(FontInfo const & f) { - static vector cache_set(LyXFont::NUM_FAMILIES, false); - static vector cache(LyXFont::NUM_FAMILIES, false); + static vector cache_set(NUM_FAMILIES, false); + static vector cache(NUM_FAMILIES, false); - LyXFont::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