]> git.lyx.org Git - lyx.git/blobdiff - development/tools/generate_symbols_images.py
Add support for mixed-encoded biblatex files
[lyx.git] / development / tools / generate_symbols_images.py
old mode 100644 (file)
new mode 100755 (executable)
index 7787e5d..f3ea8e1
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/python3
 # -*- coding: utf-8 -*-
 
 # file generate_symbols_images.py
@@ -6,22 +6,26 @@
 # Licence details can be found in the file COPYING.
 
 # author Georg Baum
+# author Juergen Spitzmueller (adaptation for SVG)
 
 # Full author contact details are available in file CREDITS
 
-# This script generates a toolbar image for each missing math symbol
-# It needs the template document generate_symbols_images.lyx, which must
-# contain the placeholder formula '$a$' for generating the png image via
-# preview.sty and dvipng.
+# This script generates a toolbar image for each missing math symbol.
+# It needs the template document generate_symbols_images.lyx for generating
+# the png image via preview.sty and dvipng, or the template document
+# generate_symbols_svg.lyx for generating the SVG image via dvisvgm.
+# Either document must contain the placeholder formula '$a$'.
 # The created images are not always optimal, therefore the existing manually
 # created images should never be replaced by automatically created ones.
 
 
+from __future__ import print_function
 import os, re, string, sys, subprocess, tempfile, shutil
 import Image
+import io
 
 def usage(prog_name):
-    return ("Usage: %s lyxexe outputpath\n" % prog_name)
+    return ("Usage: %s png|svg lyxexe outputpath\n" % prog_name)
 
 
 def error(message):
@@ -38,19 +42,23 @@ def getlist(lyxexe, lyxfile):
     cmd = "%s %s -dbg mathed -x lyx-quit" % (lyxexe, lyxfile)
     proc = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
     (stdout, stderr) = proc.communicate()
-    regexp = re.compile(r'.*: read symbol \'(\S+)\s+inset:\s+(\S+)')
+    regexp = re.compile(r'.*: read symbol \'(\S+)\s+inset:\s+(\S+)\s+draw:\s+(\S*)\s+extra:\s+(\S+)')
     # These insets are more complex than simply symbols, so the images need to
     # be created manually
     skipinsets = ['big', 'font', 'lyxblacktext', 'matrix', 'mbox', 'oldfont', \
                   'ref', 'split', 'space', 'style']
-    symbols = []
+    mathsymbols = []
+    textsymbols = []
     for line in stderr.split('\n'):
         m = regexp.match(line)
         if m:
             inset = m.group(2)
             if not inset in skipinsets:
-                symbols.append(m.group(1))
-    return symbols
+                if m.group(4) == 'textmode':
+                    textsymbols.append(m.group(1))
+                else:
+                    mathsymbols.append(m.group(1))
+    return (mathsymbols, textsymbols)
 
 
 def getreplacements(filename):
@@ -61,7 +69,7 @@ def getreplacements(filename):
     replacements['*'] = 'ast'
     replacements['AA'] = 'textrm_AA'
     replacements['O'] = 'textrm_O'
-    cppfile = open(filename, 'rt')
+    cppfile = io.open(filename, 'r', encoding='utf_8')
     regexp = re.compile(r'.*"([^"]+)",\s*"([^"]+)"')
     found = False
     for line in cppfile.readlines():
@@ -71,50 +79,97 @@ def getreplacements(filename):
                 replacements[m.group(1)] = m.group(2)
             else:
                 return replacements
-        elif line.find('PngMap sorted_png_map') == 0:
+        elif line.find('ImgMap sorted_img_map') == 0:
             found = True
 
 
-def createimage(name, path, template, lyxexe, tempdir, replacements):
+def gettoolbaritems(filename):
+    items = []
+    uifile = io.open(filename, 'r', encoding='utf_8')
+    regexp = re.compile(r'.*Item "([^"\[]+)(\[\[[^\]]+\]\])?"\s*"math-insert\s+([^"]+)"')
+    for line in uifile.readlines():
+        m = regexp.match(line)
+        if m:
+            if '\\' + m.group(1) == m.group(3):
+                items.append(m.group(1))
+    return items
+
+
+def getmakefileentries(filename):
+    items = []
+    makefile = io.open(filename, 'r', encoding='utf_8')
+    regexp = re.compile(r'.*images/math/(.+)\.(png|svgz)')
+    for line in makefile.readlines():
+        m = regexp.match(line)
+        if m:
+            items.append(m.group(1))
+    return items
+
+
+def createimage(name, path, template, lyxexe, tempdir, math, replacements, toolbaritems, makefileentries, usepng):
     """ Create the image file for symbol name in path. """
 
     if name in replacements.keys():
         filename = replacements[name]
     elif name.startswith('lyx'):
-        print 'Skipping ' + name
+        print('Skipping ' + name)
         return
     else:
         skipchars = ['|', '/', '\\', '*', '!', '?', ':', ';', '^', '<', '>']
         for i in skipchars:
             if name.find(i) >= 0:
