diff options
-rw-r--r-- | luaotfload-colors.lua | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/luaotfload-colors.lua b/luaotfload-colors.lua index 5be0a1f..4121441 100644 --- a/luaotfload-colors.lua +++ b/luaotfload-colors.lua @@ -24,6 +24,21 @@ local registerotffeature = otffeatures.register local add_color_callback --[[ this used to be a global‽ ]] --[[doc-- +This converts a single octet into a decimal with three digits of +precision. The optional second argument limits precision to a single +digit. +--doc]]-- + +--- string -> bool? -> string +local hex_to_dec = function (hex,one) --- one isn’t actually used anywhere ... + if one then + return stringformat("%.1g", tonumber(hex, 16)/255) + else + return stringformat("%.3g", tonumber(hex, 16)/255) + end +end + +--[[doc-- Color string validator / parser. --doc]]-- @@ -38,10 +53,10 @@ local p_rgb = octet * octet * octet local p_rgba = p_rgb * octet local valid_digits = C(p_rgba + p_rgb) -- matches eight or six hex digits -local p_Crgb = Cg(octet, "red") --- for captures - * Cg(octet, "green") - * Cg(octet, "blue") -local p_Crgba = p_Crgb * Cg(octet, "alpha") +local p_Crgb = Cg(octet/hex_to_dec, "red") --- for captures + * Cg(octet/hex_to_dec, "green") + * Cg(octet/hex_to_dec, "blue") +local p_Crgba = p_Crgb * Cg(octet/hex_to_dec, "alpha") local extract_color = Ct(p_Crgba + p_Crgb) --- string -> (string | nil) @@ -66,12 +81,12 @@ end --- hexadecimal, with an optional fourth transparency --- value) --- -local function setcolor (tfmdata, value) +local setcolor = function (tfmdata, value) local sanitized = sanitize_color_expression(value) local properties = tfmdata.properties if sanitized then - tfmdata.properties.color = sanitized + properties.color = sanitized add_color_callback() end end @@ -86,64 +101,62 @@ registerotffeature { } ---[[doc-- -This converts a single octet into a decimal with three digits of -precision. The optional second argument limits precision to a single -digit. ---doc]]-- - ---- string -> bool? -> float -local function hex_to_dec(hex,one) - if one then - return stringformat("%.1g", tonumber(hex, 16)/255) - else - return stringformat("%.3g", tonumber(hex, 16)/255) - end -end - --- something is carried around in ``res`` --- for later use by color_handler() --- but what? local res --- <- state of what? --- float -> unit -local function pageresources(a) +local function pageresources(alpha) local res2 if not res then res = "/TransGs1<</ca 1/CA 1>>" end - res2 = stringformat("/TransGs%s<</ca %s/CA %s>>", a, a, a) + res2 = stringformat("/TransGs%s<</ca %s/CA %s>>", + alpha, alpha, alpha) res = stringformat("%s%s", res, stringfind(res, res2) and "" or res2) end +--- we store results of below color handler as tuples of +--- push/pop strings +local color_cache = { } --- (string, (string * string)) hash_t + --- string -> (string * string) -local function hex_to_rgba(hex) - local r, g, b, a, push, pop, res3 - if hex then - --- TODO lpeg this mess - if #hex == 6 then - _, _, r, g, b = stringfind(hex, '(..)(..)(..)') - elseif #hex == 8 then - _, _, r, g, b, a = stringfind(hex, '(..)(..)(..)(..)') - a = hex_to_dec(a,true) - pageresources(a) - end - else - return nil +local hex_to_rgba = function (digits) + if not digits then + return end - r = hex_to_dec(r) - g = hex_to_dec(g) - b = hex_to_dec(b) - if a then - push = stringformat('/TransGs%g gs %s %s %s rg', a, r, g, b) - pop = '0 g /TransGs1 gs' - else - push = stringformat('%s %s %s rg', r, g, b) - pop = '0 g' + + --- this is called like a thousand times, so some + --- memoizing is in order. + local cached = color_cache[digits] + if not cached then + local push, pop + local rgb = lpegmatch(extract_color, digits) + if rgb.alpha then + pageresources(rgb.alpha) + push = stringformat( + "/TransGs%g gs %s %s %s rg", + rgb.alpha, + rgb.red, + rgb.green, + rgb.blue) + pop = "0 g /TransGs1 gs" + else + push = stringformat( + "%s %s %s rg", + rgb.red, + rgb.green, + rgb.blue) + pop = "0 g" + end + color_cache[digits] = { push, pop } + return push, pop end - return push, pop + + return cached[1], cached[2] end --- Luatex internal types |