Difference between revisions of "Changing the font for a script"

From LuaTeXWiki
 
(4 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
It is intended just for small chunks of text (a proper noun, a few words, etc.). For proper bidi writing, see typo-dha.lua, typo-dua.lua, typo-dub.lua and typo-duc.lua in context.
 
It is intended just for small chunks of text (a proper noun, a few words, etc.). For proper bidi writing, see typo-dha.lua, typo-dua.lua, typo-dub.lua and typo-duc.lua in context.
 +
 +
You may also want to readjust the vertical positioning (the baselines don't always match). This part resorts to a pdf literal and it's commented out (because it's a hack - the glyphs are moved, but the corresponding boxes are not).
 +
 +
As an alternative approach, you may use combo fonts (provided by luaotfload 2.7).
  
 
<pre>
 
<pre>
Line 10: Line 14:
 
\directlua{
 
\directlua{
 
local DIR = node.id("dir")
 
local DIR = node.id("dir")
function show_nodes (head)
+
function arabic_text (head)
 +
  local prevglyf = nil
 
   local isArab = false
 
   local isArab = false
 
   for item in node.traverse_id(node.id"glyph", head) do
 
   for item in node.traverse_id(node.id"glyph", head) do
Line 17: Line 22:
 
       if isArab == false then  
 
       if isArab == false then  
 
         isArab = true
 
         isArab = true
         d = node.new(DIR)
+
         local d = node.new(DIR)
 
         d.dir = '+TRT'
 
         d.dir = '+TRT'
         node.insert_before(head, item, d)      
+
         node.insert_before(head, item, d)
 +
        % local r = node.new(node.id'whatsit', node.subtype'pdf_literal')
 +
        % r.data = '2 Ts'
 +
        % node.insert_before(head, item, r) 
 
       end
 
       end
 
     else
 
     else
 
       if isArab == true then
 
       if isArab == true then
 
         isArab = false
 
         isArab = false
         d = node.new(DIR)
+
         local d = node.new(DIR)
 
         d.dir = '-TRT'
 
         d.dir = '-TRT'
         node.insert_after(head, prevglyf, d)
+
         node.insert_before(head, prevglyf, d)
 +
        % local r = node.new(node.id'whatsit', node.subtype'pdf_literal')
 +
        % r.data = '0 Ts'
 +
        % node.insert_before(head, item, r) 
 
       end
 
       end
 
     end
 
     end
Line 33: Line 44:
 
   return head
 
   return head
 
end
 
end
luatexbase.add_to_callback("pre_linebreak_filter", show_nodes, 'desc')
+
luatexbase.add_to_callback("pre_linebreak_filter", arabic_text, "Arabic text")
luatexbase.add_to_callback("hpack_filter", show_nodes, 'desc')
+
luatexbase.add_to_callback("hpack_filter", arabic_text, "Arabic text")
 
}
 
}
  
 
% The contextual analysis for arabic must be after the font
 
% The contextual analysis for arabic must be after the font
% changes. It fontspec is loaded before, then the callbacks must be
+
% is changed. If fontspec is loaded before, then the callbacks must be
 
% reorderer, which is feasible.
 
% reorderer, which is feasible.
  
Line 53: Line 64:
 
\begin{tabular}{rr}
 
\begin{tabular}{rr}
 
One & Two \\
 
One & Two \\
Three & أربعة % :-/ Estra space
+
Three & أربعة % :-/ Extra space
 
\end{tabular}
 
\end{tabular}
  

Latest revision as of 15:44, 30 June 2016

Typically, fonts contain only a selection of scripts, and changing them automatically (as well as the writing direction) to make sure the document is properly typeset would be a nice feature. Here is a mock up.

It is based on the pre_linebreak_filter callback, which contains the horizontal list of glyphs, kerns, whatsits, etc., before building the paragraph. This callback is used by the font loader, too. It works with LaTeX 2016 and LuaTeX 0.95, but it should work with previous versions with minimal changes.

It is intended just for small chunks of text (a proper noun, a few words, etc.). For proper bidi writing, see typo-dha.lua, typo-dua.lua, typo-dub.lua and typo-duc.lua in context.

You may also want to readjust the vertical positioning (the baselines don't always match). This part resorts to a pdf literal and it's commented out (because it's a hack - the glyphs are moved, but the corresponding boxes are not).

As an alternative approach, you may use combo fonts (provided by luaotfload 2.7).

\documentclass{article}

\directlua{
local DIR = node.id("dir")
function arabic_text (head)
  local prevglyf = nil
  local isArab = false
  for item in node.traverse_id(node.id"glyph", head) do
    if item.char > 1536 and item.char < 1792 then
      item.font = arabicfont % Defined below
      if isArab == false then 
        isArab = true
        local d = node.new(DIR)
        d.dir = '+TRT'
        node.insert_before(head, item, d)
        % local r = node.new(node.id'whatsit', node.subtype'pdf_literal')
        % r.data = '2 Ts'
        % node.insert_before(head, item, r)   
      end
    else
      if isArab == true then
        isArab = false
        local d = node.new(DIR)
        d.dir = '-TRT'
        node.insert_before(head, prevglyf, d)
        % local r = node.new(node.id'whatsit', node.subtype'pdf_literal')
        % r.data = '0 Ts'
        % node.insert_before(head, item, r)   
      end
    end
    prevglyf = item % A bit dangerous, but usually OK.
  end
  return head
end
luatexbase.add_to_callback("pre_linebreak_filter", arabic_text, "Arabic text")
luatexbase.add_to_callback("hpack_filter", arabic_text, "Arabic text")
}

% The contextual analysis for arabic must be after the font
% is changed. If fontspec is loaded before, then the callbacks must be
% reorderer, which is feasible.

\usepackage{fontspec}
\setmainfont{Iwona}
\newfontfamily\amiri[Script=Arabic]{Amiri}

\begin{document}

{\amiri (نص قصير)\directlua{ arabicfont = font.current() }} Some text

Some text نص قصير Some text

\begin{tabular}{rr}
One & Two \\
Three & أربعة % :-/ Extra space
\end{tabular}

Some text.

\end{document}