\documentclass[ ukenglish,% twoside=false,% fontsize=10pt,% bibliography=totoc,% numbers=autoenddot,% headings=normalsize,% overfullrule,% headings=optiontotoc,% ] {scrartcl} \makeatletter \providecommand\@ix{9.6} \providecommand\@xi{10.4} \providecommand\@xiii{13.15} \def\subfootnotesize{% \@setfontsize% \subfootnotesize% {7.6}{8}% } \def\supernormalsize{% \@setfontsize% \supernormalsize% \@xi{12}% } \def\subnormalsize{% \@setfontsize% \subnormalsize% \@ix{11}% } \def\sublarge{% \@setfontsize% \sublarge% {11.2}{13}% } \def\superlarge{% \@setfontsize% \superlarge% \@xiii{16}% } \makeatother \newcommand*{\sectionas}{2.3ex plus .2ex} \newcommand*{\sectionbs}{-3.5ex plus -1ex minus -.2ex} \newcommand*{\sectiontbs}{3.6pt} \newcommand*{\subsectiontbs}{1.2pt} \newcommand*{\subsectionas}{1.5ex plus .2ex} \newcommand*{\subsectionbs}{-3.25ex plus -1ex minus -.2ex} \newcommand*{\subsubsectionas}{\subsectionas} \newcommand*{\subsubsectionbs}{\subsectionbs} \newcommand*{\paragraphas}{-1em} \newcommand*{\paragraphbs}{.8\baselineskip} \newlength{\tnwsection} \newlength{\tnwsubsection} \newlength{\tnwsubsubsection} \newlength{\tnwparagraph} \newlength{\tisection} \newlength{\tisubsection} \newlength{\tisubsubsection} \newlength{\tiparagraph} \setlength{\tnwsection}{1.2em} \addtolength{\tnwsection}{.6em} \setlength{\tnwsubsection}{\tnwsection} \addtolength{\tnwsubsection}{.75em} \setlength{\tnwsubsubsection}{\tnwsubsection} \addtolength{\tnwsubsubsection}{.75em} \setlength{\tnwparagraph}{\tnwsubsubsection} \addtolength{\tnwparagraph}{.75em} \setlength{\tisection}{0em} \setlength{\tisubsection}{\tisection} \addtolength{\tisubsection}{\tnwsection} \setlength{\tisubsubsection}{\tisubsection} \addtolength{\tisubsubsection}{\tnwsubsection} \setlength{\tiparagraph}{\tisubsubsection} \addtolength{\tiparagraph}{\tnwsubsubsection} \RedeclareSectionCommands[% tocraggedentrytext=true,% ]% {section,subsection,subsubsection,paragraph} \RedeclareSectionCommand[% tocindent=\tisection,% tocnumwidth=\tnwsection,% tocbeforeskip=\sectiontbs,% tocentryformat=\supernormalsize\sffamily\bfseries,% tocentrynumberformat=\supernormalsize\sffamily\bfseries,% tocpagenumberformat=\supernormalsize\sffamily\bfseries% ]% {section} \RedeclareSectionCommand[% tocindent=\tisubsection,% tocnumwidth=\tnwsubsection,% tocbeforeskip=\subsectiontbs,% tocentryformat=\subnormalsize,% tocentrynumberformat=\subnormalsize,% tocpagenumberformat=\subnormalsize% ]% {subsection} \RedeclareSectionCommand[% tocindent=\tisubsubsection,% tocnumwidth=\tnwsubsubsection,% tocbeforeskip=\sectiontbs% ]% {subsubsection} \RedeclareSectionCommand[% afterskip=\paragraphas,% beforeskip=\paragraphbs,% tocindent=\tiparagraph,% tocnumwidth=\tnwparagraph,% tocbeforeskip=\sectiontbs% ]% {paragraph} \linespread{1.1} \newcommand*{\hs}{\hspace{.45em}} \usepackage{fontspec} \directlua{ fonts.handlers.otf.addfeature { name = "onumkern", type = "kern", data = { ["v"] = { ["zero.taboldstyle"] = 80 }, ["two.taboldstyle"] = { ["zero.taboldstyle"] = 30, ["/"] = 50 }, ["five.taboldstyle"] = { ["/"] = 20 }, ["»"] = { ["I"] = 50 }, }, } } \setmainfont{Tangent}[ BoldFont = *-Medium, ItalicFont = *-Italic, Ligatures = {Common, TeX}, Numbers = OldStyle, RawFeature = +onumkern ] \setsansfont{SegoeUI}[ BoldFont = seguisb.ttf, Ligatures = {Discretionary, TeX}, Numbers = OldStyle ] \setmonofont{Consolas}[ ItalicFont = *-Italic, Numbers = OldStyle ] \newcommand*{\mono}[1]{% {\subnormalsize\texttt{#1}}% } \usepackage{babel} \usepackage[paper=a4paper,marginratio={2:1,3:4}]{geometry} \usepackage{spacekern} \usepackage{hyperref} \usepackage{bookmark} \usepackage{microtype} \hypersetup{% pdflang=en,% unicode=true,% pdfborder={0 0 0},% bookmarksopen=true,% bookmarksopenlevel=0,% bookmarksnumbered=true,% pdftitle={The showkerning package}, pdfsubject={Showing kerns in a document}, pdfauthor={Thomas Kelkel}, pdfkeywords={tex, latex, kerning} } \setlength{\parindent}{0pt} \setlength{\parskip}{.4\baselineskip} \newcommand*{\q}[1]{% ›% #1% ‹% } \newcommand*{\qq}[1]{% »% #1% «% } \newcommand*{\textnote}[1]{% {% \ttfamily% \char174{}% #1% \char174{}% }% } \usepackage{luacode} \begin{luacode} local FLOOR = math.floor local function round ( num, dec ) return FLOOR ( num * 10^dec + 0.5 ) / 10^dec end local p_array = {false, false, false, false, false} local p_counter = 0 local ID = node.id 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 T_ID = node.traverse_id local T_GLYPH = node.traverse_glyph local INS_B = node.insert_before local GLYPH = ID ( "glyph" ) local GLUE = ID ( "glue" ) local KERN = ID ( "kern" ) local HLIST = ID ( "hlist" ) local SWAPPED = table.swapped local SUBTYPES = node.subtypes local SPACESKIP = SWAPPED ( SUBTYPES ("glue") )["spaceskip"] local WIDTH = round ( tex.sp ( "1.6em" ), 0 ) local ipairs = ipairs local page_counter = 0 local INS_A = node.insert_after local p_counter_x = 0 local ATC = luatexbase.add_to_callback local function make_marks ( head, char, id, array, counter ) for n in T_GLYPH ( head ) do if n.char == char then counter = counter + 1 array[counter] = {false, false, false} head = INS_B ( head, n, NEW ( GLYPH ) ) PREV ( n ).data = id local NEXT = n.next local inside_counter = 0 while NEXT.char ~= char do inside_counter = inside_counter + 1 array[counter][inside_counter] = COPY ( NEXT ) NEXT = NEXT.next REM ( head, NEXT.prev ) end head = REM ( head, NEXT ) head = REM ( head, n ) end end return head, array, counter end local function mark_notes ( head ) head, p_array, p_counter = make_marks ( head, 174, 427956, p_array, p_counter ) return head end local function make_margin_notes ( head, id, array, counter ) for n in T_ID ( HLIST, head ) do local first_kern = 0 local first_width = 0 for glyph_node in T_GLYPH ( n.head ) do if glyph_node.data == id then counter = counter + 1 local tail_node = TAIL ( n.head ) local glue_node = NEW ( GLUE ) glue_node.subtype = SPACESKIP glue_node.width = WIDTH local NEXT local switch_counter = 1 -- page_counter n.head = INS_A ( n.head, TAIL ( n.head ), glue_node ) if ( switch_counter % 2 == 0 ) then NEXT = glue_node else NEXT = tail_node end local kern_value = 0 for _, value in ipairs ( array[counter] ) do if value ~= false then local NUMBER = COPY ( value ) n.head = INS_A ( n.head, NEXT, NUMBER) if NEXT.next then NEXT = NEXT.next end if NUMBER.width then kern_value = kern_value - NUMBER.width end end end local kern_node = NEW ( KERN ) kern_node.kern = kern_value - glue_node.width if switch_counter % 2 ~= 0 then kern_node.kern = kern_node.kern - tex.hsize + first_kern n.head = INS_A ( n.head, tail_node, kern_node ) end if ( switch_counter % 2 == 0 ) and ( first_kern < 0 ) then kern_node.kern = kern_node.kern - first_kern + first_width - kern_value n.head = INS_A ( n.head, tail_node, kern_node ) end first_kern = kern_node.kern first_width = kern_value end end end return head, counter end local function make_text_notes ( head ) page_counter = page_counter + 1 head, p_counter_x = make_margin_notes ( head, 427956, p_array, p_counter_x ) return head end ATC ( "ligaturing", mark_notes , "mark notes" ) ATC ( "pre_output_filter", make_text_notes , "count pages" ) \end{luacode} \flushbottom \pagestyle{empty} \usepackage{showkerning} \RedeclareSectionCommand[% afterskip=1.3ex plus .2ex,% beforeskip=-2.5ex plus -1ex minus -.2ex,% font=\superlarge% ]% {section} \begin{document} \directlua{ local function rem_kern ( head ) for n in node.traverse ( head ) do if n.id == node.id ( "hlist" ) or n.id == node.id ( "vlist" ) then n.head = rem_kern ( n.head ) elseif n.id == node.id ( "glyph" ) then if n.char == 112 then n.prev.data = "" end end end return head end luatexbase.add_to_callback ( "post_linebreak_filter", rem_kern, "remove kern", 1 ) } \title{The showk\kern-.1eme\kern.2emrn\kern-.05emin\kern.1emg package\vspace{.25\baselineskip}\\\superlarge{}\directlua{luatexbase.remove_from_callback ( "post_linebreak_filter", "show kerns in postline" ) luatexbase.remove_from_callback ( "hpack_filter", "show kerns in hpack" ) luatexbase.remove_from_callback ( "post_linebreak_filter", "remove kern" )}Showing kerns in a document}% \author{\sublarge{}Thomas Kelkel\vspace{-.25\baselineskip}\\\sublarge{}kelkel@emaileon.de\vspace{-.25\baselineskip}}% \date{\addfontfeature{LetterSpace=2}\sublarge{}2023/07/08\quad{}v0.3}% \maketitle \thispagestyle{empty} \section{Introduction} This package displays all kerning values in the form of colored bars directly at the respective position in the document. Positive values are displayed in green, negative values in red. The width of the bars corresponds exactly to the respective kerning value. The left edge of the bar is always at the position where the kerning node is placed. (This corresponds to the common representation method). Please note that Lua{\addfontfeature{LetterSpace = 2}\LaTeX} is required to use this package. \section{Basic usage} To load the package, simply add the following line to the preamble of the document: \begin{quote} \mono{\textbackslash{}usepackage\{showkerning\}} \end{quote} \section{Package options} \addcontentsline{toc}{subsection}{ontop} \textnote{ontop}By default, the bars are placed behind the glyphs. With this option they are in front of them. It can be loaded in the following way: \begin{quote} \mono{\textbackslash{}usepackage[ontop]\{showkerning\}} \end{quote} \section{License} This package is copyright © 2022\kern.1em–\kern.1em2023 Thomas Kelkel. It 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. This work has the LPPL maintenance status \qq{author maintained}. \end{document}