This is a matter of "side bearings", see for example "3. Bearings and Advances".
The easiest way is the trial-and-error approach. Add a negative space before the left bracket until you are satisfied.
An exact solution is quite complicate, because
- the glyph bounding boxes are not available in vanilla TeX or pdfTeX and
- it is not easy to figure out the correct font, size and glyph that is actually
used in the output.
An analysis specific for this case
The uppercase "T" uses the font "cmr12.pfb" (pdfTeX) or "lmroman12-regular.otf" (luaLaTeX). Happily, both fonts use the same side bearing for "T".
I got the font name from the end of the .log
file written by the LaTeX run.
The Python/FontForge script extracts the left side bearing from the font and glyph "T": 0.035em
The negative space command for compensating the left side bearing is then:
\kern-0.035em
It gets trickier, if the font is scaled in LaTeX and or internal math glyph constructions are involved. The left bracket is here composed from three parts: the upper, middle and lower part.
The TeX command \showlists
helps in identifying the font and the used glyph. For the lower part of the opening bracket:
...\hbox(0.39998+17.60019)x6.66669
....\OMX/cmex/m/n/6 4
At the position of the "character 4" (0x34) I found the glyph bracketleftbt
.
The Python/FontForge script reports 0.326em for the left side bearing. Now, the correct font needs to be set to get the correct value of unit "em":
\begingroup
\csname OMX/cmex/m/n/6\endcsname
\kern-0.326em\relax
\endgroup
Using the TeX width 6.66669pt of the surrounding \hbox
can be used to calculate the side bearing in unit pt, see the Python/FontForge script:
\kern-3.263274684684685pt\relax
I have changed the minimal TeX example to add a thin \fbox
with a line width of 0.1pt and separation/margin of the same space to visualize that the "T" and the left bracket start at the same horizontal position.

The LaTeX file:
\documentclass[12pt,a4paper,twoside,openright]{report}
% \showboxdepth=\maxdimen
% \showboxbreadth=\maxdimen
% \tracingonline=1
\begin{document}
\setlength{\fboxsep}{0.1pt}
\setlength{\fboxrule}{0.1pt}
\fbox{%
\begin{tabular}{@{}l@{}}
\kern-0.035em Text left aligned.\\[0.5ex]
% \begingroup
% \csname OMX/cmex/m/n/6\endcsname
% \kern-0.326em\relax
% \endgroup
\kern-3.263274684684685pt\relax
$\left[%
\begin{tabular}{l}%
/X-ion/\\
N\\
ACT of Z-ing
\end{tabular}%
\right]$
\end{tabular}%
}
% \showlists
\end{document}
The Python/FontForge script that extracts the left side bearing values:
#!/usr/bin/env fontforge
import subprocess
from typing import Union
import fontforge # (Python 3.8)
FONT_FOR_UPPERCASE_T_1 = 'cmr12.pfb'
FONT_FOR_UPPERCASE_T_2 = 'lmroman12-regular.otf'
FONT_FOR_LEFT_BRACKET = 'cmex10.pfb'
def find_font(name: str) -> str:
process = subprocess.run(
['kpsewhich', name],
check=True,
stdout=subprocess.PIPE,
)
# Error checking omitted
return process.stdout.decode().strip()
def get_left_side_bearing(font_name: str, glyph: Union[str, int])-> float:
"""
Return the left side bearing of the specified glyph in the
font, given by font_name. The unit is em.
"""
font_path = find_font(font_name)
font = fontforge.open(font_path)
try:
left_side_bearing, _, _, _ = font[glyph].boundingBox()
return left_side_bearing / font.em
finally:
font.close()
def get_advance_width(font_name: str, glyph: Union[str, int])-> float:
"""
Return the advance width of the specified glyph in the
font, given by font_name. The unit is em.
"""
font_path = find_font(font_name)
font = fontforge.open(font_path)
try:
return font[glyph].width / font.em
finally:
font.close()
def main() -> None:
# Side bearing for uppercase T
# ----------------------------
left_side_bearing_for_uppercase_t = get_left_side_bearing(
FONT_FOR_UPPERCASE_T_1,
'T',
)
print(
f'=> Left side bearing of "T": {left_side_bearing_for_uppercase_t}em'
f' ({FONT_FOR_UPPERCASE_T_1})'
)
left_side_bearing_for_uppercase_t = get_left_side_bearing(
FONT_FOR_UPPERCASE_T_2,
'T',
)
print(
f'=> Left side bearing of "T": {left_side_bearing_for_uppercase_t}em'
f' ({FONT_FOR_UPPERCASE_T_2})'
)
# Side bearing for left bracket
# -----------------------------
glyph = 'bracketleftbt'
left_side_bearing_for_left_bracket = get_left_side_bearing(
FONT_FOR_LEFT_BRACKET,
glyph,
)
print(
f'=> Left side bearing of "[": {left_side_bearing_for_left_bracket}em'
)
# ...\hbox(0.39998+17.60019)x6.66669
# ....\OMX/cmex/m/n/6 4
tex_advance_width = 6.66669 # pt
print(f'=> TeX advance width: {tex_advance_width}pt')
advance_width = get_advance_width(FONT_FOR_LEFT_BRACKET, glyph)
print(f'=> Advance width: {advance_width}em')
left_side_bearing_pt = (
tex_advance_width / advance_width * left_side_bearing_for_left_bracket
)
print(f'=> Left side bearing: {left_side_bearing_pt}pt')
if __name__ == '__main__':
main()
Run the script with FontForge:
=> Left side bearing of "T": 0.035em (cmr12.pfb)
=> Left side bearing of "T": 0.035em (lmroman12-regular.otf)
=> Left side bearing of "[": 0.326em
=> TeX advance width: 6.66669pt
=> Advance width: 0.666em
=> Left side bearing: 3.263274684684685pt
LuaTeX
LuaTeX can access font glyph bounding boxes, see
key "bounding box" in "12.6.2 glyphs" of the LuaTeX manual.
Thus, there might be an easier way via some Lua code, e.g. for the uppercase "T" here.
Math mode is much trickier (\left
-\right
constructs, roots, \mathchoice
, ...). Maybe, the math symbols in question can be marked by LuaTeX attributes. After typesetting math in a \hbox
, page, ... the node list can be inspected afterwards to identify the marked glyphs to calculate the side bearings. The shifts can then be applied directly in the node list or in the next LaTeX run.
But this approach is just a sketch and needs further investigating and much time for implementing.