From bc004d99276155c0892b19965c967aeb2de01a1e Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Tue, 26 Jul 2016 23:48:32 +0200
Subject: [fontloader] sync with Context as of 2016-07-26

---
 src/fontloader/misc/fontloader-basics-nod.lua   | 10 ++-
 src/fontloader/misc/fontloader-font-gbn.lua     |  4 +-
 src/fontloader/misc/fontloader-font-osd.lua     | 12 +--
 src/fontloader/misc/fontloader-font-otl.lua     | 49 ++++++++++++-
 src/fontloader/misc/fontloader-font-otr.lua     |  2 +
 src/fontloader/misc/fontloader-font-ots.lua     |  6 +-
 src/fontloader/misc/fontloader-util-fil.lua     | 35 ++++++++-
 src/fontloader/runtime/fontloader-reference.lua | 97 ++++++++++++++++++++-----
 8 files changed, 181 insertions(+), 34 deletions(-)

(limited to 'src')

diff --git a/src/fontloader/misc/fontloader-basics-nod.lua b/src/fontloader/misc/fontloader-basics-nod.lua
index e7b5ab2..42a7a2e 100644
--- a/src/fontloader/misc/fontloader-basics-nod.lua
+++ b/src/fontloader/misc/fontloader-basics-nod.lua
@@ -71,7 +71,7 @@ nodes.nodecodes    = nodecodes
 nodes.glyphcodes   = glyphcodes
 nodes.disccodes    = disccodes
 
-local free_node    = node.free
+local flush_node   = node.flush_node
 local remove_node  = node.remove
 local new_node     = node.new
 local traverse_id  = node.traverse_id
@@ -95,7 +95,7 @@ function nodes.remove(head, current, free_too)
    head, current = remove_node(head,current)
    if t then
         if free_too then
-            free_node(t)
+            flush_node(t)
             t = nil
         else
             t.next, t.prev = nil, nil
@@ -128,12 +128,14 @@ nodes.setattr  = setfield
 
 nodes.tostring             = node.tostring or tostring
 nodes.copy                 = node.copy
+nodes.copy_node            = node.copy
 nodes.copy_list            = node.copy_list
 nodes.delete               = node.delete
 nodes.dimensions           = node.dimensions
 nodes.end_of_math          = node.end_of_math
 nodes.flush_list           = node.flush_list
 nodes.flush_node           = node.flush_node
+nodes.flush                = node.flush_node
 nodes.free                 = node.free
 nodes.insert_after         = node.insert_after
 nodes.insert_before        = node.insert_before
@@ -149,7 +151,6 @@ nodes.first_glyph          = node.first_glyph
 nodes.has_glyph            = node.has_glyph or node.first_glyph
 
 nodes.current_attr         = node.current_attr
-nodes.do_ligature_n        = node.do_ligature_n
 nodes.has_field            = node.has_field
 nodes.last_node            = node.last_node
 nodes.usedlist             = node.usedlist
@@ -253,9 +254,12 @@ nuts.insert_before       = direct.insert_before
 nuts.insert_after        = direct.insert_after
 nuts.delete              = direct.delete
 nuts.copy                = direct.copy
+nuts.copy_node           = direct.copy
 nuts.copy_list           = direct.copy_list
 nuts.tail                = direct.tail
 nuts.flush_list          = direct.flush_list
+nuts.flush_node          = direct.flush_node
+nuts.flush               = direct.flush
 nuts.free                = direct.free
 nuts.remove              = direct.remove
 nuts.is_node             = direct.is_node
diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua
index 1ae817d..1f8df64 100644
--- a/src/fontloader/misc/fontloader-font-gbn.lua
+++ b/src/fontloader/misc/fontloader-font-gbn.lua
@@ -19,7 +19,7 @@ local nodes = nodes
 local nuts        = nodes.nuts -- context abstraction of direct nodes
 
 local traverse_id = nuts.traverse_id
-local free_node   = nuts.free
+local flush_node  = nuts.flush_node
 
 local glyph_code  = nodes.nodecodes.glyph
 local disc_code   = nodes.nodecodes.disc
@@ -159,7 +159,7 @@ function nodes.handlers.nodepass(head)
                         end
                     end
                 end
-                free_node(r)
+                flush_node(r)
             end
         end
         for d in traverse_id(disc_code,nuthead) do
diff --git a/src/fontloader/misc/fontloader-font-osd.lua b/src/fontloader/misc/fontloader-font-osd.lua
index a3dda67..26af691 100644
--- a/src/fontloader/misc/fontloader-font-osd.lua
+++ b/src/fontloader/misc/fontloader-font-osd.lua
@@ -107,9 +107,9 @@ local ischar             = nuts.is_char
 
 local insert_node_after  = nuts.insert_after
 local copy_node          = nuts.copy
-local free_node          = nuts.free
 local remove_node        = nuts.remove
 local flush_list         = nuts.flush_list
+local flush_node         = nuts.flush_node
 
 local copyinjection      = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
 
@@ -792,7 +792,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
         if current == stop then
             stop = getprev(stop)
             head = remove_node(head,current)
