diff options
author | Karl Berry <karl@freefriends.org> | 2021-05-16 20:41:27 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-05-16 20:41:27 +0000 |
commit | 3edf95ad1430c7b724870a24cec65e8534e6e01e (patch) | |
tree | 6db191280a3893bbe4a19151c820deee1c18c645 /Master/texmf-dist/tex/generic/babel/luababel.def | |
parent | 8adb7b898db8afe6ad0edcb96d27d756751493af (diff) |
babel (16may21)
git-svn-id: svn://tug.org/texlive/trunk@59229 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/babel/luababel.def')
-rw-r--r-- | Master/texmf-dist/tex/generic/babel/luababel.def | 242 |
1 files changed, 236 insertions, 6 deletions
diff --git a/Master/texmf-dist/tex/generic/babel/luababel.def b/Master/texmf-dist/tex/generic/babel/luababel.def index ef70c733ef4..51225cfa08a 100644 --- a/Master/texmf-dist/tex/generic/babel/luababel.def +++ b/Master/texmf-dist/tex/generic/babel/luababel.def @@ -534,6 +534,203 @@ \ifx\bbl@KVP@intrapenalty\@nil\else \expandafter\bbl@intrapenalty\bbl@KVP@intrapenalty\@@ \fi}} +\ifnum\bbl@bidimode>100 \ifnum\bbl@bidimode<200 +\def\bblar@chars{% + 0628,0629,062A,062B,062C,062D,062E,062F,0630,0631,0632,0633,% + 0634,0635,0636,0637,0638,0639,063A,063B,063C,063D,063E,063F,% + 0640,0641,0642,0643,0644,0645,0646,0647,0649} +\def\bblar@elongated{% + 0626,0628,062A,062B,0633,0634,0635,0636,063B,% + 063C,063D,063E,063F,0641,0642,0643,0644,0646,% + 0649,064A} +\begingroup + \catcode`_=11 \catcode`:=11 + \gdef\bblar@nofswarn{\gdef\msg_warning:nnx##1##2##3{}} +\endgroup +\gdef\bbl@arabicjust{% + \let\bbl@arabicjust\relax + \newattribute\bblar@kashida + \bblar@kashida=\z@ + \expandafter\bbl@add\csname selectfont \endcsname{{\bbl@parsejalt}}% + \directlua{ + Babel.arabic.elong_map = Babel.arabic.elong_map or {} + Babel.arabic.elong_map[\the\localeid] = {} + luatexbase.add_to_callback('post_linebreak_filter', + Babel.arabic.justify, 'Babel.arabic.justify') + }}% +\def\bblar@fetchjalt#1#2#3#4{% + \bbl@exp{\\\bbl@foreach{#1}}{% + \bbl@ifunset{bblar@JE@##1}% + {\setbox\z@\hbox{^^^^200d\char"##1#2}}% + {\setbox\z@\hbox{^^^^200d\char"\@nameuse{bblar@JE@##1}#2}}% + \directlua{% + local last = nil + for item in node.traverse(tex.box[0].head) do + if item.id == node.id'glyph' and item.char > 0x600 and + not (item.char == 0x200D) then + last = item + end + end + Babel.arabic.#3['##1#4'] = last.char + }}} +\gdef\bbl@parsejalt{% + \ifx\addfontfeature\@undefined\else + \bbl@xin@{/e}{/\bbl@cl{lnbrk}}% + \ifin@ + \directlua{% + if Babel.arabic.elong_map[\the\localeid][\fontid\font] == nil then + Babel.arabic.elong_map[\the\localeid][\fontid\font] = {} + tex.print([[\string\csname\space bbl@parsejalti\endcsname]]) + end + }% + \fi + \fi} +\gdef\bbl@parsejalti{% + \begingroup + \let\bbl@parsejalt\relax % To avoid infinite loop + \edef\bbl@tempb{\fontid\font}% + \bblar@nofswarn + \bblar@fetchjalt\bblar@elongated{}{from}{}% + \bblar@fetchjalt\bblar@chars{^^^^064a}{from}{a}% Alef maksura + \bblar@fetchjalt\bblar@chars{^^^^0649}{from}{y}% Yeh + \addfontfeature{RawFeature=+jalt}% + % \@namedef{bblar@JE@0643}{06AA}% todo: catch medial kaf + \bblar@fetchjalt\bblar@elongated{}{dest}{}% + \bblar@fetchjalt\bblar@chars{^^^^064a}{dest}{a}% + \bblar@fetchjalt\bblar@chars{^^^^0649}{dest}{y}% + \directlua{% + for k, v in pairs(Babel.arabic.from) do + if Babel.arabic.dest[k] and + not (Babel.arabic.from[k] == Babel.arabic.dest[k]) then + Babel.arabic.elong_map[\the\localeid][\bbl@tempb] + [Babel.arabic.from[k]] = Babel.arabic.dest[k] + end + end + }% + \endgroup} +\begingroup +\catcode`#=11 +\catcode`~=11 +\directlua{ + +Babel.arabic = Babel.arabic or {} +Babel.arabic.from = {} +Babel.arabic.dest = {} +Babel.arabic.justify_factor = 0.95 +Babel.arabic.justify_enabled = true + +function Babel.arabic.justify(head) + if not Babel.arabic.justify_enabled then return head end + local d, new + local k_list, k_item, pos_inline + local width, width_new, full, k_curr, wt_pos, goal + local subst_done = false + local elong_map = Babel.arabic.elong_map + local last_line + local GLYPH = node.id'glyph' + local KASHIDA = luatexbase.registernumber'bblar@kashida' + local LOCALE = luatexbase.registernumber'bbl@attr@locale' + + for line in node.traverse_id(node.id'hlist', head) do + % Exclude last line. todo. But-- it discards one-word lines, too! + % ? Look for glue = 12:15 + if (line.glue_sign == 1 and line.glue_order == 0) then + elongs = {} % Stores elongated candidates of each line + k_list = {} % And all letters with kashida + pos_inline = 0 % Not yet used + + for n in node.traverse_id(GLYPH, line.head) do + pos_inline = pos_inline + 1 % To find where it is. Not used. + + % Elongated glyphs + if elong_map then + local locale = node.get_attribute(n, LOCALE) + if elong_map[locale] and elong_map[locale][n.font] and + elong_map[locale][n.font][n.char] then + table.insert(elongs, {node = n, locale = locale} ) + node.set_attribute(n.prev, KASHIDA, 0) + end + end + + % Tatwil + if Babel.kashida_wts then + local k_wt = node.get_attribute(n, KASHIDA) + if k_wt > 0 then % todo. parameter for multi inserts + table.insert(k_list, {node = n, weight = k_wt, pos = pos_inline}) + end + end + + end % of node.traverse_id + + if #elongs == 0 and #k_list == 0 then goto next_line end + + full = line.width + goal = full * Babel.arabic.justify_factor % A bit crude + width = node.dimensions(line.head) % The 'natural' width + + % == Elongated == + % Original idea taken from 'chikenize' + while (#elongs > 0 and width < goal) do + subst_done = true + local x = #elongs + local curr = elongs[x].node + local oldchar = curr.char + curr.char = elong_map[elongs[x].locale][curr.font][curr.char] + width = node.dimensions(line.head) % Check if the line is too wide + % Substitute back if the line would be too wide and break: + if width > goal then + curr.char = oldchar + break + end + % If continue, pop the just substituted node from the list: + table.remove(elongs, x) + end + + % == Tatwil == + if #k_list == 0 then goto next_line end + + width = node.dimensions(line.head) % The 'natural' width + k_curr = #k_list + wt_pos = 1 + + while width < goal do + subst_done = true + k_item = k_list[k_curr].node + if k_list[k_curr].weight == Babel.kashida_wts[wt_pos] then + d = node.copy(k_item) + d.char = 0x0640 + line.head, new = node.insert_after(line.head, k_item, d) + width_new = node.dimensions(line.head) + if width > goal or width == width_new then + node.remove(line.head, new) % Better compute before + break + end + width = width_new + end + if k_curr == 1 then + k_curr = #k_list + wt_pos = (wt_pos >= table.getn(Babel.kashida_wts)) and 1 or wt_pos+1 + else + k_curr = k_curr - 1 + end + end + + ::next_line:: + + % Must take into account marks and ins, see luatex manual. + % Have to be executed only if there are changes. Investigate + % what's going on exactly. + if subst_done then + node.insert_before(head, line, node.hpack(line.head, full, 'exactly')) + node.remove(head, line) + end + end % if process line + end % for lines + return head +end +} +\endgroup +\fi\fi % Arabic just block \AddBabelHook{babel-fontspec}{afterextras}{\bbl@switchfont} \AddBabelHook{babel-fontspec}{beforestart}{\bbl@ckeckstdfonts} \DisableBabelHook{babel-fontspec} @@ -1113,6 +1310,7 @@ end &% after the match, either as found by u.match (faster) or the &% computed position based on sc if w has changed. local last_match = 0 + local step = 0 &% For every match. while true do @@ -1120,9 +1318,9 @@ end print('=====') end local new &% used when inserting and removing nodes - local refetch = false local matches = { u.match(w, p, last_match) } + if #matches < 2 then break end &% Get and remove empty captures (with ()'s, which return a @@ -1188,6 +1386,10 @@ end item_base = data_nodes[crep.data] end + if crep then + step = crep.step or 0 + end + if crep and next(crep) == nil then &% = {} last_match = save_last &% Optimization goto next @@ -1197,7 +1399,14 @@ end table.remove(w_nodes, sc) w = u.sub(w, 1, sc-1) .. u.sub(w, sc+1) sc = sc - 1 &% Nothing has been inserted. - last_match = utf8.offset(w, sc+1) + last_match = utf8.offset(w, sc+1+step) + goto next + + elseif crep and crep.kashida then &% Experimental + node.set_attribute(item, + luatexbase.registernumber'bblar@kashida', + crep.kashida) + last_match = utf8.offset(w, sc+1+step) goto next elseif crep and crep.string then @@ -1233,7 +1442,7 @@ end end &% for node.remove(head, item) end &% if '' - last_match = utf8.offset(w, sc+1) + last_match = utf8.offset(w, sc+1+step) goto next elseif mode == 1 and crep and (crep.pre or crep.no or crep.post) then @@ -1302,7 +1511,7 @@ end w = u.sub(w, 1, sc-1) .. placeholder .. u.sub(w, sc+1) end - last_match = utf8.offset(w, sc+1) + last_match = utf8.offset(w, sc+1+step) ::next:: @@ -1372,6 +1581,26 @@ end return "]]..Babel.capt_map(m[" .. capno .. "]," .. (mlen) .. ").." .. "[[" end + + &% Create/Extend reversed sorted list of kashida weights: + function Babel.capture_kashida(key, wt) + wt = tonumber(wt) + if Babel.kashida_wts then + for p, q in ipairs(Babel.kashida_wts) do + if wt == q then + break + elseif wt > q then + table.insert(Babel.kashida_wts, p, wt) + break + elseif table.getn(Babel.kashida_wts) == p then + table.insert(Babel.kashida_wts, wt) + end + end + else + Babel.kashida_wts = { wt } + end + return 'kashida = ' .. wt + end } \catcode`\#=6 \gdef\babelposthyphenation#1#2#3{&% @@ -1432,10 +1661,11 @@ end rep = rep:gsub('^%s*(remove)%s*$', 'remove = true') rep = rep:gsub('^%s*(insert)%s*,', 'insert = true, ') rep = rep:gsub('(string)%s*=%s*([^%s,]*)', Babel.capture_func) - rep = rep:gsub( '(space)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)', + rep = rep:gsub('(space)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)', 'space = {' .. '%2, %3, %4' .. '}') - rep = rep:gsub( '(spacefactor)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)', + rep = rep:gsub('(spacefactor)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)', 'spacefactor = {' .. '%2, %3, %4' .. '}') + rep = rep:gsub('(kashida)%s*=%s*([^%s,]*)', Babel.capture_kashida) tex.print([[\string\babeltempa{{]] .. rep .. [[}}]]) }}}&% \directlua{ |