3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Jürgen Spitzmüller
8 * Full author contact details are available in file CREDITS.
13 #include "LaTeXFonts.h"
15 #include "LaTeXFeatures.h"
18 #include "frontends/alert.h"
20 #include "support/convert.h"
21 #include "support/debug.h"
22 #include "support/FileName.h"
23 #include "support/filetools.h"
24 #include "support/gettext.h"
25 #include "support/lstrings.h"
29 using namespace lyx::support;
34 LaTeXFonts latexfonts;
37 bool LaTeXFont::available(bool ot1) const
39 return ot1 ? available_ot1_ : available_;
43 bool LaTeXFont::providesOSF(bool ot1) const
45 if (!osfpackage_.empty())
46 return LaTeXFeatures::isAvailable(to_ascii(osfpackage_));
48 if (ot1 && !ot1package_.empty() && ot1package_ != "none")
51 if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
54 return (!osfoption_.empty() || !osfscoption_.empty());
58 bool LaTeXFont::providesSC(bool ot1) const
60 if (ot1 && !ot1package_.empty() && ot1package_ != "none")
63 if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
66 return (!scoption_.empty() || !osfscoption_.empty());
70 bool LaTeXFont::providesScale(bool ot1) const
72 if (ot1 && !ot1package_.empty() && ot1package_ != "none")
75 if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
78 return (!scaleoption_.empty());
81 bool LaTeXFont::provides(std::string const & name) const
83 if (provides_.empty())
85 for (size_t i = 0; i < provides_.size(); ++i) {
86 if (provides_[i] == name)
93 string const LaTeXFont::getAvailablePackage(bool dryrun, bool ot1, bool complete, bool & alt)
95 if (ot1 && !ot1package_.empty()) {
96 if (ot1package_ != "none"
97 && (LaTeXFeatures::isAvailable(to_ascii(ot1package_)) || dryrun))
98 return to_ascii(ot1package_);
99 if (!dryrun && ot1package_ != "none")
100 frontend::Alert::warning(_("Font not available"),
101 bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n"
102 "is not available on your system. LyX will fall back to the default font."),
103 ot1package_, guiname_), true);
106 if (family_ == "rm" && complete && !completepackage_.empty()) {
107 if (LaTeXFeatures::isAvailable(to_ascii(completepackage_)) || dryrun)
108 return to_ascii(completepackage_);
110 if (!package_.empty()) {
111 if (!requires_.empty() && LaTeXFeatures::isAvailable(to_ascii(requires_)))
112 return to_ascii(package_);
113 if (LaTeXFeatures::isAvailable(to_ascii(package_)))
114 return to_ascii(package_);
115 else if (!altpackages_.empty()) {
116 for (size_t i = 0; i < altpackages_.size(); ++i) {
117 if (LaTeXFeatures::isAvailable(to_ascii(altpackages_[i]))) {
119 return to_ascii(altpackages_[i]);
123 // Output unavailable packages in source preview
125 return to_ascii(package_);
126 docstring const req = requires_.empty() ? package_ : requires_;
127 frontend::Alert::warning(_("Font not available"),
128 bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n"
129 "is not available on your system. LyX will fall back to the default font."),
130 req, guiname_), true);
136 string const LaTeXFont::getPackageOptions(bool ot1, bool sc, bool osf, int scale)
138 if (ot1 && !ot1package_.empty())
142 bool const needosfopt = (osf != osfdefault_);
143 if (!packageoption_.empty())
144 os << to_ascii(packageoption_);
145 if (sc && needosfopt && providesOSF() && providesSC()) {
146 if (!os.str().empty())
148 if (!osfscoption_.empty())
149 os << to_ascii(osfscoption_);
151 os << to_ascii(osfoption_) << ',' << to_ascii(scoption_);
152 } else if (needosfopt && providesOSF()) {
153 if (!os.str().empty())
155 os << to_ascii(osfoption_);
156 } else if (sc && providesSC()) {
157 if (!os.str().empty())
159 os << to_ascii(scoption_);
161 if (scale != 100 && !scaleoption_.empty()) {
162 if (!os.str().empty())
164 os << subst(to_ascii(scaleoption_), "$$val",
165 convert<std::string>(float(scale) / 100));
171 string const LaTeXFont::getLaTeXCode(bool dryrun, bool ot1, bool complete, bool sc,
172 bool osf, int const & scale)
176 if (switchdefault_) {
177 if (family_.empty()) {
178 LYXERR0("Error: Font `" << name_ << "' has no family defined!");
181 if (available(ot1) || dryrun)
182 os << "\\renewcommand{\\" << to_ascii(family_) << "default}{"
183 << to_ascii(name_) << "}\n";
185 frontend::Alert::warning(_("Font not available"),
186 bformat(_("The LaTeX package `%1$s' needed for the font `%2$s'\n"
187 "is not available on your system. LyX will fall back to the default font."),
188 requires_, guiname_), true);
191 string const package =
192 getAvailablePackage(dryrun, ot1, complete, alt);
193 // Package options are not for alternative packages
194 string const packageopts = alt ? string() : getPackageOptions(ot1, sc, osf, scale);
195 if (packageopts.empty() && !package.empty())
196 os << "\\usepackage{" << package << "}\n";
197 else if (!packageopts.empty() && !package.empty())
198 os << "\\usepackage[" << packageopts << "]{" << package << "}\n";
200 if (osf && providesOSF(ot1) && !osfpackage_.empty())
201 os << "\\usepackage{" << to_ascii(osfpackage_) << "}\n";
207 bool LaTeXFont::readFont(Lexer & lex)
229 // Keep these sorted alphabetically!
230 LexerKeyword latexFontTags[] = {
231 { "altpackages", LF_ALT_PACKAGES },
232 { "completepackage", LF_COMPLETE_PACKAGE },
233 { "endfont", LF_END },
234 { "family", LF_FAMILY },
235 { "guiname", LF_GUINAME },
236 { "osfdefault", LF_OSFDEFAULT },
237 { "osfoption", LF_OSFOPTION },
238 { "osfpackage", LF_OSFPACKAGE },
239 { "osfscoption", LF_OSFSCOPTION },
240 { "ot1package", LF_OT1_PACKAGE },
241 { "package", LF_PACKAGE },
242 { "packageoption", LF_PACKAGEOPTION },
243 { "provides", LF_PROVIDES },
244 { "requires", LF_REQUIRES },
245 { "scaleoption", LF_SCALEOPTION },
246 { "scoption", LF_SCOPTION },
247 { "switchdefault", LF_SWITCHDEFAULT }
251 bool finished = false;
252 lex.pushTable(latexFontTags);
253 // parse style section
254 while (!finished && lex.isOK() && !error) {
256 // See comment in LyXRC.cpp.
258 case Lexer::LEX_FEOF:
261 case Lexer::LEX_UNDEF: // parse error
262 lex.printError("Unknown LaTeXFont tag `$$Token'");
269 switch (static_cast<LaTeXFontTags>(le)) {
270 case LF_END: // end of structure
273 case LF_ALT_PACKAGES: {
275 docstring altp = lex.getDocString();
276 altpackages_ = getVectorFromString(altp);
279 case LF_COMPLETE_PACKAGE:
280 lex >> completepackage_;
306 case LF_PACKAGEOPTION:
307 lex >> packageoption_;
311 string features = lex.getString();
312 provides_ = getVectorFromString(features);
324 case LF_SWITCHDEFAULT:
325 lex >> switchdefault_;
330 lex.printError("No End tag found for LaTeXFont tag `$$Token'");
334 return finished && !error;
338 bool LaTeXFont::read(Lexer & lex)
344 lex.printError("No name given for LaTeX font: `$$Token'.");
348 name_ = lex.getDocString();
349 LYXERR(Debug::INFO, "Reading LaTeX font " << name_);
350 if (!readFont(lex)) {
351 LYXERR0("Error parsing LaTeX font `" << name_ << '\'');
355 bool available = true;
356 if (!requires_.empty())
357 available = LaTeXFeatures::isAvailable(to_ascii(requires_));
358 else if (!package_.empty()) {
359 available = LaTeXFeatures::isAvailable(to_ascii(package_));
360 if (!available && !altpackages_.empty()) {
361 for (size_t i = 0; i < altpackages_.size(); ++i) {
362 available = LaTeXFeatures::isAvailable(to_ascii(altpackages_[i]));
368 available_ = available;
370 if (!ot1package_.empty() && ot1package_ != "none")
371 available_ot1_ = LaTeXFeatures::isAvailable(to_ascii(ot1package_));
373 available_ot1_ = available;
379 void LaTeXFonts::readLaTeXFonts()
381 // Read latexfonts file
382 FileName filename = libFileSearch(string(), "latexfonts");
383 if (filename.empty()) {
384 LYXERR0("Error: latexfonts file not found!");
388 lex.setFile(filename);
389 lex.setContext("LaTeXFeatures::readLaTeXFonts");
393 case Lexer::LEX_FEOF:
399 if (lex.getString() != "Font") {
400 lex.printError("Unknown LaTeXFont tag `$$Token'");
408 texfontmap_[f.name()] = f;
413 LaTeXFonts::TexFontMap LaTeXFonts::getLaTeXFonts()
415 if (texfontmap_.empty())
421 LaTeXFont LaTeXFonts::getLaTeXFont(docstring const & name)
423 if (name == "default")
425 if (texfontmap_.empty())
427 if (texfontmap_.find(name) == texfontmap_.end()) {
428 LYXERR0("LaTeXFonts::getLaTeXFont: font '" << name << "' not found!");
431 return texfontmap_[name];