%D \module %D [ file=m-fonts-plugins, %D version=2016.10.10, %D title=\CONTEXT\ Fonts, %D subtitle=Font Engine Plugins, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D See source code for comments. I wrote this a follow up on a presentation by Kai %D Eigner at an NTG meeting, then left it for a while, and sort of finalized it the %D last quarter of 2016. As I don't use this module, apart from maybe testing %D something, it is not guaranteed to work (but fixing should be a no real problem %D as I expect apis to be stable). Plugins like this can interfere with other %D functionality in \CONTEXT\ so don't expect too much support. The two modules %D mentioned below should work in the generic loader too. It's anyhow an %D illustration of how \type {ffi} be used in a practical application. %D %D I'm not sure if Idris will ever need this but the code has been used for some %D articles so that's why it's eventually shipped. %D %D The library is supposed to be present in %D %D \starttyping %D .../tex/texmf-win64/bin/lib/luatatex/harfbuzz/libharfbuzz-0.dll %D .../tex/texmf-win64/bin/lib/luametatex/harfbuzz/libharfbuzz-0.dll %D %D .../tex/texmf-*/bin/lib/luatatex/harfbuzz/libharfbuzz.so %D .../tex/texmf-*/bin/lib/luametatex/harfbuzz/libharfbuzz.so %D \stoptyping %D %D It might be found on the system if paths are set but with libraries that render %D (font) stuff it's best to rely on what you explictly installed. When you install %D files there make sure to run \type {mtxrun --generate}. Keep in mind that we don't %D officially support such dependencies (bug-wise). %D %D In mkiv we support binary and library, and in lmtx binary and internal where we %D default to library or internal as binary is not that fast (more meant as a %D playground I guess). You can track loading with: %D %D \starttyping %D \enabletrackers[resolvers.ffilib] %D \stoptyping %D %D This file has always been in the distribution but per end april 2021 the font-txt, %D font-phb and font-phb-imp-* files are in the distrinbution too. It's a side effect %D of some cleanup of the (luametatex) source tree (where the optional module was not %D yet in sync with the other optional ones). This module is mostly for myself and %D Idris if only because it is not tested for interferences with all kind of other %D font code (and it's unlikely to happen), so don't depend on this! % \starttext % % \definefontfeature [native] [default] % [mode=plug, % features=harfbuzz, % shaper=native] % % \definefontfeature [uniscribe] [default] % [mode=plug, % features=harfbuzz, % shaper=uniscribe] % % \definefontfeature [binary] [default] % [mode=plug, % method=binary, % features=harfbuzz, % shaper=uniscribe] % % % \nohyphens % \definedfont[Serif*default] fiets \par % \input tufte \par % \definedfont[Serif*native] fiets \par % \input tufte \par % \definedfont[Serif*uniscribe] fiets \par % \input tufte \par % \definedfont[Serif*binary] fiets \par % \input tufte \par % % \stoptext \registerctxluafile{font-phb}{autosuffix} \startluacode local function processlist(data) local list = data.list local timings = data.results for i=1,#list do local name = list[i] local data = timings[name] local none = data["context none"] or 0 local node = data["context node"] or 0 if node > 0.1 then context.starttabulate { "|l|c|c|c|c|c|" } context.NC() context.bold(name) context.NC() context([[$t$]]) context.NC() context([[$t - t_{\hbox{\tx none}}$]]) context.NC() context([[$t - t_{\hbox{\tx node}}$]]) context.NC() context([[$t / t_{\hbox{\tx node}}$]]) context.NC() context([[$\frac{t - t_{\hbox{\txx none}}}{t_{\hbox{\txx node}} - t_{\hbox{\txx none}}}$]]) context.NC() context.NR() context.TL() for k, v in table.sortedhash(data) do context.NC() context(k) context.NC() context("%0.2f",v) context.NC() context("%0.2f",v - none) context.NC() context("%0.2f",v - node) context.NC() context("%0.2f",v / node) context.NC() if node ~= none then context("%0.2f",(v-none) / (node-none)) end context.NC() context.NR() end context.stoptabulate() end end end moduledata.plugins = { processlist = processlist, } \stopluacode \continueifinputfile{m-fonts-plugins.mkiv} \usemodule[art-01] \starttext \edef\tufte{\cldloadfile{tufte.tex}} \edef\khatt{\cldloadfile{khatt-ar.tex}} \startbuffer[latin-definitions] \definefont[TestA][Serif*test] \definefont[TestB][SerifItalic*test] \definefont[TestC][SerifBold*test] \stopbuffer \startbuffer[latin-text] \TestA \tufte \par \TestB \tufte \par \TestC \tufte \par \dorecurse {10} {% \TestA Fluffy Test Font A \TestB Fluffy Test Font B \TestC Fluffy Test Font C }\par \stopbuffer \startbuffer[arabic-definitions] \definedfont[Arabic*test at 14pt] \setupinterlinespace[line=18pt] \setupalign[r2l] \stopbuffer \startbuffer[arabic-text] \dorecurse {10} { \khatt\space \khatt\space \khatt \blank } \stopbuffer \startbuffer[mixed-definitions] \definefont[TestL][Serif*test] \definefont[TestA][Arabic*test at 14pt] \setupinterlinespace[line=18pt] \setupalign[r2l] \stopbuffer \startbuffer[mixed-text] \dorecurse {2} { {\TestA\khatt\space\khatt\space\khatt} {\TestL\lefttoright\tufte} \blank \dorecurse{10}{% {\TestA وَ قَرْمِطْ بَيْنَ الْحُرُوفِ؛ فَإِنَّ} {\TestL\lefttoright A snippet text that makes no sense.} } } \stopbuffer \definefontfeature [test-none] [mode=none] \definefontfeature [test-base] [mode=base, liga=yes, kern=yes] % no tlig and no analyze \definefontfeature [test-node] [mode=node, script=auto, autoscript=position, autolanguage=position, ccmp=yes, liga=yes, % rlig=yes, % hlig=yes, % dlig=yes, clig=yes, kern=yes, mark=yes, mkmk=yes, curs=yes] \definefontfeature [test-text] [mode=plug, features=text] \definefontfeature [test-native] [mode=plug, features=harfbuzz, %liga=yes, %kern=yes, shaper=native] \definefontfeature [test-uniscribe] [mode=plug, features=harfbuzz, %liga=yes, %kern=yes, shaper=uniscribe] \definefontfeature [test-binary] [mode=plug, features=harfbuzz, %liga=yes, %kern=yes, shaper=uniscribe, method=binary] \definefontfeature [arabic-node] [arabic] [salt=yes] % seems to be needed for husayni \definefontfeature [arabic-native] [mode=plug, features=harfbuzz, % method=binary, % method=internal, script=arab,language=dflt, % ccmp=yes, % init=yes,medi=yes,fina=yes,isol=yes, % liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes, % mark=yes,mkmk=yes,kern=yes,curs=yes, shaper=native] \definefontfeature [arabic-uniscribe] [mode=plug, features=harfbuzz, script=arab,language=dflt, % ccmp=yes, % init=yes,medi=yes,fina=yes,isol=yes, % liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes, % mark=yes,mkmk=yes,kern=yes,curs=yes, shaper=uniscribe] \starttexdefinition RunLatinTest #1#2#3#4#5 \start \dontcomplain \definefontfeature[test][test-#4] \writestatus{warning}{#1 #3 #4 (1 initial run)} \page \startluacode collectgarbage("collect") \stopluacode \title{#1 #3 #4} \start \getbuffer[#5-definitions] \showfontkerns \showmakeup[discretionary] % \enabletrackers[fonts.plugins.hb.colors]% \testfeatureonce{1}{ \getbuffer[#5-text] } \stop \page \startluacode collectgarbage("collect") \stopluacode \ifnum#2>1\relax \writestatus{warning}{#1 #3 #4 (#2 timing runs)} \start \getbuffer[#5-definitions] \testfeatureonce{#2}{ \setbox\scratchbox\hbox{\getbuffer[#5-text]} } \stop \writestatus{warning}{done} \fi \startluacode document.collected_timings.timings["#5"].results["#1"]["#3 #4"] = \elapsedtime\space collectgarbage("collect") \stopluacode \stop \stoptexdefinition \starttexdefinition RunArabicTest #1#2#3#4#5 \start \dontcomplain \definefontsynonym[Arabic][#1] \definefontfeature[test][arabic-#4] \writestatus{warning}{#1 #3 #4 #5 (1 initial run)} \page \startluacode collectgarbage("collect") \stopluacode \title{#1 #3 #4} \start \getbuffer[#5-definitions] % \enabletrackers[fonts.plugins.hb.colors]% \testfeatureonce{1}{ \setupalign[flushleft] % easier to compare \getbuffer[#5-text] } \par \stop \page \ifnum#2>1\relax \writestatus{warning}{#1 #3 #4 #5 (#2 timing runs)} \start \getbuffer[#5-definitions] \testfeatureonce{#2}{ \setbox\scratchbox\hbox{\getbuffer[#5-text]} } \stop \writestatus{warning}{done} \fi \startluacode document.collected_timings.timings["#5"].results["#1"]["#3 #4"] = \elapsedtime\space collectgarbage("collect") \stopluacode \stop \stoptexdefinition \startsubject[title=Remark] These tests are no longer representative because in mode node we have a lot of additional features (control options, tracing, dynamics, user features) kicking in that impact runtime because they need to be checked. The same is true for discretionaries. On the average the font processing time is not that much the bottleneck anyway, also given that typesetting with \TEX\ has always been about full control over matters. But we keep this module around. When run with \LMTX\ \LUATEX\ is actually \LUAMETATEX . \stopsubject \page \startluacode local processlist = moduledata.plugins.processlist local data = { timings = { }, engine = jit and "luajittex" or "luatex", } document.collected_timings = data -- LATIN local list = { "modern", "pagella", "dejavu", "cambria", "ebgaramond", "lucidaot" } data.timings["latin"] = { list = list, results = table.setmetatableindex("table"), } for i=1,#list do local name = list[i] context.setupbodyfont { name } context.RunLatinTest (name, 100, "context", "none", "latin") context.RunLatinTest (name, 100, "context", "base", "latin") context.RunLatinTest (name, 100, "context", "node", "latin") context.RunLatinTest (name, 100, "harfbuzz", "native", "latin") context.RunLatinTest (name, 100, "harfbuzz", "uniscribe", "latin") -- context.RunLatinTest (name, 1, "context", "text", "latin") -- context.RunLatinTest (name, 1, "harfbuzz", "binary", "latin") end context(function() context.page() context.title((jit and "luajittex" or "luatex") .. " latin") processlist(data.timings["latin"]) context.page() end) -- ARABIC local list = { "arabtype", "husayni", } data.timings["arabic"] = { list = list, results = table.setmetatableindex("table") } for i=1,#list do local name = list[i] context.setupbodyfont { name } context.RunArabicTest (name, 100, "context", "none", "arabic") context.RunArabicTest (name, 100, "context", "base", "arabic") context.RunArabicTest (name, 100, "context", "node", "arabic") context.RunArabicTest (name, 100, "harfbuzz", "native", "arabic") context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "arabic") -- context.RunArabicTest (name, 1, "context", "text", "arabic") -- context.RunArabicTest (name, 1, "harfbuzz", "binary", "arabic") end context(function() context.page() context.title((jit and "luajittex" or "luatex") .. " arabic") processlist(data.timings["arabic"]) context.page() end) -- MIXED local list = { "arabtype", "husayni" } data.timings["mixed"] = { list = list, results = table.setmetatableindex("table") } for i=1,#list do local name = list[i] context.setupbodyfont { name } context.RunArabicTest (name, 100, "context", "none", "mixed") context.RunArabicTest (name, 100, "context", "base", "mixed") context.RunArabicTest (name, 100, "context", "node", "mixed") context.RunArabicTest (name, 100, "harfbuzz", "native", "mixed") context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "mixed") -- context.RunArabicTest (name, 1, "context", "text", "mixed") -- context.RunArabicTest (name, 1, "harfbuzz", "binary", "mixed") end context(function() context.page() context.title((jit and "luajittex" or "luatex") .. " mixed") processlist(data.timings["mixed"]) context.page() end) context(function() table.save("m-fonts-plugins-timings-" .. (jit and "luajittex" or "luatex") .. ".lua",data) end) \stopluacode \stoptext