Unified handling of IBMPlex and DejaVu fonts in lyx2lyx

This commit is contained in:
Kornel Benko 2018-08-20 15:47:49 +02:00
parent 23ea74a40b
commit a25b970296

View File

@ -56,64 +56,109 @@ def add_preamble_fonts(document, fontmap):
add_to_preamble(document, [preamble]) add_to_preamble(document, [preamble])
def convert_fonts(document, font_list, font_type, scale_type, pkg): def createkey(pkg, options):
" Handle font definition to LaTeX " options.sort()
return pkg + ':' + "-".join(options)
def createkey(pkg, options): class fontinfo:
options.sort() def __init__(self):
return pkg + ':' + "-".join(options) self.fontname = None # key into font2pkgmap
self.fonttype = None # roman,sans,typewriter,math
self.scaletype = None # None,sf,tt
self.scaleopt = None # None, 'scaled', 'scale'
self.scaleval = 1
self.package = None
self.options = []
self.pkgkey = None # key into pkg2fontmap
def getfontname(pkg, options, pkg2fontmap, font2pkgmap): def addkey(self):
"" self.pkgkey = createkey(self.package, self.options)
class fontmapping:
def __init__(self):
self.font2pkgmap = dict()
self.pkg2fontmap = dict()
self.pkginmap = dict() # defines, if a map for package exists
def expandFontMapping(self, font_list, font_type, scale_type, pkg, scaleopt = None):
" Expand fontinfo mapping"
#
# fontlist: list of fontnames, each element
# may contain a ','-separated list of needed options
# like e.g. 'IBMPlexSansCondensed,condensed'
# font_type: one of 'roman', 'sans', 'typewriter', 'math'
# scale_type: one of None, 'sf', 'tt'
# pkg: package defining the font. Defaults to fontname if None
# scaleopt: one of None, 'scale', 'scaled', or some other string
# to be used in scale option (e.g. scaled=0.7)
for fl in font_list:
fe = fontinfo()
fe.fonttype = font_type
fe.scaletype = scale_type
flt = fl.split(",")
font_name = flt[0]
fe.fontname = font_name
fe.options = flt[1:]
fe.scaleopt = scaleopt
if pkg == None:
fe.package = font_name
else:
fe.package = pkg
fe.addkey()
self.font2pkgmap[font_name] = fe
if fe.pkgkey in self.pkg2fontmap:
# Repeated the same entry? Check content
if self.pkg2fontmap[fe.pkgkey] != font_name:
document.error("Something is wrong in pkgname+options <-> fontname mapping")
self.pkg2fontmap[fe.pkgkey] = font_name
self.pkginmap[fe.package] = 1
def getfontname(self, pkg, options):
options.sort() options.sort()
pkgkey = createkey(pkg, options) pkgkey = createkey(pkg, options)
if not pkgkey in self.pkg2fontmap:
if not pkgkey in pkg2fontmap:
return None return None
fontname = pkg2fontmap[pkgkey] fontname = self.pkg2fontmap[pkgkey]
if not fontname in font2pkgmap: if not fontname in self.font2pkgmap:
document.warning("Something is wrong in pkgname+options <-> fontname conversion") document.error("Something is wrong in pkgname+options <-> fontname mapping")
return None return None
if pkgkey == self.font2pkgmap[fontname].pkgkey:
pkgkey2 = createkey(font2pkgmap[fontname].package, font2pkgmap[fontname].options)
if pkgkey == pkgkey2:
return fontname return fontname
return None return None
# We need a mapping pkg+options => font_name def createFontMapping():
# and font_name => pkg+options # Create info for known fonts for the use in
class fontinfo: # convert_latexFonts() and
package = None # revert_latexFonts()
options = [] #
# * Would be more handy to parse latexFonts file,
# but the path to this file is unknown
# * For now, add DejaVu and IBMPlex only.
# * Expand, if desired
fm = fontmapping()
fm.expandFontMapping(['DejaVuSerif', 'DejaVuSerifCondensed'], "roman", None, None)
fm.expandFontMapping(['DejaVuSans','DejaVuSansCondensed'], "sans", "sf", None, "scaled")
fm.expandFontMapping(['DejaVuSansMono'], "typewriter", "tt", None, "scaled")
fm.expandFontMapping(['IBMPlexSerif', 'IBMPlexSerifThin,thin',
'IBMPlexSerifExtraLight,extralight', 'IBMPlexSerifLight,light',
'IBMPlexSerifSemibold,semibold'],
"roman", None, "plex-serif")
fm.expandFontMapping(['IBMPlexSans','IBMPlexSansCondensed,condensed',
'IBMPlexSansThin,thin', 'IBMPlexSansExtraLight,extralight',
'IBMPlexSansLight,light', 'IBMPlexSansSemibold,semibold'],
"sans", "sf", "plex-sans", "scale")
fm.expandFontMapping(['IBMPlexMono', 'IBMPlexMonoThin,thin',
'IBMPlexMonoExtraLight,extralight', 'IBMPlexMonoLight,light',
'IBMPlexMonoSemibold,semibold'],
"typewriter", "tt", "plex-mono", "scale")
return fm
font2pkgmap = dict() def convert_fonts(document, fm):
pkg2fontmap = dict() " Handle font definition to LaTeX "
pkgmap = dict()
for fl in font_list:
fe = fontinfo()
flt = fl.split(",")
font_name = flt[0]
fe.options = flt[1:]
if pkg == None:
fe.package = font_name
else:
fe.package = pkg
font2pkgmap[font_name] = fe
pkgkey = createkey(fe.package, fe.options)
if pkgkey in pkg2fontmap:
# Repeated the same entry? Check content
if pkg2fontmap[pkgkey] != font_name:
print "ERROR:"
pkg2fontmap[pkgkey] = font_name
pkgmap[fe.package] = 1
rpkg = re.compile(r'^\\usepackage(\[([^\]]*)\])?\{([^\}]+)\}') rpkg = re.compile(r'^\\usepackage(\[([^\]]*)\])?\{([^\}]+)\}')
rscaleopt = re.compile(r'^scaled?=(.*)') rscaleopt = re.compile(r'^scaled?=(.*)')
ft = font_type
if scale_type == None:
fontscale = None
else:
fontscale = "\\font_" + scale_type + "_scale"
i = 0 i = 0
while i < len(document.preamble): while i < len(document.preamble):
i = find_re(document.preamble, rpkg, i) i = find_re(document.preamble, rpkg, i)
@ -136,15 +181,22 @@ def convert_fonts(document, font_list, font_type, scale_type, pkg):
del options[o] del options[o]
break break
if not pkg in pkgmap: if not pkg in fm.pkginmap:
i += 1 i += 1
continue continue
# determine fontname # determine fontname
fn = getfontname(pkg, options, pkg2fontmap, font2pkgmap) fn = fm.getfontname(pkg, options)
if fn == None: if fn == None:
i += 1 i += 1
continue continue
del document.preamble[i] del document.preamble[i]
fontinfo = fm.font2pkgmap[fn]
if fontinfo.scaletype == None:
fontscale = None
else:
fontscale = "\\font_" + fontinfo.scaletype + "_scale"
fontinfo.scaleval = oscale
if i > 0 and document.preamble[i-1] == "% Added by lyx2lyx": if i > 0 and document.preamble[i-1] == "% Added by lyx2lyx":
del document.preamble[i-1] del document.preamble[i-1]
if fontscale != None: if fontscale != None:
@ -156,58 +208,55 @@ def convert_fonts(document, font_list, font_type, scale_type, pkg):
if oscale != None: if oscale != None:
scale = "%03d" % int(float(oscale) * 100) scale = "%03d" % int(float(oscale) * 100)
document.header[j] = fontscale + " " + scale + " " + vals[1] document.header[j] = fontscale + " " + scale + " " + vals[1]
ft = "\\font_" + fontinfo.fonttype
j = find_token(document.header, ft, 0) j = find_token(document.header, ft, 0)
if j != -1: if j != -1:
val = get_value(document.header, ft, j) val = get_value(document.header, ft, j)
vals = val.split() vals = val.split()
document.header[j] = ft + ' "' + fn + '" ' + vals[1] document.header[j] = ft + ' "' + fn + '" ' + vals[1]
def revert_fonts(document, font_list, fontmap, package=None): def revert_fonts(document, fm, fontmap):
" Revert native font definition to LaTeX " " Revert native font definition to LaTeX "
# fonlist := list of fonts created from the same package # fonlist := list of fonts created from the same package
# Empty package means that the font-name is the same as the package-name # Empty package means that the font-name is the same as the package-name
# fontmap (key = package, val += found options) will be filled # fontmap (key = package, val += found options) will be filled
# and used later in add_preamble_fonts() to be added to user-preamble # and used later in add_preamble_fonts() to be added to user-preamble
if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: rfontscale = re.compile(r'^\s*(\\font_(roman|sans|typewriter|math))\s+')
font_types = ["\\font_roman", "\\font_sans,sf", "\\font_typewriter,tt", "\\font_math,math"] rscales = re.compile(r'^\s*(\d+)\s+(\d+)')
optmap = dict() i = 0
for fontl1 in font_list: while i < len(document.header):
fontl = fontl1.split(",") i = find_re(document.header, rfontscale, i)
font = fontl[0] if (i == -1):
optmap[font] = fontl[1:] break
for ft1 in font_types: mo = rfontscale.search(document.header[i])
fts = ft1.split(",") if mo == None:
ft = fts[0] i += 1
i = find_token(document.header, ft, 0) continue
if i == -1: ft = mo.group(1) # 'roman', 'sans', 'typewriter', 'math'
continue val = get_value(document.header, ft, i)
val = get_value(document.header, ft, i) words = val.split()
words = val.split() font = words[0].replace('"', '')
font = words[0].replace('"', '') if not font in fm.font2pkgmap:
if not font in optmap: i += 1
continue continue
if package == None: fontinfo = fm.font2pkgmap[font]
val = font; val = fontinfo.package
else: if not val in fontmap:
val = package fontmap[val] = []
if not val in fontmap: document.header[i] = ft + ' "default" ' + words[1]
fontmap[val] = [] if fontinfo.scaleopt != None:
document.header[i] = ft + ' "default" ' + words[1] xval = get_value(document.header, "\\font_" + fontinfo.scaletype + "_scale", 0)
if len(fts) > 1: mo = rscales.search(xval)
xval = get_value(document.header, "\\font_" + fts[1] + "_scale", 0) if mo != None:
if xval != '': xval1 = mo.group(1)
# cutoff " 100" xval2 = mo.group(2)
xval = xval[:-4] if xval1 != "100":
if xval != "100": # set correct scale option
# set correct scale option fontmap[val].extend([fontinfo.scaleopt + "=" + format(float(xval1) / 100, '.2f')])
if re.match('Deja.*', val): if len(fontinfo.options) > 0:
scale_par = "scaled" fontmap[val].extend(fontinfo.options)
else: i += 1
scale_par = "scale"
fontmap[val].extend([scale_par + "=" + format(float(xval) / 100, '.2f')])
if len(optmap[font]) > 0:
fontmap[val].extend(optmap[font])
############################################################################### ###############################################################################
### ###
@ -215,60 +264,21 @@ def revert_fonts(document, font_list, fontmap, package=None):
### ###
############################################################################### ###############################################################################
def convert_ibmplex(document): def convert_latexFonts(document):
" Handle IBM Plex font definition to LaTeX " " Handle DejaVu and IBMPlex fonts definition to LaTeX "
ibmplex_fonts_roman = ['IBMPlexSerif', 'IBMPlexSerifThin,thin', if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
'IBMPlexSerifExtraLight,extralight', 'IBMPlexSerifLight,light', fm = createFontMapping()
'IBMPlexSerifSemibold,semibold'] convert_fonts(document, fm)
ibmplex_fonts_sans = ['IBMPlexSans','IBMPlexSansCondensed,condensed',
'IBMPlexSansThin,thin', 'IBMPlexSansExtraLight,extralight',
'IBMPlexSansLight,light', 'IBMPlexSansSemibold,semibold']
ibmplex_fonts_typewriter = ['IBMPlexMono', 'IBMPlexMonoThin,thin',
'IBMPlexMonoExtraLight,extralight', 'IBMPlexMonoLight,light',
'IBMPlexMonoSemibold,semibold']
convert_fonts(document, ibmplex_fonts_roman, "\\font_roman", None, "plex-serif") def revert_latexFonts(document):
convert_fonts(document, ibmplex_fonts_sans, "\\font_sans", "sf", "plex-sans")
convert_fonts(document, ibmplex_fonts_typewriter, "\\font_typewriter", "tt", "plex-mono")
def revert_ibmplex(document):
" Revert native IBM Plex font definition to LaTeX "
fontmap = dict()
revert_fonts(document, ['IBMPlexSerif', 'IBMPlexSerifThin,thin',
'IBMPlexSerifExtraLight,extralight',
'IBMPlexSerifLight,light', 'IBMPlexSerifSemibold,semibold'],
fontmap, "plex-serif")
revert_fonts(document, ['IBMPlexSans','IBMPlexSansCondensed,condensed',
'IBMPlexSansThin,thin', 'IBMPlexSansExtraLight,extralight',
'IBMPlexSansLight,light', 'IBMPlexSansSemibold,semibold'],
fontmap, "plex-sans")
revert_fonts(document, ['IBMPlexMono', 'IBMPlexMonoThin,thin',
'IBMPlexMonoExtraLight,extralight', 'IBMPlexMonoLight,light',
'IBMPlexMonoSemibold,semibold'],
fontmap, "plex-mono")
add_preamble_fonts(document, fontmap)
def convert_dejavu(document):
" Handle DejaVu font definition to LaTeX "
dejavu_fonts_roman = ['DejaVuSerif', 'DejaVuSerifCondensed']
dejavu_fonts_sans = ['DejaVuSans','DejaVuSansCondensed']
dejavu_fonts_typewriter = ['DejaVuSansMono']
convert_fonts(document, dejavu_fonts_roman, "\\font_roman", None, None)
convert_fonts(document, dejavu_fonts_sans, "\\font_sans", "sf", None)
convert_fonts(document, dejavu_fonts_typewriter, "\\font_typewriter", "tt", None)
def revert_dejavu(document):
" Revert native DejaVu font definition to LaTeX " " Revert native DejaVu font definition to LaTeX "
dejavu_fonts = ['DejaVuSerif', 'DejaVuSerifCondensed', 'DejaVuSans', if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
'DejaVuSansMono', 'DejaVuSansCondensed'] fontmap = dict()
fontmap = dict() fm = createFontMapping()
revert_fonts(document, dejavu_fonts, fontmap) revert_fonts(document, fm, fontmap)
add_preamble_fonts(document, fontmap) add_preamble_fonts(document, fontmap)
def removeFrontMatterStyles(document): def removeFrontMatterStyles(document):
" Remove styles Begin/EndFrontmatter" " Remove styles Begin/EndFrontmatter"
@ -1342,7 +1352,7 @@ convert = [
[558, [removeFrontMatterStyles]], [558, [removeFrontMatterStyles]],
[559, []], [559, []],
[560, []], [560, []],
[561, [convert_dejavu, convert_ibmplex]], [561, [convert_latexFonts]], # Handle dejavu, ibmplex fonts in GUI
[562, []], [562, []],
[563, []] [563, []]
] ]
@ -1350,7 +1360,7 @@ convert = [
revert = [ revert = [
[562, [revert_listpargs]], [562, [revert_listpargs]],
[561, [revert_l7ninfo]], [561, [revert_l7ninfo]],
[560, [revert_ibmplex, revert_dejavu]], [560, [revert_latexFonts]], # Handle dejavu, ibmplex fonts in user preamble
[559, [revert_timeinfo, revert_namenoextinfo]], [559, [revert_timeinfo, revert_namenoextinfo]],
[558, [revert_dateinfo]], [558, [revert_dateinfo]],
[557, [addFrontMatterStyles]], [557, [addFrontMatterStyles]],