From 63d22f849b86544ecd568a80ce8ca3d971026a59 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 11 Jun 2022 20:43:14 +0000 Subject: spacekern (11jun22) git-svn-id: svn://tug.org/texlive/trunk@63552 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/lualatex/spacekern/spacekern.lua | 174 +++++++++++++++++++++ .../tex/lualatex/spacekern/spacekern.sty | 33 ++++ 2 files changed, 207 insertions(+) create mode 100644 Master/texmf-dist/tex/lualatex/spacekern/spacekern.lua create mode 100644 Master/texmf-dist/tex/lualatex/spacekern/spacekern.sty (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/lualatex/spacekern/spacekern.lua b/Master/texmf-dist/tex/lualatex/spacekern/spacekern.lua new file mode 100644 index 00000000000..442f3845d43 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/spacekern/spacekern.lua @@ -0,0 +1,174 @@ +-- Copyright (c) 2022 Thomas Kelkel kelkel@emaileon.de + +-- This file may be distributed and/or modified under the +-- conditions of the LaTeX Project Public License, either +-- version 1.3c of this license or (at your option) any later +-- version. The latest version of this license is in + +-- http://www.latex-project.org/lppl.txt + +-- and version 1.3c or later is part of all distributions of +-- LaTeX version 2009/09/24 or later. + +-- Version: 0.1a + +local ID = node.id +local GLYPH = ID ( "glyph" ) +local GLUE = ID ( "glue" ) +local KERN = ID ( "kern" ) +local WI = ID ( "whatsit" ) +local BOUND = ID ( "boundary" ) +local PENALTY = ID ( "penalty" ) +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 NEW = node.new +local REM = node.remove +local PREV = node.prev +local NEXT = node.next +local INS_B = node.insert_before +local T_ID = node.traverse_id +local T_GLYPH = node.traverse_glyph +local WIS = node.whatsits() +local userdefined +local pairs = pairs +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 () + no_iw_kern = true +end + +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 + 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 + n = d ( n ) + end + else + return false + end + return n +end + +local function make_kern ( head, font, first_glyph, second_glyph, insert_point ) + local tfmdata = GET_FONT ( font ) + if 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 + 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 + end + end + end + end + end + end + end + end + end + end +end + +local function check_glyph ( n, d, has_prev_next_glyph, prev_next_glyph ) + if find_glyph ( n, d ) then + prev_next_glyph = find_glyph ( n, d ) + has_prev_next_glyph = true + end + return has_prev_next_glyph, prev_next_glyph +end + +local function make_kerns ( head, n ) + local has_prev_glyph = false + local has_next_glyph = false + local prev_glyph = n + local next_glyph = 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 ) + 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 ) + 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 ) + end +end + +local function make_glues_and_kerns ( head ) + for n in T_ID ( GLUE, head ) do + make_kerns ( head, n ) + end + 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 + local next_glyph = n + next_glyph = find_glyph ( n, NEXT ) + if next_glyph.char and next_glyph.char == 59 then + REM ( head, next_glyph ) + local SIZE = 0 + if n.font then + local tfmdata = GET_FONT ( n.font ) + if tfmdata.size then + SIZE = tfmdata.size + end + end + INS_B ( head, n, NEW ( GLUE ) ) + local glue_node = PREV ( n ) + glue_node.subtype = SPACESKIP + glue_node.width = round ( SIZE * .16667, 0 ) + local has_next_glyph = false + if find_glyph ( n, NEXT ) then + next_glyph = find_glyph ( n, NEXT ) + has_next_glyph = true + end + if has_next_glyph and next_glyph.char and next_glyph.char == 59 then + INS_B ( head, glue_node, NEW ( PENALTY ) ) + PREV ( glue_node ).subtype = LBPENALTY + PREV ( glue_node ).penalty = 10000 + 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 diff --git a/Master/texmf-dist/tex/lualatex/spacekern/spacekern.sty b/Master/texmf-dist/tex/lualatex/spacekern/spacekern.sty new file mode 100644 index 00000000000..8cb91537332 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/spacekern/spacekern.sty @@ -0,0 +1,33 @@ +% Copyright (c) 2022 Thomas Kelkel kelkel@emaileon.de + +% This file may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either +% version 1.3c of this license or (at your option) any later +% version. The latest version of this license is in + +% http://www.latex-project.org/lppl.txt + +% and version 1.3c or later is part of all distributions of +% LaTeX version 2009/09/24 or later. + +\ProvidesPackage{spacekern}[2022/06/11 v0.1a Kerning between words and against space] +\RequirePackage{ifluatex,luatexbase} + +\ifluatex + \directlua{require ( "spacekern.lua" )} + + \def\redef{true} + + \DeclareOption{noiwkern}{\directlua{spacekern_no_iw_kern()}} + \DeclareOption{noredef}{\def\redef{false}} + \ProcessOptions + + \def\semicolon{\nobreak\hspace{0em};} + \def\tmp{true} + \ifx\tmp\redef + \def\,{;;;} + \fi +\else + \errhelp{Compile with LuaLaTeX to be able to use the "spacekern" package.} + \errmessage{Package "spacekern" error: This package requires LuaLaTeX!} +\fi \ No newline at end of file -- cgit v1.2.3