diff options
Diffstat (limited to 'src/fontloader/misc')
| -rw-r--r-- | src/fontloader/misc/fontloader-font-con.lua | 31 | ||||
| -rw-r--r-- | src/fontloader/misc/fontloader-font-oti.lua | 4 | ||||
| -rw-r--r-- | src/fontloader/misc/fontloader-font-otl.lua | 2 | ||||
| -rw-r--r-- | src/fontloader/misc/fontloader-font-otr.lua | 130 | ||||
| -rw-r--r-- | src/fontloader/misc/fontloader-font-ots.lua | 108 | ||||
| -rw-r--r-- | src/fontloader/misc/fontloader-util-fil.lua | 42 | 
6 files changed, 269 insertions, 48 deletions
| diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua index b3e506b..18f2217 100644 --- a/src/fontloader/misc/fontloader-font-con.lua +++ b/src/fontloader/misc/fontloader-font-con.lua @@ -447,12 +447,16 @@ function constructors.scale(tfmdata,specification)      local haskerns         = properties.haskerns     or properties.mode == "base" -- we can have afm in node mode      local hasligatures     = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode      local realdimensions   = properties.realdimensions +    local writingmode      = properties.writingmode or "horizontal" +    local identity         = properties.identity or "horizontal"      --      if changed and not next(changed) then          changed = false      end      -- -    target.type = isvirtual and "virtual" or "real" +    target.type        = isvirtual and "virtual" or "real" +    target.writingmode = writingmode == "vertical" and "vertical" or "horizontal" +    target.identity    = identity == "vertical" and "vertical" or "horizontal"      --      target.postprocessors = tfmdata.postprocessors      -- @@ -894,6 +898,8 @@ function constructors.finalize(tfmdata)              cidinfo       = tfmdata.cidinfo       or nil,              format        = tfmdata.format        or "type1",              direction     = tfmdata.direction     or 0, +            writingmode   = tfmdata.writingmode   or "horizontal", +            identity      = tfmdata.identity      or "horizontal",          }      end      if not tfmdata.resources then @@ -1091,7 +1097,11 @@ end)  do -    local function setindeed(mode,target,group,name,action,position) +    local function setindeed(mode,source,target,group,name,position) +        local action = source[mode] +        if not action then +            return +        end          local t = target[mode]          if not t then              report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode) @@ -1122,15 +1132,10 @@ do              report_defining("fatal source error in setting feature %a, group %a",name,group)              os.exit()          end -        local node     = source.node -        local base     = source.base          local position = source.position -        if node then -            setindeed("node",target,group,name,node,position) -        end -        if base then -            setindeed("base",target,group,name,base,position) -        end +        setindeed("node",source,target,group,name,position) +        setindeed("base",source,target,group,name,position) +        setindeed("plug",source,target,group,name,position)      end      local function register(where,specification) @@ -1197,9 +1202,9 @@ do                  defaults     = { },                  descriptions = tables and tables.features or { },                  used         = statistics and statistics.usedfeatures or { }, -                initializers = { base = { }, node = { } }, -                processors   = { base = { }, node = { } }, -                manipulators = { base = { }, node = { } }, +                initializers = { base = { }, node = { }, plug = { } }, +                processors   = { base = { }, node = { }, plug = { } }, +                manipulators = { base = { }, node = { }, plug = { } },              }              features.register = function(specification) return register(features,specification) end              handler.features = features -- will also become hidden diff --git a/src/fontloader/misc/fontloader-font-oti.lua b/src/fontloader/misc/fontloader-font-oti.lua index 5e812bb..e10a261 100644 --- a/src/fontloader/misc/fontloader-font-oti.lua +++ b/src/fontloader/misc/fontloader-font-oti.lua @@ -72,6 +72,7 @@ registerotffeature {      initializers = {          base = setmode,          node = setmode, +        plug = setmode,      }  } @@ -81,6 +82,7 @@ registerotffeature {      initializers = {          base = setlanguage,          node = setlanguage, +        plug = setlanguage,      }  } @@ -90,6 +92,7 @@ registerotffeature {      initializers = {          base = setscript,          node = setscript, +        plug = setscript,      }  } @@ -157,4 +160,3 @@ function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)          end      end  end - diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua index cf6603f..d4eaed7 100644 --- a/src/fontloader/misc/fontloader-font-otl.lua +++ b/src/fontloader/misc/fontloader-font-otl.lua @@ -675,7 +675,7 @@ local function getgsub(tfmdata,k,kind,value)              local properties = tfmdata.properties              local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)              if validlookups then -                local choice = tonumber(value) or 1 -- no random here (yet) +             -- local choice = tonumber(value) or 1 -- no random here (yet)                  for i=1,#lookuplist do                      local lookup   = lookuplist[i]                      local steps    = lookup.steps diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua index 9cdbc3d..2b18c1e 100644 --- a/src/fontloader/misc/fontloader-font-otr.lua +++ b/src/fontloader/misc/fontloader-font-otr.lua @@ -975,7 +975,7 @@ readers.head = function(f,fontdata)  end  -- This table is a rather simple one. No treatment of values is needed here. Most --- variables are not used but nofhmetrics is quite important. +-- variables are not used but nofmetrics is quite important.  readers.hhea = function(f,fontdata,specification)      if specification.details then @@ -983,7 +983,7 @@ readers.hhea = function(f,fontdata,specification)          if datatable then              setposition(f,datatable.offset)              fontdata.horizontalheader = { -                version             = readfixed(f), +                version             = readfixed(f), -- two ushorts: major minor                  ascender            = readfword(f),                  descender           = readfword(f),                  linegap             = readfword(f), @@ -999,11 +999,45 @@ readers.hhea = function(f,fontdata,specification)                  reserved_3          = readshort(f),                  reserved_4          = readshort(f),                  metricdataformat    = readshort(f), -                nofhmetrics         = readushort(f), +                nofmetrics          = readushort(f),              }          else              fontdata.horizontalheader = { -                nofhmetrics = 0, +                nofmetrics = 0, +            } +        end +    end +end + +readers.vhea = function(f,fontdata,specification) +    if specification.details then +        local datatable = fontdata.tables.vhea +        if datatable then +            setposition(f,datatable.offset) +            local version = readfixed(f) +            fontdata.verticalheader = { +                version              = version, +                ascender             = readfword(f), +                descender            = readfword(f), +                linegap              = readfword(f), +                maxadvanceheight     = readufword(f), +                mintopsidebearing    = readfword(f), +                minbottomsidebearing = readfword(f), +                maxextent            = readfword(f), +                caretsloperise       = readshort(f), +                caretsloperun        = readshort(f), +                caretoffset          = readshort(f), +                reserved_1           = readshort(f), +                reserved_2           = readshort(f), +                reserved_3           = readshort(f), +                reserved_4           = readshort(f), +                metricdataformat     = readshort(f), +                nofmetrics           = readushort(f), +            } +--             inspect(fontdata.verticalheader) +        else +            fontdata.verticalheader = { +                nofmetrics = 0,              }          end      end @@ -1064,11 +1098,12 @@ readers.hmtx = function(f,fontdata,specification)          local datatable = fontdata.tables.hmtx          if datatable then              setposition(f,datatable.offset) -            local nofmetrics      = fontdata.horizontalheader.nofhmetrics -            local glyphs          = fontdata.glyphs -            local nofglyphs       = fontdata.nofglyphs -            local width           = 0 -- advance -            local leftsidebearing = 0 +            local horizontalheader = fontdata.horizontalheader +            local nofmetrics       = horizontalheader.nofmetrics +            local glyphs           = fontdata.glyphs +            local nofglyphs        = fontdata.nofglyphs +            local width            = 0 -- advance +            local leftsidebearing  = 0              for i=0,nofmetrics-1 do                  local glyph     = glyphs[i]                  width           = readshort(f) @@ -1095,6 +1130,53 @@ readers.hmtx = function(f,fontdata,specification)      end  end +readers.vmtx = function(f,fontdata,specification) +    if specification.glyphs then +        local datatable = fontdata.tables.vmtx +        if datatable then +            setposition(f,datatable.offset) +            local verticalheader = fontdata.verticalheader +            local nofmetrics     = verticalheader.nofmetrics +            local glyphs         = fontdata.glyphs +            local nofglyphs      = fontdata.nofglyphs +            local vheight        = 0 +            local vdefault       = verticalheader.ascender + verticalheader.descender +            local topsidebearing = 0 +            for i=0,nofmetrics-1 do +                local glyph     = glyphs[i] +                vheight         = readshort(f) +                topsidebearing  = readshort(f) +                if vheight ~= 0 and vheight ~= vdefault then +                    glyph.vheight = vheight +                end +             -- if topsidebearing ~= 0 then +             --     glyph.tsb = topsidebearing +             -- end +            end +            -- The next can happen in for instance a monospace font or in a cjk font +            -- with fixed heights. +            for i=nofmetrics,nofglyphs-1 do +                local glyph = glyphs[i] +                if vheight ~= 0 and vheight ~= vdefault then +                    glyph.vheight = vheight +                end +             -- if topsidebearing ~= 0 then +             --     glyph.tsb = topsidebearing +             -- end +            end +        end +    end +end + +readers.vorg = function(f,fontdata,specification) +    if specification.glyphs then +        local datatable = fontdata.tables.vorg +        if datatable then +            report("todo: %s","vorg") +        end +    end +end +  -- The post table relates to postscript (printing) but has some relevant properties for other  -- usage as well. We just use the names from the microsoft specification. The version 2.0  -- description is somewhat fuzzy but it is a hybrid with overloads. @@ -1751,7 +1833,7 @@ end  -- some properties in order to read following tables. When details is true we also  -- initialize the glyphs data. -local function getinfo(maindata,sub,platformnames,rawfamilynames) +local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)      local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata      local names    = fontdata.names      local info     = nil @@ -1808,6 +1890,29 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)              descender      = metrics.typodescender,              platformnames  = platformnames and fontdata.platformnames or nil,          } +        if metricstoo then +            local keys = { +                "version", +                "ascender", "descender", "linegap", +             -- "caretoffset", "caretsloperise", "caretsloperun", +                "maxadvancewidth", "maxadvanceheight", "maxextent", +             -- "metricdataformat", +                "minbottomsidebearing", "mintopsidebearing", +            } +            local h = fontdata.horizontalheader or { } +            local v = fontdata.verticalheader   or { } +            if h then +                local th = { } +                local tv = { } +                for i=1,#keys do +                    local key = keys[i] +                    th[key] = h[key] or 0 +                    tv[key] = v[key] or 0 +                end +                info.horizontalmetrics = th +                info.verticalmetrics   = tv +            end +        end      elseif n then          info = {              filename = fontdata.filename, @@ -1900,7 +2005,10 @@ local function readdata(f,offset,specification)      readers["head"](f,fontdata,specification)      readers["maxp"](f,fontdata,specification)      readers["hhea"](f,fontdata,specification) +    readers["vhea"](f,fontdata,specification)      readers["hmtx"](f,fontdata,specification) +    readers["vmtx"](f,fontdata,specification) +    readers["vorg"](f,fontdata,specification)      readers["post"](f,fontdata,specification)      readers["cff" ](f,fontdata,specification)      readers["cmap"](f,fontdata,specification) @@ -2084,7 +2192,7 @@ function readers.loadfont(filename,n)              descriptions  = fontdata.descriptions,              format        = fontdata.format,              goodies       = { }, -            metadata      = getinfo(fontdata,n), -- no platformnames here ! +            metadata      = getinfo(fontdata,n,false,false,true), -- no platformnames here !              properties    = {                  hasitalics    = fontdata.hasitalics or false,                  maxcolorclass = fontdata.maxcolorclass, diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua index 1c64720..17e1a3c 100644 --- a/src/fontloader/misc/fontloader-font-ots.lua +++ b/src/fontloader/misc/fontloader-font-ots.lua @@ -128,6 +128,7 @@ local trace_details      = false  registertracker("otf.details",      function(v  local trace_steps        = false  registertracker("otf.steps",        function(v) trace_steps        = v end)  local trace_skips        = false  registertracker("otf.skips",        function(v) trace_skips        = v end)  local trace_directions   = false  registertracker("otf.directions",   function(v) trace_directions   = v end) +local trace_plugins      = false  registertracker("otf.plugins",      function(v) trace_plugins      = v end)  local trace_kernruns     = false  registertracker("otf.kernruns",     function(v) trace_kernruns     = v end)  local trace_discruns     = false  registertracker("otf.discruns",     function(v) trace_discruns     = v end) @@ -136,6 +137,7 @@ local trace_testruns     = false  registertracker("otf.testruns",     function(v  ----- zwnjruns           = true   registerdirective("otf.zwnjruns",     function(v) zwnjruns = v end)  local optimizekerns      = true +local alwaysdisc         = true   registerdirective("otf.alwaysdisc", function(v) alwaysdisc = v end)  local report_direct   = logs.reporter("fonts","otf direct")  local report_subchain = logs.reporter("fonts","otf subchain") @@ -599,7 +601,7 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou                  setlink(discfound,next)                  setboth(base)                  setfield(base,"components",copied) -                setdisc(discfound,pre,post,base,discretionary_code) +                setdisc(discfound,pre,post,base) -- was discretionary_code                  base = prev -- restart              end          end @@ -3047,7 +3049,11 @@ end  -- -- local a = getattr(start,0)  -- -- if not a or (a == attr) then  -- --- and even that one is probably not needed. +-- and even that one is probably not needed. However, we can handle interesting +-- cases now: +-- +--  1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par +--  1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par  local nesting = 0 @@ -3077,6 +3083,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm                      start = getnext(start)                  end              else +                -- go on can be a mixed one                  start = getnext(start)              end          elseif char == false then @@ -3122,6 +3129,8 @@ local function t_run_single(start,stop,font,attr,lookupcache)                          return true, d > 1                      end                  end +            else +                -- go on can be a mixed one              end              start = getnext(start)          else @@ -3207,6 +3216,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm                      start = getnext(start)                  end              else +                -- go on can be a mixed one                  start = getnext(start)              end          elseif char == false then @@ -3261,6 +3271,8 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)                          report_missing_coverage(dataset,sequence)                      end                  end +            else +                -- go on can be a mixed one              end              start = getnext(start)          else @@ -3324,7 +3336,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase      end  end --- to be checkedL nowadays we probably can assume properly matched directions +-- to be checked, nowadays we probably can assume properly matched directions  -- so maybe we no longer need a stack  local function txtdirstate(start,stack,top,rlparmode) @@ -3365,6 +3377,10 @@ local function pardirstate(start)      return getnext(start), new, new  end +otf.helpers             = otf.helpers or { } +otf.helpers.txtdirstate = txtdirstate +otf.helpers.pardirstate = pardirstate +  local function featuresprocessor(head,font,attr)      local sequences = sequencelists[font] -- temp hack @@ -3413,6 +3429,8 @@ local function featuresprocessor(head,font,attr)      local done      = false      local datasets  = otf.dataset(tfmdata,font,attr) +    local forcedisc = alwaysdisc or not attr +      local dirstack  = { } -- could move outside function but we can have local runs      sweephead       = { } @@ -3425,7 +3443,7 @@ local function featuresprocessor(head,font,attr)      -- Keeping track of the headnode is needed for devanagari (I generalized it a bit      -- so that multiple cases are also covered.) -    -- We don't goto the next node of a disc node is created so that we can then treat +    -- We don't goto the next node when a disc node is created so that we can then treat      -- the pre, post and replace. It's a bit of a hack but works out ok for most cases.      for s=1,#datasets do @@ -3527,16 +3545,26 @@ local function featuresprocessor(head,font,attr)                             -- whatever glyph                             start = getnext(start)                          elseif id == disc_code then -                            local ok -                            if gpossing then -                                start, ok = kernrun(start,k_run_single,             font,attr,lookupcache,step,dataset,sequence,rlmode,handler) -                            elseif typ == "gsub_ligature" then -                                start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) +                            -- ctx: we could assume the same attr as the surrounding glyphs but then we loose +                            -- the option to have interesting disc nodes (we gain upto 10% on extreme tests); +                            -- if a disc would have a font field we could even be more strict (see oldstyle test +                            -- case) +                            local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr +                            if a then +                                --     local attr = false +                                local ok +                                if gpossing then +                                    start, ok = kernrun(start,k_run_single,             font,attr,lookupcache,step,dataset,sequence,rlmode,handler) +                                elseif typ == "gsub_ligature" then +                                    start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) +                                else +                                    start, ok = comprun(start,c_run_single,             font,attr,lookupcache,step,dataset,sequence,rlmode,handler) +                                end +                                if ok then +                                    success = true +                                end                              else -                                start, ok = comprun(start,c_run_single,             font,attr,lookupcache,step,dataset,sequence,rlmode,handler) -                            end -                            if ok then -                                success = true +                                start = getnext(start)                              end                          elseif id == math_code then                              start = getnext(end_of_math(start)) @@ -3596,16 +3624,22 @@ local function featuresprocessor(head,font,attr)                      elseif char == false then                          start = getnext(start)                      elseif id == disc_code then -                        local ok -                        if gpossing then -                            start, ok = kernrun(start,k_run_multiple,               font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) -                        elseif typ == "gsub_ligature" then -                            start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) +                        -- see comment above +                        local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr +                        if a then +                            local ok +                            if gpossing then +                                start, ok = kernrun(start,k_run_multiple,               font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) +                            elseif typ == "gsub_ligature" then +                                start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) +                            else +                                start, ok = comprun(start,c_run_multiple,               font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) +                            end +                            if ok then +                                success = true +                            end                          else -                            start, ok = comprun(start,c_run_multiple,               font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) -                        end -                        if ok then -                            success = true +                            start = getnext(start)                          end                      elseif id == math_code then                          start = getnext(end_of_math(start)) @@ -3637,6 +3671,34 @@ end  -- so far +local plugins = { } +otf.plugins   = plugins + +function otf.registerplugin(name,f) +    if type(name) == "string" and type(f) == "function" then +        plugins[name] = { name, f } +    end +end + +local function plugininitializer(tfmdata,value) +    if type(value) == "string" then +        tfmdata.shared.plugin = plugins[value] +    end +end + +local function pluginprocessor(head,font) +    local s = fontdata[font].shared +    local p = s and s.plugin +    if p then +        if trace_plugins then +            report_process("applying plugin %a",p[1]) +        end +        return p[2](head,font) +    else +        return head, false +    end +end +  local function featuresinitializer(tfmdata,value)      -- nothing done here any more  end @@ -3648,9 +3710,11 @@ registerotffeature {      initializers = {          position = 1,          node     = featuresinitializer, +        plug     = plugininitializer,      },      processors   = {          node     = featuresprocessor, +        plug     = pluginprocessor,      }  } diff --git a/src/fontloader/misc/fontloader-util-fil.lua b/src/fontloader/misc/fontloader-util-fil.lua index eeb6856..eb054a5 100644 --- a/src/fontloader/misc/fontloader-util-fil.lua +++ b/src/fontloader/misc/fontloader-util-fil.lua @@ -109,6 +109,10 @@ function files.readcardinal2(f)      local a, b = byte(f:read(2),1,2)      return 0x100 * a + b  end +function files.readcardinal2le(f) +    local b, a = byte(f:read(2),1,2) +    return 0x100 * a + b +end  function files.readinteger2(f)      local a, b = byte(f:read(2),1,2) @@ -120,11 +124,25 @@ function files.readinteger2(f)          return n      end  end +function files.readinteger2le(f) +    local b, a = byte(f:read(2),1,2) +    local n = 0x100 * a + b +    if n >= 0x8000 then +     -- return n - 0xFFFF - 1 +        return n - 0x10000 +    else +        return n +    end +end  function files.readcardinal3(f)      local a, b, c = byte(f:read(3),1,3)      return 0x10000 * a + 0x100 * b + c  end +function files.readcardinal3le(f) +    local c, b, a = byte(f:read(3),1,3) +    return 0x10000 * a + 0x100 * b + c +end  function files.readinteger3(f)      local a, b, c = byte(f:read(3),1,3) @@ -136,11 +154,25 @@ function files.readinteger3(f)          return n      end  end +function files.readinteger3le(f) +    local c, b, a = byte(f:read(3),1,3) +    local n = 0x10000 * a + 0x100 * b + c +    if n >= 0x80000 then +     -- return n - 0xFFFFFF - 1 +        return n - 0x1000000 +    else +        return n +    end +end  function files.readcardinal4(f)      local a, b, c, d = byte(f:read(4),1,4)      return 0x1000000 * a + 0x10000 * b + 0x100 * c + d  end +function files.readcardinal4le(f) +    local d, c, b, a = byte(f:read(4),1,4) +    return 0x1000000 * a + 0x10000 * b + 0x100 * c + d +end  function files.readinteger4(f)      local a, b, c, d = byte(f:read(4),1,4) @@ -152,6 +184,16 @@ function files.readinteger4(f)          return n      end  end +function files.readinteger4le(f) +    local d, c, b, a = byte(f:read(4),1,4) +    local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d +    if n >= 0x8000000 then +     -- return n - 0xFFFFFFFF - 1 +        return n - 0x100000000 +    else +        return n +    end +end  function files.readfixed4(f)      local a, b, c, d = byte(f:read(4),1,4) | 
