summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luaotfload/luaotfload-colors.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/luaotfload/luaotfload-colors.lua')
-rw-r--r--macros/luatex/generic/luaotfload/luaotfload-colors.lua115
1 files changed, 99 insertions, 16 deletions
diff --git a/macros/luatex/generic/luaotfload/luaotfload-colors.lua b/macros/luatex/generic/luaotfload/luaotfload-colors.lua
index 05248b2a82..075b5210f5 100644
--- a/macros/luatex/generic/luaotfload/luaotfload-colors.lua
+++ b/macros/luatex/generic/luaotfload/luaotfload-colors.lua
@@ -5,8 +5,8 @@
assert(luaotfload_module, "This is a part of luaotfload and should not be loaded independently") {
name = "luaotfload-colors",
- version = "3.21", --TAGVERSION
- date = "2022-03-18", --TAGDATE
+ version = "3.22", --TAGVERSION
+ date = "2022-06-15", --TAGDATE
description = "luaotfload submodule / color",
license = "GPL v2.0",
author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim, David Carlisle",
@@ -48,18 +48,22 @@ local nodetail = nodedirect.tail
local getattribute = nodedirect.has_attribute
local setattribute = nodedirect.set_attribute
+local call_callback = luatexbase.call_callback
+
local stringformat = string.format
local identifiers = fonts.hashes.identifiers
local add_color_callback --[[ this used to be a global‽ ]]
+local custom_setcolor, custom_settransparent
+
--[[doc--
Color string parser.
--doc]]--
local lpeg = require"lpeg"
local lpegmatch = lpeg.match
-local C, Cg, Ct, P, R, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S
+local C, Cc, P, R, S = lpeg.C, lpeg.Cc, lpeg.P, lpeg.R, lpeg.S
local spaces = S"\t "^0
local digit16 = R("09", "af", "AF")
@@ -68,12 +72,43 @@ local octet = digit16 * digit16 / function(s)
return tonumber(s, 16) / 255
end
-local extract_color = spaces * octet * octet * octet / function(r,g,b)
+local function lpeg_repeat(patt, count)
+ patt = P(patt)
+ local result = patt
+ for i = 2, count do
+ result = result * patt
+ end
+ return result
+end
+
+local split_color = spaces * C(lpeg_repeat(digit16, 6)) * (opaque + C(lpeg_repeat(digit16, 2)))^-1 * spaces * -1
+ + spaces * (C((spaces * (1 - S', ')^1)^1) + Cc(nil)) * spaces * (',' * spaces * C((spaces * (1 - S' ,')^1)^1)^-1 * spaces)^-1 * -1
+
+luatexbase.create_callback('luaotfload.split_color', 'exclusive', function(value)
+ local rgb, a = lpegmatch(split_color, value)
+ if not rgb and not a then
+ logreport("both", 0, "color",
+ "%q is not a valid rgb[a] color expression",
+ digits)
+ end
+ return rgb, a
+end)
+
+local extract_color = octet * octet * octet / function(r,g,b)
return stringformat("%.3g %.3g %.3g rg", r, g, b)
- end * (opaque + octet)^-1 * spaces * -1
+ end * -1
+luatexbase.create_callback('luaotfload.parse_color', 'exclusive', function(value)
+ local rgb = lpegmatch(extract_color, value)
+ if not rgb then
+ logreport("both", 0, "color",
+ "Invalid color part in color expression %q",
+ value)
+ end
+ return rgb
+end)
---- something is carried around in ``res``
---- for later use by color_handler() --- but what?
+-- Keep the currently collected page resources needed for the current
+-- colors in `res`.
local res = nil
@@ -86,17 +121,37 @@ local function pageresources(alpha)
return f
end
+local extract_transparent = octet * -1
+luatexbase.create_callback('luaotfload.parse_transparent', 'exclusive', function(value)
+ local a
+ if type(value) == 'string' then
+ a = lpegmatch(extract_transparent, value)
+ if not a then
+ logreport("both", 0, "color",
+ "Invalid transparency part in color expression %q",
+ value)
+ end
+ else
+ a = value
+ end
+ if a then
+ a = pageresources(a)
+ end
+ return a
+end)
+
+
--- string -> (string | nil)
local function sanitize_color_expression (digits)
digits = tostring(digits)
- local rgb, a = lpegmatch(extract_color, digits)
- if not rgb then
- logreport("both", 0, "color",
- "%q is not a valid rgb[a] color expression",
- digits)
- return
+ local rgb, a = call_callback('luaotfload.split_color', digits)
+ if rgb then
+ rgb = call_callback('luaotfload.parse_color', rgb)
end
- return rgb, (a and pageresources(a))
+ if a then
+ a = call_callback('luaotfload.parse_transparent', a)
+ end
+ return rgb, a
end
local color_stack = 0
@@ -125,8 +180,6 @@ local colorstack_t = node.subtype("pdf_colorstack")
local color_callback
local color_attr = luatexbase.new_attribute("luaotfload_color_attribute")
-local custom_setcolor
-
-- Pass nil for new_color or old_color to indicate no color
-- If color is nil, pass tail to decide where to add whatsit
local function color_whatsit (head, curr, stack, old_color, new_color, tail)
@@ -391,8 +444,38 @@ end
function luaotfload.set_colorhandler(cb)
custom_setcolor = cb
end
+function luaotfload.set_transparenthandler(cb)
+ custom_settransparent = cb
+end
+function luaotfload.set_transparent_colorstack(stack)
+ if type(transparent_stack) == 'number' then
+ tex.error"luaotfload's transparency stack can't be changed after it has been used"
+ else
+ local t = type(stack)
+ if t == 'function' or t == 'number' then
+ function transparent_stack()
+ if t == 'function' then
+ transparent_stack = stack()
+ else
+ transparent_stack = stack
+ end
+ return transparent_stack
+ end
+ else
+ tex.error("Invalid argument in luaotfload.set_transparent_colorstack")
+ end
+ end
+end
+
+setmetatable(fonts.handlers.otf.statistics.usedfeatures.color, {
+ __index = function(t, k)
+ t[k] = k
+ return k
+ end,
+})
return function ()
+ assert(logreport == luaotfload.log.report)
logreport = luaotfload.log.report
if not fonts then
logreport ("log", 0, "color",