Clean up LaTeX font handling (#4999)

The LaTeX font information are now centralized and outsourced. This removes a lot of hardcoding and duplication and makes it easier to support new LaTeX fonts.
This commit is contained in:
Juergen Spitzmueller 2012-08-16 13:23:39 +02:00
parent 4f1fb3f6d1
commit 869b84aef9
13 changed files with 923 additions and 241 deletions

View File

@ -91,6 +91,7 @@ SOURCES += \
../../src/Language.cpp \ ../../src/Language.cpp \
../../src/LaTeX.cpp \ ../../src/LaTeX.cpp \
../../src/LaTeXFeatures.cpp \ ../../src/LaTeXFeatures.cpp \
../../src/LaTeXFonts.cpp \
../../src/Layout.cpp \ ../../src/Layout.cpp \
../../src/LayoutFile.cpp \ ../../src/LayoutFile.cpp \
../../src/LayoutModuleList.cpp \ ../../src/LayoutModuleList.cpp \
@ -439,6 +440,7 @@ HEADERS += \
../../src/KeySequence.h \ ../../src/KeySequence.h \
../../src/Language.h \ ../../src/Language.h \
../../src/LaTeXFeatures.h \ ../../src/LaTeXFeatures.h \
../../src/LaTeXFonts.h \
../../src/LaTeX.h \ ../../src/LaTeX.h \
../../src/LayoutEnums.h \ ../../src/LayoutEnums.h \
../../src/LayoutFile.h \ ../../src/LayoutFile.h \

View File

@ -5,7 +5,7 @@ SUBDIRS = doc lyx2lyx
CHMOD = chmod CHMOD = chmod
dist_pkgdata_DATA = CREDITS autocorrect chkconfig.ltx external_templates \ dist_pkgdata_DATA = CREDITS autocorrect chkconfig.ltx external_templates \
encodings layouttranslations languages symbols syntax.default \ encodings layouttranslations languages latexfonts symbols syntax.default \
unicodesymbols unicodesymbols
nodist_pkgdata_DATA = installed_translations nodist_pkgdata_DATA = installed_translations

242
lib/latexfonts Normal file
View File

@ -0,0 +1,242 @@
##########################################################################
#
# LaTeX fonts natively supported by LyX.
#
# Syntax:
#
# Font <name>
# GuiName "<Gui Name>"
# Family <rm|sf|tt>
# SwitchDefault <0|1>
# Package <LaTeX package to be loaded>
# Requires <LaTeX package to test for>
# AltPackages <alternative packages (comma-separated)>
# OT1Package <alternative package specifically for OT1 encoding>
# CompletePackage <alternative package for the complete family>
# OsfOption <option for oldstyle figure support>
# ScOption <option for true smallcaps support>
# OsfScOption <option for combined osf and true smallcaps support>
# ScaleOption <option for font scaling>
# EndFont
#
#
# NOTES:
#
# * Adding a new font results in a FILE FORMAT CHANGE. So if a new font
# is added for the LyX distribution, the according changes need to be
# done.
# * "SwitchDefault 1" makes the font to be loaded by switching the default
# family to <name> (e.g., \renewcommand{\rmdefault}{cmr}), whereas
# Package <package> loads it via \usepackage{package}. Normally, only
# one of these options is used per font.
# * If AltPackages are defined, LyX will try to load them in the defined
# order if the main package is not available. So
# Package mathptmx
# AltPackages mathptm,times
# will try to load mathptm if mathptmx is not available and then times
# if mathptm is not available either.
# * If Requires is set, LyX will check for this. If not, it will check
# for Package and AltPackages.
# * OT1Package will load the defined package instead of the default
# package if the font encoding is OT1. This is necessary since some
# newer packages for a font do not support this encoding.
# The value "none" tells LyX not to load a package in OT1 encoding.
# * CompletePackage is a package that is loaded if the current font is
# selected as rm and both sf and tt are set to "default" (this allows
# f. ex. to load "bera" as opposed to "beraserif").
# * OsfScOption overrides any OsfOption and ScOption if both features
# are selected.
# * ScaleOption supports the placeholder $$val for the scale value.
#
##########################################################################
#
# Roman fonts
#
Font cmr
GuiName "Computer Modern Roman"
Family rm
SwitchDefault 1
OsfPackage eco
EndFont
Font lmodern
GuiName "Latin Modern Roman"
Family rm
Package lmodern
EndFont
Font ae
GuiName "AE (Almost European)"
Family rm
Package "ae,aecompl"
OT1Package none
Requires ae
EndFont
Font times
GuiName "Times Roman"
Family rm
Package mathptmx
AltPackages "mathptm,times"
Requires psnfss
EndFont
Font palatino
GuiName "Palatino"
Family rm
OsfOption osf
ScOption sc
OsfScOption osf
Package mathpazo
AltPackages "mathpple,palatino"
Requires psnfss
EndFont
Font charter
GuiName "Bitstream Charter"
Family rm
Package charter
EndFont
Font newcent
GuiName "New Century Schoolbook"
Family rm
Package newcent
EndFont
Font bookman
GuiName "Bookman"
Family rm
Package bookman
EndFont
# fourier supersedes utopia.sty, but does
# not work with OT1 encoding.
Font utopia
GuiName "Utopia"
Family rm
OsfOption oldstyle
ScOption expert
Package fourier
AltPackages utopia
OT1Package utopia
EndFont
Font beraserif
GuiName "Bera Serif"
Family rm
Package beraserif
CompletePackage bera
Requires bera
EndFont
Font ccfonts
GuiName "Concrete Roman"
Family rm
Package ccfonts
EndFont
Font chancery
GuiName "Zapf Chancery"
Family rm
Package chancery
EndFont
#
# SansSerif fonts
#
Font cmss
GuiName "Computer Modern Sans"
Family sf
SwitchDefault 1
EndFont
Font lmss
GuiName "Latin Modern Sans"
Family sf
SwitchDefault 1
Requires lmodern
EndFont
Font helvet
GuiName "Helvetica"
Family sf
ScaleOption scaled=$$val
Package helvet
Requires psnfss
EndFont
Font avant
GuiName "Avant Garde"
Family sf
Package avant
EndFont
Font berasans
GuiName "Bera Sans"
Family sf
ScaleOption scaled=$$val
Package berasans
Requires bera
EndFont
Font cmbr
GuiName "CM Bright"
Family sf
SwitchDefault 1
Requires cmbright
EndFont
#
# Monospaced fonts
#
Font cmtt
GuiName "Computer Modern Typewriter"
Family tt
SwitchDefault 1
EndFont
Font lmtt
GuiName "Latin Modern Typewriter"
Family tt
SwitchDefault 1
Requires lmodern
EndFont
Font courier
GuiName "Courier"
Family tt
Package courier
Requires psnfss
EndFont
Font beramono
GuiName "Bera Mono"
Family tt
ScaleOption scaled=$$val
Package beramono
Requires bera
EndFont
Font luximono
GuiName "LuxiMono"
Family tt
ScaleOption scaled=$$val
Package luximono
EndFont
Font cmtl
GuiName "CM Typewriter Light"
Family tt
SwitchDefault 1
Requires cmbright
EndFont

View File

@ -38,6 +38,9 @@ $(top_srcdir)/lib/layouttranslations: $(POFILES) $(top_srcdir)/lib/layouts/*.lay
languages_l10n.pot: $(top_srcdir)/lib/languages languages_l10n.pot: $(top_srcdir)/lib/languages
$(PYTHON) $(srcdir)/lyx_pot.py -b $(top_srcdir) -o $@ -t languages ${top_srcdir}/lib/languages $(PYTHON) $(srcdir)/lyx_pot.py -b $(top_srcdir) -o $@ -t languages ${top_srcdir}/lib/languages
latexfonts_l10n.pot: $(top_srcdir)/lib/latexfonts
$(PYTHON) $(srcdir)/lyx_pot.py -b $(top_srcdir) -o $@ -t latexfonts ${top_srcdir}/lib/latexfonts
encodings_l10n.pot: $(top_srcdir)/lib/encodings encodings_l10n.pot: $(top_srcdir)/lib/encodings
$(PYTHON) $(srcdir)/lyx_pot.py -b $(top_srcdir) -o $@ -t encodings ${top_srcdir}/lib/encodings $(PYTHON) $(srcdir)/lyx_pot.py -b $(top_srcdir) -o $@ -t encodings ${top_srcdir}/lib/encodings

View File

@ -435,6 +435,26 @@ def languages_l10n(input_files, output, base):
out.close() out.close()
def latexfonts_l10n(input_files, output, base):
'''Generate pot file from lib/latexfonts'''
out = open(output, 'w')
GuiName = re.compile(r'^[^#]*GuiName\s+(.*)', re.IGNORECASE)
for src in input_files:
descStartLine = -1
descLines = []
lineno = 0
for line in open(src).readlines():
lineno += 1
res = GuiName.search(line)
if res != None:
string = res.group(1)
writeString(out, src, base, lineno, string)
continue
out.close()
def external_l10n(input_files, output, base): def external_l10n(input_files, output, base):
'''Generate pot file from lib/external_templates''' '''Generate pot file from lib/external_templates'''
output = open(output, 'w') output = open(output, 'w')
@ -553,6 +573,7 @@ where
layouttranslations: create lib/layouttranslations from po/*.po and lib/layouts/* layouttranslations: create lib/layouttranslations from po/*.po and lib/layouts/*
qt4: qt4 ui files qt4: qt4 ui files
languages: file lib/languages languages: file lib/languages
latexfonts: file lib/latexfonts
encodings: file lib/encodings encodings: file lib/encodings
external: external templates file external: external templates file
formats: formats predefined in lib/configure.py formats: formats predefined in lib/configure.py
@ -579,7 +600,7 @@ if __name__ == '__main__':
elif opt in ['-s', '--src_file']: elif opt in ['-s', '--src_file']:
input_files = [f.strip() for f in open(value)] input_files = [f.strip() for f in open(value)]
if input_type not in ['ui', 'layouts', 'layouttranslations', 'qt4', 'languages', 'encodings', 'external', 'formats'] or output is None: if input_type not in ['ui', 'layouts', 'layouttranslations', 'qt4', 'languages', 'latexfonts', 'encodings', 'external', 'formats'] or output is None:
print 'Wrong input type or output filename.' print 'Wrong input type or output filename.'
sys.exit(1) sys.exit(1)
@ -587,6 +608,8 @@ if __name__ == '__main__':
if input_type == 'ui': if input_type == 'ui':
ui_l10n(input_files, output, base) ui_l10n(input_files, output, base)
elif input_type == 'latexfonts':
latexfonts_l10n(input_files, output, base)
elif input_type == 'layouts': elif input_type == 'layouts':
layouts_l10n(input_files, output, base, False) layouts_l10n(input_files, output, base, False)
elif input_type == 'layouttranslations': elif input_type == 'layouttranslations':

View File

@ -30,6 +30,7 @@
#include "IndicesList.h" #include "IndicesList.h"
#include "Language.h" #include "Language.h"
#include "LaTeXFeatures.h" #include "LaTeXFeatures.h"
#include "LaTeXFonts.h"
#include "ModuleList.h" #include "ModuleList.h"
#include "Font.h" #include "Font.h"
#include "Lexer.h" #include "Lexer.h"
@ -2856,115 +2857,50 @@ string const BufferParams::loadFonts(string const & rm,
return os.str(); return os.str();
} }
// Tex Fonts
bool const ot1 = (font_encoding() == "default" || font_encoding() == "OT1");
// ROMAN FONTS // ROMAN FONTS
// Computer Modern (must be explicitly selectable -- there might be classes LaTeXFont roman = theLaTeXFonts().getLaTeXFont(from_ascii(rm));
// that define a different default font! if (roman.switchdefault())
if (rm == "cmr") { os << "\\renewcommand{\\rmdefault}{" << to_ascii(roman.name()) << "}\n";
os << "\\renewcommand{\\rmdefault}{cmr}\n"; else {
// osf for Computer Modern needs eco.sty bool const complete = (sf == "default" && tt == "default");
if (osf) string const package = roman.getAvailablePackage(ot1, complete);
os << "\\usepackage{eco}\n"; string const packageopts = roman.getPackageOptions(ot1, sc, osf);
if (packageopts.empty() && !package.empty())
os << "\\usepackage{" << package << "}\n";
else if (!packageopts.empty() && !package.empty())
os << "\\usepackage[" << packageopts << "]{" << package << "}\n";
} }
// Latin Modern Roman if (osf && roman.providesOSF(ot1) && !roman.osfpackage().empty())
else if (rm == "lmodern") os << "\\usepackage{" << to_ascii(roman.osfpackage()) << "}\n";
os << "\\usepackage{lmodern}\n";
// AE
else if (rm == "ae") {
// not needed when using OT1 font encoding.
if (font_encoding() != "default")
os << "\\usepackage{ae,aecompl}\n";
}
// Times
else if (rm == "times") {
// try to load the best available package
if (LaTeXFeatures::isAvailable("mathptmx"))
os << "\\usepackage{mathptmx}\n";
else if (LaTeXFeatures::isAvailable("mathptm"))
os << "\\usepackage{mathptm}\n";
else
os << "\\usepackage{times}\n";
}
// Palatino
else if (rm == "palatino") {
// try to load the best available package
if (LaTeXFeatures::isAvailable("mathpazo")) {
os << "\\usepackage";
if (osf || sc) {
os << '[';
if (!osf)
os << "sc";
else
// "osf" includes "sc"!
os << "osf";
os << ']';
}
os << "{mathpazo}\n";
}
else if (LaTeXFeatures::isAvailable("mathpple"))
os << "\\usepackage{mathpple}\n";
else
os << "\\usepackage{palatino}\n";
}
// Utopia
else if (rm == "utopia") {
// fourier supersedes utopia.sty, but does
// not work with OT1 encoding.
if (LaTeXFeatures::isAvailable("fourier")
&& font_encoding() != "default") {
os << "\\usepackage";
if (osf || sc) {
os << '[';
if (sc)
os << "expert";
if (osf && sc)
os << ',';
if (osf)
os << "oldstyle";
os << ']';
}
os << "{fourier}\n";
}
else
os << "\\usepackage{utopia}\n";
}
// Bera (complete fontset)
else if (rm == "bera" && sf == "default" && tt == "default")
os << "\\usepackage{bera}\n";
// everything else
else if (rm != "default")
os << "\\usepackage" << "{" << rm << "}\n";
// SANS SERIF // SANS SERIF
// Helvetica, Bera Sans LaTeXFont sans = theLaTeXFonts().getLaTeXFont(from_ascii(sf));
if (sf == "helvet" || sf == "berasans") { if (sans.switchdefault())
if (sfscale != 100) os << "\\renewcommand{\\sfdefault}{" << to_ascii(sans.name()) << "}\n";
os << "\\usepackage[scaled=" << float(sfscale) / 100 else {
<< "]{" << sf << "}\n"; string const package = sans.getAvailablePackage(ot1);
else string const packageopts = sans.getPackageOptions(ot1, sc, osf, sfscale);
os << "\\usepackage{" << sf << "}\n"; if (packageopts.empty() && !package.empty())
os << "\\usepackage{" << package << "}\n";
else if (!packageopts.empty() && !package.empty())
os << "\\usepackage[" << packageopts << "]{" << package << "}\n";
} }
// Avant Garde
else if (sf == "avant")
os << "\\usepackage{" << sf << "}\n";
// Computer Modern, Latin Modern, CM Bright
else if (sf != "default")
os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
// monospaced/typewriter // MONOSPACED/TYPEWRITER
// Courier, LuxiMono LaTeXFont mono = theLaTeXFonts().getLaTeXFont(from_ascii(tt));
if (tt == "luximono" || tt == "beramono") { if (mono.switchdefault())
if (ttscale != 100) os << "\\renewcommand{\\ttdefault}{" << to_ascii(mono.name()) << "}\n";
os << "\\usepackage[scaled=" << float(ttscale) / 100 else {
<< "]{" << tt << "}\n"; string const package = mono.getAvailablePackage(ot1);
else string const packageopts = mono.getPackageOptions(ot1, sc, osf, ttscale);
os << "\\usepackage{" << tt << "}\n"; if (packageopts.empty() && !package.empty())
os << "\\usepackage{" << package << "}\n";
else if (!packageopts.empty() && !package.empty())
os << "\\usepackage[" << packageopts << "]{" << package << "}\n";
} }
// Courier
else if (tt == "courier" )
os << "\\usepackage{" << tt << "}\n";
// Computer Modern, Latin Modern, CM Bright
else if (tt != "default")
os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
return os.str(); return os.str();
} }

335
src/LaTeXFonts.cpp Normal file
View File

@ -0,0 +1,335 @@
/**
* \file LaTeXFonts.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "LaTeXFonts.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "support/convert.h"
#include "support/debug.h"
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/lstrings.h"
using namespace std;
using namespace lyx::support;
namespace lyx {
LaTeXFonts latexfonts;
bool LaTeXFont::available(bool ot1) const
{
return ot1 ? available_ot1_ : available_;
}
bool LaTeXFont::providesOSF(bool ot1) const
{
if (!osfpackage_.empty())
return LaTeXFeatures::isAvailable(to_ascii(osfpackage_));
if (ot1 && !ot1package_.empty() && ot1package_ != "none")
return false;
if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
return false;
return (!osfoption_.empty() || !osfscoption_.empty());
}
bool LaTeXFont::providesSC(bool ot1) const
{
if (ot1 && !ot1package_.empty() && ot1package_ != "none")
return false;
if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
return false;
return (!scoption_.empty() || !osfscoption_.empty());
}
bool LaTeXFont::providesScale(bool ot1) const
{
if (ot1 && !ot1package_.empty() && ot1package_ != "none")
return false;
if (!package_.empty() && !LaTeXFeatures::isAvailable(to_ascii(package_)))
return false;
return (!scaleoption_.empty());
}
string const LaTeXFont::getAvailablePackage(bool ot1, bool complete)
{
if (ot1 && !ot1package_.empty()) {
if (ot1package_ != "none" && LaTeXFeatures::isAvailable(to_ascii(ot1package_)))
return to_ascii(ot1package_);
return string();
}
if (complete && !completepackage_.empty()) {
if (LaTeXFeatures::isAvailable(to_ascii(completepackage_)))
return to_ascii(completepackage_);
}
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]);
}
}
}
return string();
}
string const LaTeXFont::getPackageOptions(bool const & ot1, bool const & sc,
bool const & osf, int const & scale)
{
if (ot1 && !ot1package_.empty())
return string();
ostringstream os;
if (sc && osf && providesOSF() && providesSC()) {
if (!osfscoption_.empty())
os << to_ascii(osfscoption_);
else
os << to_ascii(osfoption_) << ',' << to_ascii(scoption_);
} else if (osf && providesOSF())
os << to_ascii(osfoption_);
else if (sc && providesSC())
os << to_ascii(scoption_);
if (scale != 100 && !scaleoption_.empty()) {
if (!os.str().empty())
os << ',';
os << subst(to_ascii(scaleoption_), "$$val",
convert<std::string>(float(scale) / 100));
}
return os.str();
}
bool LaTeXFont::readFont(Lexer & lex)
{
enum LaTeXFontTags {
LF_ALT_PACKAGES = 1,
LF_COMPLETE_PACKAGE,
LF_END,
LF_FAMILY,
LF_GUINAME,
LF_OSFOPTION,
LF_OSFPACKAGE,
LF_OSFSCOPTION,
LF_OT1_PACKAGE,
LF_PACKAGE,
LF_REQUIRES,
LF_SCALEOPTION,
LF_SCOPTION,
LF_SWITCHDEFAULT
};
// Keep these sorted alphabetically!
LexerKeyword latexFontTags[] = {
{ "altpackages", LF_ALT_PACKAGES },
{ "completepackage", LF_COMPLETE_PACKAGE },
{ "endfont", LF_END },
{ "family", LF_FAMILY },
{ "guiname", LF_GUINAME },
{ "osfoption", LF_OSFOPTION },
{ "osfpackage", LF_OSFPACKAGE },
{ "osfscoption", LF_OSFSCOPTION },
{ "ot1package", LF_OT1_PACKAGE },
{ "package", LF_PACKAGE },
{ "requires", LF_REQUIRES },
{ "scaleoption", LF_SCALEOPTION },
{ "scoption", LF_SCOPTION },
{ "switchdefault", LF_SWITCHDEFAULT }
};
bool error = false;
bool finished = false;
lex.pushTable(latexFontTags);
// parse style section
while (!finished && lex.isOK() && !error) {
int le = lex.lex();
// See comment in LyXRC.cpp.
switch (le) {
case Lexer::LEX_FEOF:
continue;
case Lexer::LEX_UNDEF: // parse error
lex.printError("Unknown LaTeXFont tag `$$Token'");
error = true;
continue;
default:
break;
}
switch (static_cast<LaTeXFontTags>(le)) {
case LF_END: // end of structure
finished = true;
break;
case LF_ALT_PACKAGES: {
docstring altp;
lex >> altp;
altpackages_ = getVectorFromString(altp);
break;
}
case LF_COMPLETE_PACKAGE:
lex >> completepackage_;
break;
case LF_FAMILY:
lex >> family_;
break;
case LF_GUINAME:
lex >> guiname_;
break;
case LF_OSFOPTION:
lex >> osfoption_;
break;
case LF_OSFPACKAGE:
lex >> osfpackage_;
break;
case LF_OSFSCOPTION:
lex >> osfscoption_;
break;
case LF_OT1_PACKAGE:
lex >> ot1package_;
break;
case LF_PACKAGE:
lex >> package_;
break;
case LF_REQUIRES:
lex >> requires_;
break;
case LF_SCALEOPTION:
lex >> scaleoption_;
break;
case LF_SCOPTION:
lex >> scoption_;
break;
case LF_SWITCHDEFAULT:
lex >> switchdefault_;
break;
}
}
if (!finished) {
lex.printError("No End tag found for LaTeXFont tag `$$Token'");
return false;
}
lex.popTable();
return finished && !error;
}
bool LaTeXFont::read(Lexer & lex)
{
switchdefault_ = 0;
if (!lex.next()) {
lex.printError("No name given for LaTeX font: `$$Token'.");
return false;
}
name_ = lex.getDocString();
LYXERR(Debug::INFO, "Reading LaTeX font " << name_);
if (!readFont(lex)) {
LYXERR0("Error parsing LaTeX font `" << name_ << '\'');
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;
return true;
}
void LaTeXFonts::readLaTeXFonts()
{
// Read latexfonts file
FileName filename = libFileSearch(string(), "latexfonts");
if (filename.empty()) {
LYXERR0("Error: latexfonts file not found!");
return;
}
Lexer lex;
lex.setFile(filename);
lex.setContext("LaTeXFeatures::readLaTeXFonts");
while (lex.isOK()) {
int le = lex.lex();
switch (le) {
case Lexer::LEX_FEOF:
continue;
default:
break;
}
if (lex.getString() != "Font") {
lex.printError("Unknown LaTeXFont tag `$$Token'");
continue;
}
LaTeXFont f;
f.read(lex);
if (!lex)
break;
texfontmap_[f.name()] = f;
}
}
LaTeXFonts::TexFontMap LaTeXFonts::getLaTeXFonts()
{
if (texfontmap_.empty())
readLaTeXFonts();
return texfontmap_;
}
LaTeXFont LaTeXFonts::getLaTeXFont(docstring const & name)
{
if (texfontmap_.empty())
readLaTeXFonts();
return texfontmap_[name];
}
} // namespace lyx

136
src/LaTeXFonts.h Normal file
View File

@ -0,0 +1,136 @@
// -*- C++ -*-
/**
* \file LaTeXFonts.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LATEXFONTS_H
#define LATEXFONTS_H
#include "support/docstring.h"
#include <map>
#include <vector>
namespace lyx {
class Lexer;
/// LaTeX Font definition
class LaTeXFont {
public:
/// TeX font
LaTeXFont() : switchdefault_(false) {}
/// The font name
docstring const & name() { return name_; }
/// The name to appear in the document dialog
docstring const & guiname() { return guiname_; }
/// Font family (rm, sf, tt)
docstring const & family() { return family_; }
/// The package that provides this font
docstring const & package() { return package_; }
/// Alternative packages if package() is not available
std::vector<docstring> const & altpackages() { return altpackages_; }
/// A package that provides all families
docstring const & completepackage() { return completepackage_; }
/// A package specifically needed for OT1 font encoding
docstring const & ot1package() { return ot1package_; }
/// A package that provides Old Style Figures for this font
docstring const & osfpackage() { return osfpackage_; }
/// A package option for Old Style Figures
docstring const & osfoption() { return osfoption_; }
/// A package option for true SmallCaps
docstring const & scoption() { return scoption_; }
/// A package option for both Old Style Figures and SmallCaps
docstring const & osfscoption() { return osfscoption_; }
/// A package option for font scaling
docstring const & scaleoption() { return scaleoption_; }
/// Alternative requirement to test for
docstring const & requires() { return requires_; }
/// Issue the familydefault switch
bool switchdefault() const { return switchdefault_; }
/// Is this font available?
bool available(bool ot1 = false) const;
/// Does this font provide Old Style Figures?
bool providesOSF(bool ot1 = false) const;
/// Does this font provide optional true SmallCaps?
bool providesSC(bool ot1 = false) const;
/// Does this font provide scaling?
bool providesScale(bool ot1 = false) const;
/// Return the preferred available package
std::string const getAvailablePackage(bool ot1 = false, bool complete = false);
/// Return the package options
std::string const getPackageOptions(bool const & ot1,
bool const & sc,
bool const & osf,
int const & scale = 100);
///
bool read(Lexer & lex);
///
bool readFont(Lexer & lex);
private:
///
docstring name_;
///
docstring guiname_;
///
docstring family_;
///
docstring package_;
///
std::vector<docstring> altpackages_;
///
docstring completepackage_;
///
docstring ot1package_;
///
docstring osfpackage_;
///
docstring osfoption_;
///
docstring scoption_;
///
docstring osfscoption_;
///
docstring scaleoption_;
///
docstring requires_;
///
bool switchdefault_;
///
bool available_;
///
bool available_ot1_;
};
/** The list of available LaTeX fonts
*/
class LaTeXFonts {
public:
///
typedef std::map<docstring, LaTeXFont> TexFontMap;
/// Get all LaTeXFonts
TexFontMap getLaTeXFonts();
/// Get a specific LaTeXFont \p name
LaTeXFont getLaTeXFont(docstring const & name);
private:
///
void readLaTeXFonts();
///
TexFontMap texfontmap_;
};
/// Implementation is in LyX.cpp
extern LaTeXFonts & theLaTeXFonts();
} // namespace lyx
#endif

