I am writing a package that requires extracting dimensions of certain glyphs. The package would support both xelatex & lualatex. In my testing, xelatex always returns accurate glyph dimensions with its \XeTeXglyphbounds interface. Lualatex solution provided here does not return accurate glyph dimensions for .ttf files, but does for .otf files. Here's the two files you will need to see for yourself:
sidebearings.lua (with some additions on top of code here):
--- sidebearings.lua
packagedata = packagedata or { }
packagedata.sidebearings = { }
local sidebearings = packagedata.sidebearings
local utfbyte = utf.byte
local texsprint = tex.sprint
local get_sidebearings = function (id, char)
local tfmdata = font.getfont (id)
if not (tfmdata and tfmdata.shared) then
return 0, 0
end
local descriptions = tfmdata.shared.rawdata.descriptions
local glyphdata = descriptions [char]
if not glyphdata then
--- font lacks the glyph
return 0, 0, 0, 0
end
local boundingbox = glyphdata.boundingbox
local lside = boundingbox [1] or 0
local wd = boundingbox [3] or glyphdata.width
local rside = glyphdata.width - wd
local tside = glyphdata.height or 0
local bside = glyphdata.depth or 0
--- If you would like to print the values to terminal
inspect (glyphdata)
return lside / 100, rside / 100, tside / 100, bside / 100
end
local sidebearings = function (id, char, side)
char = utfbyte (char)
local lside, rside, tside, bside = get_sidebearings (id, char)
if side == "left" then
texsprint (tostring (lside), "pt")
elseif side == "right" then
texsprint (tostring (rside), "pt")
elseif side == "top" then
texsprint (tostring (tside), "pt")
elseif side == "bottom" then
texsprint (tostring (bside), "pt")
end
end
packagedata.sidebearings.left = function (char)
return sidebearings (font.current (), char, "left")
end
packagedata.sidebearings.right = function (char)
return sidebearings (font.current (), char, "right")
end
packagedata.sidebearings.top = function (char)
return sidebearings (font.current (), char, "top")
end
packagedata.sidebearings.bottom = function (char)
return sidebearings (font.current (), char, "bottom")
end
and main file sidebearings.tex:
\documentclass[notitlepage,letterpaper]{article}
\usepackage[letterpaper,left=0in,right=0in,top=0in,bottom=0in]{geometry}
\usepackage{fontspec}
\usepackage{microtype}
\ifdefined \directlua
\directlua {require "sidebearings"}
\def \lsidebearing #1{%
\directlua {packagedata.sidebearings.left [[#1]]}%
}
\def \rsidebearing #1{%
\directlua {packagedata.sidebearings.right [[#1]]}%
}
\def \tsidebearing #1{%
\directlua {packagedata.sidebearings.top [[#1]]}%
}
\def \bsidebearing #1{%
\directlua {packagedata.sidebearings.bottom [[#1]]}%
}
\else
\def \lsidebearing #1{%
\ifnum\the\XeTeXcharglyph\expandafter`#1=0
0pt%
\else%
%\number \XeTeXglyphbounds1 \the \XeTeXcharglyph`#1 sp% %for output in unit sp
\the \XeTeXglyphbounds1 \the \XeTeXcharglyph\expandafter`#1%
\fi%
}
\def \rsidebearing #1{%
\ifnum\the\XeTeXcharglyph\expandafter`#1=0
0pt%
\else%
\the \XeTeXglyphbounds3 \the \XeTeXcharglyph\expandafter`#1%
\fi%
}
\def \tsidebearing #1{%
\ifnum\the\XeTeXcharglyph\expandafter`#1=0
0pt%
\else%
\the \XeTeXglyphbounds2 \the \XeTeXcharglyph\expandafter`#1%
\fi%
}
\def \bsidebearing #1{%
\ifnum\the\XeTeXcharglyph\expandafter`#1=0
0pt%
\else%
\the \XeTeXglyphbounds4 \the \XeTeXcharglyph\expandafter`#1%
\fi%
}
\fi
\setmainfont{Verdana}% switch to Aleo-Regular when testing Aleo
\def \test #1{[#1] left: \lsidebearing {#1}, right: \rsidebearing {#1}, bottom: \bsidebearing {#1}, top: \tsidebearing {#1}\par}
\begin{document}
\thispagestyle{plain}
\test a
\test b
\test y
\test z
\test а
\test б
\test ю
\test я
\fontname\font
\end{document}
I ran this code with both >> xelatex sidebearings.tex
, and >> lualatex sidebearings.tex
for multiple .otf, and .ttf fonts. As can be seen from the screenshots below, xelatex & lualatex return same values for .otf font Aleo available for free here, and different values for .ttf font Verdana (generally comes free as system font). In both cases xelatex is accurate, lualatex is inaccurate for .ttf files. As I observe the glyph dimensions in case of .ttf files are always 2.05ish times the correct values, though am not sure this will hold true for all fonts. Is the sidebearings.lua file missing an if statement that makes sure to divide dimensions by some factor for .ttf fonts?
a) Aleo regular (.otf file, both lualatex & xelatex are accurate):
b) Verdana regular (.ttf file, xelatex is accurate, lualatex is inaccurate):