if not modules then modules = { } end modules ['mtx-server-ctx-fonttest'] = { version = 1.001, comment = "Font Feature Tester", author = "Hans Hagen", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- probably too much but who cares dofile(resolvers.findfile("trac-lmx.lua","tex")) dofile(resolvers.findfile("char-def.lua","tex")) dofile(resolvers.findfile("font-ini.lua","tex")) dofile(resolvers.findfile("font-log.lua","tex")) dofile(resolvers.findfile("font-con.lua","tex")) dofile(resolvers.findfile("font-cft.lua","tex")) dofile(resolvers.findfile("font-enc.lua","tex")) dofile(resolvers.findfile("font-agl.lua","tex")) dofile(resolvers.findfile("font-cid.lua","tex")) dofile(resolvers.findfile("font-map.lua","tex")) dofile(resolvers.findfile("font-otr.lua","tex")) dofile(resolvers.findfile("font-web.lua","tex")) dofile(resolvers.findfile("font-cff.lua","tex")) dofile(resolvers.findfile("font-ttf.lua","tex")) dofile(resolvers.findfile("font-dsp.lua","tex")) dofile(resolvers.findfile("font-hsh.lua","tex")) dofile(resolvers.findfile("font-oti.lua","tex")) dofile(resolvers.findfile("font-ott.lua","tex")) dofile(resolvers.findfile("font-otl.lua","tex")) -- dofile(resolvers.findfile("font-oto.lua","tex")) -- dofile(resolvers.findfile("font-otj.lua","tex")) dofile(resolvers.findfile("font-oup.lua","tex")) -- dofile(resolvers.findfile("font-ots.lua","tex")) -- dofile(resolvers.findfile("font-otd.lua","tex")) -- dofile(resolvers.findfile("font-otc.lua","tex")) -- dofile(resolvers.findfile("font-oth.lua","tex")) -- dofile(resolvers.findfile("font-osd.lua","tex")) -- dofile(resolvers.findfile("font-ocl.lua","tex")) dofile(resolvers.findfile("font-onr.lua","tex")) dofile(resolvers.findfile("font-syn.lua","tex")) dofile(resolvers.findfile("font-mis.lua","tex")) local format, gsub, concat, match, find = string.format, string.gsub, table.concat, string.match, string.find local formatters = string.formatters local report = logs.reporter("ctx-fonttest") local sample_line = "This is a sample line!" local tempname = "mtx-server-ctx-fonttest-temp" local temppath = caches.setfirstwritablefile("temp","mtx-server-ctx-fonttest") local basename = "mtx-server-ctx-fonttest-data.lua" local basepath = temppath local remove_suffixes = { "tex", "pdf", "log" } local what_options = { "trace", "basemode" } for i=1,#remove_suffixes do os.remove(file.join(temppath,file.addsuffix(tempname,remove_suffixes[i]))) end local foolcache = 0 local function makename(name,new) if new then foolcache = foolcache > 25 and 1 or foolcache + 1 end return formatters["%s-%02i"](name,foolcache) end -- nowadays i would use the more advanced template mechanism with named variables local process_templates = { } -- %\definedfont[name:%s*sample] process_templates.default = formatters [ [[ \starttext \setupdirections[bidi=one] \definefontfeature[sample][analyze=yes,%s] \definedfont[name:%s*none] \startTEXpage[offset=3pt] \detokenize{%s} \blank \definedfont[name:%s*sample] \detokenize{%s} \stopTEXpage \stoptext ]] ] process_templates.cache = formatters [ [[ \starttext \definedfont[name:%s] \startTEXpage[offset=3pt] cached: \detokenize{%s} \stopTEXpage \stoptext ]] ] process_templates.trace = formatters [ [[ \usemodule[fnt-20] \definefontfeature[sample][%s] \setupcolors[state=start] \setupdirections[bidi=global] \setvariables [otftracker] [title=Test Run, font=name:%s, direction=0, features=sample, sample={‍\detokenize{%s}}] ]] ] local javascripts = formatters [ [[ function selected_radio(name) { var form = document.forms["main-form"] ; var script = form.elements[name] ; if (script) { var n = script.length ; if (n) { for (var i=0; i safe name     family name     style-variant-weight-width     font name     weight     filename ]] ] local template_d = formatters [ [[ %s     %s     %s-%s-%s-%s     %s     %s     %s ]] ] local function select_font() local t = fonts.names.list(".*",false,true) if t then local listoffonts = { } listoffonts[#listoffonts+1] = "

Fonts


" listoffonts[#listoffonts+1] = "" listoffonts[#listoffonts+1] = template_h() for k, v in table.sortedhash(t) do local kind = v.format if kind == "otf" or kind == "ttf" or kind == "ttc" then local fontname = v.fontname listoffonts[#listoffonts+1] = template_d( fontname, fontname, v.familyname or "", t.variant or "normal", t.weight or "normal", t.width or "normal", t.style or "normal", v.rawname or fontname, v.fontweight or "", v.filename or "" ) end end listoffonts[#listoffonts+1] = "
" return concat(listoffonts,"\n") end return "no fonts" end local edit_template = formatters [ [[

name:    title: 

scripts: %s

languages: %s

features: %s

options: %s ]] ] -- local result_template = formatters [ [[



results:  tex file   pdf file   (runtime: %s)

]] ] local main_template = formatters [ [[

Font: %s


%s %s ]] ] scripts.webserver.registerpath(temppath) local function get_specification(name) return fonts.names.resolvedspecification(name or "") end local function edit_font(currentfont,detail,tempname,runtime) report("entering edit mode for '%s'",currentfont) local specification = get_specification(currentfont) if specification then local htmldata = showfeatures(specification.filename) if htmldata then local features, languages, scripts, options = { }, { }, { }, { } local sorted = table.sortedkeys(htmldata.scripts) for k=1,#sorted do local v = sorted[k] local s = fonts.handlers.otf.tables.scripts[v] or v if detail and v == detail.script then scripts[#scripts+1] = formatters[" %s"](s,v,v,v,v) else scripts[#scripts+1] = formatters[" %s"](s,v,v,v,v) end end local sorted = table.sortedkeys(htmldata.languages) for k=1,#sorted do local v = sorted[k] local l = fonts.handlers.otf.tables.languages[v] or v if detail and v == detail.language then languages[#languages+1] = formatters[" %s"](l,v,v,v,v) else languages[#languages+1] = formatters[" %s"](l,v,v,v,v) end end local sorted = table.sortedkeys(htmldata.features) for k=1,#sorted do local v = sorted[k] local f = fonts.handlers.otf.tables.features[v] or v if detail and detail["f-"..v] then features[#features+1] = formatters[" %s"](f,v,v,v,v) else features[#features+1] = formatters[" %s"](f,v,v,v,v) end end for k=1,#what_options do local v = what_options[k] if detail and detail["o-"..v] then options[#options+1] = formatters[" %s"](v,v,v) else options[#options+1] = formatters[" %s"](v,v,v) end end local e = edit_template( detail and detail.sampletext or sample_line, detail and detail.name or "no name", detail and detail.title or "", concat(scripts," "), concat(languages," "), concat(features," "), concat(options," ") ) if tempname then local pdffile, texfile = file.replacesuffix(tempname,"pdf"), file.replacesuffix(tempname,"tex") local r = result_template(pdffile,texfile,pdffile,runtime and formatters["%0.3f"](runtime) or "-") return main_template(currentfont,e,r), htmldata.javascript or "" else return main_template(currentfont,e,""), htmldata.javascript or "" end else return "error, nothing set up yet" end else return "error, no info about font" end end local function process_font(currentfont,detail) -- maybe just fontname local features = { "mode=node", formatters["language=%s"](detail.language or "dflt"), formatters["script=%s"](detail.script or "dflt"), } for k,v in next, detail do local f = match(k,"^f%-(.*)$") if f then features[#features+1] = formatters["%s=yes"](f) end end local variant = process_templates.default if detail["o-trace"] then variant = process_templates.trace end local sample = string.strip(detail.sampletext or "") if sample == "" then sample = sample_line end report("sample text: %s",sample) dir.mkdirs(temppath) local tempname = makename(tempname,true) local usedname = file.addsuffix(tempname,"tex") local fullname = file.join(temppath,usedname) local data = variant(concat(features,","),currentfont,sample,currentfont,sample) io.savedata(fullname,data) io.flush() local runtime = runcontext(temppath,usedname) return edit_font(currentfont,detail,tempname,runtime) end local tex_template = formatters [ [[