-                print 'Skipping ' + name
+                print('Skipping ' + name)
                 return
         filename = name
-    pngname = os.path.join(path, filename + '.png')
-    if os.path.exists(pngname):
-        print 'Skipping ' + name
+    if usepng:
+        imgname = os.path.join(path, filename + '.png')
+    else:
+        imgname = os.path.join(path, filename + '.svgz')
+    if name in toolbaritems:
+        if filename in makefileentries:
+            suffix = ' (found in toolbar and makefile)'
+        else:
+            suffix = ' (found in only in toolbar)'
+    else:
+        if filename in makefileentries:
+            suffix = ' (found only in makefile)'
+        else:
+            suffix = ' (not found)'
+    if os.path.exists(imgname):
+        print('Skipping ' + name + suffix)
         return
-    print 'Generating ' + name
+    print('Generating ' + name + suffix)
     lyxname = os.path.join(tempdir, filename)
-    lyxfile = open(lyxname + '.lyx', 'wt')
-    lyxfile.write(template.replace('$a$', '$\\' + name + '$'))
+    lyxfile = io.open(lyxname + '.lyx', 'w', encoding='utf_8')
+    if math:
+        lyxfile.write(template.replace('$a$', '$\\' + name + '$'))
+    else:
+        lyxfile.write(template.replace('$a$', '$\\text{\\' + name + '}$'))
     lyxfile.close()
     cmd = "%s %s.lyx -e dvi" % (lyxexe, lyxname)
     proc = subprocess.Popen(cmd, shell=True)
     proc.wait()
     if proc.returncode != 0:
-        print 'Error in DVI creation for ' + name
+        print('Error in DVI creation for ' + name)
         return
     # The magnifaction factor is calculated such that we get an image of
     # height 18 px for most symbols and document font size 11. Then we can
     # add a small border to get the standard math image height of 20 px.
-    cmd = "dvipng %s.dvi -bg Transparent -D 115 -o %s" % (lyxname, pngname)
+    if usepng:
+        cmd = "dvipng %s.dvi -bg Transparent -D 115 -o %s" % (lyxname, imgname)
+    else:
+        cmd = "dvisvgm -z --no-fonts --exact --output=%s%s%%f %s.dvi" % (path, os.path.sep, lyxname)
     proc = subprocess.Popen(cmd, shell=True)
     proc.wait()
     if proc.returncode != 0:
-        print 'Error in PNG creation for ' + name
+        if png:
+            print('Error in PNG creation for ' + name)
+        else:
+            print('Error in SVG creation for ' + name)
         return
-    image = Image.open(pngname)
+    if not usepng:
+        return
+    image = Image.open(imgname)
     (width, height) = image.size
     if width < 20 and height < 20:
         if width == 19 and height == 19:
@@ -130,23 +185,36 @@ def createimage(name, path, template, lyxexe, tempdir, replacements):
             padded = Image.new('RGBA', (width+2, height+2), (0, 0, 0, 0))
             padded.paste(image, (1, 1))
         padded.convert(image.mode)
-        padded.save(pngname, "PNG")
+        padded.save(imgname, "PNG")
 
 
 def main(argv):
 
-    if len(argv) == 3:
+    if len(argv) == 4:
         (base, ext) = os.path.splitext(argv[0])
-        symbols = getlist(argv[1], base)
+        (mathsymbols, textsymbols) = getlist(argv[2], base)
         cppfile = os.path.join(os.path.dirname(base), '../../src/frontends/qt4/GuiApplication.cpp')
         replacements = getreplacements(cppfile)
-        lyxtemplate = base + '.lyx'
-        templatefile = open(base + '.lyx', 'rt')
+        uifile = os.path.join(os.path.dirname(base), '../../lib/ui/stdtoolbars.inc')
+        toolbaritems = gettoolbaritems(uifile)
+        makefile = os.path.join(os.path.dirname(base), '../../lib/Makefile.am')
+        makefileentries = getmakefileentries(makefile)
+        if argv[1] == 'png':
+            lyxtemplate = base + '.lyx'
+            usepng = True
+        elif argv[1] == 'svg':
+            lyxtemplate = os.path.join(os.path.dirname(base), 'generate_symbols_svg.lyx')
+            usepng = False
+        else:
+            error(usage(argv[0]))
+        templatefile = io.open(base + '.lyx', 'r', encoding='utf_8')
         template = templatefile.read()
         templatefile.close()
         tempdir = tempfile.mkdtemp()
-        for i in symbols:
-            createimage(i, argv[2], template, argv[1], tempdir, replacements)
+        for i in mathsymbols:
+            createimage(i, argv[3], template, argv[2], tempdir, True, replacements, toolbaritems, makefileentries, usepng)
+        for i in textsymbols:
+            createimage(i, argv[3], template, argv[2], tempdir, False, replacements, toolbaritems, makefileentries, usepng)
         shutil.rmtree(tempdir)
     else:
         error(usage(argv[0]))