Add support for \babelfont

This is a higher-level (non-TeX) font interface of babel that draws on,
but is supposed to be used rather than, fontspec with babel and XeTeX/
LuaTeX.

File format change.

Addresses: #11614
This commit is contained in:
Juergen Spitzmueller 2019-07-11 13:21:32 +02:00
parent 0018e4ec96
commit cb5bd87e9c
5 changed files with 217 additions and 20 deletions

View File

@ -7,6 +7,9 @@ changes happened in particular if possible. A good example would be
----------------------- -----------------------
2019-07-11 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 579: Add support for \babelfont.
2019-06-23 Jürgen Spitzmüller <spitz@lyx.org> 2019-06-23 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 578: Add support for Discourse Representation Structures * Format incremented to 578: Add support for Discourse Representation Structures
in the Linguistics module (using drs package). in the Linguistics module (using drs package).

View File

@ -37,11 +37,11 @@ from parser_tools import (count_pars_in_inset, del_token, find_end_of_inset,
# is_in_inset, set_bool_value # is_in_inset, set_bool_value
# find_tokens, check_token # find_tokens, check_token
from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble, lyx2latex, from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble, insert_to_preamble, lyx2latex,
revert_language, revert_flex_inset) revert_language, revert_flex_inset, str2bool)
# revert_font_attrs, insert_to_preamble, latex_length # revert_font_attrs, latex_length
# get_ert, lyx2verbatim, length_in_bp, convert_info_insets # get_ert, lyx2verbatim, length_in_bp, convert_info_insets
# revert_flex_inset, hex2ratio, str2bool # revert_flex_inset, hex2ratio
#################################################################### ####################################################################
# Private helper functions # Private helper functions
@ -2172,6 +2172,117 @@ def revert_drs(document):
i = beginPlain i = beginPlain
def revert_babelfont(document):
" Reverts the use of \\babelfont to user preamble "
i = find_token(document.header, '\\use_non_tex_fonts', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\use_non_tex_fonts.")
return
if not str2bool(get_value(document.header, "\\use_non_tex_fonts", i)):
return
i = find_token(document.header, '\\language_package', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\language_package.")
return
if get_value(document.header, "\\language_package", 0) != "babel":
return
# check font settings
# defaults
roman = sans = typew = "default"
osf = False
sf_scale = tt_scale = 100.0
j = find_token(document.header, "\\font_roman", 0)
if j == -1:
document.warning("Malformed LyX document: Missing \\font_roman.")
else:
# We need to use this regex since split() does not handle quote protection
romanfont = re.findall(r'[^"\s]\S*|".+?"', document.header[j])
roman = romanfont[2].strip('"')
romanfont[2] = '"default"'
document.header[j] = " ".join(romanfont)
j = find_token(document.header, "\\font_sans", 0)
if j == -1:
document.warning("Malformed LyX document: Missing \\font_sans.")
else:
# We need to use this regex since split() does not handle quote protection
sansfont = re.findall(r'[^"\s]\S*|".+?"', document.header[j])
sans = sansfont[2].strip('"')
sansfont[2] = '"default"'
document.header[j] = " ".join(sansfont)
j = find_token(document.header, "\\font_typewriter", 0)
if j == -1:
document.warning("Malformed LyX document: Missing \\font_typewriter.")
else:
# We need to use this regex since split() does not handle quote protection
ttfont = re.findall(r'[^"\s]\S*|".+?"', document.header[j])
typew = ttfont[2].strip('"')
ttfont[2] = '"default"'
document.header[j] = " ".join(ttfont)
i = find_token(document.header, "\\font_osf", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_osf.")
else:
osf = str2bool(get_value(document.header, "\\font_osf", i))
j = find_token(document.header, "\\font_sf_scale", 0)
if j == -1:
document.warning("Malformed LyX document: Missing \\font_sf_scale.")
else:
sfscale = document.header[j].split()
val = sfscale[2]
sfscale[2] = "100"
document.header[j] = " ".join(sfscale)
try:
# float() can throw
sf_scale = float(val)
except:
document.warning("Invalid font_sf_scale value: " + val)
j = find_token(document.header, "\\font_tt_scale", 0)
if j == -1:
document.warning("Malformed LyX document: Missing \\font_tt_scale.")
else:
ttscale = document.header[j].split()
val = ttscale[2]
ttscale[2] = "100"
document.header[j] = " ".join(ttscale)
try:
# float() can throw
tt_scale = float(val)
except:
document.warning("Invalid font_tt_scale value: " + val)
# set preamble stuff
pretext = ['%% This document must be processed with xelatex or lualatex!']
pretext.append('\\AtBeginDocument{%')
if roman != "default":
pretext.append('\\babelfont{rm}[Mapping=tex-text]{' + roman + '}')
if sans != "default":
sf = '\\babelfont{sf}['
if sf_scale != 100.0:
sf += 'Scale=' + str(sf_scale / 100.0) + ','
sf += 'Mapping=tex-text]{' + sans + '}'
pretext.append(sf)
if typew != "default":
tw = '\\babelfont{tt}'
if tt_scale != 100.0:
tw += '[Scale=' + str(tt_scale / 100.0) + ']'
tw += '{' + typew + '}'
pretext.append(tw)
if osf:
pretext.append('\\defaultfontfeatures{Numbers=OldStyle}')
pretext.append('}')
insert_to_preamble(document, pretext)
## ##
# Conversion hub # Conversion hub
# #
@ -2211,10 +2322,12 @@ convert = [
[575, [convert_lineno]], [575, [convert_lineno]],
[576, []], [576, []],
[577, [convert_linggloss]], [577, [convert_linggloss]],
[578, []] [578, []],
[579, []]
] ]
revert = [[577, [revert_drs]], revert = [[578, [revert_babelfont]],
[577, [revert_drs]],
[576, [revert_linggloss, revert_subexarg]], [576, [revert_linggloss, revert_subexarg]],
[575, [revert_new_languages]], [575, [revert_new_languages]],
[574, [revert_lineno]], [574, [revert_lineno]],

View File

@ -1763,7 +1763,8 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
os << from_ascii(ams); os << from_ascii(ams);
if (useNonTeXFonts) { if (useNonTeXFonts) {
if (!features.isProvided("fontspec")) // Babel loads fontspec itself
if (!features.isProvided("fontspec") && !features.useBabel())
os << "\\usepackage{fontspec}\n"; os << "\\usepackage{fontspec}\n";
if (features.mustProvide("unicode-math") if (features.mustProvide("unicode-math")
&& features.isAvailable("unicode-math")) && features.isAvailable("unicode-math"))
@ -1781,8 +1782,9 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
} }
// font selection must be done before loading fontenc.sty // font selection must be done before loading fontenc.sty
// but after babel with non-TeX fonts
string const fonts = loadFonts(features); string const fonts = loadFonts(features);
if (!fonts.empty()) if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
os << from_utf8(fonts); os << from_utf8(fonts);
if (fonts_default_family != "default") if (fonts_default_family != "default")
@ -2313,6 +2315,10 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf"))) if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
writeEncodingPreamble(os, features); writeEncodingPreamble(os, features);
// font selection must be done after babel with non-TeX fonts
if (!fonts.empty() && features.useBabel() && useNonTeXFonts)
os << from_utf8(fonts);
if (features.isRequired("bicaption")) if (features.isRequired("bicaption"))
os << "\\usepackage{bicaption}\n"; os << "\\usepackage{bicaption}\n";
if (!listings_params.empty() if (!listings_params.empty()
@ -3391,36 +3397,60 @@ string const BufferParams::loadFonts(LaTeXFeatures & features) const
// variants are understood by both engines. However, // variants are understood by both engines. However,
// we want to provide support for at least TeXLive 2009 // we want to provide support for at least TeXLive 2009
// (for XeTeX; LuaTeX is only supported as of v.2) // (for XeTeX; LuaTeX is only supported as of v.2)
// Babel has its own higher-level interface on top of
// fontspec that is to be used.
bool const babel = features.useBabel();
string const texmapping = string const texmapping =
(features.runparams().flavor == OutputParams::XETEX) ? (features.runparams().flavor == OutputParams::XETEX) ?
"Mapping=tex-text" : "Ligatures=TeX"; "Mapping=tex-text" : "Ligatures=TeX";
if (fontsRoman() != "default") { if (fontsRoman() != "default") {
os << "\\setmainfont[" << texmapping; if (babel)
os << "\\babelfont{rm}[";
else
os << "\\setmainfont[";
os << texmapping;
if (fonts_old_figures) if (fonts_old_figures)
os << ",Numbers=OldStyle"; os << ",Numbers=OldStyle";
os << "]{" << parseFontName(fontsRoman()) << "}\n"; os << "]{" << parseFontName(fontsRoman()) << "}\n";
} }
if (fontsSans() != "default") { if (fontsSans() != "default") {
string const sans = parseFontName(fontsSans()); string const sans = parseFontName(fontsSans());
if (fontsSansScale() != 100) if (fontsSansScale() != 100) {
os << "\\setsansfont[Scale=" if (babel)
os << "\\babelfont{sf}";
else
os << "\\setsansfont";
os << "[Scale="
<< float(fontsSansScale()) / 100 << float(fontsSansScale()) / 100
<< "," << texmapping << "]{" << "," << texmapping << "]{"
<< sans << "}\n"; << sans << "}\n";
} else {
if (babel)
os << "\\babelfont{sf}[";
else else
os << "\\setsansfont[" << texmapping << "]{" os << "\\setsansfont[";
os << texmapping << "]{"
<< sans << "}\n"; << sans << "}\n";
} }
}
if (fontsTypewriter() != "default") { if (fontsTypewriter() != "default") {
string const mono = parseFontName(fontsTypewriter()); string const mono = parseFontName(fontsTypewriter());
if (fontsTypewriterScale() != 100) if (fontsTypewriterScale() != 100) {
os << "\\setmonofont[Scale=" if (babel)
os << "\\babelfont{tt}";
else
os << "\\setmonofont";
os << "[Scale="
<< float(fontsTypewriterScale()) / 100 << float(fontsTypewriterScale()) / 100
<< "]{" << "]{"
<< mono << "}\n"; << mono << "}\n";
} else {
if (babel)
os << "\\babelfont{tt}{";
else else
os << "\\setmonofont{" os << "\\setmonofont{";
<< mono << "}\n"; os << mono << "}\n";
}
} }
return os.str(); return os.str();
} }

View File

@ -1716,6 +1716,57 @@ void Preamble::parse(Parser & p, string const & forceclass,
continue; continue;
} }
if (t.cs() == "babelfont") {
xetex = true;
h_use_non_tex_fonts = true;
h_language_package = "babel";
if (h_inputencoding == "auto-legacy")
p.setEncoding("UTF-8");
// we don't care about the lang option
string const lang = p.hasOpt() ? p.getArg('[', ']') : string();
string const family = p.getArg('{', '}');
string const fontopts = p.hasOpt() ? p.getArg('[', ']') : string();
string const fontname = p.getArg('{', '}');
if (lang.empty() && family == "rm") {
h_font_roman[1] = fontname;
continue;
} else if (lang.empty() && (family == "sf" || family == "tt")) {
// LyX currently only supports the scale option
string scale;
if (!fontopts.empty()) {
// check if the option contains a scaling, if yes, extract it
string::size_type pos = fontopts.find("Scale");
if (pos != string::npos) {
string::size_type i = fontopts.find(',', pos);
if (i == string::npos)
scale_as_percentage(fontopts.substr(pos + 1), scale);
else
scale_as_percentage(fontopts.substr(pos, i - pos), scale);
}
}
if (family == "sf") {
if (!scale.empty())
h_font_sf_scale[1] = scale;
h_font_sans[1] = fontname;
} else {
if (!scale.empty())
h_font_tt_scale[1] = scale;
h_font_typewriter[1] = fontname;
}
continue;
} else {
// not rm, sf or tt or lang specific
h_preamble << '\\' << t.cs();
if (!lang.empty())
h_preamble << '[' << lang << ']';
h_preamble << '{' << family << '}';
if (!fontopts.empty())
h_preamble << '[' << fontopts << ']';
h_preamble << '{' << fontname << '}' << '\n';
continue;
}
}
if (t.cs() == "date") { if (t.cs() == "date") {
string argument = p.getArg('{', '}'); string argument = p.getArg('{', '}');
if (argument.empty()) if (argument.empty())

View File

@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in // Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own. // independent branches. Instead add your own.
#define LYX_FORMAT_LYX 578 // spitz: drs #define LYX_FORMAT_LYX 579 // spitz: babelfont
#define LYX_FORMAT_TEX2LYX 578 #define LYX_FORMAT_TEX2LYX 579
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER #ifndef _MSC_VER