X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeXFonts.cpp;h=b61c4c7fc509fbadbaf94f235f9fda56bf9104f6;hb=ed44aed58cd48eb744cb50a546859297f9e67e58;hp=1e89e4c63fc3dfd7a675b7c569490ea905593e9f;hpb=924f71c792f82bfdcf3ec161df38833142fab280;p=lyx.git diff --git a/src/LaTeXFonts.cpp b/src/LaTeXFonts.cpp index 1e89e4c63f..b61c4c7fc5 100644 --- a/src/LaTeXFonts.cpp +++ b/src/LaTeXFonts.cpp @@ -19,6 +19,7 @@ #include "support/convert.h" #include "support/debug.h" +#include "support/docstream.h" #include "support/FileName.h" #include "support/filetools.h" #include "support/gettext.h" @@ -34,131 +35,336 @@ namespace lyx { LaTeXFonts latexfonts; -bool LaTeXFont::available(bool ot1) const +LaTeXFont LaTeXFont::altFont(docstring const & name) { - return ot1 ? available_ot1_ : available_; + return theLaTeXFonts().getAltFont(name); } -bool LaTeXFont::providesOSF(bool ot1) const +bool LaTeXFont::available(bool ot1, bool nomath) { - if (!osfpackage_.empty()) - return LaTeXFeatures::isAvailable(to_ascii(osfpackage_)); + if (nomath && !nomathfont_.empty()) + return altFont(nomathfont_).available(ot1, nomath); + else if (ot1 && !ot1font_.empty()) + return (ot1font_ == "none") ? + true : altFont(ot1font_).available(ot1, nomath); + else if (requires_.empty() && package_.empty()) + return true; + else if (!requires_.empty() + && LaTeXFeatures::isAvailable(to_ascii(requires_))) + return true; + else if (requires_.empty() && !package_.empty() + && LaTeXFeatures::isAvailable(to_ascii(package_))) + return true; + else if (!altfonts_.empty()) { + for (size_t i = 0; i < altfonts_.size(); ++i) { + if (altFont(altfonts_[i]).available(ot1, nomath)) + return true; + } + } + return false; +} + - if (ot1 && !ot1package_.empty() && ot1package_ != "none") +bool LaTeXFont::providesNoMath(bool ot1, bool complete) +{ + docstring const usedfont = getUsedFont(ot1, complete, false); + + if (usedfont.empty()) return false; + else if (usedfont != name_) + return altFont(usedfont).providesNoMath(ot1, complete); + + return (!nomathfont_.empty() && available(ot1, true)); +} + + +bool LaTeXFont::providesOSF(bool ot1, bool complete, bool nomath) +{ + docstring const usedfont = getUsedFont(ot1, complete, nomath); - if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_))) + if (usedfont.empty()) + return false; + else if (usedfont != name_) + return altFont(usedfont).providesOSF(ot1, complete, nomath); + else if (!osffont_.empty()) + return altFont(osffont_).available(ot1, nomath); + else if (!available(ot1, nomath)) return false; return (!osfoption_.empty() || !osfscoption_.empty()); } -bool LaTeXFont::providesSC(bool ot1) const +bool LaTeXFont::providesSC(bool ot1, bool complete, bool nomath) { - if (ot1 && !ot1package_.empty() && ot1package_ != "none") - return false; + docstring const usedfont = getUsedFont(ot1, complete, nomath); - if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_))) + if (usedfont.empty()) + return false; + else if (usedfont != name_) + return altFont(usedfont).providesSC(ot1, complete, nomath); + else if (!available(ot1, nomath)) return false; return (!scoption_.empty() || !osfscoption_.empty()); } -bool LaTeXFont::providesScale(bool ot1) const +bool LaTeXFont::hasMonolithicExpertSet(bool ot1, bool complete, bool nomath) { - if (ot1 && !ot1package_.empty() && ot1package_ != "none") - return false; + docstring const usedfont = getUsedFont(ot1, complete, nomath); - if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_))) + if (usedfont.empty()) return false; + else if (usedfont != name_) + return altFont(usedfont).hasMonolithicExpertSet(ot1, complete, nomath); + return (!osfoption_.empty() && !scoption_.empty() && osfoption_ == scoption_) + || (osfoption_.empty() && scoption_.empty() && !osfscoption_.empty()); +} + +bool LaTeXFont::providesScale(bool ot1, bool complete, bool nomath) +{ + docstring const usedfont = getUsedFont(ot1, complete, nomath); + + if (usedfont.empty()) + return false; + else if (usedfont != name_) + return altFont(usedfont).providesScale(ot1, complete, nomath); + else if (!available(ot1, nomath)) + return false; return (!scaleoption_.empty()); } -string const LaTeXFont::getAvailablePackage(bool dryrun, bool ot1, bool complete) +bool LaTeXFont::providesMoreOptions(bool ot1, bool complete, bool nomath) { - if (ot1 && !ot1package_.empty()) { - if (ot1package_ != "none" - && (LaTeXFeatures::isAvailable(to_ascii(ot1package_)) || dryrun)) - return to_ascii(ot1package_); - if (!dryrun && ot1package_ != "none") - frontend::Alert::warning(_("Font not available"), - bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n" - "is not available on your system. LyX will fall back to the default font."), - ot1package_, guiname_), true); - return string(); + docstring const usedfont = getUsedFont(ot1, complete, nomath); + + if (usedfont.empty()) + return false; + else if (usedfont != name_) + return altFont(usedfont).providesMoreOptions(ot1, complete, nomath); + else if (!available(ot1, nomath)) + return false; + + return (moreopts_); +} + +bool LaTeXFont::provides(std::string const & name, bool ot1, bool complete, bool nomath) +{ + docstring const usedfont = getUsedFont(ot1, complete, nomath); + + if (usedfont.empty()) + return false; + else if (usedfont != name_) + return altFont(usedfont).provides(name, ot1, complete, nomath); + else if (provides_.empty()) + return false; + + for (size_t i = 0; i < provides_.size(); ++i) { + if (provides_[i] == name) + return true; } - if (complete && !completepackage_.empty()) { - if (LaTeXFeatures::isAvailable(to_ascii(completepackage_)) || dryrun) - return to_ascii(completepackage_); + return false; +} + + +docstring const LaTeXFont::getUsedFont(bool ot1, bool complete, bool nomath) +{ + if (nomath && !nomathfont_.empty() && available(ot1, true)) + return nomathfont_; + else if (ot1 && !ot1font_.empty()) + return (ot1font_ == "none") ? docstring() : ot1font_; + else if (family_ == "rm" && complete && !completefont_.empty() + && altFont(completefont_).available(ot1, nomath)) + return completefont_; + else if (switchdefault_) { + if (requires_.empty() + || (!requires_.empty() + && LaTeXFeatures::isAvailable(to_ascii(requires_)))) + return name_; + } + else if (!requires_.empty() + && LaTeXFeatures::isAvailable(to_ascii(requires_))) + return name_; + else if (!package_.empty() + && LaTeXFeatures::isAvailable(to_ascii(package_))) + return name_; + else if (!preamble_.empty() && package_.empty() + && requires_.empty() && !switchdefault_ + && altfonts_.empty()) { + return name_; } - if (!package_.empty()) { - if (!requires_.empty() && LaTeXFeatures::isAvailable(to_ascii(requires_))) - return to_ascii(package_); - if (LaTeXFeatures::isAvailable(to_ascii(package_))) - return to_ascii(package_); - else if (!altpackages_.empty()) { - for (size_t i = 0; i < altpackages_.size(); ++i) { - if (LaTeXFeatures::isAvailable(to_ascii(altpackages_[i]))) - return to_ascii(altpackages_[i]); - } + else if (!altfonts_.empty()) { + for (size_t i = 0; i < altfonts_.size(); ++i) { + LaTeXFont altf = altFont(altfonts_[i]); + if (altf.available(ot1, nomath)) + return altf.getUsedFont(ot1, complete, nomath); } - // Output unavailable packages in source preview - if (dryrun) - return to_ascii(package_); - docstring const req = requires_.empty() ? package_ : requires_; - frontend::Alert::warning(_("Font not available"), - bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n" - "is not available on your system. LyX will fall back to the default font."), - req, guiname_), true); } - return string(); + + return docstring(); +} + + +docstring const LaTeXFont::getUsedPackage(bool ot1, bool complete, bool nomath) +{ + docstring const usedfont = getUsedFont(ot1, complete, nomath); + if (usedfont.empty()) + return docstring(); + return theLaTeXFonts().getLaTeXFont(usedfont).package(); } -string const LaTeXFont::getPackageOptions(bool const & ot1, bool const & sc, - bool const & osf, int const & scale) +string const LaTeXFont::getAvailablePackage(bool dryrun) { - if (ot1 && !ot1package_.empty()) + if (package_.empty()) return string(); + string const package = to_ascii(package_); + if (!requires_.empty() && LaTeXFeatures::isAvailable(to_ascii(requires_))) + return package; + else if (LaTeXFeatures::isAvailable(package)) + return package; + // Output unavailable packages in source preview + else if (dryrun) + return package; + + docstring const req = requires_.empty() ? package_ : requires_; + frontend::Alert::warning(_("Font not available"), + bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n" + "is not available on your system. LyX will fall back to the default font."), + req, guiname_), true); + + return string(); +} + + +string const LaTeXFont::getPackageOptions(bool ot1, bool complete, bool sc, bool osf, + int scale, string const extraopts, bool nomath) +{ ostringstream os; - if (sc && osf && providesOSF() && providesSC()) { + bool const needosfopt = (osf != osfdefault_); + bool const has_osf = providesOSF(ot1, complete, nomath); + bool const has_sc = providesSC(ot1, complete, nomath); + bool const moreopts = providesMoreOptions(ot1, complete, nomath); + + if (!packageoptions_.empty()) + os << to_ascii(packageoptions_); + + if (sc && needosfopt && has_osf && has_sc) { + if (!os.str().empty()) + os << ','; if (!osfscoption_.empty()) os << to_ascii(osfscoption_); else - os << to_ascii(osfoption_) << ',' << to_ascii(scoption_); - } else if (osf && providesOSF()) + os << to_ascii(osfoption_) + << ',' << to_ascii(scoption_); + } else if (needosfopt && has_osf) { + if (!os.str().empty()) + os << ','; os << to_ascii(osfoption_); - else if (sc && providesSC()) + } else if (sc && has_sc) { + if (!os.str().empty()) + os << ','; os << to_ascii(scoption_); - if (scale != 100 && !scaleoption_.empty()) { + } + + if (scale != 100 && !scaleoption_.empty() + && providesScale(ot1, complete, nomath)) { if (!os.str().empty()) os << ','; os << subst(to_ascii(scaleoption_), "$$val", convert(float(scale) / 100)); } + + if (moreopts && !extraopts.empty()) { + if (!os.str().empty()) + os << ','; + os << extraopts; + } + return os.str(); +} + + +string const LaTeXFont::getLaTeXCode(bool dryrun, bool ot1, bool complete, bool sc, + bool osf, bool nomath, string const extraopts, + int const & scale) +{ + ostringstream os; + + docstring const usedfont = getUsedFont(ot1, complete, nomath); + if (usedfont.empty()) + return string(); + else if (usedfont != name_) + return altFont(usedfont).getLaTeXCode(dryrun, ot1, complete, sc, + osf, nomath, extraopts, scale); + + if (switchdefault_) { + if (family_.empty()) { + LYXERR0("Error: Font `" << name_ << "' has no family defined!"); + return string(); + } + if (available(ot1, nomath) || dryrun) + os << "\\renewcommand{\\" << to_ascii(family_) << "default}{" + << to_ascii(name_) << "}\n"; + else + frontend::Alert::warning(_("Font not available"), + bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n" + "is not available on your system. LyX will fall back to the default font."), + requires_, guiname_), true); + } else { + string const package = + getAvailablePackage(dryrun); + string const packageopts = getPackageOptions(ot1, complete, sc, osf, scale, extraopts, nomath); + if (packageopts.empty() && !package.empty()) + os << "\\usepackage{" << package << "}\n"; + else if (!packageopts.empty() && !package.empty()) + os << "\\usepackage[" << packageopts << "]{" << package << "}\n"; + } + if (osf && providesOSF(ot1, complete, nomath) && !osffont_.empty()) + os << altFont(osffont_).getLaTeXCode(dryrun, ot1, complete, sc, osf, + nomath, extraopts, scale); + + if (!preamble_.empty()) + os << to_utf8(preamble_); + return os.str(); } +bool LaTeXFont::hasFontenc(string const & name) const +{ + for (auto const & fe : fontenc_) { + if (fe == name) + return true; + } + return false; +} + + bool LaTeXFont::readFont(Lexer & lex) { enum LaTeXFontTags { - LF_ALT_PACKAGES = 1, - LF_COMPLETE_PACKAGE, + LF_ALT_FONTS = 1, + LF_COMPLETE_FONT, LF_END, LF_FAMILY, + LF_FONTENC, LF_GUINAME, + LF_NOMATHFONT, + LF_OSFDEFAULT, + LF_OSFFONT, LF_OSFOPTION, - LF_OSFPACKAGE, LF_OSFSCOPTION, - LF_OT1_PACKAGE, + LF_OT1_FONT, + LF_MOREOPTS, LF_PACKAGE, + LF_PACKAGEOPTIONS, + LF_PREAMBLE, + LF_PROVIDES, LF_REQUIRES, LF_SCALEOPTION, LF_SCOPTION, @@ -167,16 +373,23 @@ bool LaTeXFont::readFont(Lexer & lex) // Keep these sorted alphabetically! LexerKeyword latexFontTags[] = { - { "altpackages", LF_ALT_PACKAGES }, - { "completepackage", LF_COMPLETE_PACKAGE }, + { "altfonts", LF_ALT_FONTS }, + { "completefont", LF_COMPLETE_FONT }, { "endfont", LF_END }, { "family", LF_FAMILY }, + { "fontencoding", LF_FONTENC }, { "guiname", LF_GUINAME }, + { "moreoptions", LF_MOREOPTS }, + { "nomathfont", LF_NOMATHFONT }, + { "osfdefault", LF_OSFDEFAULT }, + { "osffont", LF_OSFFONT }, { "osfoption", LF_OSFOPTION }, - { "osfpackage", LF_OSFPACKAGE }, { "osfscoption", LF_OSFSCOPTION }, - { "ot1package", LF_OT1_PACKAGE }, + { "ot1font", LF_OT1_FONT }, { "package", LF_PACKAGE }, + { "packageoptions", LF_PACKAGEOPTIONS }, + { "preamble", LF_PREAMBLE }, + { "provides", LF_PROVIDES }, { "requires", LF_REQUIRES }, { "scaleoption", LF_SCALEOPTION }, { "scoption", LF_SCOPTION }, @@ -199,21 +412,21 @@ bool LaTeXFont::readFont(Lexer & lex) error = true; continue; - default: + default: break; } switch (static_cast(le)) { case LF_END: // end of structure finished = true; break; - case LF_ALT_PACKAGES: { - docstring altp; - lex >> altp; - altpackages_ = getVectorFromString(altp); + case LF_ALT_FONTS: { + lex.eatLine(); + docstring altp = lex.getDocString(); + altfonts_ = getVectorFromString(altp); break; } - case LF_COMPLETE_PACKAGE: - lex >> completepackage_; + case LF_COMPLETE_FONT: + lex >> completefont_; break; case LF_FAMILY: lex >> family_; @@ -221,21 +434,45 @@ bool LaTeXFont::readFont(Lexer & lex) case LF_GUINAME: lex >> guiname_; break; + case LF_FONTENC: { + lex.eatLine(); + string fe = lex.getString(); + fontenc_ = getVectorFromString(fe); + break; + } + case LF_NOMATHFONT: + lex >> nomathfont_; + break; case LF_OSFOPTION: lex >> osfoption_; break; - case LF_OSFPACKAGE: - lex >> osfpackage_; + case LF_OSFFONT: + lex >> osffont_; + break; + case LF_OSFDEFAULT: + lex >> osfdefault_; break; case LF_OSFSCOPTION: lex >> osfscoption_; break; - case LF_OT1_PACKAGE: - lex >> ot1package_; + case LF_OT1_FONT: + lex >> ot1font_; break; case LF_PACKAGE: lex >> package_; break; + case LF_PACKAGEOPTIONS: + lex >> packageoptions_; + break; + case LF_PREAMBLE: + preamble_ = lex.getLongString(from_ascii("EndPreamble")); + break; + case LF_PROVIDES: { + lex.eatLine(); + string features = lex.getString(); + provides_ = getVectorFromString(features); + break; + } case LF_REQUIRES: lex >> requires_; break; @@ -245,6 +482,9 @@ bool LaTeXFont::readFont(Lexer & lex) case LF_SCOPTION: lex >> scoption_; break; + case LF_MOREOPTS: + lex >> moreopts_; + break; case LF_SWITCHDEFAULT: lex >> switchdefault_; break; @@ -262,6 +502,8 @@ bool LaTeXFont::readFont(Lexer & lex) bool LaTeXFont::read(Lexer & lex) { switchdefault_ = 0; + osfdefault_ = 0; + moreopts_ = 0; if (!lex.next()) { lex.printError("No name given for LaTeX font: `$$Token'."); @@ -275,25 +517,8 @@ bool LaTeXFont::read(Lexer & lex) return false; } - bool available = true; - if (!requires_.empty()) - available = LaTeXFeatures::isAvailable(to_ascii(requires_)); - else if (!package_.empty()) { - available = LaTeXFeatures::isAvailable(to_ascii(package_)); - if (!available && !altpackages_.empty()) { - for (size_t i = 0; i < altpackages_.size(); ++i) { - available = LaTeXFeatures::isAvailable(to_ascii(altpackages_[i])); - if (available) - break; - } - } - } - available_ = available; - - if (!ot1package_.empty() && ot1package_ != "none") - available_ot1_ = LaTeXFeatures::isAvailable(to_ascii(ot1package_)); - else - available_ot1_ = available; + if (fontenc_.empty()) + fontenc_.push_back("T1"); return true; } @@ -319,7 +544,8 @@ void LaTeXFonts::readLaTeXFonts() default: break; } - if (lex.getString() != "Font") { + string const type = lex.getString(); + if (type != "Font" && type != "AltFont") { lex.printError("Unknown LaTeXFont tag `$$Token'"); continue; } @@ -328,7 +554,10 @@ void LaTeXFonts::readLaTeXFonts() if (!lex) break; - texfontmap_[f.name()] = f; + if (type == "AltFont") + texaltfontmap_[f.name()] = f; + else + texfontmap_[f.name()] = f; } } @@ -343,10 +572,30 @@ LaTeXFonts::TexFontMap LaTeXFonts::getLaTeXFonts() LaTeXFont LaTeXFonts::getLaTeXFont(docstring const & name) { + if (name == "default" || name == "auto") + return LaTeXFont(); if (texfontmap_.empty()) readLaTeXFonts(); + if (texfontmap_.find(name) == texfontmap_.end()) { + LYXERR0("LaTeXFonts::getLaTeXFont: font '" << name << "' not found!"); + return LaTeXFont(); + } return texfontmap_[name]; } +LaTeXFont LaTeXFonts::getAltFont(docstring const & name) +{ + if (name == "default" || name == "auto") + return LaTeXFont(); + if (texaltfontmap_.empty()) + readLaTeXFonts(); + if (texaltfontmap_.find(name) == texaltfontmap_.end()) { + LYXERR0("LaTeXFonts::getAltFont: alternative font '" << name << "' not found!"); + return LaTeXFont(); + } + return texaltfontmap_[name]; +} + + } // namespace lyx