-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- We keep the original around for a while so that we can check it -- -- when the above code does it wrong (data tables are not included). -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- author : Kai Eigner, TAT Zetwerk -- copyright : TAT Zetwerk -- comment : see font-odv.lua for current implementation -- local state = attributes.private('state') -- local sylnr = attributes.private('syllabe') -- -- local function install_dev(tfmdata) -- local features = tfmdata.resources.features -- local sequences = tfmdata.resources.sequences -- -- local insertpos = 1 -- for s=1,#sequences do -- classify chars -- for k in pairs(basic_shaping_forms) do -- if sequences[s].features and ( sequences[s].features[k] or sequences[s].features.locl ) then insertpos = s + 1 end -- end -- end -- -- features.gsub["dev2_reorder_matras"] = { ["dev2"] = { ["dflt"] = true } } -- features.gsub["dev2_reorder_reph"] = { ["dev2"] = { ["dflt"] = true } } -- features.gsub["dev2_reorder_pre_base_reordering_consonants"] = { ["dev2"] = { ["dflt"] = true } } -- features.gsub["remove_joiners"] = { ["deva"] = { ["dflt"] = true }, ["dev2"] = { ["dflt"] = true } } -- -- local sequence_dev2_reorder_matras = { -- chain = 0, -- features = { dev2_reorder_matras = { dev2 = { dflt = true } } }, -- flags = { false, false, false, false }, -- name = "dev2_reorder_matras", -- subtables = { "dev2_reorder_matras" }, -- type = "dev2_reorder_matras", -- } -- local sequence_dev2_reorder_reph = { -- chain = 0, -- features = { dev2_reorder_reph = { dev2 = { dflt = true } } }, -- flags = { false, false, false, false }, -- name = "dev2_reorder_reph", -- subtables = { "dev2_reorder_reph" }, -- type = "dev2_reorder_reph", -- } -- local sequence_dev2_reorder_pre_base_reordering_consonants = { -- chain = 0, -- features = { dev2_reorder_pre_base_reordering_consonants = { dev2 = { dflt = true } } }, -- flags = { false, false, false, false }, -- name = "dev2_reorder_pre_base_reordering_consonants", -- subtables = { "dev2_reorder_pre_base_reordering_consonants" }, -- type = "dev2_reorder_pre_base_reordering_consonants", -- } -- local sequence_remove_joiners = { -- chain = 0, -- features = { remove_joiners = { deva = { dflt = true }, dev2 = { dflt = true } } }, -- flags = { false, false, false, false }, -- name = "remove_joiners", -- subtables = { "remove_joiners" }, -- type = "remove_joiners", -- } -- table.insert(sequences, insertpos, sequence_dev2_reorder_pre_base_reordering_consonants) -- table.insert(sequences, insertpos, sequence_dev2_reorder_reph) -- table.insert(sequences, insertpos, sequence_dev2_reorder_matras) -- table.insert(sequences, insertpos, sequence_remove_joiners) -- end -- -- local function deva_reorder(head,start,stop,font,attr) -- local tfmdata = fontdata[font] -- local lookuphash = tfmdata.resources.lookuphash -- local sequences = tfmdata.resources.sequences -- -- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features -- -- local sharedfeatures = tfmdata.shared.features -- sharedfeatures["remove_joiners"] = true -- local datasets = otf.dataset(tfmdata,font,attr) -- -- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true } -- -- local current, n, base, firstcons, lastcons, basefound = start, start.next, nil, nil, nil, false -- local reph, vattu = false, false -- for s=1,#sequences do -- local dataset = datasets[s] -- featurevalue = dataset and dataset[1] -- if featurevalue and dataset[4] == "rphf" then reph = true end -- if featurevalue and dataset[4] == "blwf" then vattu = true end -- end -- if ra[start.char] and halant[n.char] and reph then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants -- if n == stop then return head, stop end -- if zwj[n.next.char] then -- current = start -- else -- current = n.next -- set_attribute(start,state,5) -- rphf -- end -- end -- -- if nbsp[current.char] then --Stand Alone cluster -- if current == stop then -- stop = stop.prev -- head = node.remove(head, current) -- node.free(current) -- return head, stop -- else -- base, firstcons, lastcons = current, current, current -- current = current.next -- if current ~= stop then -- if nukta[current.char] then current = current.next end -- if zwj[current.char] then -- if current ~= stop and current.next ~= stop and halant[current.next.char] then -- current = current.next -- local tmp = current.next.next -- local changestop = current.next == stop -- local tempcurrent = node.copy(current.next) -- tempcurrent.next = node.copy(current) -- tempcurrent.next.prev = tempcurrent -- set_attribute(tempcurrent,state,8) --blwf -- tempcurrent = nodes.handlers.characters(tempcurrent) -- unset_attribute(tempcurrent,state) -- if current.next.char == tempcurrent.char then -- node.flush_list(tempcurrent) -- local n = node.copy(current) -- current.char = dotted_circle -- head = node.insert_after(head, current, n) -- else -- current.char = tempcurrent.char -- (assumes that result of blwf consists of one node) -- local freenode = current.next -- current.next = tmp -- tmp.prev = current -- node.free(freenode) -- node.flush_list(tempcurrent) -- if changestop then stop = current end -- end -- end -- end -- end -- end -- end -- -- while not basefound do -- find base consonant -- if consonant[current.char] then -- set_attribute(current, state, 6) -- half -- if not firstcons then firstcons = current end -- lastcons = current -- if not base then -- base = current -- else --check whether consonant has below-base (or post-base) form -- local baseform = true -- for s=1,#sequences do -- local sequence = sequences[s] -- local dataset = datasets[s] -- featurevalue = dataset and dataset[1] -- if featurevalue and dataset[4] == "blwf" then -- local subtables = sequence.subtables -- for i=1,#subtables do -- local lookupname = subtables[i] -- local lookupcache = lookuphash[lookupname] -- if lookupcache then -- local lookupmatch = lookupcache[current.char] -- if lookupmatch then -- set_attribute(current, state, 8) -- blwf -- baseform = false -- end -- end -- end -- end -- end -- if baseform then base = current end -- end -- end -- basefound = current == stop -- current = current.next -- end -- if base ~= lastcons then -- if base consonant is not last one then move halant from base consonant to last one -- n = base.next -- if nukta[n.char] then n = n.next end -- if halant[n.char] then -- if lastcons ~= stop then -- local ln = lastcons.next -- if nukta[ln.char] then lastcons = ln end -- end -- local np, nn, ln = n.prev, n.next, lastcons.next -- np.next = n.next -- nn.prev = n.prev -- lastcons.next = n -- if ln then ln.prev = n end -- n.next = ln -- n.prev = lastcons -- if lastcons == stop then stop = n end -- end -- end -- -- n = start.next -- if ra[start.char] and halant[n.char] and not ( n ~= stop and ( zwj[n.next.char] or zwnj[n.next.char] ) ) then -- if syllable starts with Ra + H then move this combination so that it follows either: the post-base 'matra' (if any) or the base consonant -- local matra = base -- if base ~= stop and dependent_vowel[base.next.char] then matra = base.next end -- local sp, nn, mn = start.prev, n.next, matra.next -- if sp then sp.next = nn end -- nn.prev = sp -- matra.next = start -- start.prev = matra -- n.next = mn -- if mn then mn.prev = n end -- if head == start then head = nn end -- start = nn -- if matra == stop then stop = n end -- end -- -- local current = start -- while current ~= stop do -- if halant[current.next.char] and current.next ~= stop and zwnj[current.next.next.char] then unset_attribute(current, state) end -- current = current.next -- end -- -- if has_attribute(base, state) and base ~= stop and halant[base.next.char] and not ( base.next ~= stop and zwj[base.next.next.char] ) then unset_attribute(base, state) end -- -- local current, allreordered, moved = start, false, { [base] = true } -- local a, b, p, bn = base, base, base, base.next -- if base ~= stop and nukta[bn.char] then a, b, p = bn, bn, bn end -- while not allreordered do -- local c, n, l = current, current.next, nil --current is always consonant -- if c ~= stop and nukta[n.char] then c = n n = n.next end -- if c ~= stop and halant[n.char] then c = n n = n.next end -- while c ~= stop and dependent_vowel[n.char] do c = n n = n.next end -- if c ~= stop and vowel_modifier[n.char] then c = n n = n.next end -- if c ~= stop and stress_tone_mark[n.char] then c = n n = n.next end -- local bp, cn = firstcons.prev, current.next -- while cn ~= c.next do -- move pre-base matras... -- if pre_mark[cn.char] then -- if bp then bp.next = cn end -- cn.prev.next = cn.next -- if cn.next then cn.next.prev = cn.prev end -- if cn == stop then stop = cn.prev end -- cn.prev = bp -- cn.next = firstcons -- firstcons.prev = cn -- if firstcons == start then -- if head == start then head = cn end -- start = cn -- end -- break -- end -- cn = cn.next -- end -- allreordered = c == stop -- current = c.next -- end -- -- if reph or vattu then -- local current, cns = start, nil -- while current ~= stop do -- local c, n = current, current.next -- if ra[current.char] and halant[n.char] then -- c, n = n, n.next -- local b, bn = base, base -- while bn ~= stop do -- if dependent_vowel[bn.next.char] then b = bn.next end -- bn = bn.next -- end -- if has_attribute(current,state,attribute) == 5 then -- position Reph (Ra + H) after post-base 'matra' (if any) since these become marks on the 'matra', not on the base glyph -- if b ~= current then -- if current == start then -- if head == start then head = n end -- start = n -- end -- if b == stop then stop = c end -- if current.prev then current.prev.next = n end -- if n then n.prev = current.prev end -- c.next = b.next -- if b.next then b.next.prev = c end -- b.next = current -- current.prev = b -- end -- elseif cns and cns.next ~= current then -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants) -- local cp, cnsn = current.prev, cns.next -- if cp then cp.next = n end -- if n then n.prev = cp end -- cns.next = current -- current.prev = cns -- c.next = cnsn -- if cnsn then cnsn.prev = c end -- if c == stop then stop = cp break end -- current = n.prev -- end -- elseif consonant[current.char] or nbsp[current.char] then -- cns = current -- if halant[cns.next.char] then cns = cns.next end -- end -- current = current.next -- end -- end -- -- if nbsp[base.char] then -- head = node.remove(head, base) -- node.free(base) -- end -- -- return head, stop -- end -- -- function dev2_reorder_matras(start,kind,lookupname,replacement) -- local current = start -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do -- if halant[current.char] and not has_attribute(current, state) then -- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end -- local sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- if current.next then current.next.prev = start end -- start.next = current.next -- current.next = start -- start.prev = current -- start = sn -- break -- end -- current = current.next -- end -- return start, true -- end -- -- function dev2_reorder_reph(start,kind,lookupname,replacement) -- local current, sn = start.next, nil -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 2 -- if halant[current.char] and not has_attribute(current, state) then -- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- if current.next then current.next.prev = start end -- start.next = current.next -- current.next = start -- start.prev = current -- start = sn -- break -- end -- current = current.next -- end -- if not sn then -- current = start.next -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 4 -- if has_attribute(current, state) == 9 then --post-base -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- start.prev = current.prev -- current.prev.next = start -- start.next = current -- current.prev = start -- start = sn -- break -- end -- current = current.next -- end -- end -- if not sn then -- current = start.next -- local c = nil -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 5 -- if not c and ( above_mark[current.char] or below_mark[current.char] or post_mark[current.char] ) and ReorderClass[current.char] ~= "after subscript" then c = current end -- current = current.next -- end -- if c then -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- start.prev = c.prev -- c.prev.next = start -- start.next = c -- c.prev = start -- start = sn -- end -- end -- if not sn then -- current = start -- while current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) do --step 6 -- current = current.next -- end -- if start ~= current then -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- if current.next then current.next.prev = start end -- start.next = current.next -- current.next = start -- start.prev = current -- start = sn -- end -- end -- return start, true -- end -- -- function dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) -- local current, sn = start, nil -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do -- if halant[current.char] and not has_attribute(current, state) then -- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- if current.next then current.next.prev = start end -- start.next = current.next -- current.next = start -- start.prev = current -- start = sn -- break -- end -- current = current.next -- end -- if not sn then -- current = start.next -- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do -- if not consonant[current.char] and has_attribute(current, state) then --main -- sn = start.next -- start.next.prev = start.prev -- if start.prev then start.prev.next = start.next end -- start.prev = current.prev -- current.prev.next = start -- start.next = current -- current.prev = start -- start = sn -- break -- end -- current = current.next -- end -- end -- return start, true -- end -- -- function remove_joiners(start,kind,lookupname,replacement) -- local stop = start.next -- while stop and stop.id == glyph and stop.subtype<256 and stop.font == start.font and (zwj[stop.char] or zwnj[stop.char]) do stop = stop.next end -- if stop then stop.prev.next = nil stop.prev = start.prev end -- if start.prev then start.prev.next = stop end -- node.flush_list(start) -- return stop, true -- end -- -- local function dev2_reorder(head,start,stop,font,attr) -- local tfmdata = fontdata[font] -- local lookuphash = tfmdata.resources.lookuphash -- local sequences = tfmdata.resources.sequences -- -- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features -- -- local sharedfeatures = tfmdata.shared.features -- sharedfeatures["dev2_reorder_matras"] = true -- sharedfeatures["dev2_reorder_reph"] = true -- sharedfeatures["dev2_reorder_pre_base_reordering_consonants"] = true -- sharedfeatures["remove_joiners"] = true -- local datasets = otf.dataset(tfmdata,font,attr) -- -- local reph, pre_base_reordering_consonants = false, nil -- local halfpos, basepos, subpos, postpos = nil, nil, nil, nil -- local locl = { } -- -- for s=1,#sequences do -- classify chars -- local sequence = sequences[s] -- local dataset = datasets[s] -- featurevalue = dataset and dataset[1] -- if featurevalue and dataset[4] then -- local subtables = sequence.subtables -- for i=1,#subtables do -- local lookupname = subtables[i] -- local lookupcache = lookuphash[lookupname] -- if lookupcache then -- if dataset[4] == "rphf" then -- if dataset[3] ~= 0 then --rphf is result of of chain -- else -- reph = lookupcache[0x0930] and lookupcache[0x0930][0x094D] and lookupcache[0x0930][0x094D]["ligature"] -- end -- end -- if dataset[4] == "pref" and not pre_base_reordering_consonants then -- for k, v in pairs(lookupcache[0x094D]) do -- pre_base_reordering_consonants[k] = v and v["ligature"] --ToDo: reph might also be result of chain -- end -- end -- local current = start -- while current ~= stop.next do -- if dataset[4] == "locl" then locl[current] = lookupcache[current.char] end --ToDo: locl might also be result of chain -- if current ~= stop then -- local c, n = locl[current] or current.char, locl[current.next] or current.next.char -- if dataset[4] == "rphf" and lookupcache[c] and lookupcache[c][n] then --above-base: rphf Consonant + Halant -- if current.next ~= stop and ( zwj[current.next.next.char] or zwnj[current.next.next.char] ) then --ZWJ and ZWNJ prevent creation of reph -- current = current.next -- elseif current == start then -- set_attribute(current,state,5) -- end -- current = current.next -- end -- if dataset[4] == "half" and lookupcache[c] and lookupcache[c][n] then --half forms: half Consonant + Halant -- if current.next ~= stop and zwnj[current.next.next.char] then --ZWNJ prevent creation of half -- current = current.next -- else -- set_attribute(current,state,6) -- if not halfpos then halfpos = current end -- end -- current = current.next -- end -- if dataset[4] == "pref" and lookupcache[c] and lookupcache[c][n] then --pre-base: pref Halant + Consonant -- set_attribute(current,state,7) -- set_attribute(current.next,state,7) -- current = current.next -- end -- if dataset[4] == "blwf" and lookupcache[c] and lookupcache[c][n] then --below-base: blwf Halant + Consonant -- set_attribute(current,state,8) -- set_attribute(current.next,state,8) -- current = current.next -- subpos = current -- end -- if dataset[4] == "pstf" and lookupcache[c] and lookupcache[c][n] then --post-base: pstf Halant + Consonant -- set_attribute(current,state,9) -- set_attribute(current.next,state,9) -- current = current.next -- postpos = current -- end -- end -- current = current.next -- end -- end -- end -- end -- end -- -- lookuphash["dev2_reorder_matras"] = pre_mark -- lookuphash["dev2_reorder_reph"] = { [reph] = true } -- lookuphash["dev2_reorder_pre_base_reordering_consonants"] = pre_base_reordering_consonants or { } -- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true } -- -- local current, base, firstcons = start, nil, nil -- if has_attribute(start,state) == 5 then current = start.next.next end -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants -- -- if current ~= stop.next and nbsp[current.char] then --Stand Alone cluster -- if current == stop then -- stop = stop.prev -- head = node.remove(head, current) -- node.free(current) -- return head, stop -- else -- base = current -- current = current.next -- if current ~= stop then -- if nukta[current.char] then current = current.next end -- if zwj[current.char] then -- if current ~= stop and current.next ~= stop and halant[current.next.char] then -- current = current.next -- local tmp = current.next.next -- local changestop = current.next == stop -- current.next.next = nil -- set_attribute(current,state,7) --pref -- current = nodes.handlers.characters(current) -- set_attribute(current,state,8) --blwf -- current = nodes.handlers.characters(current) -- set_attribute(current,state,9) --pstf -- current = nodes.handlers.characters(current) -- unset_attribute(current,state) -- if halant[current.char] then -- current.next.next = tmp -- local nc = node.copy(current) -- current.char = dotted_circle -- head = node.insert_after(head, current, nc) -- else -- current.next = tmp -- (assumes that result of pref, blwf, or pstf consists of one node) -- if changestop then stop = current end -- end -- end -- end -- end -- end -- else --not Stand Alone cluster -- while current ~= stop.next do -- find base consonant -- if consonant[current.char] and not ( current ~= stop and halant[current.next.char] and current.next ~= stop and zwj[current.next.next.char] ) then -- if not firstcons then firstcons = current end -- if not ( has_attribute(current, state) == 7 or has_attribute(current, state) == 8 or has_attribute(current, state) == 9 ) then base = current end --check whether consonant has below-base or post-base form or is pre-base reordering Ra -- end -- current = current.next -- end -- if not base then -- base = firstcons -- end -- end -- -- if not base then -- if has_attribute(start, state) == 5 then unset_attribute(start, state) end -- return head, stop -- else -- if has_attribute(base, state) then unset_attribute(base, state) end -- basepos = base -- end -- if not halfpos then halfpos = base end -- if not subpos then subpos = base end -- if not postpos then postpos = subpos or base end -- -- --Matra characters are classified and reordered by which consonant in a conjunct they have affinity for -- local moved = { } -- current = start -- while current ~= stop.next do -- local char, target, cn = locl[current] or current.char, nil, current.next -- if not moved[current] and dependent_vowel[char] then -- if pre_mark[char] then -- Before first half form in the syllable -- moved[current] = true -- if current.prev then current.prev.next = current.next end -- if current.next then current.next.prev = current.prev end -- if current == stop then stop = current.prev end -- if halfpos == start then -- if head == start then head = current end -- start = current -- end -- if halfpos.prev then halfpos.prev.next = current end -- current.prev = halfpos.prev -- halfpos.prev = current -- current.next = halfpos -- halfpos = current -- elseif above_mark[char] then -- After main consonant -- target = basepos -- if subpos == basepos then subpos = current end -- if postpos == basepos then postpos = current end -- basepos = current -- elseif below_mark[char] then -- After subjoined consonants -- target = subpos -- if postpos == subpos then postpos = current end -- subpos = current -- elseif post_mark[char] then -- After post-form consonant -- target = postpos -- postpos = current -- end -- if ( above_mark[char] or below_mark[char] or post_mark[char] ) and current.prev ~= target then -- if current.prev then current.prev.next = current.next end -- if current.next then current.next.prev = current.prev end -- if current == stop then stop = current.prev end -- if target.next then target.next.prev = current end -- current.next = target.next -- target.next = current -- current.prev = target -- end -- end -- current = cn -- end -- -- --Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first. -- local current, c = start, nil -- while current ~= stop do -- if halant[current.char] or stress_tone_mark[current.char] then -- if not c then c = current end -- else -- c = nil -- end -- if c and nukta[current.next.char] then -- if head == c then head = current.next end -- if stop == current.next then stop = current end -- if c.prev then c.prev.next = current.next end -- current.next.prev = c.prev -- current.next = current.next.next -- if current.next.next then current.next.next.prev = current end -- c.prev = current.next -- current.next.next = c -- end -- if stop == current then break end -- current = current.next -- end -- -- if nbsp[base.char] then -- head = node.remove(head, base) -- node.free(base) -- end -- -- return head, stop -- end -- -- function fonts.analyzers.methods.deva(head,font,attr) -- local orighead = head -- local current, start, done = head, true, false -- while current do -- if current.id == glyph and current.subtype<256 and current.font == font then -- done = true -- local syllablestart, syllableend = current, nil -- -- local c = current --Checking Stand Alone cluster (this behavior is copied from dev2) -- if ra[c.char] and c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] and c.next.next and c.next.next.id == glyph and c.next.next.subtype<256 and c.next.next.font == font then c = c.next.next end -- if nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or -- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and -- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] ) -- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- local n = c.next -- if n and n.id == glyph and n.subtype<256 and n.font == font then -- local ni = n.next -- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end -- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end -- end -- while c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] do c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- current = c.next -- syllableend = c -- if syllablestart ~= syllableend then -- head, current = deva_reorder(head, syllablestart,syllableend,font,attr) -- current = current.next -- end -- elseif consonant[current.char] then -- syllable containing consonant -- prevc = true -- while prevc do -- prevc = false -- local n = current.next -- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end -- if n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] then -- local n = n.next -- if n and n.id == glyph and n.subtype<256 and n.font == font and ( zwj[n.char] or zwnj[n.char] ) then n = n.next end -- if n and n.id == glyph and n.subtype<256 and n.font == font and consonant[n.char] then -- prevc = true -- current = n -- end -- end -- end -- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and nukta[current.next.char] then current = current.next end -- nukta (not specified in Microsft Devanagari OpenType specification) -- syllableend = current -- current = current.next -- if current and current.id == glyph and current.subtype<256 and current.font == font and halant[current.char] then -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H -- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end -- syllableend = current -- current = current.next -- else -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM] -- if current and current.id == glyph and current.subtype<256 and current.font == font and dependent_vowel[current.char] then -- syllableend = current -- current = current.next -- end -- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then -- syllableend = current -- current = current.next -- end -- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then -- syllableend = current -- current = current.next -- end -- end -- if syllablestart ~= syllableend then -- head, current = deva_reorder(head,syllablestart,syllableend,font,attr) -- current = current.next -- end -- elseif current.id == glyph and current.subtype<256 and current.font == font and independent_vowel[current.char] then -- syllable without consonants: VO + [VM] + [SM] -- syllableend = current -- current = current.next -- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then -- syllableend = current -- current = current.next -- end -- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then -- syllableend = current -- current = current.next -- end -- else -- Syntax error -- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then -- local n = node.copy(current) -- if pre_mark[current.char] then -- n.char = dotted_circle -- else -- current.char = dotted_circle -- end -- head, current = node.insert_after(head, current, n) -- end -- current = current.next -- end -- else -- current = current.next -- end -- start = false -- end -- -- return head, done -- end -- -- function fonts.analyzers.methods.dev2(head,font,attr) -- local current, start, done, syl_nr = head, true, false, 0 -- while current do -- local syllablestart, syllableend = nil, nil -- if current.id == glyph and current.subtype<256 and current.font == font then -- syllablestart = current -- done = true -- local c, n = current, current.next -- if ra[current.char] and n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] and n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font then c = n.next end -- if independent_vowel[c.char] then --Vowel-based syllable: [Ra+H]+V+[N]+[<[]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] -- n = c.next -- local ni, nii = nil, nil -- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end -- if n and n.id == glyph and n.subtype<256 and n.font == font then local ni = n.next end -- if ni and ni.id == glyph and ni.subtype<256 and ni.font == font and ni.next and ni.next.id == glyph and ni.next.subtype<256 and ni.next.font == font then -- nii = ni.next -- if zwj[ni.char] and consonant[nii.char] then -- c = nii -- elseif (zwj[ni.char] or zwnj[ni.char]) and halant[nii.char] and nii.next and nii.next.id == glyph and nii.next.subtype<256 and nii.next.font == font and consonant[nii.next.char] then -- c = nii.next -- end -- end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- current = c -- syllableend = c -- elseif nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or -- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and -- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] ) -- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- n = c.next -- if n and n.id == glyph and n.subtype<256 and n.font == font then -- local ni = n.next -- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end -- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end -- end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- current = c -- syllableend = c -- elseif consonant[current.char] then --Consonant syllable: {C+[N]+]|+H>} + C+[N]+[A] + [< H+[] | {M}+[N]+[H]>]+[SM]+[(VD)] -- c = current -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- n = c -- while n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( halant[n.next.char] or zwnj[n.next.char] or zwj[n.next.char] ) do -- if halant[n.next.char] then -- n = n.next -- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( zwnj[n.next.char] or zwj[n.next.char] ) then n = n.next end -- else -- if n.next.next and n.next.next.id == glyph and n.next.next.subtype<256 and n.next.next.font == font and halant[n.next.next.char] then n = n.next.next end -- end -- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and consonant[n.next.char] then -- n = n.next -- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and nukta[n.next.char] then n = n.next end -- c = n -- else -- break -- end -- end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and anudatta[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then -- c = c.next -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and ( zwnj[c.next.char] or zwj[c.next.char] ) then c = c.next end -- else -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end -- end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end -- current = c -- syllableend = c -- end -- end -- -- if syllableend then -- syl_nr = syl_nr + 1 -- c = syllablestart -- while c ~= syllableend.next do -- set_attribute(c,sylnr,syl_nr) -- c = c.next -- end -- end -- if syllableend and syllablestart ~= syllableend then -- head, current = dev2_reorder(head,syllablestart,syllableend,font,attr) -- end -- -- if not syllableend and not has_attribute(current, state) and current.id == glyph and current.subtype<256 and current.font == font then -- Syntax error -- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then -- local n = node.copy(current) -- if pre_mark[current.char] then -- n.char = dotted_circle -- else -- current.char = dotted_circle -- end -- head, current = node.insert_after(head, current, n) -- end -- end -- -- start = false -- current = current.next -- end -- -- return head, done -- end -- -- function otf.handlers.dev2_reorder_matras(start,kind,lookupname,replacement) -- return dev2_reorder_matras(start,kind,lookupname,replacement) -- end -- -- function otf.handlers.dev2_reorder_reph(start,kind,lookupname,replacement) -- return dev2_reorder_reph(start,kind,lookupname,replacement) -- end -- -- function otf.handlers.dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) -- return dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) -- end -- -- function otf.handlers.remove_joiners(start,kind,lookupname,replacement) -- return remove_joiners(start,kind,lookupname,replacement) -- end