diff options
author | Norbert Preining <norbert@preining.info> | 2023-07-11 03:00:46 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-07-11 03:00:46 +0000 |
commit | 24bb3e3ee10fe79c39e9202be49c62c4d888f4ae (patch) | |
tree | 176d5ee37e8ab19ef7d3d91a357f3875c44ebccd /macros/luatex/latex/spacekern/spacekern.lua | |
parent | ab107e0f744efc9a2173da9b69e53fd83183988a (diff) |
CTAN sync 202307110300
Diffstat (limited to 'macros/luatex/latex/spacekern/spacekern.lua')
-rw-r--r-- | macros/luatex/latex/spacekern/spacekern.lua | 181 |
1 files changed, 129 insertions, 52 deletions
diff --git a/macros/luatex/latex/spacekern/spacekern.lua b/macros/luatex/latex/spacekern/spacekern.lua index 442f3845d4..1fd2d5624b 100644 --- a/macros/luatex/latex/spacekern/spacekern.lua +++ b/macros/luatex/latex/spacekern/spacekern.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,34 +10,48 @@ -- and version 1.3c or later is part of all distributions of -- LaTeX version 2009/09/24 or later. --- Version: 0.1a +-- Version: 0.3 local ID = node.id local GLYPH = ID ( "glyph" ) +local DISC = ID ( "disc" ) local GLUE = ID ( "glue" ) -local KERN = ID ( "kern" ) -local WI = ID ( "whatsit" ) -local BOUND = ID ( "boundary" ) local PENALTY = ID ( "penalty" ) +local HLIST = ID ( "hlist" ) +local INS = ID ( "ins" ) + local SWAPPED = table.swapped local SUBTYPES = node.subtypes -local USERKERN = SWAPPED ( SUBTYPES ("kern") )["userkern"] -local LBPENALTY = SWAPPED ( SUBTYPES ("penalty") )["linebreakpenalty"] local SPACESKIP = SWAPPED ( SUBTYPES ("glue") )["spaceskip"] +local LEADERS = SWAPPED ( SUBTYPES ("glue") )["leaders"] +local LBPENALTY = SWAPPED ( SUBTYPES ("penalty") )["linebreakpenalty"] + local NEW = node.new local REM = node.remove local PREV = node.prev local NEXT = node.next +local TAIL = node.tail local INS_B = node.insert_before -local T_ID = node.traverse_id +local HAS_GLYPH = node.has_glyph +local T = node.traverse local T_GLYPH = node.traverse_glyph -local WIS = node.whatsits() -local userdefined + local pairs = pairs +local type = type + +local U = unicode.utf8 +local SUB = U.sub +local GSUB = U.gsub +local FIND = U.find + local FLOOR = math.floor + local GET_FONT = font.getfont + local ATC = luatexbase.add_to_callback +----- + local no_iw_kern = false function spacekern_no_iw_kern () @@ -48,50 +62,92 @@ local function round ( num, dec ) return FLOOR ( num * 10^dec + 0.5 ) / 10^dec end -for key, value in pairs ( WIS ) do - if value == "user_defined" then - userdefined = key +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 ) - if d ( n ) then - n = d ( n ) - while n.id ~= GLYPH 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 +local function check_node ( n, space_check, disc_check, last ) + if n.replace then + return find_first_last ( n.replace, GLYPH, last ), space_check, disc_check + end + return n, space_check, disc_check +end + +local function find_glyph ( n, d, hlist_check, macro ) + if n then + local space_check = false + local disc_check = false + if hlist_check and ( n.id == GLYPH or n.replace and HAS_GLYPH ( n.replace ) ) then + return check_node ( n, space_check, disc_check, d == PREV ) + elseif not hlist_check then + if d ( n ) then + n = d ( n ) + else + return false + end + end + while not ( n.id == GLYPH or n.replace and HAS_GLYPH ( n.replace ) ) do + if n.id == HLIST and n.head then + local point = n.head + if d == PREV then + point = TAIL ( point ) + end + return find_glyph ( point, d, true, macro ) + end + if not d ( n ) or n.id == INS or macro and n.id == GLUE and n.width == 0 then + return false + else + if n.id == GLUE and n.subtype == SPACESKIP then + space_check = n + elseif n.subtype == LEADERS or n.id == GLUE and n.stretch > 0 then + return false + end + end + if n.id == DISC then + disc_check = n + end n = d ( n ) end - else - return false + return check_node ( n, space_check, disc_check, d == PREV ) end - return n + return false end local function make_kern ( head, font, first_glyph, second_glyph, insert_point ) local tfmdata = GET_FONT ( font ) - if tfmdata.resources then + if tfmdata and tfmdata.resources then local resources = tfmdata.resources if resources.sequences then local seq = resources.sequences for _, t in pairs ( seq ) do - if t.steps then + if t.steps and ( table.swapped ( t.order )["kern"] or tfmdata.specification.features.raw[t.name] ) then local steps = t.steps for _, k in pairs ( steps ) do - if k.coverage then - local first_number = true - if k.coverage[first_glyph] then - local glyph_table = k.coverage[first_glyph] - if type ( glyph_table ) == "table" then - for key, value in pairs ( glyph_table ) do - if key == second_glyph and type ( value ) == "number" and first_number and ( k.format == "move" or tfmdata.specification.features.raw[t.name] ) then - if tfmdata.specification.features.raw[t.name] then - first_number = false - end - if PREV ( insert_point ).id == PENALTY then - insert_point = PREV ( insert_point ) - end - INS_B ( head, insert_point, NEW ( KERN ) ) - PREV ( insert_point ).kern = value / tfmdata.units_per_em * tfmdata.size + if k.coverage and k.coverage[first_glyph] then + local glyph_table = k.coverage[first_glyph] + if type ( glyph_table ) == "table" then + for key, value in pairs ( glyph_table ) do + if key == second_glyph and type ( value ) == "number" then + if not ( ( first_glyph == 32 or second_glyph == 32 ) and table.swapped ( t.order )["kern"] ) then + insert_point.width = insert_point.width + value / tfmdata.units_per_em * tfmdata.size + end + if first_glyph == 32 or second_glyph == 32 then + insert_point.stretch = insert_point.stretch + value / tfmdata.units_per_em * tfmdata.size * 0.5 + insert_point.shrink = insert_point.shrink + value / tfmdata.units_per_em * tfmdata.size * 0.33333 end end end @@ -102,6 +158,7 @@ local function make_kern ( head, font, first_glyph, second_glyph, insert_point ) end end end + return head, disc_node end local function check_glyph ( n, d, has_prev_next_glyph, prev_next_glyph ) @@ -120,25 +177,33 @@ local function make_kerns ( head, n ) has_prev_glyph, prev_glyph = check_glyph ( n, PREV, has_prev_glyph, prev_glyph ) has_next_glyph, next_glyph = check_glyph ( n, NEXT, has_next_glyph, next_glyph ) if has_prev_glyph and prev_glyph.char and prev_glyph.font then - make_kern ( head, prev_glyph.font, prev_glyph.char, 32, n ) + head = make_kern ( head, prev_glyph.font, prev_glyph.char, 32, n ) end if has_next_glyph and next_glyph.char and next_glyph.font then - make_kern ( head, next_glyph.font, 32, next_glyph.char, n ) + head = make_kern ( head, next_glyph.font, 32, next_glyph.char, n ) end - if not no_iw_kern and has_prev_glyph and has_next_glyph and prev_glyph.char and next_glyph.char and prev_glyph.font and next_glyph.font and ( prev_glyph.font == next_glyph.font ) then - make_kern ( head, prev_glyph.font, prev_glyph.char, next_glyph.char, n ) + if not no_iw_kern and has_prev_glyph and has_next_glyph and prev_glyph.char and next_glyph.char and prev_glyph.font and next_glyph.font then + local tfmdata = GET_FONT ( prev_glyph.font ) + if tfmdata and tfmdata.name then + local font_id = GSUB ( SUB ( tfmdata.name, 1, FIND ( tfmdata.name, ":" ) - 1 ), "\"", "" ) + local second_tfmdata = GET_FONT ( next_glyph.font ) + if second_tfmdata and second_tfmdata.name then + local second_font_id = GSUB ( SUB ( second_tfmdata.name, 1, FIND ( second_tfmdata.name, ":" ) - 1 ), "\"", "" ) + if font_id == second_font_id then + head = make_kern ( head, prev_glyph.font, prev_glyph.char, next_glyph.char, n ) + end + end + end end + return head end -local function make_glues_and_kerns ( head ) - for n in T_ID ( GLUE, head ) do - make_kerns ( head, n ) - end +local function make_short_spaces ( head ) for n in T_GLYPH ( head ) do if n.char and n.char == 59 and ( not find_glyph ( n, PREV ) or find_glyph ( n, PREV ).char ~= 59 ) then - if find_glyph ( n, NEXT ) then + if find_glyph ( n, NEXT, false, true ) then local next_glyph = n - next_glyph = find_glyph ( n, NEXT ) + next_glyph = find_glyph ( n, NEXT, false, true ) if next_glyph.char and next_glyph.char == 59 then REM ( head, next_glyph ) local SIZE = 0 @@ -152,9 +217,11 @@ local function make_glues_and_kerns ( head ) local glue_node = PREV ( n ) glue_node.subtype = SPACESKIP glue_node.width = round ( SIZE * .16667, 0 ) + glue_node.stretch = glue_node.width * 0.5 + glue_node.shrink = glue_node.width * 0.33333 local has_next_glyph = false - if find_glyph ( n, NEXT ) then - next_glyph = find_glyph ( n, NEXT ) + if find_glyph ( n, NEXT, false, true ) then + next_glyph = find_glyph ( n, NEXT, false, true ) has_next_glyph = true end if has_next_glyph and next_glyph.char and next_glyph.char == 59 then @@ -164,11 +231,21 @@ local function make_glues_and_kerns ( head ) REM ( head, next_glyph ) end REM ( head, n ) - make_kerns ( head, glue_node ) end end end end end -ATC ( "ligaturing", make_glues_and_kerns, "kern between words and against space", 1 )
\ No newline at end of file +local function make_glues_and_kerns ( head ) + for n in T ( head ) do + if n.id == GLUE and n.subtype == SPACESKIP then + head = make_kerns ( head, n ) + end + end + return head +end + +ATC ( "ligaturing", make_short_spaces, "make short spaces", 1 ) +ATC ( "pre_linebreak_filter", make_glues_and_kerns, "kern between words and against space preline", 1 ) +ATC ( "hpack_filter", make_glues_and_kerns, "kern between words and against space hpack" )
\ No newline at end of file |