[luatex] Kerning: when does it not work?

Paul Isambert zappathustra at free.fr
Wed May 4 16:32:10 CEST 2011


Le 04/05/2011 12:45, Paul Isambert a écrit :
> Anyway, the solution is: rewrite the package.

Since I have tons of urgent things to do, this thread gives me the 
wonderful opportunity not to do them. So here's a first stab at a 
LuaTeX-oriented \url command. Tell me if it works for you, Till:

%%%
\def\makeother#1{\catcode`#1=12 }
\def\url{%
   \begingroup
   \let\do\makeother \dospecials
   \catcode`\{=1 \catcode`\}=2
   \URL
   }
\newbox\urlbox
\def\URL#1{%
   \setbox\urlbox=\hbox{#1}%
   \directlua{%
     local box = tex.box["urlbox"].list
     local glyf, disc = node.id("glyph"), node.id("disc")
     for n in node.traverse_id(disc, box) do
       node.remove(box, n)
     end
     for n in node.traverse_id(glyf, box) do
       local b = url.breakpoints[n.char]
       if b == "before" then
         url.before(box, n)
       elseif b == "after" then
         url.after(box, n)
       elseif b == "both" then
         url.before(box, n)
         url.after(box, n)
       end
     end}%
   \unhbox\urlbox
   \endgroup
   }

\directlua{
local id, copy, insert_before, insert_after = node.id, node.copy, 
node.insert_before, node.insert_after

url = {}
url.breakpoints = {}
local penalty = node.new(id("penalty"))
penalty.penalty = 0

function url.before (l, n)
   if n.prev then
     if n.prev.id == id("kern") and n.prev.subtype == 0 then
       n = n.prev
     end
     insert_before(l, n, copy(penalty))
   end
end

function url.after(l, n)
   if n.next then
     insert_after(l, n, copy(penalty))
   end
end
}

\def\urladdbreakpoint#1#2{%
   \directlua{url.breakpoints[\the\numexpr`#1] = "#2"}%
   }
%%%

The two commands are:
- \url{<url>} which typesets the url normally (hence good kerning) and 
then inserts penalties as defined by the following command; <url> can 
contain any character but braces, which I think don't occur very often 
in urls anyway;
- \urladdbreakpoint{<character>}{<position>} defines <character> as a 
possible breakpoint; <position> should one of "before", "after" or 
"both", meaning that the url can be broken in those positions relative 
to <character>; such breakpoints aren't inserted before the first 
character and after the last one.

Remarks:
- There are probably many bells and whistles in the original url package 
that I haven't tried to mimick here; particularly I don't change fonts;
- The breakpoints are just penalty with value 0; one could give other 
values to inhibit or encourage breaking;
- There is something quite bad: you don't want an url to hyphenate; to 
avoid that I'd temporarily set the "hyphenate" callback to "false", so 
no hyphenation occurs when \urlbox is built; however, I don't know how 
to do that with luatexbase (which you're using covertly, Till) because 
callback.register is unavailable; so I let the hyphenation pass occur 
and then remove all discretionary nodes, which is a bad idea leading to 
trouble with anything but (the Lua equivalent of) \discretionary{-}{}{}; 
that'd be easily fixed with the intervention of a LaTeX user.

As a stupid example one can try:

\urladdbreakpoint{/}{after}
\urladdbreakpoint{_}{both}
\hsize=0pt
\url{http://www.tug.org/tug/#something_with_a_%_sign}

Best,
Paul


More information about the luatex mailing list