View File

@ -34,6 +34,7 @@
#include "HunspellChecker.h" #include "HunspellChecker.h"
#include "KeyMap.h" #include "KeyMap.h"
#include "Language.h" #include "Language.h"
#include "LaTeXFonts.h"
#include "LayoutFile.h" #include "LayoutFile.h"
#include "Lexer.h" #include "Lexer.h"
#include "LyX.h" #include "LyX.h"
@ -139,12 +140,13 @@ void reconfigureUserLyXDir()
/// The main application class private implementation. /// The main application class private implementation.
struct LyX::Impl struct LyX::Impl
{ {
Impl() : spell_checker_(0), apple_spell_checker_(0), aspell_checker_(0), enchant_checker_(0), hunspell_checker_(0) Impl() : latexfonts_(0), spell_checker_(0), apple_spell_checker_(0), aspell_checker_(0), enchant_checker_(0), hunspell_checker_(0)
{ {
} }
~Impl() ~Impl()
{ {
delete latexfonts_;
delete apple_spell_checker_; delete apple_spell_checker_;
delete aspell_checker_; delete aspell_checker_;
delete enchant_checker_; delete enchant_checker_;
@ -188,6 +190,9 @@ struct LyX::Impl
/// the parsed command line batch command if any /// the parsed command line batch command if any
vector<string> batch_commands; vector<string> batch_commands;
///
LaTeXFonts * latexfonts_;
/// ///
SpellChecker * spell_checker_; SpellChecker * spell_checker_;
/// ///
@ -1387,6 +1392,15 @@ Session & theSession()
} }
LaTeXFonts & theLaTeXFonts()
{
LASSERT(singleton_, /**/);
if (!singleton_->pimpl_->latexfonts_)
singleton_->pimpl_->latexfonts_ = new LaTeXFonts;
return *singleton_->pimpl_->latexfonts_;
}
CmdDef & theTopLevelCmdDef() CmdDef & theTopLevelCmdDef()
{ {
LASSERT(singleton_, /**/); LASSERT(singleton_, /**/);

View File

@ -28,6 +28,7 @@ class ErrorItem;
class FuncRequest; class FuncRequest;
class FuncStatus; class FuncStatus;
class KeyMap; class KeyMap;
class LaTeXFonts;
class Messages; class Messages;
class Mover; class Mover;
class Movers; class Movers;
@ -148,6 +149,7 @@ private:
friend Movers & theSystemMovers(); friend Movers & theSystemMovers();
friend frontend::Application * theApp(); friend frontend::Application * theApp();
friend Session & theSession(); friend Session & theSession();
friend LaTeXFonts & theLaTeXFonts();
friend CmdDef & theTopLevelCmdDef(); friend CmdDef & theTopLevelCmdDef();
friend SpellChecker * theSpellChecker(); friend SpellChecker * theSpellChecker();
friend void setSpellChecker(); friend void setSpellChecker();

View File

@ -85,6 +85,8 @@ lyx_SOURCES = \
$(ENCHANT) \ $(ENCHANT) \
$(HUNSPELL) \ $(HUNSPELL) \
$(PWL) \ $(PWL) \
LaTeXFonts.cpp \
LaTeXFonts.h \
PrinterParams.cpp \ PrinterParams.cpp \
PrinterParams.h \ PrinterParams.h \
Thesaurus.cpp \ Thesaurus.cpp \

View File

@ -38,6 +38,7 @@
#include "IndicesList.h" #include "IndicesList.h"
#include "Language.h" #include "Language.h"
#include "LaTeXFeatures.h" #include "LaTeXFeatures.h"
#include "LaTeXFonts.h"
#include "Layout.h" #include "Layout.h"
#include "LayoutModuleList.h" #include "LayoutModuleList.h"
#include "LyXRC.h" #include "LyXRC.h"
@ -115,51 +116,6 @@ char const * const tex_graphics_gui[] =
}; };
char const * const tex_fonts_roman[] =
{
"default", "cmr", "lmodern", "ae", "times", "palatino",
"charter", "newcent", "bookman", "utopia", "beraserif",
"ccfonts", "chancery", ""
};
char const * tex_fonts_roman_gui[] =
{
N_("Default"), N_("Computer Modern Roman"), N_("Latin Modern Roman"),
N_("AE (Almost European)"), N_("Times Roman"), N_("Palatino"),
N_("Bitstream Charter"), N_("New Century Schoolbook"), N_("Bookman"),
N_("Utopia"), N_("Bera Serif"), N_("Concrete Roman"), N_("Zapf Chancery"),
""
};
char const * const tex_fonts_sans[] =
{
"default", "cmss", "lmss", "helvet", "avant", "berasans", "cmbr", ""
};
char const * tex_fonts_sans_gui[] =
{
N_("Default"), N_("Computer Modern Sans"), N_("Latin Modern Sans"),
N_("Helvetica"), N_("Avant Garde"), N_("Bera Sans"), N_("CM Bright"), ""
};
char const * const tex_fonts_monospaced[] =
{
"default", "cmtt", "lmtt", "courier", "beramono", "luximono", "cmtl", ""
};
char const * tex_fonts_monospaced_gui[] =
{
N_("Default"), N_("Computer Modern Typewriter"),
N_("Latin Modern Typewriter"), N_("Courier"), N_("Bera Mono"),
N_("LuxiMono"), N_("CM Typewriter Light"), ""
};
char const * backref_opts[] = char const * backref_opts[] =
{ {
"false", "section", "slide", "page", "" "false", "section", "slide", "page", ""
@ -209,6 +165,10 @@ char const * packages_gui[][4] =
vector<string> engine_types_; vector<string> engine_types_;
vector<pair<string, QString> > pagestyles; vector<pair<string, QString> > pagestyles;
QMap<QString, QString> rmfonts_;
QMap<QString, QString> sffonts_;
QMap<QString, QString> ttfonts_;
} // anonymous namespace } // anonymous namespace
@ -890,9 +850,9 @@ GuiDocument::GuiDocument(GuiView & lv)
fontModule->fontsizeCO->addItem(qt_("11")); fontModule->fontsizeCO->addItem(qt_("11"));
fontModule->fontsizeCO->addItem(qt_("12")); fontModule->fontsizeCO->addItem(qt_("12"));
fontModule->fontencCO->addItem(qt_("Default")); fontModule->fontencCO->addItem(qt_("Default"), QString("global"));
fontModule->fontencCO->addItem(qt_("Custom")); fontModule->fontencCO->addItem(qt_("Custom"), QString("custom"));
fontModule->fontencCO->addItem(qt_("None (no fontenc)")); fontModule->fontencCO->addItem(qt_("None (no fontenc)"), QString("default"));
for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n) for (int n = 0; GuiDocument::fontfamilies_gui[n][0]; ++n)
fontModule->fontsDefaultCO->addItem( fontModule->fontsDefaultCO->addItem(
@ -1808,21 +1768,8 @@ void GuiDocument::osFontsChanged(bool nontexfonts)
fontModule->fontsDefaultLA->setEnabled(tex_fonts); fontModule->fontsDefaultLA->setEnabled(tex_fonts);
fontModule->cjkFontLE->setEnabled(tex_fonts); fontModule->cjkFontLE->setEnabled(tex_fonts);
fontModule->cjkFontLA->setEnabled(tex_fonts); fontModule->cjkFontLA->setEnabled(tex_fonts);
string font;
if (tex_fonts) updateFontOptions();
font = tex_fonts_sans[fontModule->fontsSansCO->currentIndex()];
bool scaleable = providesScale(font);
fontModule->scaleSansSB->setEnabled(scaleable);
fontModule->scaleSansLA->setEnabled(scaleable);
if (tex_fonts)
font = tex_fonts_monospaced[fontModule->fontsTypewriterCO->currentIndex()];
scaleable = providesScale(font);
fontModule->scaleTypewriterSB->setEnabled(scaleable);
fontModule->scaleTypewriterLA->setEnabled(scaleable);
if (tex_fonts)
font = tex_fonts_roman[fontModule->fontsRomanCO->currentIndex()];
fontModule->fontScCB->setEnabled(providesSC(font));
fontModule->fontOsfCB->setEnabled(providesOSF(font));
fontModule->fontencLA->setEnabled(tex_fonts); fontModule->fontencLA->setEnabled(tex_fonts);
fontModule->fontencCO->setEnabled(tex_fonts); fontModule->fontencCO->setEnabled(tex_fonts);
@ -1833,6 +1780,30 @@ void GuiDocument::osFontsChanged(bool nontexfonts)
} }
void GuiDocument::updateFontOptions()
{
bool const tex_fonts = !fontModule->osFontsCB->isChecked();
QString font;
if (tex_fonts)
font = fontModule->fontsSansCO->itemData(
fontModule->fontsSansCO->currentIndex()).toString();
bool scaleable = providesScale(font);
fontModule->scaleSansSB->setEnabled(scaleable);
fontModule->scaleSansLA->setEnabled(scaleable);
if (tex_fonts)
font = fontModule->fontsTypewriterCO->itemData(
fontModule->fontsTypewriterCO->currentIndex()).toString();
scaleable = providesScale(font);
fontModule->scaleTypewriterSB->setEnabled(scaleable);
fontModule->scaleTypewriterLA->setEnabled(scaleable);
if (tex_fonts)
font = fontModule->fontsRomanCO->itemData(
fontModule->fontsRomanCO->currentIndex()).toString();
fontModule->fontScCB->setEnabled(providesSC(font));
fontModule->fontOsfCB->setEnabled(providesOSF(font));
}
void GuiDocument::updateFontsize(string const & items, string const & sel) void GuiDocument::updateFontsize(string const & items, string const & sel)
{ {
fontModule->fontsizeCO->clear(); fontModule->fontsizeCO->clear();
@ -1851,6 +1822,40 @@ void GuiDocument::updateFontsize(string const & items, string const & sel)
} }
bool GuiDocument::ot1() const
{
QString const fontenc =
fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
return (fontenc == "default"
|| (fontenc == "global" && (lyxrc.fontenc == "default" || lyxrc.fontenc == "OT1"))
|| (fontenc == "custom" && fontModule->fontencLE->text() == "OT1"));
}
void GuiDocument::updateTexFonts()
{
LaTeXFonts::TexFontMap texfontmap = theLaTeXFonts().getLaTeXFonts();
LaTeXFonts::TexFontMap::const_iterator it = texfontmap.begin();
LaTeXFonts::TexFontMap::const_iterator end = texfontmap.end();
for (; it != end; ++it) {
LaTeXFont lf = it->second;
if (lf.name().empty())
return;
docstring const family = lf.family();
docstring guiname = translateIfPossible(lf.guiname());
if (!lf.available(ot1()))
guiname += _(" (not installed)");
if (family == "rm")
rmfonts_.insert(toqstr(guiname), toqstr(it->first));
else if (family == "sf")
sffonts_.insert(toqstr(guiname), toqstr(it->first));
else if (family == "tt")
ttfonts_.insert(toqstr(guiname), toqstr(it->first));
}
}
void GuiDocument::updateFontlist() void GuiDocument::updateFontlist()
{ {
fontModule->fontsRomanCO->clear(); fontModule->fontsRomanCO->clear();
@ -1873,30 +1878,39 @@ void GuiDocument::updateFontlist()
return; return;
} }
for (int n = 0; tex_fonts_roman[n][0]; ++n) { if (rmfonts_.empty())
QString font = qt_(tex_fonts_roman_gui[n]); updateTexFonts();
if (!isFontAvailable(tex_fonts_roman[n]))
font += qt_(" (not installed)"); fontModule->fontsRomanCO->addItem(qt_("Default"), QString("default"));
fontModule->fontsRomanCO->addItem(font, qt_(tex_fonts_roman[n])); QMap<QString, QString>::const_iterator rmi = rmfonts_.constBegin();
while (rmi != rmfonts_.constEnd()) {
fontModule->fontsRomanCO->addItem(rmi.key(), rmi.value());
++rmi;
} }
for (int n = 0; tex_fonts_sans[n][0]; ++n) {
QString font = qt_(tex_fonts_sans_gui[n]); fontModule->fontsSansCO->addItem(qt_("Default"), QString("default"));
if (!isFontAvailable(tex_fonts_sans[n])) QMap<QString, QString>::const_iterator sfi = sffonts_.constBegin();
font += qt_(" (not installed)"); while (sfi != sffonts_.constEnd()) {
fontModule->fontsSansCO->addItem(font, qt_(tex_fonts_sans[n])); fontModule->fontsSansCO->addItem(sfi.key(), sfi.value());
++sfi;
} }
for (int n = 0; tex_fonts_monospaced[n][0]; ++n) {
QString font = qt_(tex_fonts_monospaced_gui[n]); fontModule->fontsTypewriterCO->addItem(qt_("Default"), QString("default"));
if (!isFontAvailable(tex_fonts_monospaced[n])) QMap<QString, QString>::const_iterator tti = ttfonts_.constBegin();
font += qt_(" (not installed)"); while (tti != ttfonts_.constEnd()) {
fontModule->fontsTypewriterCO->addItem(font, qt_(tex_fonts_monospaced[n])); fontModule->fontsTypewriterCO->addItem(tti.key(), tti.value());
++tti;
} }
} }
void GuiDocument::fontencChanged(int item) void GuiDocument::fontencChanged(int item)
{ {
fontModule->fontencLE->setEnabled(item == 1); fontModule->fontencLE->setEnabled(
fontModule->fontencCO->itemData(item).toString() == "custom");
// The availability of TeX fonts depends on the font encoding
updateTexFonts();
updateFontOptions();
} }
@ -1904,7 +1918,8 @@ void GuiDocument::romanChanged(int item)
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
return; return;
string const font = tex_fonts_roman[item]; QString const font =
fontModule->fontsRomanCO->itemData(item).toString();
fontModule->fontScCB->setEnabled(providesSC(font)); fontModule->fontScCB->setEnabled(providesSC(font));
fontModule->fontOsfCB->setEnabled(providesOSF(font)); fontModule->fontOsfCB->setEnabled(providesOSF(font));
} }
@ -1914,7 +1929,8 @@ void GuiDocument::sansChanged(int item)
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
return; return;
string const font = tex_fonts_sans[item]; QString const font =
fontModule->fontsSansCO->itemData(item).toString();
bool scaleable = providesScale(font); bool scaleable = providesScale(font);
fontModule->scaleSansSB->setEnabled(scaleable); fontModule->scaleSansSB->setEnabled(scaleable);
fontModule->scaleSansLA->setEnabled(scaleable); fontModule->scaleSansLA->setEnabled(scaleable);
@ -1925,7 +1941,8 @@ void GuiDocument::ttChanged(int item)
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
return; return;
string const font = tex_fonts_monospaced[item]; QString const font =
fontModule->fontsTypewriterCO->itemData(item).toString();
bool scaleable = providesScale(font); bool scaleable = providesScale(font);
fontModule->scaleTypewriterSB->setEnabled(scaleable); fontModule->scaleTypewriterSB->setEnabled(scaleable);
fontModule->scaleTypewriterLA->setEnabled(scaleable); fontModule->scaleTypewriterLA->setEnabled(scaleable);
@ -2680,12 +2697,12 @@ void GuiDocument::applyView()
fromqstr(fontModule->fontsTypewriterCO-> fromqstr(fontModule->fontsTypewriterCO->
itemData(fontModule->fontsTypewriterCO->currentIndex()).toString()); itemData(fontModule->fontsTypewriterCO->currentIndex()).toString());
if (fontModule->fontencCO->currentIndex() == 0) QString const fontenc =
bp_.fontenc = "global"; fontModule->fontencCO->itemData(fontModule->fontencCO->currentIndex()).toString();
else if (fontModule->fontencCO->currentIndex() == 1) if (fontenc == "custom")
bp_.fontenc = fromqstr(fontModule->fontencLE->text()); bp_.fontenc = fromqstr(fontModule->fontencLE->text());
else if (fontModule->fontencCO->currentIndex() == 2) else
bp_.fontenc = "default"; bp_.fontenc = fromqstr(fontenc);
bp_.fonts_cjk = bp_.fonts_cjk =
fromqstr(fontModule->cjkFontLE->text()); fromqstr(fontModule->cjkFontLE->text());
@ -3136,11 +3153,9 @@ void GuiDocument::paramsToDialog()
if (nn >= 0) if (nn >= 0)
fontModule->fontsDefaultCO->setCurrentIndex(nn); fontModule->fontsDefaultCO->setCurrentIndex(nn);
if (bp_.fontenc == "global") { if (bp_.fontenc == "global" || bp_.fontenc == "default") {
fontModule->fontencCO->setCurrentIndex(0); fontModule->fontencCO->setCurrentIndex(
fontModule->fontencLE->setEnabled(false); fontModule->fontencCO->findData(toqstr(bp_.fontenc)));
} else if (bp_.fontenc == "default") {
fontModule->fontencCO->setCurrentIndex(2);
fontModule->fontencLE->setEnabled(false); fontModule->fontencLE->setEnabled(false);
} else { } else {
fontModule->fontencCO->setCurrentIndex(1); fontModule->fontencCO->setCurrentIndex(1);
@ -3599,61 +3614,29 @@ void GuiDocument::saveAsDefault() const
} }
bool GuiDocument::isFontAvailable(string const & font) const bool GuiDocument::providesOSF(QString const & font) const
{
if (font == "default" || font == "cmr"
|| font == "cmss" || font == "cmtt")
// these are standard
return true;
if (font == "lmodern" || font == "lmss" || font == "lmtt")
return LaTeXFeatures::isAvailable("lmodern");
if (font == "times" || font == "palatino"
|| font == "helvet" || font == "courier")
return LaTeXFeatures::isAvailable("psnfss");
if (font == "cmbr" || font == "cmtl")
return LaTeXFeatures::isAvailable("cmbright");
if (font == "utopia")
return LaTeXFeatures::isAvailable("utopia")
|| LaTeXFeatures::isAvailable("fourier");
if (font == "beraserif" || font == "berasans"
|| font == "beramono")
return LaTeXFeatures::isAvailable("bera");
return LaTeXFeatures::isAvailable(font);
}
bool GuiDocument::providesOSF(string const & font) const
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
// FIXME: we should check if the fonts really // FIXME: we should check if the fonts really
// have OSF support. But how? // have OSF support. But how?
return true; return true;
if (font == "cmr") return theLaTeXFonts().getLaTeXFont(qstring_to_ucs4(font)).providesOSF(ot1());
return isFontAvailable("eco");
if (font == "palatino")
return isFontAvailable("mathpazo");
return false;
} }
bool GuiDocument::providesSC(string const & font) const bool GuiDocument::providesSC(QString const & font) const
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
return false; return false;
if (font == "palatino") return theLaTeXFonts().getLaTeXFont(qstring_to_ucs4(font)).providesSC(ot1());
return isFontAvailable("mathpazo");
if (font == "utopia")
return isFontAvailable("fourier");
return false;
} }
bool GuiDocument::providesScale(string const & font) const bool GuiDocument::providesScale(QString const & font) const
{ {
if (fontModule->osFontsCB->isChecked()) if (fontModule->osFontsCB->isChecked())
return true; return true;
return font == "helvet" || font == "luximono" return theLaTeXFonts().getLaTeXFont(qstring_to_ucs4(font)).providesScale(ot1());
|| font == "berasans" || font == "beramono";
} }

View File

@ -228,14 +228,12 @@ private:
void setLanguage() const; void setLanguage() const;
/// ///
void saveAsDefault() const; void saveAsDefault() const;
///
bool isFontAvailable(std::string const & font) const;
/// does this font provide Old Style figures? /// does this font provide Old Style figures?
bool providesOSF(std::string const & font) const; bool providesOSF(QString const & font) const;
/// does this font provide true Small Caps? /// does this font provide true Small Caps?
bool providesSC(std::string const & font) const; bool providesSC(QString const & font) const;
/// does this font provide size adjustment? /// does this font provide size adjustment?
bool providesScale(std::string const & font) const; bool providesScale(QString const & font) const;
/// ///
void executeBranchRenaming() const; void executeBranchRenaming() const;
/// ///
@ -246,6 +244,12 @@ private:
/// ///
void updateUnknownBranches(); void updateUnknownBranches();
/// ///
void updateTexFonts();
///
void updateFontOptions();
///
bool ot1() const;
///
BufferParams bp_; BufferParams bp_;
/// List of names of available modules /// List of names of available modules
std::list<modInfoStruct> moduleNames_; std::list<modInfoStruct> moduleNames_;