summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/showkerning/showkerning.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/showkerning/showkerning.lua')
-rw-r--r--macros/luatex/latex/showkerning/showkerning.lua163
1 files changed, 114 insertions, 49 deletions
diff --git a/macros/luatex/latex/showkerning/showkerning.lua b/macros/luatex/latex/showkerning/showkerning.lua
index 5c7faf3f6a..b298a6fb22 100644
--- a/macros/luatex/latex/showkerning/showkerning.lua
+++ b/macros/luatex/latex/showkerning/showkerning.lua
@@ -1,4 +1,4 @@
--- Copyright (c) 2022 Thomas Kelkel kelkel@emaileon.de
+-- Copyright (c) 2022-2023 Thomas Kelkel kelkel@emaileon.de
-- This file may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either
@@ -10,53 +10,41 @@
-- and version 1.3c or later is part of all distributions of
-- LaTeX version 2009/09/24 or later.
--- Version: 0.1
-
-local FLOOR = math.floor
-local ABS = math.abs
-
-local function round ( num, dec )
- return FLOOR ( num * 10^dec + 0.5 ) / 10^dec
-end
+-- Version: 0.3
local ID = node.id
local GLYPH = ID ( "glyph" )
local DISC = ID ( "disc" )
-local KERN = ID ( "kern" )
local GLUE = ID ( "glue" )
-local BOUND = ID ( "boundary" )
+local KERN = ID ( "kern" )
local WI = ID ( "whatsit" )
local HLIST = ID ( "hlist" )
local VLIST = ID ( "vlist" )
-local USERKERN = table.swapped ( node.subtypes ("kern") )["userkern"]
+
+local PDF_LITERAL = table.swapped ( node.whatsits () )["pdf_literal"]
+
local NEW = node.new
-local COPY = node.copy
-local REM = node.remove
local PREV = node.prev
local NEXT = node.next
local TAIL = node.tail
-local HAS_GLYPH = node.has_glyph
local INS_B = node.insert_before
local INS_A = node.insert_after
+local HAS_GLYPH = node.has_glyph
local T = node.traverse
local T_ID = node.traverse_id
-local T_GLYPH = node.traverse_glyph
-local WIS = node.whatsits()
-local pdfliteral
-local pairs = pairs
+
+local FLOOR = math.floor
+local ABS = math.abs
+
local ATC = luatexbase.add_to_callback
+-----
+
local on_top = false
local DIR = PREV
local AB = INS_B
local f = 1
-for key, value in pairs ( WIS ) do
- if value == "pdf_literal" then
- pdfliteral = key
- end
-end
-
function showkerning_on_top ()
on_top = true
DIR = NEXT
@@ -64,16 +52,42 @@ function showkerning_on_top ()
f = - 1
end
+local function round ( num, dec )
+ return FLOOR ( num * 10^dec + 0.5 ) / 10^dec
+end
+
local function calc_value ( value )
- value = round ( value / 65536, 3 )
+ value = round ( value / 65781, 3 )
return value
end
+local function find_first_last ( n, node_type, last )
+ local d = NEXT
+ if last then
+ d = PREV
+ n = TAIL ( n )
+ end
+ while true do
+ if n and n.id == node_type then
+ return n
+ end
+ if d ( n ) then
+ n = d ( n )
+ else
+ return false
+ end
+ end
+end
+
local function find_glyph ( n, d )
+ local kern_value = 0
if d ( n ) then
n = d ( n )
- while n.id ~= GLYPH and not ( n.id == DISC and n.replace and HAS_GLYPH ( n.replace ) ) do
- if not d ( n ) or n.id == GLUE or n.id == BOUND or ( n.id == KERN and n.subtype == USERKERN ) then return false end
+ while not ( n.id == GLYPH or n.replace and HAS_GLYPH ( n.replace ) ) do
+ if not d ( n ) then return false end
+ if n.id == GLUE then
+ kern_value = kern_value + n.width
+ end
n = d ( n )
end
else
@@ -81,19 +95,21 @@ local function find_glyph ( n, d )
end
local return_value = n
if n.id == DISC then
- for glyph_node in T_GLYPH ( n.replace ) do
- return_value = glyph_node
+ return_value = find_first_last ( n.replace, GLYPH, d == PREV )
+ for kern_node in T_ID ( KERN, n.replace ) do
+ kern_value = kern_value + kern_node.kern
end
end
- return return_value, n
+ return return_value, n, kern_value
end
local function check_glyph ( n, d, has_prev_next_glyph, prev_next_glyph, insert_prev_next )
+ local kern_value
if find_glyph ( n, d ) then
- prev_next_glyph, insert_prev_next = find_glyph ( n, d )
+ prev_next_glyph, insert_prev_next, kern_value = find_glyph ( n, d )
has_prev_next_glyph = true
end
- return has_prev_next_glyph, prev_next_glyph, insert_prev_next
+ return has_prev_next_glyph, prev_next_glyph, insert_prev_next, kern_value
end
local function get_x_value ( n, x_value )
@@ -101,14 +117,45 @@ local function get_x_value ( n, x_value )
if n.expansion_factor then
exp_fac = n.expansion_factor / 1000000 + 1
end
- if n.id == GLYPH and n.width then
+ if n.width then
x_value = x_value + calc_value ( n.width ) * exp_fac
- elseif n.id == KERN and n.kern then
+ elseif n.kern then
x_value = x_value + calc_value ( n.kern ) * exp_fac
end
return x_value
end
+local function find_kern ( n, d )
+ local kern_value = 0
+ local disc = false
+ if d ( n ) then
+ n = d ( n )
+ while n and not ( n.id == GLYPH or disc ) do
+ if n.id == KERN then
+ kern_value = get_x_value ( n, kern_value )
+ elseif n.replace then
+ local start_point = n.replace
+ if d == PREV then
+ start_point = TAIL ( n.replace )
+ end
+ if start_point.id == KERN then
+ kern_value = get_x_value ( start_point, kern_value )
+ end
+ disc = true
+ end
+ if d ( n ) then
+ n = d ( n )
+ else
+ break
+ end
+ end
+ if not ( kern_value == 0 ) then
+ return kern_value
+ end
+ end
+ return false
+end
+
local function make_rule ( head, n, kern_node, current_head, disc_list )
local color = "0 0 0"
local has_prev_glyph = false
@@ -121,27 +168,44 @@ local function make_rule ( head, n, kern_node, current_head, disc_list )
local x_value = 0
local height = 0
local depth = 0
+ local prev_kern_value = 0
+ local next_kern_value = 0
local thickness = calc_value ( kern_node.kern )
- has_prev_glyph, prev_glyph, insert_prev = check_glyph ( n, PREV, has_prev_glyph, prev_glyph, insert_prev )
- has_next_glyph, next_glyph, insert_next = check_glyph ( n, NEXT, has_next_glyph, next_glyph, insert_next )
+ has_prev_glyph, prev_glyph, insert_prev, prev_kern_value = check_glyph ( n, PREV, has_prev_glyph, prev_glyph, insert_prev )
+ has_next_glyph, next_glyph, insert_next, next_kern_value = check_glyph ( n, NEXT, has_next_glyph, next_glyph, insert_next )
+ if disc_list and not ( TAIL ( current_head ) == kern_node ) and not ( current_head == kern_node ) then
+ has_prev_glyph, prev_glyph, insert_prev, prev_kern_value = check_glyph ( kern_node, PREV, has_prev_glyph, kern_node, kern_node )
+ has_next_glyph, next_glyph, insert_next, next_kern_value = check_glyph ( kern_node, NEXT, has_next_glyph, kern_node, kern_node )
+ end
if not on_top and has_prev_glyph then
insert_point = insert_prev
x_value = get_x_value ( prev_glyph, x_value )
+ x_value = x_value + calc_value ( prev_kern_value )
if disc_list and HAS_GLYPH ( current_head ) and TAIL ( current_head ) == kern_node then
for some_node in T ( current_head ) do
if some_node == TAIL ( current_head ) then break end
x_value = get_x_value ( some_node, x_value )
end
end
- elseif on_top and has_next_glyph then
+ elseif on_top then
insert_point = insert_next
- x_value = get_x_value ( next_glyph, x_value )
+ if has_next_glyph then
+ x_value = get_x_value ( next_glyph, x_value )
+ x_value = x_value + calc_value ( next_kern_value )
+ end
if disc_list and HAS_GLYPH ( current_head ) and current_head == kern_node then
+ local kern_counter = 0
for some_node in T ( current_head ) do
- if some_node ~= current_head then
+ if some_node.id == KERN then
+ kern_counter = kern_counter + 1
+ end
+ if not ( some_node == current_head ) then
x_value = get_x_value ( some_node, x_value )
end
end
+ if find_kern ( n, NEXT ) then
+ x_value = x_value + find_kern ( n, NEXT )
+ end
end
end
if disc_list and HAS_GLYPH ( current_head ) then
@@ -165,19 +229,20 @@ local function make_rule ( head, n, kern_node, current_head, disc_list )
height = calc_value ( next_glyph.height )
depth = calc_value ( next_glyph.depth )
end
- if PREV ( kern_node ) and PREV ( kern_node ).id == KERN then
- thickness = get_x_value ( PREV ( kern_node ), thickness )
- if PREV ( PREV ( kern_node ) ) and PREV ( PREV ( kern_node ) ).id == KERN then
- thickness = get_x_value ( PREV ( PREV ( kern_node ) ), thickness )
- end
+ if find_kern ( n, PREV ) then
+ thickness = thickness + find_kern ( n, PREV )
end
- if ( thickness ~= 0 ) and ( thickness > calc_value ( tex.hsize ) * - 1 ) then
- head = AB ( head, insert_point, NEW ( WI, pdfliteral ) )
+ if thickness ~= 0 and thickness > calc_value ( tex.hsize ) * - 1 then
if thickness > 0 then
color = "0 1 0"
else
color = "1 0 0"
end
+ if disc_list and not ( TAIL ( current_head ) == kern_node ) and not ( current_head == kern_node ) then
+ current_head = AB ( current_head, insert_point, NEW ( WI, PDF_LITERAL ) )
+ else
+ head = AB ( head, insert_point, NEW ( WI, PDF_LITERAL ) )
+ end
x_value = ( x_value + calc_value ( kern_node.expansion_factor ) + thickness * 0.5 ) * f
DIR ( insert_point ).mode = 0
DIR ( insert_point ).data = "q " .. ABS ( thickness ) .. " w " .. x_value .. " " .. - depth .. " m " .. x_value .. " " .. height .. " l " .. color .. " RG S Q"
@@ -189,12 +254,12 @@ local function show_kerns ( head )
for n in T ( head ) do
if n.id == HLIST or n.id == VLIST then
n.head = show_kerns ( n.head )
- elseif n.id == KERN and not ( NEXT ( n ) and NEXT ( n ).id == KERN ) then
+ elseif n.id == KERN and not find_kern ( n, NEXT ) then
head = make_rule ( head, n, n, head, false )
elseif n.replace then
local REPLACE = n.replace
for kern_node in T_ID ( KERN, REPLACE ) do
- if not ( n.subtype == USERKERN ) and not ( NEXT ( kern_node ) and NEXT ( kern_node ).id == KERN ) then
+ if not find_kern ( kern_node, NEXT ) then
head, REPLACE = make_rule ( head , n, kern_node, REPLACE, true )
end
end