From 3a9d5bbcba410869be83a42f5d6f0d0301c05416 Mon Sep 17 00:00:00 2001
From: Khaled Hosny <khaledhosny@eglug.org>
Date: Wed, 30 Dec 2009 13:13:13 +0200
Subject: Initial XeTeX-like font color support

The idea is very simple, we set a special |color| field in the font
table, then we surround each glyph in that font with color |whatsit|
node (actually pdfliteral whatsit nodes).

The resulting PDF file is larger than XeTeX output (because insert
color nodes around continues glyph nodes only, even if it was
interrupted by just a |glue| or |kern| node). This can be better
optimized, but I gave up.

Also we don't handle transparency, yet.
---
 luaotfload.dtx | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

(limited to 'luaotfload.dtx')

diff --git a/luaotfload.dtx b/luaotfload.dtx
index cc33913..36e0841 100644
--- a/luaotfload.dtx
+++ b/luaotfload.dtx
@@ -647,6 +647,76 @@ end
 initializers.base.otf.extend = initializers.common.extend
 initializers.node.otf.extend = initializers.common.extend
 
+%    \end{macrocode}
+%
+%    Support for font color.
+%
+%    \begin{macrocode}
+
+table.insert(fonts.triggers,"color")
+
+function initializers.common.color(tfmdata,value)
+    if value then
+        tfmdata.color = value
+    end
+end
+
+initializers.base.otf.color = initializers.common.color
+initializers.node.otf.color = initializers.common.color
+
+local function hex_to_rgba(hex)
+    local r, g, b, a, color
+    if hex and #hex == 6 then
+        _, _, r, g, b = hex:find('(..)(..)(..)')
+    elseif #hex == 8 then
+        _, _, r, g, b, a = hex:find('(..)(..)(..)(..)')
+    else
+        return nil
+    end
+    r = tonumber(r, 16)/255
+    g = tonumber(g, 16)/255
+    b = tonumber(b, 16)/255
+    color = string.format("%.3g %.3g %.3g rg", r, g, b)
+    return color
+end
+
+local glyph = node.id('glyph')
+local hlist = node.id('hlist')
+local vlist = node.id('vlist')
+
+local function colorize(head)
+   for n in node.traverse(head) do
+       if n.id == hlist or n.id == vlist then
+           colorize(n.list)
+       end
+       if n.id == glyph then
+           local tfmdata = fonts.ids[n.font]
+           if tfmdata and tfmdata.color then
+               local prev = n.prev
+               local next = n.next
+               if prev.id == glyph and fonts.ids[prev.font].color == tfmdata.color then
+               else
+                   local push = node.new(node.id("whatsit"), 8)
+                   push.mode  = 2
+                   push.data  = hex_to_rgba(tfmdata.color)
+                   head       = node.insert_before(head, n, push)
+               end
+               if next.id == glyph and fonts.ids[next.font].color == tfmdata.color then
+               else
+                   local pop  = node.new(node.id("whatsit"), 8)
+                   pop.mode   = 2
+                   pop.data   = "0 g"
+                   head       = node.insert_after(head, n, pop)
+               end
+           end
+       end
+   end
+   return head
+end
+
+callback.add("hpack_filter",         colorize, "Font color")
+callback.add("pre_linebreak_filter", colorize, "Font color")
+
 %    \end{macrocode}
 % \iffalse
 %</font-msc>
-- 
cgit v1.2.3

