# aligning glosses on the baseline

I got code for glossing leaves in linguistic trees. Unfortunately the glossings seem to be not aligned to a common baseline. This is hardly visible when the glosses are in Latin but with Chinese characters they are really jumping.

In the German glossing, Ann seems to be lower than the other glosses. Is there a way to fix this?

\documentclass{article}

\usepackage{xeCJK}
\setCJKmainfont{SimSun}

\usepackage[linguistics]{forest}

% specification for all trees, "default preamble" appends to existing specification.
% The version with apostrophe replaces it.
\forestset{default preamble'={
for tree={align=center,parent anchor=south, child anchor=north,anchor=north,base=bottom},
% This would align trees to the baseline. We do not want this for TAG
% where several trees have to be aligned with respect to their center.
%    before drawing tree={
%      sort by=y,
%      for min={tree}{baseline}
%    }
}}

\forestset{
declare dimen={child anchor yshift}{0pt},
if n children>=2{
before packing={
tempdima/.max={max_y}{children},
for children={
child anchor yshift=tempdima()-max_y()
},
}
}{}
},
default preamble={
for tree={
edge path'={(!u.parent anchor)--([yshift=\forestoption{child anchor yshift}].child anchor)},
}
},
}

% The following code fixes the size of triangles for examples with translations. The specification
% ",delay=with translation" at the leaves is important to make this work.
% http://tex.stackexchange.com/questions/167978/smaller-roofs-for-forest/205311#205311
\forestset{
with translation/.style={
l sep=0,inner xsep=0,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={
if={strequal("#1","")}{}{
append={[#1,no edge,inner xsep=0,inner ysep=0,outer ysep=0,
l=\baselineskip + 0.2ex,
]}
}
}
}

\def\gettext#1{\gettextA#1;;\endget}
\def\gettextA#1;#2;{\removesep#1;}
\def\gettranslation#1{\gettranslationA#1;;\endget}
\def\gettranslationA#1;#2;{\removesep#2;}
\def\removesep#1;#2\endget{#1}

% a specific style that specifies the word tier: all nodes that do not have any children
% to do: make this style default and change all other figures explicitely as is described here:
% http://tex.stackexchange.com/questions/167983/getting-rid-of-a-default-where-specification
\forestset{
sm edges/.style={for tree={parent anchor=south, child anchor=north,base=top}, % changed base=bottom
% to top since we have NP and AVM nodes and the NP has to start
% right away at the same hight as the AVM St. Mü. 18.10.2017
where n children=0{tier=word,delay=with translation}{} %,delay=with translation
},
}

\robustify\textsc
\robustify\textit

\begin{document}

\begin{forest}
sm edges
[CP
[C$'$
[C$^0$[that; \textsc{comp}]]
[IP
[NP[Ann; Ann,roof]]
[I$'$
[I$^0$[will; \textsc{aux}]]
[VP
[V$'$
[V$^0$[read; 读]]
[NP[the newspaper; \textsc{det} 报纸, roof]]]]]]]]
\end{forest}

\begin{forest}
sm edges
[CP
[C$'$
[C$^0$[that; dass]]
[IP
[NP[Ann; Ann,roof]]
[I$'$
[I$^0$[will; wird]]
[VP
[V$'$
[V$^0$[read; lesen]]
[NP[the newspaper; die Zeitung, roof]]]]]]]]
\end{forest}

\end{document}


Edit: The solution works well for most of my trees but it does not work when the words to be glossed are not at the baseline. I did experiment with having a different gloss style for my TAG trees, but then the problem reappears:

AUX and John and tell and Sam are not aligned.

This happens because not all nodes in the gloss have the same height. One way to solve the problem is by tier-alignment, simply add tier=gloss into the definition of append translation, like this:

\forestset{
append translation/.style={
if={strequal("#1","")}{}{
append={[#1,no edge,inner xsep=0,inner ysep=0,outer ysep=0,
tier=gloss,
l=\baselineskip + 0.2ex,
]}
}
}
}


Another solution, in the hope that it works for the problem in the edit.

The image below highlights the original problem by drawing the node edges. The inner ysep of the glossed material is set so that the words are nicely separated from the lines above. However, as tikz's has no separate options for the top and bottom margin, this creates a problem below. The depth plus inner ysep of the glossed material are large enough that l=\baselineskip + 0.2ex of the gloss has no effect whatsoever, at least in the OP's example.

A way to solve this problem is to set all inner ysep's to 0 and simulate it by struts. Below, I define two commands, \glossedstrut and \glossstrut, which control the height and depth of the words and their glosses. While these are acutally enough to control the vertical space between a word and its gloss, I also add a l sep to the word (this pushes the gloss a bit down), so that the edges of the nodes are sensible.

Here are the styles that achieve the desired alignment:

\def\glossedstrut{\rule[-0.8ex]{0pt}{3.5ex}}
\let\glossstrut\strut
\forestset{
with translation/.style={
l sep=0,inner xsep=0,
+content format={\noexpand\glossedstrut}, inner ysep=0, l sep=0.1ex,
append translation/.expanded/.wrap pgfmath arg={\gettranslation{##1}}{content},
content/.expanded/.wrap pgfmath arg={\gettext{##1}}{content},
},
append translation/.style={
if={strequal("#1","")}{}{
append={[#1,no edge,inner xsep=0,inner ysep=0,outer ysep=0,
l=0, +content format={\noexpand\glossstrut},
]}
}
}
}

• This does not work for the general case. See edit. – Stefan Müller Apr 15 '18 at 6:21