-            free_node(current)
+            flush_node(current)
             return head, stop, nbspaces
         else
             nbspaces  = nbspaces + 1
@@ -830,7 +830,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
                                 setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
                                 local freenode = getnext(current)
                                 setlink(current,tmp)
-                                free_node(freenode)
+                                flush_node(freenode)
                                 flush_list(tempcurrent)
                                 if changestop then
                                     stop = current
@@ -1093,7 +1093,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
     if getchar(base) == c_nbsp then
         nbspaces = nbspaces - 1
         head = remove_node(head,base)
-        free_node(base)
+        flush_node(base)
     end
 
     return head, stop, nbspaces
@@ -1571,7 +1571,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
         if current == stop then
             stop = getprev(stop)
             head = remove_node(head,current)
-            free_node(current)
+            flush_node(current)
             return head, stop, nbspaces
         else
             nbspaces = nbspaces + 1
@@ -1768,7 +1768,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
     if getchar(base) == c_nbsp then
         nbspaces = nbspaces - 1
         head = remove_node(head, base)
-        free_node(base)
+        flush_node(base)
     end
 
     return head, stop, nbspaces
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index a35db5b..bdce80d 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -574,10 +574,48 @@ local function copytotfm(data,cache_id)
     end
 end
 
+-- These woff files are a kind of joke in a tex environment because one can simply convert
+-- them to ttf/otf and use them as such (after all, we cache them too). The successor format
+-- woff2 is more complex so there we can as well call an external converter which in the end
+-- makes this code kind of obsolete before it's even used. Although ... it might become a
+-- more general conversion plug in.
+
+local converters = {
+    woff = {
+        cachename = "webfonts",
+        action    = otf.readers.woff2otf,
+    }
+}
+
+local function checkconversion(specification)
+    local filename  = specification.filename
+    local converter = converters[lower(file.suffix(filename))]
+    if converter then
+        local base = file.basename(filename)
+        local name = file.removesuffix(base)
+        local attr = lfs.attributes(filename)
+        local size = attr and attr.size or 0
+        local time = attr and attr.modification or 0
+        if size > 0 then
+            local cleanname = containers.cleanname(name)
+            local cachename = caches.setfirstwritablefile(cleanname,converter.cachename)
+            if not io.exists(cachename) or (time ~= lfs.attributes(cachename).modification) then
+                report_otf("caching font %a in %a",filename,cachename)
+                converter.action(filename,cachename) -- todo infoonly
+                lfs.touch(cachename,time,time)
+            end
+            specification.filename = cachename
+        end
+    end
+end
+
 local function otftotfm(specification)
     local cache_id = specification.hash
     local tfmdata  = containers.read(constructors.cache,cache_id)
     if not tfmdata then
+
+        checkconversion(specification) -- for the moment here
+
         local name     = specification.name
         local sub      = specification.sub
         local subindex = specification.subindex
@@ -811,9 +849,14 @@ end
 
 readers.opentype = opentypereader -- kind of useless and obsolete
 
