diff options
27 files changed, 548 insertions, 247 deletions
diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv index 764863b65..fbd533ff3 100644 --- a/metapost/context/base/mp-tool.mpiv +++ b/metapost/context/base/mp-tool.mpiv @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% def loadfile(expr name) = scantokens("input " & name & ";") enddef ; + if known context_tool : endinput ; fi ; boolean context_tool ; context_tool := true ; diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 93901f665..58d0e7f59 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -599,7 +599,8 @@ local function do_serialize(root,name,depth,level,indexed) if compact then last = #root for k=1,last do - if not root[k] then +-- if not root[k] then + if root[k] == nil then last = k - 1 break end diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 93901f665..58d0e7f59 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -599,7 +599,8 @@ local function do_serialize(root,name,depth,level,indexed) if compact then last = #root for k=1,last do - if not root[k] then +-- if not root[k] then + if root[k] == nil then last = k - 1 break end diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 93901f665..58d0e7f59 100755 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -599,7 +599,8 @@ local function do_serialize(root,name,depth,level,indexed) if compact then last = #root for k=1,last do - if not root[k] then +-- if not root[k] then + if root[k] == nil then last = k - 1 break end diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index d398d6cc5..cd49e7efc 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2012.10.02 22:03} +\newcontextversion{2012.10.05 19:52} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index c5e0682b0..d8adcf388 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2012.10.02 22:03} +\newcontextversion{2012.10.05 19:52} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex b04ab3399..e9bc07c32 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex 7d1880385..8f66709c2 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 02d5ae27c..a69d67d62 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2012.10.02 22:03} +\edef\contextversion{2012.10.05 19:52} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index d491e43e7..7cfee6b89 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -25,7 +25,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2012.10.02 22:03} +\edef\contextversion{2012.10.05 19:52} %D For those who want to use this: diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index 7d4fa35db..1b3384833 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -1623,3 +1623,91 @@ nodes.injections.installnewkern(function(k) end) directives.register("nodes.injections.fontkern", function(v) kern.subtype = v and 0 or 1 end) + +-- here + +local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) + +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register + +local analyzers = fonts.analyzers +local methods = analyzers.methods + +local get_attribute = node.has_attribute +local set_attribute = node.set_attribute +local unset_attribute = node.unset_attribute +local traverse_by_id = node.traverse_id + +local a_color = attributes.private('color') +local a_colormodel = attributes.private('colormodel') +local a_state = attributes.private('state') +local m_color = attributes.list[a_color] or { } + +local glyph_code = nodes.nodecodes.glyph + +local names = { + "font:1", "font:2", "font:3", "font:3", -- arabic + "font:4", "font:5", "font:6", "font:7", "font:8", "font:9", -- devanagary +} + +local function markstates(head) + if head then + local model = get_attribute(head,a_colormodel) or 1 + for glyph in traverse_by_id(glyph_code,head) do + local a = get_attribute(glyph,a_state) + if a then + local name = names[a] + if name then + local color = m_color[name] + if color then + set_attribute(glyph,a_colormodel,model) + set_attribute(glyph,a_color,color) + end + end + end + end + end +end + +local function analyzeprocessor(head,font,attr) + local tfmdata = fontdata[font] + local script, language = otf.scriptandlanguage(tfmdata,attr) + local action = methods[script] + if not action then + return head, false + end + if type(action) == "function" then + local head, done = action(head,font,attr) + if done and trace_analyzing then + markstates(head) + end + return head, done + end + action = action[language] + if action then + local head, done = action(head,font,attr) + if done and trace_analyzing then + markstates(head) + end + return head, done + else + return head, false + end +end + +registerotffeature { -- adapts + name = "analyze", + processors = { + node = analyzeprocessor, + } +} + +function methods.nocolor(head,font,attr) + for n in traverse_by_id(glyph_code,head) do + if not font or n.font == font then + unset_attribute(n,a_color) + end + end + return head, true +end diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua index edf5996b3..962f5d4d3 100644 --- a/tex/context/base/font-ota.lua +++ b/tex/context/base/font-ota.lua @@ -40,11 +40,6 @@ local fontdata = fonts.hashes.identifiers local state = attributes.private('state') local categories = characters and characters.categories or { } -- sorry, only in context -local tracers = nodes.tracers -local colortracers = tracers and tracers.colors -local setnodecolor = colortracers and colortracers.set or function() end -local resetnodecolor = colortracers and colortracers.reset or function() end - local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -117,14 +112,14 @@ end local function analyzeinitializer(tfmdata,value) -- attr local script, language = otf.scriptandlanguage(tfmdata) -- attr local action = initializers[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(tfmdata,value) + else + local action = action[language] + if action then return action(tfmdata,value) - else - local action = action[language] - if action then - return action(tfmdata,value) - end end end end @@ -133,14 +128,14 @@ local function analyzeprocessor(head,font,attr) local tfmdata = fontdata[font] local script, language = otf.scriptandlanguage(tfmdata,attr) local action = methods[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(head,font,attr) + else + action = action[language] + if action then return action(head,font,attr) - else - action = action[language] - if action then - return action(head,font,attr) - end end end return head, false @@ -252,7 +247,6 @@ local isol_fina_medi_init = { local arab_warned = { } - -- todo: gref local function warning(current,what) @@ -263,37 +257,24 @@ local function warning(current,what) end end -function methods.nocolor(head,font,attr) - for n in traverse_id(glyph_code,head) do - if not font or n.font == font then - resetnodecolor(n) - end - end - return head, true -end - local function finish(first,last) if last then if first == last then local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end else local lc = last.char if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? -- if laststate == 1 or laststate == 2 or laststate == 4 then set_attribute(last,state,3) -- fina - if trace_analyzing then setnodecolor(last,"font:fina") end else warning(last,"fina") set_attribute(last,state,0) -- error - if trace_analyzing then resetnodecolor(last) end end end first, last = nil, nil @@ -302,11 +283,9 @@ local function finish(first,last) local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end first = nil end @@ -324,20 +303,16 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr local char = current.char if marks[char] or (useunicodemarks and categories[char] == "mn") then set_attribute(current,state,5) -- mark - if trace_analyzing then setnodecolor(current,"font:mark") end elseif isol[char] then -- can be zwj or zwnj too first, last = finish(first,last) set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil elseif not first then if isol_fina_medi_init[char] then set_attribute(current,state,1) -- init - if trace_analyzing then setnodecolor(current,"font:init") end first, last = first or current, current elseif isol_fina[char] then set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil else -- no arab first, last = finish(first,last) @@ -345,18 +320,15 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr elseif isol_fina_medi_init[char] then first, last = first or current, current set_attribute(current,state,2) -- medi - if trace_analyzing then setnodecolor(current,"font:medi") end elseif isol_fina[char] then if not has_attribute(last,state,1) then -- tricky, we need to check what last may be ! set_attribute(last,state,2) -- medi - if trace_analyzing then setnodecolor(last,"font:medi") end end set_attribute(current,state,3) -- fina - if trace_analyzing then setnodecolor(current,"font:fina") end first, last = nil, nil elseif char >= 0x0600 and char <= 0x06FF then - if trace_analyzing then setnodecolor(current,"font:rest") end + set_attribute(current,state,6) -- rest first, last = finish(first,last) else --no first, last = finish(first,last) diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index ebd487959..1d8c4ad43 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['font-otd'] = { license = "see context related readme files" } +local type = type local match = string.match local sequenced = table.sequenced @@ -120,6 +121,12 @@ local special_attributes = { medi = 2, fina = 3, isol = 4 + -- devanagari + rphf = 5, + half = 6, + pref = 7, + blwf = 8, + pstf = 9, } local resolved = { } -- we only resolve a font,script,language,attribute pair once @@ -180,7 +187,7 @@ end -- return v -- end) -function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as in special parbuilder) +function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder) local script, language, s_enabled, a_enabled, dynamic @@ -220,12 +227,17 @@ function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as end local ra = rl[attr] if ra == nil then -- attr can be false - ra = { } + ra = { + -- indexed but we can also add specific data by key in: + } rl[attr] = ra + local sequences = tfmdata.resources.sequences setmetatableindex(ra, function(t,k) - local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) - t[k] = v or false - return v + if type(k) == "number" then + local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) + t[k] = v or false + return v + end end) end diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index ef842b099..ba9b0ed94 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -116,6 +116,8 @@ results in different tables.</p> -- we now use only one hash. If needed we can have multiple again but in that -- case I will probably prefix (i.e. rename) the lookups in the cached font file. +-- Todo: make plugin feature that operates on char/glyphnode arrays + local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip local type, next, tonumber, tostring = type, next, tonumber, tostring @@ -151,6 +153,7 @@ local report_subchain = logs.reporter("fonts","otf subchain") local report_chain = logs.reporter("fonts","otf chain") local report_process = logs.reporter("fonts","otf process") local report_prepare = logs.reporter("fonts","otf prepare") +local report_warning = logs.reporter("fonts","otf warning") registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) @@ -185,7 +188,6 @@ local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue local disc_code = nodecodes.disc local whatsit_code = nodecodes.whatsit -local user_code = nodecodes.user local dir_code = whatcodes.dir local localpar_code = whatcodes.localpar @@ -311,35 +313,110 @@ local function pref(kind,lookupname) return format("feature %s, lookup %s",kind,lookupname) end --- we can assume that languages that use marks are not hyphenated --- we can also assume that at most one discretionary is present +-- We can assume that languages that use marks are not hyphenated. We can also assume +-- that at most one discretionary is present. + +-- We do need components in funny kerning mode but maybe I can better reconstruct then +-- as we do have the font components info available; removing components makes the +-- previous code much simpler. Also, later on copying and freeing becomes easier. +-- However, for arabic we need to keep them around for the sake of mark placement +-- and indices. + +-- local function collapsecomponents(start) +-- local c = start +-- while c do +-- local cp = c.components +-- if cp then +-- flush_node_list(cp) +-- c.components = nil +-- end +-- c = c.next +-- end +-- return start +-- end -local function markstoligature(kind,lookupname,start,stop,char) - local n = copy_node(start) +local function collapsecomponents(start) + if not start.next then + report_warning("suspicious ligature components") + -- actually an error + return components + else + local head = nil + local tail = nil + while start do + local components = start.components + if components then + if head then + tail.next = components + components.prev = tail + else + head = components + end + tail = find_node_tail(components) + start.components = nil + else + if head then + tail.next = start + start.prev = tail + tail = start + else + head = start + tail = start + end + end + start = start.next + end + return head + end +end + +local function markstoligature(kind,lookupname,start,stop,char) -- some trickery to keep head as is + -- [start]..[stop] local keep = start - local current - current, start = insert_node_after(start,start,n) + local current, start = insert_node_after(start,start,copy_node(start)) + -- [current][start]..[stop] local snext = stop.next current.next = snext if snext then snext.prev = current end - start.prev, stop.next = nil, nil - current.char, current.subtype, current.components = char, ligature_code, start + start.prev = nil + stop.next = nil + current.char = char + current.subtype = ligature_code + current.components = collapsecomponents(start) return keep end +-- The next code is somewhat complicated by the fact that some fonts can have ligatures made +-- from ligatures that themselves have marks. This was identified by Kai in for instance +-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes +-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next +-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the +-- third component. + +local function getcomponentindex(start) -- so we cannot remove components ! + local i = 0 + if start.subtype == ligature_code then + local comp = start.components + while comp do + i = i + getcomponentindex(comp) + comp = comp.next + end + return i + elseif not marks[start.char] then + return 1 + else + return 0 + end +end + local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head if start == stop then start.char = char return start elseif discfound then -- print("start->stop",nodes.tosequence(start,stop)) - local components = start.components - if components then - flush_node_list(components) - start.components = nil - end local lignode = copy_node(start) lignode.font = start.font lignode.char = char @@ -348,7 +425,7 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- local prev = start.prev stop.next = nil start.prev = nil - lignode.components = start + lignode.components = collapsecomponents(start) -- print("lignode",nodes.tosequence(lignode)) -- print("components",nodes.tosequence(lignode.components)) prev.next = lignode @@ -362,29 +439,32 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- else -- start is the ligature local deletemarks = markflag ~= "mark" - local n = copy_node(start) - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current + local prev = start.prev + local next = stop.next + local current, start = insert_node_after(start,start,copy_node(start)) + -- [start->current][copyofstart->start]...[stop] + current.next = next + if next then + next.prev = current end start.prev = nil stop.next = nil current.char = char current.subtype = ligature_code - current.components = start + current.components = collapsecomponents(start) local head = current -- this is messy ... we should get rid of the components eventually - local i = 0 -- is index of base + local baseindex = 0 + local componentindex = 0 while start do - if not marks[start.char] then - i = i + 1 + local char = start.char + if not marks[char] then + baseindex = baseindex + componentindex + componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - set_attribute(start,ligacomp,i) + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end head, current = insert_node_after(head,current,copy_node(start)) end @@ -392,22 +472,17 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- end start = current.next while start and start.id == glyph_code do - if marks[start.char] then - set_attribute(start,ligacomp,i) + local char = start.char + if marks[char] then + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end else break end start = start.next end - -- - -- we do need components in funny kerning mode but maybe I can better reconstruct then - -- as we do have the font components info available; removing components makes the - -- previous code much simpler - -- - -- flush_node_list(head.components) return head end end @@ -489,12 +564,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) local choice = get_alternative_glyph(start,alternative,value) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),choice) + logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice) end start.char = choice else if trace_alternatives then - logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char)) + logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char)) end end return start, true @@ -577,6 +652,7 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) local stopchar = stop.char start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) +-- print("start",nodes.listtoutf(start.components)) else start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) end @@ -988,6 +1064,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start repeat -- start x x m x x stop => start m local next = start.next if not marks[next.char] then +local components = next.components +if components then + node.flush_list(components) +end delete_node(start,next) end n = n + 1 @@ -995,6 +1075,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start else -- start x x x stop => start repeat local next = start.next +local components = next.components +if components then + node.flush_list(components) +end delete_node(start,next) n = n + 1 until next == stop @@ -1967,7 +2051,13 @@ local special_attributes = { init = 1, medi = 2, fina = 3, - isol = 4 + isol = 4, + -- devanagari + rphf = 5, + half = 6, + pref = 7, + blwf = 8, + pstf = 9, } local function initialize(sequence,script,language,enabled) @@ -1986,7 +2076,7 @@ local function initialize(sequence,script,language,enabled) return false end -function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context +function otf.dataset(tfmdata,font) -- generic variant, overloaded in context local shared = tfmdata.shared local properties = tfmdata.properties local language = properties.language or "dflt" @@ -2004,12 +2094,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c end local rl = rs[language] if not rl then - rl = { } + rl = { + -- indexed but we can also add specific data by key + } rs[language] = rl + local sequences = tfmdata.resources.sequences setmetatableindex(rl, function(t,k) - local v = enabled and initialize(sequences[k],script,language,enabled) - t[k] = v - return v + if type(k) == "number" then + local v = enabled and initialize(sequences[k],script,language,enabled) + t[k] = v + return v + end end) end return rl @@ -2060,7 +2155,7 @@ local function featuresprocessor(head,font,attr) local sequences = resources.sequences local done = false - local datasets = otf.dataset(tfmdata,sequences,font,attr) + local datasets = otf.dataset(tfmdata,font,attr) local dirstack = { } -- could move outside function @@ -2069,6 +2164,9 @@ local function featuresprocessor(head,font,attr) -- to keep track of directions anyway. Also at some point I want to play with -- font interactions and then we do need the full sweeps. + -- Keeping track of the headnode is needed for devanagari (I generalized it a bit + -- so that multiple cases are also covered. + for s=1,#sequences do local dataset = datasets[s] if dataset then @@ -2104,8 +2202,12 @@ local function featuresprocessor(head,font,attr) if lookupcache then local lookupmatch = lookupcache[start.char] if lookupmatch then + local headnode = start == head start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then + if headnode then + head = start + end break end end @@ -2149,10 +2251,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then success = true + if headnode then + head = start + end end end if start then start = start.next end @@ -2222,10 +2328,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then success = true + if headnode then + head = start + end break end end @@ -2551,3 +2661,7 @@ registerotffeature { node = featuresprocessor, } } + +-- this will change but is needed for an experiment: + +otf.handlers = handlers diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 1aeda273b..c0a6c4d27 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -626,9 +626,11 @@ local features = allocate { ['trep'] = 'traditional tex replacements', ['tlig'] = 'traditional tex ligatures', - ['ss..'] = 'stylistic set ..', - ['cv..'] = 'character variant ..', - ['js..'] = 'justification ..', + ['ss..'] = 'stylistic set ..', + ['cv..'] = 'character variant ..', + ['js..'] = 'justification ..', + + ["dv.."] = "devanagari ..", } local baselines = allocate { diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv index 8288ef412..8d3edb9ec 100644 --- a/tex/context/base/font-pre.mkiv +++ b/tex/context/base/font-pre.mkiv @@ -169,7 +169,7 @@ \definecolor[font:fina][b=.75] \definecolor[font:isol][r=.75,g=.75] % [y=.75] \definecolor[font:mark][r=.75,b=.75] % [m=.75] -\definecolor[font:rest][g=.75,b=.75] % [c=.75] +\definecolor[font:rest][b=.75,g=.75] % [c=.75] \definecolor[trace:r][r=.75,t=.5,a=1] \definecolor[trace:g][g=.75,t=.5,a=1] @@ -189,6 +189,16 @@ \definecolor[trace:ds][s=.75,t=.75,a=1] \definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1] +\definecolor[font:1] [r=.75] +\definecolor[font:2] [g=.75] +\definecolor[font:3] [b=.75] +\definecolor[font:4] [r=.75,g=.75] +\definecolor[font:5] [r=.75,b=.75] +\definecolor[font:6] [b=.75,g=.75] +\definecolor[font:7] [r=.75] +\definecolor[font:8] [g=.75] +\definecolor[font:9] [b=.75] + %D Now we're up to some definitions. \definebodyfontenvironment diff --git a/tex/context/base/font-tra.mkiv b/tex/context/base/font-tra.mkiv index abe034d8a..e838d4938 100644 --- a/tex/context/base/font-tra.mkiv +++ b/tex/context/base/font-tra.mkiv @@ -116,9 +116,9 @@ \unexpanded\def\otfstepcharcommand#1#2#3% font char class {\removeunwantedspaces - \hskip.5em plus .125em\relax + \hskip.5\emwidth \s!plus .125\emwidth\relax \doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}% - \hskip.5em plus .125em\relax} + \hskip.5\emwidth \s!plus .125\emwidth\relax} \unexpanded\def\otfstepmessagecommand#1#2% {\begingroup @@ -126,7 +126,7 @@ \veryraggedright \forgetparindent \forgeteverypar - \hangindent1em + \hangindent\emwidth \hangafter\plusone \dontleavehmode\hbox{\detokenize{#1}}\removeunwantedspaces \doifsomething{#2}{\break\detokenize{#2}}\endgraf diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 2b3319e45..80f28c2cd 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -415,7 +415,8 @@ local function do_serialize(root,name,depth,level,indexed) if compact then last = #root for k=1,last do - if not root[k] then +-- if not root[k] then + if root[k] == nil then last = k - 1 break end diff --git a/tex/context/base/math-arr.mkiv b/tex/context/base/math-arr.mkiv index 2d57a9337..5b50303d0 100644 --- a/tex/context/base/math-arr.mkiv +++ b/tex/context/base/math-arr.mkiv @@ -336,6 +336,14 @@ \unexpanded\def\doublebond{{\xequal}} \unexpanded\def\triplebond{{\xtriplerel}} +%D A bit or arrow juggling: +%D +%D \startbuffer +%D \hbox to \hsize{\rightoverleftarrowfill} +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank + \unexpanded\def\rightoverleftarrowfill {\specrightoverleftarrowfill} diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 387dd99a6..6b5f49964 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -46,6 +46,7 @@ local copy_node_list = node.copy_list local hpack_node_list = node.hpack local free_node_list = node.flush_list local traverse_nodes = node.traverse +local traverse_by_id = node.traverse_id local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -352,7 +353,7 @@ end function nodes.handlers.checkglyphs(head,message) local t = { } - for g in traverse_id(glyph_code,head) do + for g in traverse_by_id(glyph_code,head) do t[#t+1] = format("U+%04X:%s",g.char,g.subtype) end if #t > 0 then @@ -714,72 +715,73 @@ local get_attribute = node.has_attribute local set_attribute = node.set_attribute local unset_attribute = node.unset_attribute -local attribute = attributes.private('color') -local colormodel = attributes.private('colormodel') -local mapping = attributes.list[attribute] or { } +local a_color = attributes.private('color') +local a_colormodel = attributes.private('colormodel') +local a_state = attributes.private('state') +local m_color = attributes.list[a_color] or { } function colors.set(n,c,s) - local mc = mapping[c] + local mc = m_color[c] if not mc then - unset_attribute(n,attribute) + unset_attribute(n,a_color) else - if not get_attribute(n,colormodel) then - set_attribute(n,colormodel,s or 1) + if not get_attribute(n,a_colormodel) then + set_attribute(n,a_colormodel,s or 1) end - set_attribute(n,attribute,mc) + set_attribute(n,a_color,mc) end end function colors.setlist(n,c,s) while n do - local mc = mapping[c] + local mc = m_color[c] if not mc then - unset_attribute(n,attribute) + unset_attribute(n,a_color) else - if not get_attribute(n,colormodel) then - set_attribute(n,colormodel,s or 1) + if not get_attribute(n,a_colormodel) then + set_attribute(n,a_colormodel,s or 1) end - set_attribute(n,attribute,mc) + set_attribute(n,a_color,mc) end n = n.next end end function colors.reset(n) - unset_attribute(n,attribute) + unset_attribute(n,a_color) end -- maybe -local transparencies = { } +local transparencies = { } tracers.transparencies = transparencies -local attribute = attributes.private('transparency') -local mapping = attributes.list[attribute] or { } +local a_transparency = attributes.private('transparency') +local m_transparency = attributes.list[a_transparency] or { } function transparencies.set(n,t) - local mt = mapping[t] + local mt = m_transparency[t] if not mt then - unset_attribute(n,attribute) + unset_attribute(n,a_transparency) else - set_attribute(n,attribute,mt) + set_attribute(n,a_transparency,mt) end end function transparencies.setlist(n,c,s) while n do - local mt = mapping[c] + local mt = m_transparency[c] if not mt then - unset_attribute(n,attribute) + unset_attribute(n,a_transparency) else - set_attribute(n,attribute,mt) + set_attribute(n,a_transparency,mt) end n = n.next end end function transparencies.reset(n) - unset_attribute(n,attribute) + unset_attribute(n,a_transparency) end -- for the moment here diff --git a/tex/context/base/pack-com.mkiv b/tex/context/base/pack-com.mkiv index 8b4d5c0c6..9320411ce 100644 --- a/tex/context/base/pack-com.mkiv +++ b/tex/context/base/pack-com.mkiv @@ -663,8 +663,8 @@ \setvalue{\??pairedboxalign\v!middle}% 4 {\let\pack_pairedboxes_align_l\hss \let\pack_pairedboxes_align_r\hss - \let\pack_pairedboxes_align_t\hss - \let\pack_pairedboxes_align_b\hss} + \let\pack_pairedboxes_align_t\vss + \let\pack_pairedboxes_align_b\vss} \setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }} \setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}} diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf Binary files differindex 7cda58a77..e4b35c632 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex 02aab58d1..cedb02ae4 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf diff --git a/tex/context/base/util-sql-imp-library.lua b/tex/context/base/util-sql-imp-library.lua index e04c4ac44..f16739085 100644 --- a/tex/context/base/util-sql-imp-library.lua +++ b/tex/context/base/util-sql-imp-library.lua @@ -276,6 +276,7 @@ local celltemplate = "cells[%s]" methods.library = { runner = function() end, -- never called execute = execute, + initialize = initialize, -- returns session usesfiles = false, wraptemplate = wraptemplate, celltemplate = celltemplate, diff --git a/tex/context/base/util-sql-imp-swiglib.lua b/tex/context/base/util-sql-imp-swiglib.lua index 4b9cda896..25723ee84 100644 --- a/tex/context/base/util-sql-imp-swiglib.lua +++ b/tex/context/base/util-sql-imp-swiglib.lua @@ -153,6 +153,7 @@ end -- end local util_mysql_fetch_fields_from_current_row = mysql.util_mysql_fetch_fields_from_current_row +local util_mysql_fetch_all_rows = mysql.util_mysql_fetch_all_rows local function list(t) return util_mysql_fetch_fields_from_current_row(t._result_) @@ -168,11 +169,16 @@ local function hash(t) return data end +local function wholelist(t) + return util_mysql_fetch_all_rows(t._result_) +end + local mt = { __index = { -- regular finish = finish, list = list, hash = hash, + wholelist = wholelist, -- compatibility numrows = numrows, getcolnames = getcolnames, @@ -413,6 +419,7 @@ local celltemplate = "cells[%s]" methods.swiglib = { runner = function() end, -- never called execute = execute, + initialize = initialize, -- returns session usesfiles = false, wraptemplate = wraptemplate, celltemplate = celltemplate, diff --git a/tex/generic/context/luatex/luatex-fonts-ext.lua b/tex/generic/context/luatex/luatex-fonts-ext.lua index d8884ccc7..b60d04512 100644 --- a/tex/generic/context/luatex/luatex-fonts-ext.lua +++ b/tex/generic/context/luatex/luatex-fonts-ext.lua @@ -18,18 +18,14 @@ local otffeatures = fonts.constructors.newfeatures("otf") local function initializeitlc(tfmdata,value) if value then - -- the magic 40 and it formula come from Dohyun Kim - local parameters = tfmdata.parameters + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess + local parameters = tfmdata.parameters local italicangle = parameters.italicangle if italicangle and italicangle ~= 0 then - local uwidth = (parameters.uwidth or 40)/2 - for unicode, d in next, tfmdata.descriptions do - local it = d.boundingbox[3] - d.width + uwidth - if it ~= 0 then - d.italic = it - end - end - tfmdata.properties.hasitalics = true + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 end end end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 1a375d009..920b43eff 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 10/02/12 22:03:14 +-- merge date : 10/05/12 19:52:22 do -- begin closure to overcome local limits and interference @@ -561,7 +561,8 @@ local function do_serialize(root,name,depth,level,indexed) if compact then last = #root for k=1,last do - if not root[k] then +-- if not root[k] then + if root[k] == nil then last = k - 1 break end @@ -8934,6 +8935,8 @@ results in different tables.</p> -- we now use only one hash. If needed we can have multiple again but in that -- case I will probably prefix (i.e. rename) the lookups in the cached font file. +-- Todo: make plugin feature that operates on char/glyphnode arrays + local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip local type, next, tonumber, tostring = type, next, tonumber, tostring @@ -8969,6 +8972,7 @@ local report_subchain = logs.reporter("fonts","otf subchain") local report_chain = logs.reporter("fonts","otf chain") local report_process = logs.reporter("fonts","otf process") local report_prepare = logs.reporter("fonts","otf prepare") +local report_warning = logs.reporter("fonts","otf warning") registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) @@ -9003,7 +9007,6 @@ local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue local disc_code = nodecodes.disc local whatsit_code = nodecodes.whatsit -local user_code = nodecodes.user local dir_code = whatcodes.dir local localpar_code = whatcodes.localpar @@ -9129,35 +9132,110 @@ local function pref(kind,lookupname) return format("feature %s, lookup %s",kind,lookupname) end --- we can assume that languages that use marks are not hyphenated --- we can also assume that at most one discretionary is present +-- We can assume that languages that use marks are not hyphenated. We can also assume +-- that at most one discretionary is present. + +-- We do need components in funny kerning mode but maybe I can better reconstruct then +-- as we do have the font components info available; removing components makes the +-- previous code much simpler. Also, later on copying and freeing becomes easier. +-- However, for arabic we need to keep them around for the sake of mark placement +-- and indices. + +-- local function collapsecomponents(start) +-- local c = start +-- while c do +-- local cp = c.components +-- if cp then +-- flush_node_list(cp) +-- c.components = nil +-- end +-- c = c.next +-- end +-- return start +-- end + +local function collapsecomponents(start) + if not start.next then + report_warning("suspicious ligature components") + -- actually an error + return components + else + local head = nil + local tail = nil + while start do + local components = start.components + if components then + if head then + tail.next = components + components.prev = tail + else + head = components + end + tail = find_node_tail(components) + start.components = nil + else + if head then + tail.next = start + start.prev = tail + tail = start + else + head = start + tail = start + end + end + start = start.next + end + return head + end +end -local function markstoligature(kind,lookupname,start,stop,char) - local n = copy_node(start) +local function markstoligature(kind,lookupname,start,stop,char) -- some trickery to keep head as is + -- [start]..[stop] local keep = start - local current - current, start = insert_node_after(start,start,n) + local current, start = insert_node_after(start,start,copy_node(start)) + -- [current][start]..[stop] local snext = stop.next current.next = snext if snext then snext.prev = current end - start.prev, stop.next = nil, nil - current.char, current.subtype, current.components = char, ligature_code, start + start.prev = nil + stop.next = nil + current.char = char + current.subtype = ligature_code + current.components = collapsecomponents(start) return keep end +-- The next code is somewhat complicated by the fact that some fonts can have ligatures made +-- from ligatures that themselves have marks. This was identified by Kai in for instance +-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes +-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next +-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the +-- third component. + +local function getcomponentindex(start) -- so we cannot remove components ! + local i = 0 + if start.subtype == ligature_code then + local comp = start.components + while comp do + i = i + getcomponentindex(comp) + comp = comp.next + end + return i + elseif not marks[start.char] then + return 1 + else + return 0 + end +end + local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head if start == stop then start.char = char return start elseif discfound then -- print("start->stop",nodes.tosequence(start,stop)) - local components = start.components - if components then - flush_node_list(components) - start.components = nil - end local lignode = copy_node(start) lignode.font = start.font lignode.char = char @@ -9166,7 +9244,7 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- local prev = start.prev stop.next = nil start.prev = nil - lignode.components = start + lignode.components = collapsecomponents(start) -- print("lignode",nodes.tosequence(lignode)) -- print("components",nodes.tosequence(lignode.components)) prev.next = lignode @@ -9180,29 +9258,32 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- else -- start is the ligature local deletemarks = markflag ~= "mark" - local n = copy_node(start) - local current - current, start = insert_node_after(start,start,n) - local snext = stop.next - current.next = snext - if snext then - snext.prev = current + local prev = start.prev + local next = stop.next + local current, start = insert_node_after(start,start,copy_node(start)) + -- [start->current][copyofstart->start]...[stop] + current.next = next + if next then + next.prev = current end start.prev = nil stop.next = nil current.char = char current.subtype = ligature_code - current.components = start + current.components = collapsecomponents(start) local head = current -- this is messy ... we should get rid of the components eventually - local i = 0 -- is index of base + local baseindex = 0 + local componentindex = 0 while start do - if not marks[start.char] then - i = i + 1 + local char = start.char + if not marks[char] then + baseindex = baseindex + componentindex + componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - set_attribute(start,ligacomp,i) + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end head, current = insert_node_after(head,current,copy_node(start)) end @@ -9210,22 +9291,17 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- end start = current.next while start and start.id == glyph_code do - if marks[start.char] then - set_attribute(start,ligacomp,i) + local char = start.char + if marks[char] then + set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) end else break end start = start.next end - -- - -- we do need components in funny kerning mode but maybe I can better reconstruct then - -- as we do have the font components info available; removing components makes the - -- previous code much simpler - -- - -- flush_node_list(head.components) return head end end @@ -9307,12 +9383,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) local choice = get_alternative_glyph(start,alternative,value) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),choice) + logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice) end start.char = choice else if trace_alternatives then - logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char)) + logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char)) end end return start, true @@ -9395,6 +9471,7 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) local stopchar = stop.char start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) +-- print("start",nodes.listtoutf(start.components)) else start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) end @@ -9806,6 +9883,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start repeat -- start x x m x x stop => start m local next = start.next if not marks[next.char] then +local components = next.components +if components then + node.flush_list(components) +end delete_node(start,next) end n = n + 1 @@ -9813,6 +9894,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start else -- start x x x stop => start repeat local next = start.next +local components = next.components +if components then + node.flush_list(components) +end delete_node(start,next) n = n + 1 until next == stop @@ -10785,7 +10870,13 @@ local special_attributes = { init = 1, medi = 2, fina = 3, - isol = 4 + isol = 4, + -- devanagari + rphf = 5, + half = 6, + pref = 7, + blwf = 8, + pstf = 9, } local function initialize(sequence,script,language,enabled) @@ -10804,7 +10895,7 @@ local function initialize(sequence,script,language,enabled) return false end -function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context +function otf.dataset(tfmdata,font) -- generic variant, overloaded in context local shared = tfmdata.shared local properties = tfmdata.properties local language = properties.language or "dflt" @@ -10822,12 +10913,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c end local rl = rs[language] if not rl then - rl = { } + rl = { + -- indexed but we can also add specific data by key + } rs[language] = rl + local sequences = tfmdata.resources.sequences setmetatableindex(rl, function(t,k) - local v = enabled and initialize(sequences[k],script,language,enabled) - t[k] = v - return v + if type(k) == "number" then + local v = enabled and initialize(sequences[k],script,language,enabled) + t[k] = v + return v + end end) end return rl @@ -10878,7 +10974,7 @@ local function featuresprocessor(head,font,attr) local sequences = resources.sequences local done = false - local datasets = otf.dataset(tfmdata,sequences,font,attr) + local datasets = otf.dataset(tfmdata,font,attr) local dirstack = { } -- could move outside function @@ -10887,6 +10983,9 @@ local function featuresprocessor(head,font,attr) -- to keep track of directions anyway. Also at some point I want to play with -- font interactions and then we do need the full sweeps. + -- Keeping track of the headnode is needed for devanagari (I generalized it a bit + -- so that multiple cases are also covered. + for s=1,#sequences do local dataset = datasets[s] if dataset then @@ -10922,8 +11021,12 @@ local function featuresprocessor(head,font,attr) if lookupcache then local lookupmatch = lookupcache[start.char] if lookupmatch then + local headnode = start == head start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then + if headnode then + head = start + end break end end @@ -10967,10 +11070,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then success = true + if headnode then + head = start + end end end if start then start = start.next end @@ -11040,10 +11147,14 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable + local headnode = start == head local ok start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then success = true + if headnode then + head = start + end break end end @@ -11370,6 +11481,10 @@ registerotffeature { } } +-- this will change but is needed for an experiment: + +otf.handlers = handlers + end -- closure do -- begin closure to overcome local limits and interference @@ -12039,11 +12154,6 @@ local fontdata = fonts.hashes.identifiers local state = attributes.private('state') local categories = characters and characters.categories or { } -- sorry, only in context -local tracers = nodes.tracers -local colortracers = tracers and tracers.colors -local setnodecolor = colortracers and colortracers.set or function() end -local resetnodecolor = colortracers and colortracers.reset or function() end - local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -12116,14 +12226,14 @@ end local function analyzeinitializer(tfmdata,value) -- attr local script, language = otf.scriptandlanguage(tfmdata) -- attr local action = initializers[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(tfmdata,value) + else + local action = action[language] + if action then return action(tfmdata,value) - else - local action = action[language] - if action then - return action(tfmdata,value) - end end end end @@ -12132,14 +12242,14 @@ local function analyzeprocessor(head,font,attr) local tfmdata = fontdata[font] local script, language = otf.scriptandlanguage(tfmdata,attr) local action = methods[script] - if action then - if type(action) == "function" then + if not action then + -- skip + elseif type(action) == "function" then + return action(head,font,attr) + else + action = action[language] + if action then return action(head,font,attr) - else - action = action[language] - if action then - return action(head,font,attr) - end end end return head, false @@ -12251,7 +12361,6 @@ local isol_fina_medi_init = { local arab_warned = { } - -- todo: gref local function warning(current,what) @@ -12262,37 +12371,24 @@ local function warning(current,what) end end -function methods.nocolor(head,font,attr) - for n in traverse_id(glyph_code,head) do - if not font or n.font == font then - resetnodecolor(n) - end - end - return head, true -end - local function finish(first,last) if last then if first == last then local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end else local lc = last.char if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? -- if laststate == 1 or laststate == 2 or laststate == 4 then set_attribute(last,state,3) -- fina - if trace_analyzing then setnodecolor(last,"font:fina") end else warning(last,"fina") set_attribute(last,state,0) -- error - if trace_analyzing then resetnodecolor(last) end end end first, last = nil, nil @@ -12301,11 +12397,9 @@ local function finish(first,last) local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then set_attribute(first,state,4) -- isol - if trace_analyzing then setnodecolor(first,"font:isol") end else warning(first,"isol") set_attribute(first,state,0) -- error - if trace_analyzing then resetnodecolor(first) end end first = nil end @@ -12323,20 +12417,16 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr local char = current.char if marks[char] or (useunicodemarks and categories[char] == "mn") then set_attribute(current,state,5) -- mark - if trace_analyzing then setnodecolor(current,"font:mark") end elseif isol[char] then -- can be zwj or zwnj too first, last = finish(first,last) set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil elseif not first then if isol_fina_medi_init[char] then set_attribute(current,state,1) -- init - if trace_analyzing then setnodecolor(current,"font:init") end first, last = first or current, current elseif isol_fina[char] then set_attribute(current,state,4) -- isol - if trace_analyzing then setnodecolor(current,"font:isol") end first, last = nil, nil else -- no arab first, last = finish(first,last) @@ -12344,18 +12434,15 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr elseif isol_fina_medi_init[char] then first, last = first or current, current set_attribute(current,state,2) -- medi - if trace_analyzing then setnodecolor(current,"font:medi") end elseif isol_fina[char] then if not has_attribute(last,state,1) then -- tricky, we need to check what last may be ! set_attribute(last,state,2) -- medi - if trace_analyzing then setnodecolor(last,"font:medi") end end set_attribute(current,state,3) -- fina - if trace_analyzing then setnodecolor(current,"font:fina") end first, last = nil, nil elseif char >= 0x0600 and char <= 0x06FF then - if trace_analyzing then setnodecolor(current,"font:rest") end + set_attribute(current,state,6) -- rest first, last = finish(first,last) else --no first, last = finish(first,last) @@ -12989,18 +13076,14 @@ local otffeatures = fonts.constructors.newfeatures("otf") local function initializeitlc(tfmdata,value) if value then - -- the magic 40 and it formula come from Dohyun Kim - local parameters = tfmdata.parameters + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess + local parameters = tfmdata.parameters local italicangle = parameters.italicangle if italicangle and italicangle ~= 0 then - local uwidth = (parameters.uwidth or 40)/2 - for unicode, d in next, tfmdata.descriptions do - local it = d.boundingbox[3] - d.width + uwidth - if it ~= 0 then - d.italic = it - end - end - tfmdata.properties.hasitalics = true + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 end end end |