summaryrefslogtreecommitdiff
path: root/tex/context/base/font-otx.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-otx.lua')
-rw-r--r--tex/context/base/font-otx.lua404
1 files changed, 0 insertions, 404 deletions
diff --git a/tex/context/base/font-otx.lua b/tex/context/base/font-otx.lua
deleted file mode 100644
index f39045223..000000000
--- a/tex/context/base/font-otx.lua
+++ /dev/null
@@ -1,404 +0,0 @@
-if not modules then modules = { } end modules ['font-otx'] = {
- version = 1.001,
- comment = "companion to font-otf.lua (analysing)",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- context only
-
-local type = type
-
-if not trackers then trackers = { register = function() end } end
-
------ trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
-
-local fonts, nodes, node = fonts, nodes, node
-
-local allocate = utilities.storage.allocate
-
-local otf = fonts.handlers.otf
-
-local analyzers = fonts.analyzers
-local initializers = allocate()
-local methods = allocate()
-
-analyzers.initializers = initializers
-analyzers.methods = methods
----------.useunicodemarks = false
-
-local a_state = attributes.private('state')
-
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local math_code = nodecodes.math
-
-local traverse_id = node.traverse_id
-local traverse_node_list = node.traverse
-local end_of_math = node.end_of_math
-
-local fontdata = fonts.hashes.identifiers
-local categories = characters and characters.categories or { } -- sorry, only in context
-local chardata = characters and characters.data
-
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
---[[ldx--
-<p>Analyzers run per script and/or language and are needed in order to
-process features right.</p>
---ldx]]--
-
--- never use these numbers directly
-
-local s_init = 1 local s_rphf = 7
-local s_medi = 2 local s_half = 8
-local s_fina = 3 local s_pref = 9
-local s_isol = 4 local s_blwf = 10
-local s_mark = 5 local s_pstf = 11
-local s_rest = 6
-
-local states = {
- init = s_init,
- medi = s_medi,
- fina = s_fina,
- isol = s_isol,
- mark = s_mark,
- rest = s_rest,
- rphf = s_rphf,
- half = s_half,
- pref = s_pref,
- blwf = s_blwf,
- pstf = s_pstf,
-}
-
-local features = {
- init = s_init,
- medi = s_medi,
- fina = s_fina,
- isol = s_isol,
- -- mark = s_mark,
- -- rest = s_rest,
- rphf = s_rphf,
- half = s_half,
- pref = s_pref,
- blwf = s_blwf,
- pstf = s_pstf,
-}
-
-analyzers.states = states
-analyzers.features = features
-analyzers.useunicodemarks = false
-
--- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
--- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
-
-function analyzers.setstate(head,font)
- local useunicodemarks = analyzers.useunicodemarks
- local tfmdata = fontdata[font]
- local descriptions = tfmdata.descriptions
- local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
- while current do
- local id = current.id
- if id == glyph_code and current.font == font then
- done = true
- local char = current.char
- local d = descriptions[char]
- if d then
- if d.class == "mark" then
- done = true
- current[a_state] = s_mark
- elseif useunicodemarks and categories[char] == "mn" then
- done = true
- current[a_state] = s_mark
- elseif n == 0 then
- first, last, n = current, current, 1
- current[a_state] = s_init
- else
- last, n = current, n+1
- current[a_state] = s_medi
- end
- else -- finish
- if first and first == last then
- last[a_state] = s_isol
- elseif last then
- last[a_state] = s_fina
- end
- first, last, n = nil, nil, 0
- end
- elseif id == disc_code then
- -- always in the middle
- current[a_state] = s_medi
- last = current
- else -- finish
- if first and first == last then
- last[a_state] = s_isol
- elseif last then
- last[a_state] = s_fina
- end
- first, last, n = nil, nil, 0
- if id == math_code then
- current = end_of_math(current)
- end
- end
- current = current.next
- end
- if first and first == last then
- last[a_state] = s_isol
- elseif last then
- last[a_state] = s_fina
- end
- return head, done
-end
-
--- in the future we will use language/script attributes instead of the
--- font related value, but then we also need dynamic features which is
--- somewhat slower; and .. we need a chain of them
-
-local function analyzeinitializer(tfmdata,value) -- attr
- local script, language = otf.scriptandlanguage(tfmdata) -- attr
- local action = initializers[script]
- 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)
- 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
- -- skip
- elseif type(action) == "function" then
- return action(head,font,attr)
- else
- action = action[language]
- if action then
- return action(head,font,attr)
- end
- end
- return head, false
-end
-
-registerotffeature {
- name = "analyze",
- description = "analysis of character classes",
- default = true,
- initializers = {
- node = analyzeinitializer,
- },
- processors = {
- position = 1,
- node = analyzeprocessor,
- }
-}
-
--- latin
-
-methods.latn = analyzers.setstate
-
-local arab_warned = { }
-
-local function warning(current,what)
- local char = current.char
- if not arab_warned[char] then
- log.report("analyze","arab: character %C has no %a class",char,what)
- arab_warned[char] = true
- end
-end
-
-local mappers = {
- l = s_init, -- left
- d = s_medi, -- double
- c = s_medi, -- joiner
- r = s_fina, -- right
- u = s_isol, -- nonjoiner
-}
-
-local classifiers = { } -- we can also use this trick for devanagari
-
-local first_arabic, last_arabic = characters.blockrange("arabic")
-local first_syriac, last_syriac = characters.blockrange("syriac")
-local first_mandiac, last_mandiac = characters.blockrange("mandiac")
-local first_nko, last_nko = characters.blockrange("nko")
-
-table.setmetatableindex(classifiers,function(t,k)
- local c = chardata[k]
- local v = false
- if c then
- local arabic = c.arabic
- if arabic then
- v = mappers[arabic]
- if not v then
- log.report("analyze","error in mapping arabic %C",k)
- -- error
- v = false
- end
- elseif k >= first_arabic and k <= last_arabic or k >= first_syriac and k <= last_syriac or
- k >= first_mandiac and k <= last_mandiac or k >= first_nko and k <= last_nko then
- if categories[k] == "mn" then
- v = s_mark
- else
- v = s_rest
- end
- else
- end
- end
- t[k] = v
- return v
-end)
-
-function methods.arab(head,font,attr)
- local first, last = nil, nil
- local c_first, c_last = nil, nil
- local current, done = head, false
- while current do
- local id = current.id
- if id == glyph_code and current.font == font and current.subtype<256 and not current[a_state] then
- done = true
- local char = current.char
- local classifier = classifiers[char]
- if not classifier then
- if last then
- if c_last == s_medi or c_last == s_fina then
- last[a_state] = s_fina
- else
- warning(last,"fina")
- last[a_state] = s_error
- end
- first, last = nil, nil
- elseif first then
- if c_first == s_medi or c_first == s_fina then
- first[a_state] = s_isol
- else
- warning(first,"isol")
- first[a_state] = s_error
- end
- first = nil
- end
- elseif classifier == s_mark then
- current[a_state] = s_mark
- elseif classifier == s_isol then
- if last then
- if c_last == s_medi or c_last == s_fina then
- last[a_state] = s_fina
- else
- warning(last,"fina")
- last[a_state] = s_error
- end
- first, last = nil, nil
- elseif first then
- if c_first == s_medi or c_first == s_fina then
- first[a_state] = s_isol
- else
- warning(first,"isol")
- first[a_state] = s_error
- end
- first = nil
- end
- current[a_state] = s_isol
- elseif classifier == s_medi then
- if first then
- last = current
- c_last = classifier
- current[a_state] = s_medi
- else
- current[a_state] = s_init
- first = current
- c_first = classifier
- end
- elseif classifier == s_fina then
- if last then
- if last[a_state] ~= s_init then
- last[a_state] = s_medi
- end
- current[a_state] = s_fina
- first, last = nil, nil
- elseif first then
- -- if first[a_state] ~= s_init then
- -- -- needs checking
- -- first[a_state] = s_medi
- -- end
- current[a_state] = s_fina
- first = nil
- else
- current[a_state] = s_isol
- end
- else -- classifier == s_rest
- current[a_state] = s_rest
- if last then
- if c_last == s_medi or c_last == s_fina then
- last[a_state] = s_fina
- else
- warning(last,"fina")
- last[a_state] = s_error
- end
- first, last = nil, nil
- elseif first then
- if c_first == s_medi or c_first == s_fina then
- first[a_state] = s_isol
- else
- warning(first,"isol")
- first[a_state] = s_error
- end
- first = nil
- end
- end
- else
- if last then
- if c_last == s_medi or c_last == s_fina then
- last[a_state] = s_fina
- else
- warning(last,"fina")
- last[a_state] = s_error
- end
- first, last = nil, nil
- elseif first then
- if c_first == s_medi or c_first == s_fina then
- first[a_state] = s_isol
- else
- warning(first,"isol")
- first[a_state] = s_error
- end
- first = nil
- end
- if id == math_code then -- a bit duplicate as we test for glyphs twice
- current = end_of_math(current)
- end
- end
- current = current.next
- end
- if last then
- if c_last == s_medi or c_last == s_fina then
- last[a_state] = s_fina
- else
- warning(last,"fina")
- last[a_state] = s_error
- end
- elseif first then
- if c_first == s_medi or c_first == s_fina then
- first[a_state] = s_isol
- else
- warning(first,"isol")
- first[a_state] = s_error
- end
- end
- return head, done
-end
-
-methods.syrc = methods.arab
-methods.mand = methods.arab
-methods.nko = methods.arab
-
-directives.register("otf.analyze.useunicodemarks",function(v)
- analyzers.useunicodemarks = v
-end)