Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm coding an algorithm to detect and highlight homeoarchies.

Here my current almost working (but compiling at least) code:

\documentclass{article}
\usepackage[french]{babel}
\usepackage{kpfonts}

\usepackage{luatexbase}
 \usepackage{luacode}
 \begin{luacode}
 compare_lines = function (line1,line2)
   local head1 = line1.head
   local head2 = line2.head

   local char_count = 0
   local word_count = 0

   while (head1.id == 37 and head2.id == 37
          and head1.char == head2.char)          -- identical glyph
      or (head1.id == 10 and head2.id == 10) do  -- glue

      if (head1.id == 37) then -- glyph
         char_count = char_count + 1
      elseif (head1.id == 10) then -- glue
         word_count = word_count + 1
      end
      head1 = head1.next
      head2 = head2.next
   end
   return char_count,word_count,head1,head2
 end

 homeoarchy = function ( head )
   local cur_line = head
   local prev_line -- initiate prev_head

   local max_char = 3
   local max_word = 1

   while head do
     if head.id == 0 then -- new line
       print("new line")
       prev_line = cur_line
       cur_line = head
       if prev_line.id == 0 then
          char_count,word_count,prev_head,cur_head = compare_lines(prev_line,cur_line)
          if char_count >= max_char or word_count >= max_word then
             w1_prev = node.new("whatsit","pdf_literal")
             w1_prev.data = "q 1 0 1 rg"
             w1_prev.mode = 1

             w2_prev = node.new("whatsit","pdf_literal")
             w2_prev.data = "Q"
             w2_prev.mode = 1

             node.insert_before(prev_line,prev_line.head.next,w1_prev)
             node.insert_before(prev_line,prev_head,w2_prev)

             w1_cur = node.new("whatsit","pdf_literal")
             w1_cur.data = "q 1 0 1 rg"
             w1_prev.mode = 1

             w2_cur = node.new("whatsit","pdf_literal")
             w2_cur.data = "Q"
             w2_cur.mode = 1

             node.insert_before(cur_line,cur_line.head.next,w1_cur)
             node.insert_before(cur_line,cur_head,w2_cur)

             print("done placing markers")
          end
       end
     end
     head = head.next
   end
       return true
 end

 luatexbase.add_to_callback("post_linebreak_filter",homeoarchy,"homeoarchy")
 \end{luacode}

\begin{document}

\begin{minipage}{1.7in}
Je suis venu non pour juger le monde, mais pour sauver le monde. Celui qui me rejette
et qui ne re\c coit pas mes
\end{minipage}

\bigskip
\begin{minipage}{1.7in}
Je suis venu non pour juger~le monde, mais pour sauver le monde. Celui qui me rejette
et qui ne re\c coit pas mes
\end{minipage}

\bigskip
\begin{minipage}{1.7in}
Je suis venu non pour juger le monde, mais pour sauver~le monde. Celui qui me rejette
et qui ne re\c coit pas mes
\end{minipage}

\bigskip
\begin{minipage}{1.6in}
Je suis venu non pour juger le monde, mais pour sauver le monde. Celui qui me rejette
et qui ne re\c coit pas mes
\end{minipage}

\bigskip
\begin{minipage}{1.8in}
Je suis venu non pour juger le monde, mais pour sauver le monde. Celui qui me rejette
et qui ne re\c coit pas mes
\end{minipage}
\end{document}

and the result:

two bugs to go

It's easy to spot two bugs here:

  • the color starts after the "l" instead of before it. I've tried all sorts of combinations, from "prev_line.head" to "prev_line.head.next.prev", and I always get an error saying I can't insert before a non-existing node. I'm pretty sure the "l" node does exist. How can I insert before it?
  • the text stops after the second colored word. So I've colored the words alright, but I'd still like the rest of the text... How can I do that?
share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

There are several non-obvious problems in the code. It's really tricky!

  • node.insert_before(prev_line,prev_line.head.next,w1_prev). You should never use insert_before without assigning the new_head return value, for the second argument could be the beginning of the list and inserting something before will require a new head pointer.

  • The whatsit/pdf_literal trick is not really suitable for running text, but don't ask me for a perfect solution. I use pdf colorstacks from pdftex, but these will probably break in a lot of situations (vsplit and alike). If you have a look at the generated pdf (use qpdf to view it) you will find out that the text is in the PDF, but not visible.


...
1 0 0 1 148.712 674.423 Tm [(jette)-204(et)-205(qui)-205(ne)-204(rec)383<b8>-70(oit)-205(pas)-204(mes)]TJ
1 0 0 1 148.712 652.062 Tm [(J)31(e)-507(suis)-508(v)17(en)15(u)-506(non)-508(pour)-507(ju-)]TJ
1 0 0 1 148.712 640.106 Tm [(g)15(er)-640(le)-641(monde,)-642(mais)-640(pour)]TJ
1 0 0 1 148.712 628.151 Tm [(sa)16(uv)18(er)-363(le)-363(monde.)-363(C)5(el)15(ui)-362(qui)]TJ
1 0 0 1 148.712 616.196 Tm [(me)-453(rejette)-454(et)-453(qui)-454(ne)-453(rec)383<b8>-70(oit)]TJ
1 0 0 1 148.712 604.241 Tm [(pas)-255(mes)]TJ
1 0 0 1 148.712 581.969 Tm [(J)31(e)-301(suis)-301(v)17(en)15(u)-300(non)-301(pour)-301(jug)14(er)]TJ
1 0 0 1 148.712 570.014 Tm [(le)-527(monde,)-527(mais)-527(pour)-527(sa)15(u-)]TJ
1 0 0 1 148.712 558.059 Tm [(v)18(er)-317(le)-318(monde.)-317(C)5(el)15(ui)-317(qui)-317(me)]TJ
1 0 0 1 148.712 546.104 Tm [(rejette)-422(et)-423(qui)-423(ne)-423(rec)383<b8>-70(oit)-422(pas)]TJ
1 0 0 1 148.712 534.149 Tm [(mes)]TJ
1 0 0 1 148.712 514.313 Tm [(J)31(e)-363(suis)-363(v)17(en)15(u)-362(non)-363(pour)-363(ju-)]TJ
1 0 0 1 148.712 502.358 Tm [(g)15(er)-460(le)-460(monde,)-461(mais)-460(pour)]TJ
1 0 0 1 148.712 490.403 Tm [(sa)16(uv)18(er)-729(le)-729(monde.)-732(C)5(el)15(ui)]TJ
...
share|improve this answer
    
thanks. Does the answer I provided fix the insert_before issue properly? –  ℝaphink Sep 19 '11 at 9:32
add comment

Here is a fix for the first bug already:

By replacing node.insert_before(prev_line,prev_line.head.next,w1_prev with node.insert_after(prev_line.prev,prev_line.prev,w1_prev), I got it to work.

The second but is that I had w1_prev.mode = 1 instead of w1_cur.mode = 1...

share|improve this answer
    
prev_line looks like a hlist to me, so prev_line.prev could be a penalty or a glue or even nil - this doesn't look right. It should probably be prev_line.head. –  topskip Sep 19 '11 at 9:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.