Font: %s



%s
]] ] local function show_source(currentfont,detail) local tempname = makename(tempname) if tempname and tempname ~= "" then local data = io.loaddata(file.join(temppath,file.replacesuffix(tempname,"tex"))) or "no source yet" return tex_template(currentfont,data) else return "no source file" end end local function show_log(currentfont,detail) local tempname = makename(tempname) if tempname and tempname ~= "" then local data = io.loaddata(file.join(temppath,file.replacesuffix(tempname,'log'))) or "no log file yet" data = gsub(data,"[%s%%]*begin of optionfile.-end of optionfile[%s%%]*","\n") return tex_template(currentfont,data) else return "no log file" end end -- much nicer would be an lmx template local function show_font(currentfont,detail) local specification = get_specification(currentfont) local features = fonts.helpers.getfeatures(specification.filename) local result = { } result[#result+1] = formatters["

Font: %s


"](currentfont) result[#result+1] = "" result[#result+1] = formatters[""] (specification.fontname or "-") result[#result+1] = formatters[" "](specification.designsize or "-") result[#result+1] = formatters[""] (specification.fullname or "-") result[#result+1] = formatters[" "](specification.minsize or "-") result[#result+1] = formatters[""] (specification.fontfile or "-") result[#result+1] = formatters[" "](specification.maxsize or "-") result[#result+1] = formatters[""] (specification.rawname or "-") result[#result+1] = formatters[" "](specification.fontweight or "-") result[#result+1] = formatters[""] (specification.familyname or "-") result[#result+1] = formatters[" "](specification.angle or "-") result[#result+1] = formatters[""] (specification.subfamily or "-") result[#result+1] = formatters[" "](specification.variant ~= "" and specification.variant or "normal") result[#result+1] = formatters[""] (specification.format or "-") result[#result+1] = formatters[" "](specification.style ~= "" and specification.style or "normal") result[#result+1] = formatters[""] (specification.pfmwidth ~= "" and specification.pfmwidth or "-") result[#result+1] = formatters[" "](specification.weight ~= "" and specification.weight or "normal") result[#result+1] = formatters[""] (specification.pfmweight ~= "" and specification.pfmweight or "-") result[#result+1] = formatters[" "](specification.width ~= "" and specification.width or "normal") result[#result+1] = "
fontname %sdesignsize %s
fullname %sminimumsize%s
filename %smaximumsize%s
rawname %sfontweight %s
familyname %sangle %s
subfamily %svariant %s
format %sstyle %s
pfmwidth %sweight %s
pfmheight %swidth %s
" if features then for what, v in table.sortedhash(features) do local data = features[what] if data and next(data) then result[#result+1] = formatters["

%s features


"](what) result[#result+1] = "" result[#result+1] = "" for f,ff in table.sortedhash(data) do local done = false for s, ss in table.sortedhash(ff) do if s == "*" then s = "all" end if ss ["*"] then ss["*"] = nil ss.all = true end if done then f = "" else done = true end local title = fonts.handlers.otf.tables.features[f] or "" result[#result+1] = formatters[""](title,f,s,concat(table.sortedkeys(ss)," ")) end end result[#result+1] = "
featuretag script languages 
%s  %s  %s  %s  
" end end else result[#result+1] = "

This font has no features." end return concat(result,"\n") end local info_template = formatters [ [[

version   : %s
comment   : %s
author    : %s
copyright : %s

maillist  : ntg-context at ntg.nl
webpage   : www.pragma-ade.nl
wiki      : contextgarden.net
]] ] local function info_about() local m = modules ['mtx-server-ctx-fonttest'] return info_template(m.version,m.comment,m.author,m.copyright) end local save_template = formatters [ [[ the current setup has been saved:

name  %s
title  %s
font  %s
script  %s
language  %s
features  %s
options  %s
sampletext %s
]] ] local function loadbase() local datafile = file.join(basepath,basename) local storage = io.loaddata(datafile) or "" if storage == "" then storage = { } else report("loading '%s'",datafile) storage = loadstring(storage) storage = (storage and storage()) or { } end return storage end local function loadstored(detail,currentfont,name) local storage = loadbase() storage = storage and storage[name] if storage then currentfont = storage.font detail.script = storage.script or detail.script detail.language = storage.language or detail.language detail.title = storage.title or detail.title detail.sampletext = storage.text or detail.sampletext detail.name = name or "no name" for k,v in next, storage.features do detail["f-"..k] = v end for k,v in next, storage.options do detail["o-"..k] = v end end detail.loadname = nil return detail, currentfont end local function savebase(storage,name) local datafile = file.join(basepath,basename) report("saving '%s' in '%s'",name or "data",datafile) io.savedata(datafile,table.serialize(storage,true)) end local function deletestored(detail,currentfont,name) local storage = loadbase() if storage and name and storage[name] then report("deleting '%s' from base",name) storage[name] = nil savebase(storage) end detail.deletename = nil return detail, "" end local function save_font(currentfont,detail) local specification = get_specification(currentfont) local name, title, script, language, features, options, text = currentfont, "", "dflt", "dflt", { }, { }, "" if detail then local htmldata = showfeatures(specification.filename) script = detail.script or script language = detail.language or language text = string.strip(detail.sampletext or text) name = string.strip(detail.name or name) title = string.strip(detail.title or title) for k,v in next, htmldata.features do if detail["f-"..k] then features[k] = true end end for k=1,#what_options do local v = what_options[k] if detail["o-"..v] then options[k] = true end end end if name == "" then name = "no name" end local storage = loadbase() storage[name] = { font = currentfont, title = title, script = script, language = language, features = features, options = options, text = text, } savebase(storage,name) return save_template(name,title,currentfont,script,language,concat(table.sortedkeys(features)," "),concat(table.sortedkeys(options)," "),text) end local function load_font(currentfont) local datafile = file.join(basepath,basename) local storage = loadbase(datafile) local result = {} result[#result+1] = "del name font fontname script language features title sampletext " for k,v in table.sortedhash(storage) do local fontname, fontfile = get_specification(v.font) result[#result+1] = formatters["x %s %s %s %s %s %s %s %s "]( k,k,k,v.font,fontname,v.script,v.language,concat(table.sortedkeys(v.features)," "),v.title or "no title",v.text or "") end if #result == 1 then return "nothing saved yet" else return formatters["%s
"](concat(result,"\n")) end end local function reset_font(currentfont) return edit_font(currentfont) end local extras_template = formatters [ [[ remake font database (take some time)

]] ] local function do_extras(detail,currentfont,extra) return extras_template() end local extras = { } local function do_extra(detail,currentfont,extra) local e = extras[extra] if e then e(detail,currentfont,extra) end return do_extras(detail,currentfont,extra) end function extras.reload() identifyfonts() return do_extras() end local status_template = formatters [ [[ ]] ] local variables = { ['color-background-one'] = lmx.get('color-background-green'), ['color-background-two'] = lmx.get('color-background-blue'), ['title'] = 'ConTeXt Font Tester', ['formaction'] = "mtx-server-ctx-fonttest.lua", } -- todo: use lmx file function doit(configuration,filename,hashed) local start = os.clock() local detail = url.query(hashed.query or "") local currentfont = detail.currentfont local action = detail.action local selection = detail.selection if action == "luajittex" then jitmode = true elseif action == "luatex" then jitmode = false end local loadname = detail.loadname local deletename = detail.deletename local extra = detail.extra if loadname and loadname ~= "" then detail, currentfont = loadstored(detail,currentfont,loadname) action = "process" elseif deletename and deletename ~= "" then detail, currentfont = deletestored(detail,currentfont,deletename) action = "load" elseif selection and selection ~= "" then currentfont = selection elseif extra and extra ~= "" then do_extra(detail,currentfont,extra) action = "extras" end local fontname, fontfile = get_specification(currentfont) if fontfile then variables.title = formatters['ConTeXt Font Tester: %s (%s)'](fontname,fontfile) else variables.title = 'ConTeXt Font Tester' end if jitmode then variables.title = variables.title .. " (using LuaJit vm)" end -- lua table and adapt report("action: %s",action or "no action") local buttons = { 'process', 'select', 'save', 'load', 'edit', 'reset', 'features', 'source', 'log', 'info', 'extras', jitmode and "luatex" or "luajittex" } local menu = { } for i=1,#buttons do local button = buttons[i] menu[#menu+1] = formatters[""](button,button) end variables.menu = concat(menu," ") variables.status = status_template(currentfont or "") variables.maintext = "" variables.javascriptdata = "" variables.javascripts = "" variables.javascriptinit = "" local result if action == "select" then variables.maintext = select_font() elseif action == "info" then variables.maintext = info_about() elseif action == "extras" then variables.maintext = do_extras() elseif currentfont and currentfont ~= "" then if action == "save" then variables.maintext = save_font(currentfont,detail) elseif action == "load" then variables.maintext = load_font(currentfont,detail) elseif action == "source" then variables.maintext = show_source(currentfont,detail) elseif action == "log" then variables.maintext = show_log(currentfont,detail) elseif action == "features" then variables.maintext = show_font(currentfont,detail) else local e, s if action == "process" then e, s = process_font(currentfont,detail) elseif action == "reset" then e, s = reset_font(currentfont) elseif action == "edit" then e, s = edit_font(currentfont,detail) else e, s = process_font(currentfont,detail) end variables.maintext = e variables.javascriptdata = s variables.javascripts = javascripts variables.javascriptinit = "check_form()" end else variables.maintext = select_font() end result = { content = lmx.convert('context-fonttest.lmx',false,variables) } report("time spent on page: %0.03f seconds",os.clock()-start) return result end return doit, true --~ make_lmx_page("test")