diff options
Diffstat (limited to 'src/fontloader/runtime')
| -rw-r--r-- | src/fontloader/runtime/fontloader-reference.lua | 773 | 
1 files changed, 772 insertions, 1 deletions
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua index 4cefe9a..6ef9430 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/30/16 00:26:47 +-- merge date  : 08/11/16 13:56:03  do -- begin closure to overcome local limits and interference @@ -23430,6 +23430,777 @@ end -- closure  do -- begin closure to overcome local limits and interference +if not modules then modules={} end modules ['font-otc']={ +  version=1.001, +  comment="companion to font-otf.lua (context)", +  author="Hans Hagen, PRAGMA-ADE, Hasselt NL", +  copyright="PRAGMA ADE / ConTeXt Development Team", +  license="see context related readme files" +} +local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash +local type,next=type,next +local lpegmatch=lpeg.match +local utfbyte,utflen=utf.byte,utf.len +local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) +local report_otf=logs.reporter("fonts","otf loading") +local fonts=fonts +local otf=fonts.handlers.otf +local registerotffeature=otf.features.register +local setmetatableindex=table.setmetatableindex +local normalized={ +  substitution="substitution", +  single="substitution", +  ligature="ligature", +  alternate="alternate", +  multiple="multiple", +  kern="kern", +  pair="pair", +  chainsubstitution="chainsubstitution", +  chainposition="chainposition", +} +local types={ +  substitution="gsub_single", +  ligature="gsub_ligature", +  alternate="gsub_alternate", +  multiple="gsub_multiple", +  kern="gpos_pair", +  pair="gpos_pair", +  chainsubstitution="gsub_contextchain", +  chainposition="gpos_contextchain", +} +local names={ +  gsub_single="gsub", +  gsub_multiple="gsub", +  gsub_alternate="gsub", +  gsub_ligature="gsub", +  gsub_context="gsub", +  gsub_contextchain="gsub", +  gsub_reversecontextchain="gsub", +  gpos_single="gpos", +  gpos_pair="gpos", +  gpos_cursive="gpos", +  gpos_mark2base="gpos", +  gpos_mark2ligature="gpos", +  gpos_mark2mark="gpos", +  gpos_context="gpos", +  gpos_contextchain="gpos", +} +setmetatableindex(types,function(t,k) t[k]=k return k end)  +local everywhere={ ["*"]={ ["*"]=true } }  +local noflags={ false,false,false,false } +local function getrange(sequences,category) +  local count=#sequences +  local first=nil +  local last=nil +  for i=1,count do +    local t=sequences[i].type +    if t and names[t]==category then +      if not first then +        first=i +      end +      last=i +    end +  end +  return first or 1,last or count +end +local function validspecification(specification,name) +  local dataset=specification.dataset +  if dataset then +  elseif specification[1] then +    dataset=specification +    specification={ dataset=dataset } +  else +    dataset={ { data=specification.data } } +    specification.data=nil +    specification.dataset=dataset +  end +  local first=dataset[1] +  if first then +    first=first.data +  end +  if not first then +    report_otf("invalid feature specification, no dataset") +    return +  end +  if type(name)~="string" then +    name=specification.name or first.name +  end +  if type(name)~="string" then +    report_otf("invalid feature specification, no name") +    return +  end +  local n=#dataset +  if n>0 then +    for i=1,n do +      setmetatableindex(dataset[i],specification) +    end +    return specification,name +  end +end +local function addfeature(data,feature,specifications) +  if not specifications then +    report_otf("missing specification") +    return +  end +  local descriptions=data.descriptions +  local resources=data.resources +  local features=resources.features +  local sequences=resources.sequences +  if not features or not sequences then +    report_otf("missing specification") +    return +  end +  local alreadydone=resources.alreadydone +  if not alreadydone then +    alreadydone={} +    resources.alreadydone=alreadydone +  end +  if alreadydone[specifications] then +    return +  else +    alreadydone[specifications]=true +  end +  local fontfeatures=resources.features or everywhere +  local unicodes=resources.unicodes +  local splitter=lpeg.splitter(" ",unicodes) +  local done=0 +  local skip=0 +  local aglunicodes=false +  local specifications=validspecification(specifications,feature) +  if not specifications then +    return +  end +  local function tounicode(code) +    if not code then +      return +    end +    if type(code)=="number" then +      return code +    end +    local u=unicodes[code] +    if u then +      return u +    end +    if utflen(code)==1 then +      u=utfbyte(code) +      if u then +        return u +      end +    end +    if not aglunicodes then +      aglunicodes=fonts.encodings.agl.unicodes  +    end +    return aglunicodes[code] +  end +  local coverup=otf.coverup +  local coveractions=coverup.actions +  local stepkey=coverup.stepkey +  local register=coverup.register +  local function prepare_substitution(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    for code,replacement in next,list do +      local unicode=tounicode(code) +      local description=descriptions[unicode] +      if description then +        if type(replacement)=="table" then +          replacement=replacement[1] +        end +        replacement=tounicode(replacement) +        if replacement and descriptions[replacement] then +          cover(coverage,unicode,replacement) +          done=done+1 +        else +          skip=skip+1 +        end +      else +        skip=skip+1 +      end +    end +    return coverage +  end +  local function prepare_alternate(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    for code,replacement in next,list do +      local unicode=tounicode(code) +      local description=descriptions[unicode] +      if not description then +        skip=skip+1 +      elseif type(replacement)=="table" then +        local r={} +        for i=1,#replacement do +          local u=tounicode(replacement[i]) +          r[i]=descriptions[u] and u or unicode +        end +        cover(coverage,unicode,r) +        done=done+1 +      else +        local u=tounicode(replacement) +        if u then +          cover(coverage,unicode,{ u }) +          done=done+1 +        else +          skip=skip+1 +        end +      end +    end +    return coverage +  end +  local function prepare_multiple(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    for code,replacement in next,list do +      local unicode=tounicode(code) +      local description=descriptions[unicode] +      if not description then +        skip=skip+1 +      elseif type(replacement)=="table" then +        local r,n={},0 +        for i=1,#replacement do +          local u=tounicode(replacement[i]) +          if descriptions[u] then +            n=n+1 +            r[n]=u +          end +        end +        if n>0 then +          cover(coverage,unicode,r) +          done=done+1 +        else +          skip=skip+1 +        end +      else +        local u=tounicode(replacement) +        if u then +          cover(coverage,unicode,{ u }) +          done=done+1 +        else +          skip=skip+1 +        end +      end +    end +    return coverage +  end +  local function prepare_ligature(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    for code,ligature in next,list do +      local unicode=tounicode(code) +      local description=descriptions[unicode] +      if description then +        if type(ligature)=="string" then +          ligature={ lpegmatch(splitter,ligature) } +        end +        local present=true +        for i=1,#ligature do +          local l=ligature[i] +          local u=tounicode(l) +          if descriptions[u] then +            ligature[i]=u +          else +            present=false +            break +          end +        end +        if present then +          cover(coverage,unicode,ligature) +          done=done+1 +        else +          skip=skip+1 +        end +      else +        skip=skip+1 +      end +    end +    return coverage +  end +  local function prepare_kern(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    for code,replacement in next,list do +      local unicode=tounicode(code) +      local description=descriptions[unicode] +      if description and type(replacement)=="table" then +        local r={} +        for k,v in next,replacement do +          local u=tounicode(k) +          if u then +            r[u]=v +          end +        end +        if next(r) then +          cover(coverage,unicode,r) +          done=done+1 +        else +          skip=skip+1 +        end +      else +        skip=skip+1 +      end +    end +    return coverage +  end +  local function prepare_pair(list,featuretype) +    local coverage={} +    local cover=coveractions[featuretype] +    if cover then +      for code,replacement in next,list do +        local unicode=tounicode(code) +        local description=descriptions[unicode] +        if description and type(replacement)=="table" then +          local r={} +          for k,v in next,replacement do +            local u=tounicode(k) +            if u then +              r[u]=v +            end +          end +          if next(r) then +            cover(coverage,unicode,r) +            done=done+1 +          else +            skip=skip+1 +          end +        else +          skip=skip+1 +        end +      end +    else +      report_otf("unknown cover type %a",featuretype) +    end +    return coverage +  end +  local function prepare_chain(list,featuretype,sublookups) +    local rules=list.rules +    local coverage={} +    if rules then +      local rulehash={} +      local rulesize=0 +      local sequence={} +      local nofsequences=0 +      local lookuptype=types[featuretype] +      for nofrules=1,#rules do +        local rule=rules[nofrules] +        local current=rule.current +        local before=rule.before +        local after=rule.after +        local replacements=rule.replacements or false +        local sequence={} +        local nofsequences=0 +        if before then +          for n=1,#before do +            nofsequences=nofsequences+1 +            sequence[nofsequences]=before[n] +          end +        end +        local start=nofsequences+1 +        for n=1,#current do +          nofsequences=nofsequences+1 +          sequence[nofsequences]=current[n] +        end +        local stop=nofsequences +        if after then +          for n=1,#after do +            nofsequences=nofsequences+1 +            sequence[nofsequences]=after[n] +          end +        end +        local lookups=rule.lookups or false +        local subtype=nil +        if lookups and sublookups then +          for k,v in next,lookups do +            local lookup=sublookups[v] +            if lookup then +              lookups[k]=lookup +              if not subtype then +                subtype=lookup.type +              end +            else +            end +          end +        end +        if nofsequences>0 then +          local hashed={} +          for i=1,nofsequences do +            local t={} +            local s=sequence[i] +            for i=1,#s do +              local u=tounicode(s[i]) +              if u then +                t[u]=true +              end +            end +            hashed[i]=t +          end +          sequence=hashed +          rulesize=rulesize+1 +          rulehash[rulesize]={ +            nofrules, +            lookuptype, +            sequence, +            start, +            stop, +            lookups, +            replacements, +            subtype, +          } +          for unic in next,sequence[start] do +            local cu=coverage[unic] +            if not cu then +              coverage[unic]=rulehash  +            end +          end +        end +      end +    end +    return coverage +  end +  local dataset=specifications.dataset +  local function report(name,category,position,first,last,sequences) +    report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]", +      name,category,position,first,last,1,#sequences) +  end +  local function inject(specification,sequences,sequence,first,last,category,name) +    local position=specification.position or false +    if not position then +      position=specification.prepend +      if position==true then +        if trace_loading then +          report(name,category,first,first,last,sequences) +        end +        insert(sequences,first,sequence) +        return +      end +    end +    if not position then +      position=specification.append +      if position==true then +        if trace_loading then +          report(name,category,last+1,first,last,sequences) +        end +        insert(sequences,last+1,sequence) +        return +      end +    end +    local kind=type(position) +    if kind=="string" then +      local index=false +      for i=first,last do +        local s=sequences[i] +        local f=s.features +        if f then +          for k in next,f do +            if k==position then +              index=i +              break +            end +          end +          if index then +            break +          end +        end +      end +      if index then +        position=index +      else +        position=last+1 +      end +    elseif kind=="number" then +      if position<0 then +        position=last-position+1 +      end +      if position>last then +        position=last+1 +      elseif position<first then +        position=first +      end +    else +      position=last+1 +    end +    if trace_loading then +      report(name,category,position,first,last,sequences) +    end +    insert(sequences,position,sequence) +  end +  for s=1,#dataset do +    local specification=dataset[s] +    local valid=specification.valid  +    local feature=specification.name or feature +    if not feature or feature=="" then +      report_otf("no valid name given for extra feature") +    elseif not valid or valid(data,specification,feature) then  +      local initialize=specification.initialize +      if initialize then +        specification.initialize=initialize(specification,data) and initialize or nil +      end +      local askedfeatures=specification.features or everywhere +      local askedsteps=specification.steps or specification.subtables or { specification.data } or {} +      local featuretype=normalized[specification.type or "substitution"] or "substitution" +      local featureflags=specification.flags or noflags +      local featureorder=specification.order or { feature } +      local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0 +      local nofsteps=0 +      local steps={} +      local sublookups=specification.lookups +      local category=nil +      if sublookups then +        local s={} +        for i=1,#sublookups do +          local specification=sublookups[i] +          local askedsteps=specification.steps or specification.subtables or { specification.data } or {} +          local featuretype=normalized[specification.type or "substitution"] or "substitution" +          local featureflags=specification.flags or noflags +          local nofsteps=0 +          local steps={} +          for i=1,#askedsteps do +            local list=askedsteps[i] +            local coverage=nil +            local format=nil +            if featuretype=="substitution" then +              coverage=prepare_substitution(list,featuretype) +            elseif featuretype=="ligature" then +              coverage=prepare_ligature(list,featuretype) +            elseif featuretype=="alternate" then +              coverage=prepare_alternate(list,featuretype) +            elseif featuretype=="multiple" then +              coverage=prepare_multiple(list,featuretype) +            elseif featuretype=="kern" then +              format="kern" +              coverage=prepare_kern(list,featuretype) +            elseif featuretype=="pair" then +              format="pair" +              coverage=prepare_pair(list,featuretype) +            end +            if coverage and next(coverage) then +              nofsteps=nofsteps+1 +              steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) +            end +          end +          s[i]={ +            [stepkey]=steps, +            nofsteps=nofsteps, +            type=types[featuretype], +          } +        end +        sublookups=s +      end +      for i=1,#askedsteps do +        local list=askedsteps[i] +        local coverage=nil +        local format=nil +        if featuretype=="substitution" then +          category="gsub" +          coverage=prepare_substitution(list,featuretype) +        elseif featuretype=="ligature" then +          category="gsub" +          coverage=prepare_ligature(list,featuretype) +        elseif featuretype=="alternate" then +          category="gsub" +          coverage=prepare_alternate(list,featuretype) +        elseif featuretype=="multiple" then +          category="gsub" +          coverage=prepare_multiple(list,featuretype) +        elseif featuretype=="kern" then +          category="gpos" +          format="kern" +          coverage=prepare_kern(list,featuretype) +        elseif featuretype=="pair" then +          category="gpos" +          format="pair" +          coverage=prepare_pair(list,featuretype) +        elseif featuretype=="chainsubstitution" then +          category="gsub" +          coverage=prepare_chain(list,featuretype,sublookups) +        elseif featuretype=="chainposition" then +          category="gpos" +          coverage=prepare_chain(list,featuretype,sublookups) +        else +          report_otf("not registering feature %a, unknown category",feature) +          return +        end +        if coverage and next(coverage) then +          nofsteps=nofsteps+1 +          steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) +        end +      end +      if nofsteps>0 then +        for k,v in next,askedfeatures do +          if v[1] then +            askedfeatures[k]=tohash(v) +          end +        end +        if featureflags[1] then featureflags[1]="mark" end +        if featureflags[2] then featureflags[2]="ligature" end +        if featureflags[3] then featureflags[3]="base" end +        local steptype=types[featuretype] +        local sequence={ +          chain=featurechain, +          features={ [feature]=askedfeatures }, +          flags=featureflags, +          name=feature, +          order=featureorder, +          [stepkey]=steps, +          nofsteps=nofsteps, +          type=steptype, +        } +        local first,last=getrange(sequences,category) +        inject(specification,sequences,sequence,first,last,category,feature) +        local features=fontfeatures[category] +        if not features then +          features={} +          fontfeatures[category]=features +        end +        local k=features[feature] +        if not k then +          k={} +          features[feature]=k +        end +        for script,languages in next,askedfeatures do +          local kk=k[script] +          if not kk then +            kk={} +            k[script]=kk +          end +          for language,value in next,languages do +            kk[language]=value +          end +        end +      end +    end +  end +  if trace_loading then +    report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip) +  end +end +otf.enhancers.addfeature=addfeature +local extrafeatures={} +local knownfeatures={} +function otf.addfeature(name,specification) +  if type(name)=="table" then +    specification=name +  end +  if type(specification)~="table" then +    report_otf("invalid feature specification, no valid table") +    return +  end +  specification,name=validspecification(specification,name) +  if name and specification then +    local slot=knownfeatures[name] +    if slot then +    else +      slot=#extrafeatures+1 +      knownfeatures[name]=slot +    end +    specification.name=name  +    extrafeatures[slot]=specification +  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 +otf.enhancers.register("check extra features",enhance) +local tlig={ +  [0x2013]={ 0x002D,0x002D }, +  [0x2014]={ 0x002D,0x002D,0x002D }, +} +local tlig_specification={ +  type="ligature", +  features=everywhere, +  data=tlig, +  order={ "tlig" }, +  flags=noflags, +  prepend=true, +} +otf.addfeature("tlig",tlig_specification) +registerotffeature { +  name='tlig', +  description='tex ligatures', +} +local trep={ +  [0x0027]=0x2019, +} +local trep_specification={ +  type="substitution", +  features=everywhere, +  data=trep, +  order={ "trep" }, +  flags=noflags, +  prepend=true, +} +otf.addfeature("trep",trep_specification) +registerotffeature { +  name='trep', +  description='tex replacements', +} +local anum_arabic={ +  [0x0030]=0x0660, +  [0x0031]=0x0661, +  [0x0032]=0x0662, +  [0x0033]=0x0663, +  [0x0034]=0x0664, +  [0x0035]=0x0665, +  [0x0036]=0x0666, +  [0x0037]=0x0667, +  [0x0038]=0x0668, +  [0x0039]=0x0669, +} +local anum_persian={ +  [0x0030]=0x06F0, +  [0x0031]=0x06F1, +  [0x0032]=0x06F2, +  [0x0033]=0x06F3, +  [0x0034]=0x06F4, +  [0x0035]=0x06F5, +  [0x0036]=0x06F6, +  [0x0037]=0x06F7, +  [0x0038]=0x06F8, +  [0x0039]=0x06F9, +} +local function valid(data) +  local features=data.resources.features +  if features then +    for k,v in next,features do +      for k,v in next,v do +        if v.arab then +          return true +        end +      end +    end +  end +end +local anum_specification={ +  { +    type="substitution", +    features={ arab={ urd=true,dflt=true } }, +    order={ "anum" }, +    data=anum_arabic, +    flags=noflags, +    valid=valid, +  }, +  { +    type="substitution", +    features={ arab={ urd=true } }, +    order={ "anum" }, +    data=anum_persian, +    flags=noflags, +    valid=valid, +  }, +} +otf.addfeature("anum",anum_specification)  +registerotffeature { +  name='anum', +  description='arabic digits', +} + +end -- closure + +do -- begin closure to overcome local limits and interference +  if not modules then modules={} end modules ['font-onr']={    version=1.001,    comment="companion to font-ini.mkiv",  | 