-function readers.otf  (specification) return opentypereader(specification,"otf") end
-function readers.ttf  (specification) return opentypereader(specification,"ttf") end
-function readers.ttc  (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+
+function readers.woff(specification)
+    checkconversion(specification)
+    opentypereader(specification,"")
+end
 
 -- this will be overloaded
 
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 7d0bf04..7c81285 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -94,8 +94,10 @@ otf.readers             = readers
 
 ----- streamreader      = utilities.streams -- faster on big files
 local streamreader      = utilities.files   -- faster on identify
+local streamwriter      = utilities.files
 
 readers.streamreader    = streamreader
+readers.streamwriter    = streamwriter
 
 local openfile          = streamreader.open
 local closefile         = streamreader.close
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 0f38508..10f0518 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -184,7 +184,7 @@ local copy_node          = nuts.copy
 local copy_node_list     = nuts.copy_list
 local find_node_tail     = nuts.tail
 local flush_node_list    = nuts.flush_list
-local free_node          = nuts.free
+local flush_node         = nuts.flush_node
 local end_of_math        = nuts.end_of_math
 local traverse_nodes     = nuts.traverse
 local traverse_id        = nuts.traverse_id
@@ -366,7 +366,7 @@ end
 local function flattendisk(head,disc)
     local _, _, replace, _, _, replacetail = getdisc(disc,true)
     setfield(disc,"replace",nil)
-    free_node(disc)
+    flush_node(disc)
     if head == disc then
         local next = getnext(disc)
         if replace then
@@ -2744,6 +2744,7 @@ local function kernrun(disc,k_run,font,attr,...)
                 done = true
             end
             setprev(pre,nest)
+-- setprev(pre,nil)
             setnext(prev,disc)
         end
     end
@@ -2773,6 +2774,7 @@ local function kernrun(disc,k_run,font,attr,...)
                 done = true
             end
             setprev(replace,nest)
+-- setprev(replace,nil)
             setnext(prev,disc)
         end
         if next then
diff --git a/src/fontloader/misc/fontloader-util-fil.lua b/src/fontloader/misc/fontloader-util-fil.lua
index 47d9d03..eeb6856 100644
--- a/src/fontloader/misc/fontloader-util-fil.lua
+++ b/src/fontloader/misc/fontloader-util-fil.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['util-fil'] = {
     license   = "see context related readme files"
 }
 
-local byte = string.byte
+local byte    = string.byte
+local char    = string.char
 local extract = bit32.extract
+local floor   = math.floor
 
 -- Here are a few helpers (the starting point were old ones I used for parsing
 -- flac files). In Lua 5.3 we can probably do this better. Some code will move
@@ -36,6 +38,8 @@ function files.size(f)
     return f:seek("end")
 end
 
+files.getsize = files.size
+
 function files.setposition(f,n)
     if zerobased[f] then
         f:seek("set",n)
@@ -180,3 +184,32 @@ end
 function files.skiplong(f,n)
     f:read(4*(n or 1))
 end
+
+-- writers (kind of slow)
+
+function files.writecardinal2(f,n)
+    local a = char(n % 256)
+    n = floor(n/256)
+    local b = char(n % 256)
+    f:write(b,a)
+end
+
+function files.writecardinal4(f,n)
+    local a = char(n % 256)
+    n = floor(n/256)
+    local b = char(n % 256)
+    n = floor(n/256)
+    local c = char(n % 256)
+    n = floor(n/256)
+    local d = char(n % 256)
+    f:write(d,c,b,a)
+end
+
+function files.writestring(f,s)
+    f:write(char(byte(s,1,#s)))
+end
+
+function files.writebyte(f,b)
+    f:write(char(b))
+end
+
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index e6738ea..13c45aa 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date  : 07/13/16 15:09:54
+-- merge date  : 07/25/16 21:49:08
 
 do -- begin closure to overcome local limits and interference
 
@@ -4103,7 +4103,9 @@ if not modules then modules={} end modules ['util-fil']={
   license="see context related readme files"
 }
 local byte=string.byte
+local char=string.char
 local extract=bit32.extract
+local floor=math.floor
 utilities=utilities or {}
 local files={}
 utilities.files=files
@@ -4122,6 +4124,7 @@ end
 function files.size(f)
   return f:seek("end")
 end
+files.getsize=files.size
 function files.setposition(f,n)
   if zerobased[f] then
     f:seek("set",n)
@@ -4242,6 +4245,28 @@ end
 function files.skiplong(f,n)
   f:read(4*(n or 1))
 end
+function files.writecardinal2(f,n)
+  local a=char(n%256)
+  n=floor(n/256)
+  local b=char(n%256)
+  f:write(b,a)
+end
+function files.writecardinal4(f,n)
+  local a=char(n%256)
+  n=floor(n/256)
+  local b=char(n%256)
+  n=floor(n/256)
+  local c=char(n%256)
+  n=floor(n/256)
+  local d=char(n%256)
+  f:write(d,c,b,a)
+end
+function files.writestring(f,s)
+  f:write(char(byte(s,1,#s)))
+end
+function files.writebyte(f,b)
+  f:write(char(b))
+end
 
 end -- closure
 
@@ -4704,7 +4729,7 @@ end
 nodes.nodecodes=nodecodes
 nodes.glyphcodes=glyphcodes
 nodes.disccodes=disccodes
-local free_node=node.free
+local flush_node=node.flush_node
 local remove_node=node.remove
 local new_node=node.new
 local traverse_id=node.traverse_id
@@ -4724,7 +4749,7 @@ function nodes.remove(head,current,free_too)
   head,current=remove_node(head,current)
   if t then
     if free_too then
-      free_node(t)
+      flush_node(t)
       t=nil
     else
       t.next,t.prev=nil,nil
@@ -4748,12 +4773,14 @@ nodes.getattr=getfield
 nodes.setattr=setfield
 nodes.tostring=node.tostring or tostring
 nodes.copy=node.copy
+nodes.copy_node=node.copy
 nodes.copy_list=node.copy_list
 nodes.delete=node.delete
 nodes.dimensions=node.dimensions
 nodes.end_of_math=node.end_of_math
 nodes.flush_list=node.flush_list
 nodes.flush_node=node.flush_node
+nodes.flush=node.flush_node
 nodes.free=node.free
 nodes.insert_after=node.insert_after
 nodes.insert_before=node.insert_before
@@ -4767,7 +4794,6 @@ nodes.vpack=node.vpack
 nodes.first_glyph=node.first_glyph
 nodes.has_glyph=node.has_glyph or node.first_glyph
 nodes.current_attr=node.current_attr
-nodes.do_ligature_n=node.do_ligature_n
 nodes.has_field=node.has_field
 nodes.last_node=node.last_node
 nodes.usedlist=node.usedlist
@@ -4854,9 +4880,12 @@ nuts.insert_before=direct.insert_before
 nuts.insert_after=direct.insert_after
 nuts.delete=direct.delete
 nuts.copy=direct.copy
+nuts.copy_node=direct.copy
 nuts.copy_list=direct.copy_list
 nuts.tail=direct.tail
 nuts.flush_list=direct.flush_list
+nuts.flush_node=direct.flush_node
+nuts.flush=direct.flush
 nuts.free=direct.free
 nuts.remove=direct.remove
 nuts.is_node=direct.is_node
@@ -7608,7 +7637,9 @@ handlers.otf=otf
 local readers=otf.readers or {}
 otf.readers=readers
 local streamreader=utilities.files  
+local streamwriter=utilities.files
 readers.streamreader=streamreader
+readers.streamwriter=streamwriter
 local openfile=streamreader.open
 local closefile=streamreader.close
 local setposition=streamreader.setposition
@@ -15613,10 +15644,38 @@ local function copytotfm(data,cache_id)
     }
   end
 end
+local converters={
+  woff={
+    cachename="webfonts",
+    action=otf.readers.woff2otf,
+  }
+}
+local function checkconversion(specification)
+  local filename=specification.filename
+  local converter=converters[lower(file.suffix(filename))]
+  if converter then
+    local base=file.basename(filename)
+    local name=file.removesuffix(base)
+    local attr=lfs.attributes(filename)
+    local size=attr and attr.size or 0
+    local time=attr and attr.modification or 0
+    if size>0 then
+      local cleanname=containers.cleanname(name)
+      local cachename=caches.setfirstwritablefile(cleanname,converter.cachename)
+      if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then
+        report_otf("caching font %a in %a",filename,cachename)
+        converter.action(filename,cachename) 
+        lfs.touch(cachename,time,time)
+      end
+      specification.filename=cachename
+    end
+  end
+end
 local function otftotfm(specification)
   local cache_id=specification.hash
   local tfmdata=containers.read(constructors.cache,cache_id)
   if not tfmdata then
+    checkconversion(specification) 
     local name=specification.name
     local sub=specification.sub
     local subindex=specification.subindex
@@ -15824,9 +15883,13 @@ local function opentypereader(specification,suffix)
   end
 end
 readers.opentype=opentypereader 
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+function readers.woff(specification)
+  checkconversion(specification)
+  opentypereader(specification,"")
+end
 function otf.scriptandlanguage(tfmdata,attr)
   local properties=tfmdata.properties
   return properties.script or "dflt",properties.language or "dflt"
@@ -18042,7 +18105,7 @@ local copy_node=nuts.copy
 local copy_node_list=nuts.copy_list
 local find_node_tail=nuts.tail
 local flush_node_list=nuts.flush_list
-local free_node=nuts.free
+local flush_node=nuts.flush_node
 local end_of_math=nuts.end_of_math
 local traverse_nodes=nuts.traverse
 local traverse_id=nuts.traverse_id
@@ -18176,7 +18239,7 @@ end
 local function flattendisk(head,disc)
   local _,_,replace,_,_,replacetail=getdisc(disc,true)
   setfield(disc,"replace",nil)
-  free_node(disc)
+  flush_node(disc)
   if head==disc then
     local next=getnext(disc)
     if replace then
@@ -21087,9 +21150,9 @@ local setprop=nuts.setprop
 local ischar=nuts.is_char
 local insert_node_after=nuts.insert_after
 local copy_node=nuts.copy
-local free_node=nuts.free
 local remove_node=nuts.remove
 local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
 local copyinjection=nodes.injections.copy 
 local unsetvalue=attributes.unsetvalue
 local fontdata=fonts.hashes.identifiers
@@ -21599,7 +21662,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
     if current==stop then
       stop=getprev(stop)
       head=remove_node(head,current)
-      free_node(current)
+      flush_node(current)
       return head,stop,nbspaces
     else
       nbspaces=nbspaces+1
@@ -21637,7 +21700,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
                 setchar(current,getchar(tempcurrent)) 
                 local freenode=getnext(current)
                 setlink(current,tmp)
-                free_node(freenode)
+                flush_node(freenode)
                 flush_list(tempcurrent)
                 if changestop then
                   stop=current
@@ -21874,7 +21937,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
   if getchar(base)==c_nbsp then
     nbspaces=nbspaces-1
     head=remove_node(head,base)
-    free_node(base)
+    flush_node(base)
   end
   return head,stop,nbspaces
 end
@@ -22242,7 +22305,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
     if current==stop then
       stop=getprev(stop)
       head=remove_node(head,current)
-      free_node(current)
+      flush_node(current)
       return head,stop,nbspaces
     else
       nbspaces=nbspaces+1
@@ -22427,7 +22490,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
   if getchar(base)==c_nbsp then
     nbspaces=nbspaces-1
     head=remove_node(head,base)
-    free_node(base)
+    flush_node(base)
   end
   return head,stop,nbspaces
 end
@@ -25658,7 +25721,7 @@ local fonts=fonts
 local nodes=nodes
 local nuts=nodes.nuts 
 local traverse_id=nuts.traverse_id
-local free_node=nuts.free
+local flush_node=nuts.flush_node
 local glyph_code=nodes.nodecodes.glyph
 local disc_code=nodes.nodecodes.disc
 local tonode=nuts.tonode
@@ -25782,7 +25845,7 @@ function nodes.handlers.nodepass(head)
             end
           end
         end
-        free_node(r)
+        flush_node(r)
       end
     end
     for d in traverse_id(disc_code,nuthead) do
-- 
cgit v1.2.3


From f344446dc7bd712641ae217e04177b72f1158e8c Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 00:06:36 +0200
Subject: [fontloader,import] drop font-otd.lua

---
 src/fontloader/misc/fontloader-font-otd.lua | 268 ----------------------------
 1 file changed, 268 deletions(-)
 delete mode 100644 src/fontloader/misc/fontloader-font-otd.lua

(limited to 'src')

diff --git a/src/fontloader/misc/fontloader-font-otd.lua b/src/fontloader/misc/fontloader-font-otd.lua
deleted file mode 100644
index 64cb1bc..0000000
--- a/src/fontloader/misc/fontloader-font-otd.lua
+++ /dev/null
@@ -1,268 +0,0 @@
-if not modules then modules = { } end modules ['font-otd'] = {
-    version   = 1.001,
-    comment   = "companion to font-ini.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local type = type
-local match = string.match
-local sequenced = table.sequenced
-
-local trace_dynamics     = false  trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_applied      = false  trackers.register("otf.applied",  function(v) trace_applied      = v end)
-
-local report_otf         = logs.reporter("fonts","otf loading")
-local report_process     = logs.reporter("fonts","otf process")
-
-local allocate           = utilities.storage.allocate
-
-local fonts              = fonts
-local otf                = fonts.handlers.otf
-local hashes             = fonts.hashes
-local definers           = fonts.definers
-local constructors       = fonts.constructors
-local specifiers         = fonts.specifiers
-
-local fontidentifiers    = hashes.identifiers
-local fontresources      = hashes.resources
-local fontproperties     = hashes.properties
-local fontdynamics       = hashes.dynamics
-
-local contextsetups      = specifiers.contextsetups
-local contextnumbers     = specifiers.contextnumbers
-local contextmerged      = specifiers.contextmerged
-
-local setmetatableindex  = table.setmetatableindex
-
-local a_to_script        = { }
-local a_to_language      = { }
-
--- we can have a scripts hash in fonts.hashes
-
-function otf.setdynamics(font,attribute)
- -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
-    local features = contextsetups[attribute]
-    if features then
-        local dynamics = fontdynamics[font]
-        dynamic = contextmerged[attribute] or 0
-        local script, language
-        if dynamic == 2 then -- merge
-            language  = features.language or fontproperties[font].language or "dflt"
-            script    = features.script   or fontproperties[font].script   or "dflt"
-        else -- if dynamic == 1 then -- replace
-            language  = features.language or "dflt"
-            script    = features.script   or "dflt"
-        end
-        if script == "auto" then
-            -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
-            script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
-        end
-        local ds = dynamics[script] -- can be metatable magic (less testing)
--- or dynamics.dflt
-        if not ds then
-            ds = { }
-            dynamics[script] = ds
-        end
-        local dsl = ds[language]
--- or ds.dflt
-        if not dsl then
-            dsl = { }
-            ds[language] = dsl
-        end
-        local dsla = dsl[attribute]
-        if not dsla then
-            local tfmdata = fontidentifiers[font]
-            a_to_script  [attribute] = script
-            a_to_language[attribute] = language
-            -- we need to save some values .. quite messy
-            local properties = tfmdata.properties
-            local shared     = tfmdata.shared
-            local s_script   = properties.script
-            local s_language = properties.language
-            local s_mode     = properties.mode
-            local s_features = shared.features
-            properties.mode     = "node"
-            properties.language = language
-            properties.script   = script
-            properties.dynamics = true -- handy for tracing
-            shared.features     = { }
-            -- end of save
-            local set = constructors.checkedfeatures("otf",features)
-            set.mode = "node" -- really needed
-            dsla = otf.setfeatures(tfmdata,set)
-            if trace_dynamics then
-                report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set)
-            end
-            -- we need to restore some values
-            properties.script   = s_script
-            properties.language = s_language
-            properties.mode     = s_mode
-            shared.features     = s_features
-            -- end of restore
-            dynamics[script][language][attribute] = dsla -- cache
-        elseif trace_dynamics then
-         -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
-        end
-        return dsla
-    end
-end
-
-function otf.scriptandlanguage(tfmdata,attr)
-    local properties = tfmdata.properties
-    if attr and attr > 0 then
-        return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt"
-    else
-        return properties.script or "dflt", properties.language or "dflt"
-    end
-end
-
--- we reimplement the dataset resolver
-
-local autofeatures    = fonts.analyzers.features
-local featuretypes    = otf.tables.featuretypes
-local defaultscript   = otf.features.checkeddefaultscript
-local defaultlanguage = otf.features.checkeddefaultlanguage
-
-local resolved = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard = "*"
-
--- what about analyze in local and not in font
-
--- needs checking: some added features can pass twice
-
-local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match
-
-local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1))
-
-local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
-    local features = sequence.features
-    if features then
-        local order = sequence.order
-        if order then
-            local featuretype = featuretypes[sequence.type or "unknown"]
-            for i=1,#order do --
-                local kind = order[i] --
-                local e_e
-                local a_e = a_enabled and a_enabled[kind] -- the value (location)
-                if a_e ~= nil then
-                    e_e = a_e
-                else
-                    e_e = s_enabled and s_enabled[kind] -- the value (font)
-                end
-                if e_e then
-                    local valid = type(e_e) == "string" and lpegmatch(pattern,e_e)
-                    if valid then
-                        -- we have hit always
-                        local attribute = autofeatures[kind] or false
-                        if trace_applied then
-                            report_process(
-                                "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
-                                    font,attr or 0,dynamic,kind,"*","*",sequence.name,valid)
-                        end
-                        ra[#ra+1] = { valid, attribute, sequence, kind }
-                    else
-                        -- we already checked for e_e
-                        local scripts   = features[kind] --
-                        local languages = scripts[script] or scripts[wildcard]
-                        if not languages and autoscript then
-                            langages = defaultscript(featuretype,autoscript,scripts)
-                        end
-                        if languages then
-                            -- we need detailed control over default becase we want to trace
-                            -- only first attribute match check, so we assume simple fina's
-                         -- local valid = false
-                            if languages[language] then
-                                valid = e_e
-                            elseif languages[wildcard] then
-                                valid = e_e
-                            elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
-                                valid = e_e
-                            end
-                        end
-                        if valid then
-                            local attribute = autofeatures[kind] or false
-                            if trace_applied then
-                                report_process(
-                                    "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
-                                        font,attr or 0,dynamic,kind,script,language,sequence.name,valid)
-                            end
-                            ra[#ra+1] = { valid, attribute, sequence, kind }
-                        end
-                    end
-                end
-            end
-        end
-    end
-end
-
--- there is some fuzzy language/script state stuff in properties (temporary)
-
-function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
-
-    local script, language, s_enabled, a_enabled, dynamic
-
-    if attr and attr ~= 0 then
-        dynamic = contextmerged[attr] or 0
-     -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
-        local features = contextsetups[attr]
-        a_enabled = features -- location based
-        if dynamic == 1 then -- or dynamic == -1 then
-            -- replace
-            language  = features.language or "dflt"
-            script    = features.script   or "dflt"
-        elseif dynamic == 2 then -- or dynamic == -2 then
-            -- merge
-            local properties = tfmdata.properties
-            s_enabled = tfmdata.shared.features -- font based
-            language  = features.language or properties.language or  "dflt"
-            script    = features.script   or properties.script   or  "dflt"
-        else
-            -- error
-            local properties = tfmdata.properties
-            language  = properties.language or "dflt"
-            script    = properties.script   or "dflt"
-        end
-    else
-        local properties = tfmdata.properties
-        language  = properties.language or "dflt"
-        script    = properties.script   or "dflt"
-        s_enabled = tfmdata.shared.features -- can be made local to the resolver
-        dynamic   = 0
-    end
-
-    local res = resolved[font]
-    if not res then
-        res = { }
-        resolved[font] = res
-    end
-    local rs = res[script]
-    if not rs then
-        rs = { }
-        res[script] = rs
-    end
-    local rl = rs[language]
-    if not rl then
-        rl = { }
-        rs[language] = rl
-    end
-    local ra = rl[attr]
-    if ra == nil then -- attr can be false
-        ra = {
-            -- indexed but we can also add specific data by key in:
-        }
-        rl[attr] = ra
-        local sequences = tfmdata.resources.sequences
-        if sequences then
-            local autoscript   = (s_enabled and s_enabled.autoscript  ) or (a_enabled and a_enabled.autoscript  )
-            local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
-            for s=1,#sequences do
-                -- just return nil or ra step
-                initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
-            end
-        end
-    end
-    return ra
-
-end
-- 
cgit v1.2.3


From 633aa6b951eff4221b4595c3ca19563813dd89df Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 00:11:11 +0200
Subject: [fontloader,import,status] drop luatex-plain-tfm.lua

---
 src/fontloader/misc/fontloader-plain-tfm.lua | 120 ---------------------------
 1 file changed, 120 deletions(-)
 delete mode 100644 src/fontloader/misc/fontloader-plain-tfm.lua

(limited to 'src')

diff --git a/src/fontloader/misc/fontloader-plain-tfm.lua b/src/fontloader/misc/fontloader-plain-tfm.lua
deleted file mode 100644
index 4a08fb4..0000000
--- a/src/fontloader/misc/fontloader-plain-tfm.lua
+++ /dev/null
@@ -1,120 +0,0 @@
-if not modules then modules = { } end modules ['luatex-plain-tfm'] = {
-    version   = 1.001,
-    comment   = "companion to luatex-*.tex",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
--- \font\foo=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr;pfb=csr10 at 12pt
--- \font\bar=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr           at 12pt
---
--- \foo áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par
--- \bar áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par
-
-local outfiles = { }
-
-return function(specification)
-
-    local size = specification.size
-    local name = specification.name
-    local feat = specification.features and specification.features.normal
-
-    if not feat then
-        return
-    end
-
-    local tfm = feat.tfm
-    local enc = feat.enc or tfm
-    local pfb = feat.pfb
-
-    if not tfm then
-        return
-    end
-
-    local tfmfile = tfm .. ".tfm"
-    local encfile = enc .. ".enc"
-
-    local tfmdata, id = fonts.constructors.readanddefine("file:"..tfmfile,size)
-
-    local encoding = fonts.encodings.load(encfile)
-    if encoding then
-        encoding = encoding.hash
-    else
-        encoding = false
-    end
-
-    local unicoding = fonts.encodings.agl and fonts.encodings.agl.unicodes
-
-    if tfmdata and encoding and unicoding then
-
-        tfmdata = table.copy(tfmdata) -- good enough for small fonts
-
-        local characters = { }
-        local originals  = tfmdata.characters
-        local indices    = { }
-        local parentfont = { "font", 1 }
-        local private    = fonts.constructors.privateoffset
-
-        -- create characters table
-
-        for name, index in table.sortedhash(encoding) do -- predictable order
-            local unicode  = unicoding[name]
-            local original = originals[index]
-            if not unicode then
-                unicode = private
-                private = private + 1
-                report_tfm("glyph %a in font %a gets private unicode %U",name,tfmfile,private)
-            end
-            characters[unicode] = original
-            indices[index]      = unicode
-            original.name       = name -- so one can lookup weird names
-            original.commands   = { parentfont, { "char", index } }
-        end
-
-        -- redo kerns and ligatures
-
-        for k, v in next, characters do
-            local kerns = v.kerns
-            if kerns then
-                local t = { }
-                for k, v in next, kerns do
-                    local i = indices[k]
-                    t[i] = v
-                end
-                v.kerns = t
-            end
-            local ligatures = v.ligatures
-            if ligatures then
-                local t = { }
-                for k, v in next, ligatures do
-                    t[indices[k]] = v
-                    v.char = indices[v.char]
-                end
-                v.ligatures = t
-            end
-        end
-
-        -- wrap up
-
-        tfmdata.fonts      = { { id = id } }
-        tfmdata.characters = characters
-
-        -- resources
-
-        local outfile = outfiles[tfmfile]
-
-        if outfile == nil then
-            if pfb then
-                outfile = pfb .. ".pfb"
-                pdf.mapline(tfm .. "<" .. outfile)
-            else
-                outfile = false
-            end
-            outfiles[tfmfile] = outfile
-        end
-
-    end
-
-    return tfmdata
-end
-- 
cgit v1.2.3


From 9daf6699e10df529ad035a0a8a89451d74ee6fbf Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 01:06:13 +0200
Subject: [aux] unrestrict fontname rewriting

Since TFM fonts now take the same path as OTF and suchlike, not passing
on the spec literally may actually be harmful.
---
 src/luaotfload-auxiliary.lua | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 3c43eb9..1a21405 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -43,13 +43,11 @@ local luaotfload_callbacks  = { }
 
 local rewrite_fontname = function (tfmdata, specification)
   local format = tfmdata.format or tfmdata.properties.format
-  if format ~= "type1" then
-    if stringfind (specification, " ") then
-      tfmdata.name = stringformat ("%q", specification)
-    else
-      --- other specs should parse just fine
-      tfmdata.name = specification
-    end
+  if stringfind (specification, " ") then
+    tfmdata.name = stringformat ("%q", specification)
+  else
+    --- other specs should parse just fine
+    tfmdata.name = specification
   end
 end
 
-- 
cgit v1.2.3


From c2ee46eb5b2cecfa08c7d31f57e0c46d2457ad36 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 01:15:26 +0200
Subject: [features] remove check preventing application of features to TFM
 files

---
 src/luaotfload-features.lua | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'src')

diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index b432022..0af59fb 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -2068,11 +2068,12 @@ local install_extra_features = function (data, filename, raw)
     end
     local format = data.format
     if not format then
+        --- font not fully loaded, happens with TFM/PFB
         logreport ("both", 4, "features",
-                   "no format info for font “%s”/“%s”; not \z
+                   "no format info for font “%s”; not \z
                    installing extra features.",
-                   fontname, filename)
-        return
+                   filename)
+        --return
     end
     for feature, specification in next, extrafeatures do
         if not fontname then fontname = "<unknown>" end
-- 
cgit v1.2.3


From ca62681c4174dae59d0f45f6432d5ab60d4207f3 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 23:09:58 +0200
Subject: [loaders] take tfm path directly where appropriate

The AFM one is still preferable when passed a PFB because of the extra
checking it does.
---
 src/luaotfload-loaders.lua | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index d7be31e..87275ef 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -50,6 +50,7 @@ local unsupported_reader = function (format)
 end
 
 local type1_reader = fonts.readers.afm
+local tfm_reader   = fonts.readers.tfm
 
 local install_formats = function ()
   local fonts = fonts
@@ -82,9 +83,9 @@ local install_formats = function ()
      and aux ("lua", lua_reader)
      and aux ("pfa", unsupported_reader "pfa")
      and aux ("afm", type1_reader)
-     and aux ("tfm", type1_reader)
      and aux ("pfb", type1_reader)
-     and aux ("ofm", readers.tfm)
+     and aux ("tfm", tfm_reader)
+     and aux ("ofm", tfm_reader)
      and aux ("dfont", unsupported_reader "dfont")
 end
 
-- 
cgit v1.2.3


From d37cfaf8b6bd3e82c8220d385e5da53793f332e1 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 27 Jul 2016 23:55:25 +0200
Subject: [features,fontloader] fix adding features
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This makes our own features work with otf.addfeature().

However, for TFM it’s still not functional out of the box since the
enhancer is installed at a time when it has not been defined yet. An
answer from Hans is pending. In the meantime, we put a crude hack into
our font-tfm.lua to allow injecting the enhancer retroactively on
Luaotfload init.
---
 src/fontloader/misc/fontloader-font-tfm.lua |  6 +++
 src/luaotfload-features.lua                 | 59 +++++++++++++++++++++++------
 src/luaotfload-resolvers.lua                |  1 +
 3 files changed, 55 insertions(+), 11 deletions(-)

(limited to 'src')

diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index d9b0523..6565a0e 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -85,6 +85,12 @@ local steps     = {
 
 enhancers["check extra features"] = otf.enhancers.enhance
 
+--[[ PHG: begin hack for Luaotfload ]]--
+luaotfload_tfm_enhancers_reregister = function ()
+  enhancers["check extra features"]=otf.enhancers.enhance
+end
+--[[ PHG: end hack for Luaotfload ]]--
+
 local function applyenhancers(data,filename)
     for i=1,#steps do
         local step     = steps[i]
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index 0af59fb..5905c19 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -2035,29 +2035,61 @@ local rot13_specification = {
     prepend   = true,
 }
 
-local extrafeatures = {
-    tlig  = { tlig_specification,  "tex ligatures and substitutions" },
-    anum  = { anum_specification,  "arabic numerals"                 },
-    rot13 = { rot13_specification, "rot13"                           },
-}
+
+local extrafeatures = { }
+local knownfeatures = { }
 
 function add_otf_feature (name, specification)
     if type (name) == "table" then
         specification = name
-        name = specification.name
     end
+    specification, name = validspecification (specification, name)
     if type (specification) ~= "table" then
         logreport ("both", 0, "features",
                    "invalid feature specification “%s”", tostring (name))
         return
     end
+    specification.name = name
     if name and specification then
-        extrafeatures[name] = specification
+        if knownfeatures [name] then
+            logreport ("both", 0, "features",
+                       "prevent redefinition of extra feature “%s”", name)
+        else
+            extrafeatures [#extrafeatures + 1] = specification
+            knownfeatures [name] = true
+        end
     end
 end
 
 otf.addfeature = add_otf_feature
 
+local autofeatures = {
+    --- always present with Luaotfload
+    { "tlig" , tlig_specification , "tex ligatures and substitutions" },
+    { "anum" , anum_specification , "arabic numerals"                 },
+    { "rot13", rot13_specification, "rot13"                           },
+}
+
+local add_auto_features = function ()
+    local nfeats = #autofeatures
+    logreport ("both", 5, "features",
+               "auto-installing %d feature definitions", nfeats)
+    for i = 1, nfeats do
+        local name, spec, desc = unpack (autofeatures [i])
+        spec.description = desc
+        add_otf_feature (name, spec)
+    end
+end
+
+local function enhance(data,filename,raw)
+    for slot=1,#extrafeatures do
+        local specification = extrafeatures[slot]
+        addfeature(data,specification.name,specification)
+    end
+end
+
+otf.enhancers.enhance = enhance
+
 local install_extra_features = function (data, filename, raw)
     local metadata = data and data.metadata
     if not metadata then
@@ -2075,14 +2107,16 @@ local install_extra_features = function (data, filename, raw)
                    filename)
         --return
     end
-    for feature, specification in next, extrafeatures do
-        if not fontname then fontname = "<unknown>" end
-        if not subfont  then subfont  = -1          end
+    for i = 1, #extrafeatures do
+        local specification = extrafeatures [i]
+        local feature       = specification.name
         local fontname = tostring (data.metadata.fontname) or "<unknown>"
         local subfont  = tonumber (metadata.subfontindex)  or -1
+        if not fontname then fontname = filename end
+        if not subfont  then subfont  = -1          end
         logreport ("both", 3, "features",
                    "register synthetic feature “%s” for %s font “%s”(%d)",
-                   feature, format, fontname, subfont)
+                   feature, format or "tfm", filename, subfont)
         otf.features.register { name = feature, description = specification[2] }
         otf.enhancers.addfeature (data, feature, specification[1])
     end
@@ -2100,8 +2134,11 @@ return {
             return false
         end
 
+        add_auto_features ()
+
         otf = fonts.handlers.otf
         otf.enhancers.addfeature = addfeature
+        luaotfload_tfm_enhancers_reregister ()
         otf.enhancers.register ("check extra features",
                                 install_extra_features)
 
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index a1e702b..983d3fc 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -173,6 +173,7 @@ local resolve_tex_format = function (specification)
             local usename = suffix == format and fileremovesuffix (name) or name
             specification.forcedname = file.addsuffix (usename, format)
             specification.forced     = format
+----        specification.resolved   = name
             return true
         end
     end
-- 
cgit v1.2.3