|
|
|
from flask import Flask, Response, request, render_template
|
|
|
|
import subprocess
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
import io
|
|
|
|
from svg_to_hpgl import svgToHPGL
|
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
|
|
title = 'Cobbled paths'
|
|
|
|
|
|
|
|
fonts_directory = 'db/'
|
|
|
|
possible_extensions = [".flf"]
|
|
|
|
etherpad = 'https://pad.constantvzw.org/p/'
|
|
|
|
prefix = 'cobbled-pad-'
|
|
|
|
|
|
|
|
# VARIABLES
|
|
|
|
# ------------------------------
|
|
|
|
|
|
|
|
# all the character that svgbob understand
|
|
|
|
spec = [".", ",", "’", "'", "`", "+", "*", "o", "O", "V", "\\-", "|", "~", "_", ":", "!", "<", ">", "v", "^", "/", "\\\\", '\\”', '\\"', "(", ")", "=", "#"]
|
|
|
|
r_spec = "".join(spec)
|
|
|
|
r_nspec = "[^" + r_spec + "\€\$\s]"
|
|
|
|
|
|
|
|
# autofix regex
|
|
|
|
autofix = [
|
|
|
|
|
|
|
|
# every arrowshead into lines
|
|
|
|
[re.compile("[<{]"), "("],
|
|
|
|
[re.compile("[>}L]"), ")"],
|
|
|
|
[re.compile("[vV]"), "-"],
|
|
|
|
[re.compile("[\\^]"), "-"],
|
|
|
|
|
|
|
|
[";", ":"],
|
|
|
|
["7", "/"],
|
|
|
|
|
|
|
|
[re.compile("[1Tlj\\[\\]]"), "|"],
|
|
|
|
[re.compile("[Y]"), "+"],
|
|
|
|
|
|
|
|
# every not in the spec --> block
|
|
|
|
[re.compile(r_nspec), "#"],
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
def most_common(lst):
|
|
|
|
return max(set(lst), key=lst.count)
|
|
|
|
|
|
|
|
# ROUTES
|
|
|
|
# ------------------------------
|
|
|
|
|
|
|
|
@app.route("/")
|
|
|
|
def index():
|
|
|
|
|
|
|
|
return render_template(
|
|
|
|
'index.html',
|
|
|
|
title = title)
|
|
|
|
|
|
|
|
@app.route("/draw.html")
|
|
|
|
def draw():
|
|
|
|
|
|
|
|
params = {
|
|
|
|
'pad': request.args.get('p') or 'default',
|
|
|
|
'weight': request.args.get('w') or '3',
|
|
|
|
}
|
|
|
|
params['pad-full'] = etherpad + prefix + params['pad']
|
|
|
|
|
|
|
|
return render_template(
|
|
|
|
'draw.html',
|
|
|
|
title = title,
|
|
|
|
params = params)
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/catalogue.html")
|
|
|
|
def catalogue():
|
|
|
|
|
|
|
|
# text and weight as get parameter
|
|
|
|
params = {
|
|
|
|
'text': request.args.get('t') or 'Echoes',
|
|
|
|
'weight': request.args.get('w') or '3',
|
|
|
|
}
|
|
|
|
output = {
|
|
|
|
'stroke': { 'ascii': ' | ' , 'fonts': [] },
|
|
|
|
'script': { 'ascii': ' _/' , 'fonts': [] },
|
|
|
|
'block': { 'ascii': '|_|' , 'fonts': [] },
|
|
|
|
'outline': { 'ascii': '/ /' , 'fonts': [] },
|
|
|
|
'effect': { 'ascii': ': :' , 'fonts': [] },
|
|
|
|
'pattern': { 'ascii': ')()' , 'fonts': [] },
|
|
|
|
|
|
|
|
# 'fill': { 'ascii': '_/', 'fonts': {} },
|
|
|
|
|
|
|
|
# 'directions': { 'ascii': '_/', 'fonts': {} },
|
|
|
|
# '3d': { 'ascii': '_/', 'fonts': {} },
|
|
|
|
|
|
|
|
# 'frame': { 'ascii': '_/', 'fonts': {} },
|
|
|
|
# 'code': { 'ascii': '_/', 'fonts': {} },
|
|
|
|
}
|
|
|
|
databases = {
|
|
|
|
'default': 'fonts made by the figlet developpers and given with the program, early 1993',
|
|
|
|
'contributed': 'fonts made by figlet amateurs and submitted to the official figlet ftp, from before 1993 to 2005',
|
|
|
|
'jave': 'figlet font library of JavE (a free Ascii drawing Editor)',
|
|
|
|
}
|
|
|
|
|
|
|
|
# walk in the figlet font directory
|
|
|
|
for root, dirs, files in os.walk(fonts_directory):
|
|
|
|
for name in files:
|
|
|
|
|
|
|
|
(basename, ext) = os.path.splitext(name)
|
|
|
|
if ext in possible_extensions:
|
|
|
|
|
|
|
|
path = os.path.join(root, name)
|
|
|
|
print(path)
|
|
|
|
|
|
|
|
# get font category out of last folder
|
|
|
|
catalogue = root.split('/')[-2]
|
|
|
|
type = root.split('/')[-1]
|
|
|
|
if type in output:
|
|
|
|
|
|
|
|
f = {}
|
|
|
|
output[type]['fonts'].append(f)
|
|
|
|
f['name'] = name
|
|
|
|
f['catalogue'] = catalogue
|
|
|
|
|
|
|
|
figlet = subprocess.run(["figlet", params['text'], "-f", path, "-w", "160"], stdout = subprocess.PIPE, text=True)
|
|
|
|
f['ascii'] = figlet.stdout
|
|
|
|
|
|
|
|
font_info = subprocess.run(["figlet", "-I", path, "-w", "160"], stdout = subprocess.PIPE, text=True)
|
|
|
|
f['info'] = font_info
|
|
|
|
|
|
|
|
svgbob = subprocess.run(["svgbob_cli", '--stroke-width', params['weight']], input = f['ascii'], stdout = subprocess.PIPE, text=True)
|
|
|
|
f['svg'] = svgbob.stdout
|
|
|
|
|
|
|
|
# regex auto_fix
|
|
|
|
fixed = f['ascii']
|
|
|
|
for regex, replace in autofix:
|
|
|
|
fixed = re.sub(regex, replace, fixed)
|
|
|
|
f['ascii_fix'] = fixed
|
|
|
|
|
|
|
|
if f['ascii'] != f['ascii_fix']:
|
|
|
|
f['autofix'] = True
|
|
|
|
|
|
|
|
fix_indication = f['ascii']
|
|
|
|
for regex, replace in autofix:
|
|
|
|
# the two markers have to not appear in any regex
|
|
|
|
fix_indication = re.sub(regex, "$" + replace + "€", fix_indication)
|
|
|
|
fix_indication = re.sub("[\$]", "<span class='fix'>", fix_indication)
|
|
|
|
fix_indication = re.sub("[\€]", "</span>", fix_indication)
|
|
|
|
f['ascii_fix_indication'] = fix_indication
|
|
|
|
|
|
|
|
svgbob_fix = subprocess.run(["svgbob_cli", '--stroke-width', params['weight']], input = f['ascii_fix'], stdout = subprocess.PIPE, text=True)
|
|
|
|
f['svg_fix'] = svgbob_fix.stdout
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return render_template(
|
|
|
|
'catalogue.html',
|
|
|
|
title = title,
|
|
|
|
databases = databases,
|
|
|
|
output = output,
|
|
|
|
params = params)
|
|
|
|
|
|
|
|
def make_svg ():
|
|
|
|
return ''
|
|
|
|
|
|
|
|
@app.route('/hpgl/')
|
|
|
|
def hpgl ():
|
|
|
|
# generate svg
|
|
|
|
svg = make_svg()
|
|
|
|
# store as a temporary file
|
|
|
|
(svg_file, svg_path) = tempfile.mkstemp()
|
|
|
|
svg_file.write(svg)
|
|
|
|
|
|
|
|
# transform to hpgl
|
|
|
|
hpgl = svgToHPGL(svg_path)
|
|
|
|
|
|
|
|
# remove tmp file
|
|
|
|
os.remove(svg_path)
|
|
|
|
|
|
|
|
r = Response(hpgl, mimetype='application/hpgl')
|
|
|
|
|
|
|
|
r.headers.extend({
|
|
|
|
'Content-Disposition': 'attachment; filename="cobbled-paths.hpgl"'
|
|
|
|
})
|
|
|
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
app.run(debug=True, host='0.0.0.0')
|