-----------------------
+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>
* Format incremented to 578: Add support for Discourse Representation Structures
in the Linguistics module (using drs package).
# is_in_inset, set_bool_value
# find_tokens, check_token
-from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble, lyx2latex,
- revert_language, revert_flex_inset)
-# revert_font_attrs, insert_to_preamble, latex_length
+from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble, insert_to_preamble, lyx2latex,
+ revert_language, revert_flex_inset, str2bool)
+# revert_font_attrs, latex_length
# get_ert, lyx2verbatim, length_in_bp, convert_info_insets
-# revert_flex_inset, hex2ratio, str2bool
+# revert_flex_inset, hex2ratio
####################################################################
# Private helper functions
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
#
[575, [convert_lineno]],
[576, []],
[577, [convert_linggloss]],
- [578, []]
+ [578, []],
+ [579, []]
]
-revert = [[577, [revert_drs]],
+revert = [[578, [revert_babelfont]],
+ [577, [revert_drs]],
[576, [revert_linggloss, revert_subexarg]],
[575, [revert_new_languages]],
[574, [revert_lineno]],
os << from_ascii(ams);
if (useNonTeXFonts) {
- if (!features.isProvided("fontspec"))
+ // Babel loads fontspec itself
+ if (!features.isProvided("fontspec") && !features.useBabel())
os << "\\usepackage{fontspec}\n";
if (features.mustProvide("unicode-math")
&& features.isAvailable("unicode-math"))
}
// font selection must be done before loading fontenc.sty
+ // but after babel with non-TeX fonts
string const fonts = loadFonts(features);
- if (!fonts.empty())
+ if (!fonts.empty() && (!features.useBabel() || !useNonTeXFonts))
os << from_utf8(fonts);
if (fonts_default_family != "default")
if (contains(features.getBabelPostsettings(), from_ascii("thai.ldf")))
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"))
os << "\\usepackage{bicaption}\n";
if (!listings_params.empty()
// variants are understood by both engines. However,
// we want to provide support for at least TeXLive 2009
// (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 =
(features.runparams().flavor == OutputParams::XETEX) ?
"Mapping=tex-text" : "Ligatures=TeX";
if (fontsRoman() != "default") {
- os << "\\setmainfont[" << texmapping;
+ if (babel)
+ os << "\\babelfont{rm}[";
+ else
+ os << "\\setmainfont[";
+ os << texmapping;
if (fonts_old_figures)
os << ",Numbers=OldStyle";
os << "]{" << parseFontName(fontsRoman()) << "}\n";
}
if (fontsSans() != "default") {
string const sans = parseFontName(fontsSans());
- if (fontsSansScale() != 100)
- os << "\\setsansfont[Scale="
+ if (fontsSansScale() != 100) {
+ if (babel)
+ os << "\\babelfont{sf}";
+ else
+ os << "\\setsansfont";
+ os << "[Scale="
<< float(fontsSansScale()) / 100
<< "," << texmapping << "]{"
<< sans << "}\n";
- else
- os << "\\setsansfont[" << texmapping << "]{"
+ } else {
+ if (babel)
+ os << "\\babelfont{sf}[";
+ else
+ os << "\\setsansfont[";
+ os << texmapping << "]{"
<< sans << "}\n";
+ }
}
if (fontsTypewriter() != "default") {
string const mono = parseFontName(fontsTypewriter());
- if (fontsTypewriterScale() != 100)
- os << "\\setmonofont[Scale="
+ if (fontsTypewriterScale() != 100) {
+ if (babel)
+ os << "\\babelfont{tt}";
+ else
+ os << "\\setmonofont";
+ os << "[Scale="
<< float(fontsTypewriterScale()) / 100
<< "]{"
<< mono << "}\n";
- else
- os << "\\setmonofont{"
- << mono << "}\n";
+ } else {
+ if (babel)
+ os << "\\babelfont{tt}{";
+ else
+ os << "\\setmonofont{";
+ os << mono << "}\n";
+ }
}
return os.str();
}
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") {
string argument = p.getArg('{', '}');
if (argument.empty())
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 578 // spitz: drs
-#define LYX_FORMAT_TEX2LYX 578
+#define LYX_FORMAT_LYX 579 // spitz: babelfont
+#define LYX_FORMAT_TEX2LYX 579
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER