在我最近关于语调,我鼓起勇气提出一个相关的问题。在前一个问题中,特定的音高水平被连接起来以产生语调轮廓,但对于声调语言(单词中的每个音节通常都有一个与之相关的特定音高),需要一种不同的方法,其中音高水平由小水平线表示。我已经有几种方法可以解决这个问题,现在我根据 Matthew Leingang 对先前问题的方法创建了一个新的 TikZ 方法,但我相信可以改进。下面的 MWE 列出了这些选项,使用了非洲班图语言 kiKongo 的示例。
%!TEX TS-program = xelatex
%!TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{fontspec}
\defaultfontfeatures{Mapping=tex-text, Scale=MatchLowercase}
\setmainfont{Charis SIL}
\usepackage{tikz}
\usetikzlibrary{backgrounds}
\newcommand{\tikzpitch}[1]{\tikz[overlay, remember picture, baseline] \coordinate (#1);}%
\tikzstyle{pitchlevel}=[x=1mm, y=1mm, yshift=-7mm, semithick]
% Charis SIL pitchlevel glyphs
\newcommand \pitch[1]{\char"F1F#1} % use \pitch1..9 to generate the 9 pitch-level marks fromthe glyphs F1F{1..9}
% John Frampton's pitchlevels code
\usepackage{pstricks}
\newdimen\dimpla
\newdimen\dimplb
\newdimen\dimplc
\def\1{\contourpitch{-2.5ex}{-2.5ex}}
\def\2{\contourpitch{-2.1ex}{-2.1ex}}
\def\3{\contourpitch{-1.7ex}{-1.7ex}}
\def\4{\contourpitch{-1.3ex}{-1.3ex}}
\def\5{\contourpitch{-.9ex}{-.9ex}}
\def\6{\contourpitch{-.5ex}{-.5ex}}
% level pitches
\def\contourpitch #1#2#3{\setbox0=\hbox{#3}\dimpla=.5\wd0 \dimplb=.5\wd0
\advance\dimpla by -.25em
\advance\dimplb by .25em
\dimplc=#1
\ifdim#2<#1 \dimplc=#2 \fi
\dimplc=-\dimplc
\advance\dimplc by 1ex
\psline(\dimpla,#1)(\dimplb,#2)
\vrule width0pt depth\the\dimplc #3}
% glides
\def\pitchup{\contourpitch{-2.5ex}{-1.7ex}}
\def\pitchdown{\contourpitch{-1.7ex}{-2.5ex}}
\def\steepup{\contourpitch{-2.5ex}{-.5ex}}
% format fbox
\setlength\fboxsep{1pt}
\begin{document}
% generate glides in Charis SIL
\fontspec[Renderer=Graphite]{Charis SIL}
\section{Pitchlevel marking using xelatex}
In Africanist linguistics, pitchlevel marks are often used so that the pitches can be discussed without drawing premature conclusions as to how these pitches should be represented in the eventual tone-marking.
\subsection{Word-side (inline) marking}
The example of \textbf{ibuuna [~\pitch1\, \pitch9\pitch9\, \pitch1~]} (\textit{so}) can be used to show inline marking of individual words. This solution uses the pitchlevel glyphs in Charis SIL. Glide variants are possible:
[~\pitch1\, \pitch9\, \pitch1\pitch5~]
[~\pitch1\, \pitch9\, \pitch1\pitch1\pitch5~]
[~\pitch1\, \pitch9\, \pitch1\pitch1\pitch5\pitch5~]
[~\pitch1\, \pitch9\, \pitch1\pitch5\pitch5~]
\bigskip
\noindent An alternative solution to the same issue of showing \noindent \textbf{ibuuna} [ \tikz\draw[x=1mm, y=1mm, semithick](0,0)--(1.5,0) (2.5,2)--(5,2) (6,0)--(7.5,0); ] uses TikZ. Glide variants are also possible here:
[ \tikz\draw[x=1mm, y=1mm, semithick](0,0)--(1.5,0) (2.5,2)--(5,2) (6,0)--(7.5,1); ]
[ \tikz\draw[x=1mm, y=1mm, semithick](0,0)--(1.5,0) (2.5,2)--(5,2) (6,0)--(7.5,0)--(8.5,1); ]
[ \tikz\draw[x=1mm, y=1mm, semithick](0,0)--(1.5,0) (2.5,2)--(5,2) (6,0)--(7.5,0)--(8.5,1)--(10,1); ]
[ \tikz\draw[x=1mm, y=1mm, semithick](0,0)--(1.5,0) (2.5,2)--(5,2) (6,0)--(7.5,1)--(9,1); ]
\subsection{Parallel marking}
\subsubsection{Using Charis font features}
\noindent ibuuna · basiidi kilumbu · ki-bakweenda kuna-kiziitu \\
\pitch1~~\pitch9\pitch9~~\pitch1~~~\pitch1~~\pitch9~~\pitch7~~\pitch5~\pitch3~~~~~\pitch1\pitch5 ~~~~\pitch1~~~\pitch1~~~~\pitch9\pitch9~~~\pitch8~~~\pitch4~~\pitch1~~~\pitch5~\pitch5~\fbox{\pitch1\pitch5} \\
\textit{so · they set aside a day · on which they would go to the in-laws \dots}
\subsubsection{Using pstricks}
\noindent\1ib\5u\5un\1a · b\1as\5i\5id\4i k\3il\2umb\pitchup u · k\1i-b\1akw\5e\5end\4a k\3un\1a-k\3iz\3i\3it\fbox{\pitchup u}\\
\textit{so · they set aside a day · on which they would go to the in-laws \dots}
\subsubsection{Using TikZ}
\noindent\begin{tikzpicture}[remember picture]
\node{\tikzpitch{1}ib\tikzpitch{2}u\tikzpitch{3}un\tikzpitch{4}a · b\tikzpitch{5}as\tikzpitch{6}iid\tikzpitch{7}i k\tikzpitch{8}il\tikzpitch{9}umb\tikzpitch{10}u · k\tikzpitch{11}i-b\tikzpitch{12}akw\tikzpitch{13}eend\tikzpitch{14}a k\tikzpitch{15}un\tikzpitch{16}a-k\tikzpitch{17}iz\tikzpitch{18}iit\tikzpitch{19}u}; \\
\draw[pitchlevel] (1 |- 0,0)--+(2,0) (2 |- 0, 4.5)--+(2,0) (3 |- 0, 4.5)--+(2,0) (4 |- 0, 0)--+(2,0) (5 |- 0,0)--+(2,0) (6 |- 0, 4.5)--+(2,0) (7 |- 0, 4)--+(2,0) (8 |- 0, 3)--+(2,0) (9 |- 0,1.5)--+(2,0) (10 |- 0, 0)--+(1,0.5)--+(2,1.5) (11 |- 0,0)--+(2,0) (12 |- 0, 0)--+(2,0) (13 |- 0, 4.5)--+(3,0) (14 |- 0, 3.5)--+(2,0) (15 |- 0,3)--+(2,0) (16 |- 0, 1)--+(2,0) (17 |- 0, 3)--+(2,0) (18 |- 0, 3)--+(2,0) (19 |- 0,0)--+(1,0.5)--+(2,1.5);
\end{tikzpicture}\\
\mbox{\textit{so · they set aside a day · on which they would go to the in-laws \dots}}
\end{document}
内联标记(1.1)很简单。关于并行标记(1.2)的三个版本:
tipa
1.2.1:Charis SIL 只能与 XeTeX 一起使用。(对于 LaTeX,可以使用包和一些附加代码的替代方法- 请参阅这个问题。)这似乎是目前唯一包含这些字形的字体(在其私人使用区),但实际上这不太可能成为问题。主要问题是,就像在语调问题中一样,需要使用反复试验来将字形隔开以匹配单词。一个好处是可以使用它\fbox
来突出显示特定的音调。
1.2.2:该pstricks
代码由 的作者 John Frampton 友情提供expex
。主要优点是它将音高级别嵌入文本中,使示例更容易写出。\fbox
可用于突出显示音高(尽管它也会标记字母,这在视觉上不太美观)。音高级别线也比其他两个选项“更清晰”。与此相反,它的编译速度较慢,并且当前代码不允许在单词侧(内联)进行音高标记。(它似乎也不适用于 LaTeX,但也许这只是我的看法。)
1.2.3:这是我通过骚扰 Matthew Leingang 的语调问题解决方案整理出来的(在 mwibrow 更全面的代码上,我甚至不知道从哪里开始!)。我所做的就是获取坐标,然后从该坐标向右 2 毫米处画一条线。(理想情况下,我会在坐标的每一侧画 1 毫米,但该怎么做呢?)这实际上效果很好 - 特别是,可以更详细地指定滑行。但是,就目前而言,由于 ,它需要两次编译remember picture
,而且我无法突出显示音高。此外,出于某种原因,kiKongo 文本似乎略有缩进。
所以所有这些都有效,但我对任何改进建议都很感兴趣,特别是整理 TikZ 解决方案,因为它适用于 LaTeX 和 XeTeX,并且与字体无关。
答案1
编辑添加一些修复和内联使用的示例(可能应该与宏绑定)。
通过对语调问题的代码进行一些额外的添加(我在这里提供了整个代码,因为它包含许多修复),可以添加标记。不确定字体是否独立,可能不是目前的情况。毫无疑问,如果不进行额外的工作,对于从右到左的语言来说,这将是垃圾。
基本思想是将符号与标记关联起来,然后在字符排版后解析这些标记。主要目的是能够将标记符号对齐在文本上方,这看起来比将标记放在文本中更清晰一些。
\contour[contour marks={0.55.0..0.55.?..3.2..+..0..0..5|..!..3.2..3.33.+}]
{ibuuna basiidi kilumbu ki-bakweenda kuna-kiziitu};
下面显示的例子在语言上并不正确,但只是说明了它能做什么。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\newdimen\contourraise
\newdimen\contourspacetokenwidth
\newdimen\contourtokenkern
\newcount\lasttokennumber
\newcount\currenttokennumber
\newcount\contourmarkcount
\newcount\contourtokenunderlinestate
\newbox\contourbox
\makeatletter
\tikzset{
tight fit/.style={
inner sep=0pt,
outer sep=0pt,
},
%
%
% How far above the reference anchor of the text,
contour raise/.code=\pgfmathsetlength\contourraise{#1},
contour reference anchor/.store in=\contourreferenceanchor,
contour reference anchor=base east,
% The `scale' for the values in the contour height specification
contour scale/.store in=\contourscale,
contour scale=3pt,
% The prefix for the contour marks.
contour mark prefix/.store in=\contourmarkprefix,
contour mark prefix=contour,
% The style for the contour path
contour/.style={
draw,
rounded corners=1ex,
},
% The style for the token nodes
every contour token/.style={
anchor=base west,
tight fit,
},
contour underline/.style={
draw
},
% The character to insert a mark (use with care)
contour mark character/.store in=\contourmarkchar,
contour mark character=|,
% Want to change the code for contour marks? Use this key.
contour mark code/.store in=\contourmarkcode,
% Want to change the code for tokens? Use this key.
contour token code/.store in=\contourtokencode,
% Want to change the code for drawing the contour? Use this key.
contour code/.store in=\contourcode,
%
% Default stuff
contour mark code={%
\coordinate (\contourmarkprefix-\the\contourmarkcount)
at ([yshift=\contourraise, y=\contourscale,
shift={(0,\currentcontourheight)}]token-\the\currenttokennumber.\contourreferenceanchor);
},
contour token code={%
\node [every contour token/.try] at
([xshift=\contourtokenkern]token-\the\lasttokennumber.base east)
(token-\the\currenttokennumber) {\token};
},
contour code={
\draw [contour] (\contourmarkprefix-1)
\foreach \y in {2,...,\the\contourmarkcount}{ --
(\contourmarkprefix-\y) };
},
contour marks/.style={
contour mark list={#1},
contour code={
\draw [y=\contourscale, contour] \contourpath;
},
contour mark code={%
\coordinate (@a) at ([yshift=\contourraise]token-\the\currenttokennumber.base west);
\coordinate (@b) at ([yshift=\contourraise]token-\the\currenttokennumber.base east);
\node [tight fit, fit={(@a) (@b)}] (\contourmarkprefix-\the\contourmarkcount) {};
},
},
% Don't draw the contour.
tokens only/.style={
contour code={}
},
%
% Only draw the contour (but the space is still used for the tokens)
contour only/.style={
every contour token/.append style={
execute at begin node={\setbox\contourbox=\hbox\bgroup},
execute at end node=\egroup\phantom{\box\contourbox}%
},
underline/.style={
draw=none
}
},
%
% Make tokens follow the contour marks.
tokens follow contour/.style={
tokens only,
contour token code={%
\node [every contour token/.try, y=\contourscale] at
([xshift=\contourtokenkern]token-\the\lasttokennumber.base east |-
0,\currentcontourheight)
(token-\the\currenttokennumber) {\token};
},
},
% What style to use when drawing underline
underline/.style={
draw
},
% The underline is drawn along the south side of a node which
% takes this style.
underline token/.style={
inner ysep=1pt
},
% When grouping tokens (e.g., for putting box around)
% this style is applied to a node that is fitted around the group
token group/.style={
inner xsep=1pt,
inner ysep=2pt,
rounded corners=2pt
},
% Draw boxes around tokens groups.
box tokens/.style={
token group/.append style={
draw
}
},
% Change the width of the spaces.
space token width/.code=\pgfmathsetlength\contourspacetokenwidth{#1},
space token width=0.125cm,
contour mark list/.store in=\@contourmarklist%
}
\def\at@{@}
\let\@contourmarklist=\@empty
\def\contour{%
\pgfutil@ifnextchar[{\contour@opts}{\contour@opts[]}}
\def\contour@opts[#1]{%
\pgfutil@ifnextchar x{\contour@@opts[#1]}{\contour@@opts[#1]}}
\def\contour@@opts[#1]#2;{%
\begin{scope}[#1]
\coordinate (token-0);
\currenttokennumber=0\relax%
\lasttokennumber=0\relax%
\contourmarkcount=0\relax%
\def\lastcontourheight{0}%
\contourtokenunderlinestate=0\relax%
\let\lastcontourtoken=\relax%
\contourtokenkern=0pt\relax%
\def\contourpath{}%
\@contour#2@%
}
% Must check for a spaces
\def\@contour{\futurelet\@token\@checkforspace}
\def\@uscore{_}
\def\@checkforspace{%
\ifx\@token\pgfutil@sptoken%
\let\@next=\@replacespace%
\else%
\if\@token\contourmarkchar%
\let\@next=\@contour@insertmark
\else%
\if\@token\@uscore
\let\@next=\@contourtoggleunderline%
\else%
\let\@next=\@@contour%
\fi%
\fi%
\fi%
\@next%
}
\def\@contourtoggleunderline#1{%
\advance\contourtokenunderlinestate by1\relax
\ifnum\contourtokenunderlinestate>3\relax%
\contourtokenunderlinestate=0\relax%
\fi%
\@contour%
}
\def\@contour@insertmark{%
\afterassignment\@@contour@insertmark\let\@token=%
}
\def\@@contour@insertmark{%
\futurelet\@token\@@@contour@insertmark}%
\def\@@@contour@insertmark{%
\if\@token[%
\let\@next=\@@@@contour@insertmark%
\else%
\let\currentcontourheight=\lastcontourheight%
\let\@next=\@@@@@contour@insertmark%
\fi%
\@next%
}
\def\@@@@contour@insertmark[#1]{%
\def\@tmp{#1}%
\ifx\@tmp\@empty%
\let\currentcontourheight=\lastcontourheight%
\else%
\def\currentcontourheight{#1}%
\fi%
\@@@@@contour@insertmark}
\def\@@@@@contour@insertmark{%
\advance\contourmarkcount by1\relax%
% Code for inserting mark
\contourmarkcode%
\let\lastcontourheight=\currentcontourheight%
\@contour}
\def\contourspacetoken{{\hbox to \contourspacetokenwidth{\hfill}}}
\def\@replacespace#1{%
\@contour\contourspacetoken#1%
}
\def\@@countour@afterlatenode{%
\pgf@x=\pgfpositionnodelatermaxx\relax%
\advance\pgf@x by-\pgfpositionnodelaterminx\relax%
\global\edef\@contournodewidth{\the\pgf@x}%
}
\def\@@contour#1{%
\def\@token{#1}%
\if\@token\at@%
\@contourdounderline%
\pgfutil@ifundefined{pgf@sh@ns@tokengroup}{}{%
\node [tight fit, fit={(tokengroup)}, token group/.try] {};
\global\let\pgf@sh@ns@tokengroup=\relax%
}%
\let\@next=\@@@contour%
\else%
\lasttokennumber=\currenttokennumber%
\advance\currenttokennumber by1%
\contourtokenkern=0pt\relax%
\ifnum\currenttokennumber>1\relax%
%
% Take care of kerning.
%
% First get the width of the last and current token in the same hbox.
%
\let\pgfpositionnodelaterbox=\contourbox
\pgfpositionnodelater\@@countour@afterlatenode%
\def\token{\lastcontourtoken\@token}%
\begingroup%
\tikzset{every contour token/.append style={tight fit}}%
\contourtokencode%
\endgroup%
\let\@contourkerntmp=\@contournodewidth%
%
% Now subtract the width of last and current token in separate boxes.
%
\def\token{\hbox{\lastcontourtoken}\hbox{\@token}}%
\begingroup%
\tikzset{every contour token/.append style={tight fit}}%
\contourtokencode%
\endgroup%
\pgfmathsetlength\contourtokenkern{\@contourkerntmp-\@contournodewidth}%
\pgfpositionnodelater\relax%
\fi%
%
% OK, now actually typset the current token
%
\let\token=\@token%
\contourtokencode%
\let\lastcontourtoken=\token%
% Manage underline state
\@contourdounderline%
\def\@@token{\contourspacetoken}%
\ifx\@token\@@token%
\pgfutil@ifundefined{pgf@sh@ns@tokengroup}{}{%
\pgfutil@ifundefined{pgf@sh@ns@underline}{}{%
\node [tight fit, fit={(tokengroup) (underline)}]
(tokengroup)
{};}%
\node [tight fit, fit={(tokengroup)}, token group/.try] {};
\global\let\pgf@sh@ns@tokengroup=\relax%
}%
\else
\pgfutil@ifundefined{pgf@sh@ns@tokengroup}{%
\node [tight fit,
fit={(token-\the\currenttokennumber)}]
(tokengroup) {};
}{%
\node [tight fit,
fit={(token-\the\currenttokennumber)
(tokengroup)}]
(tokengroup){};
}%
\fi%
\let\@next=\@contour
%
\fi%
\@next%
}
\def\@contourdounderline{%
\ifcase\contourtokenunderlinestate%
\or
\node [tight fit, fit={(token-\the\currenttokennumber)}]
(underline) {};
\contourtokenunderlinestate=2\relax%
\or%
\node [tight fit,fit={(token-\the\currenttokennumber) (underline)}]
(underline) {};
\or%
\node [tight fit, fit={(underline)}, underline token/.try]
(underline) {};
\draw [underline/.try]
(underline.south west) -- (underline.south east);
\pgfutil@ifundefined{pgf@sh@ns@tokengroup}{}{%
\node [tight fit, fit={(tokengroup) (underline)}]
(tokengroup) {};%
\node [tight fit, fit={(tokengroup)}, token group/.try] {};
\global\let\pgf@sh@ns@tokengroup=\relax%
\global\let\pgf@sh@ns@underline=\relax%
}
\contourtokenunderlinestate=0\relax
\fi%
}
\def\@@@contour{%
\ifx\@contourmarklist\@empty%
\else%
\@contourdolist%
\fi%
\ifnum\contourmarkcount>1
% Code for drawing contour
\contourcode%
\fi%
\end{scope}%
\ignorespaces%
}
\def\@contourstackpop{%
\let\@contourstackitem=\@empty%
\ifx\@contourstack\@empty%
\else%
\expandafter\@@contourstackpop\@contourstack\@@contourstackpop%
\fi%
}
\def\@@contourstackpop#1#2\@@contourstackpop{%
\def\@contourstackitem{#1}%
\ifx\@contourstackitem\@empty%
\def\@contourstackitem{#2}%
\let\@contourstack=\@empty%
\else%
\def\@contourstack{#2}%
\fi%
}
\def\@contourdolist{%
\let\@contourstack=\@contourmarklist%
\let\@contourstacklastitem=\@empty%
\let\contourpath=\@empty%
\edef\contourtotaltokens{\the\currenttokennumber}%
\currenttokennumber=0\relax%
\contourmarkcount=0\relax%
\@@contourdolist%
}
\def\@@contourdolist{%
\@contourstackpop%
\advance\currenttokennumber by1\relax%
\ifx\@contourstackitem\@empty%
\let\@next=\relax%
\else%
\expandafter\ifx\csname contourcontourpathcommand@\@contourstackitem @\endcsname\relax%
\else%
\advance\contourmarkcount by1\relax%
\let\currentcontourheight=\@contourstackitem%
\contourmarkcode%
\def\contourmarkstart{\contourmarkprefix-\the\contourmarkcount.west}%
\def\contourmarkend{\contourmarkprefix-\the\contourmarkcount.east}%
\edef\contourpath{\contourpath \csname contourcontourpathcommand@\@contourstackitem @\endcsname}%
\fi%
\let\@next=\@@contourdolist%
\let\@contourstacklastitem=\@contourstackitem%
\fi
\@next%
}
% \contourcontourpathcommand{<symbol>}{<contour path command code>}
% \contourmarkstart and \contourmarkend are setup as the
% left and right points of the charactor at zero contour height.
\def\contourcontourpathcommand#1{\expandafter\def\csname contourcontourpathcommand@#1@\endcsname}
% \contourmark{<symbol>}{<mark start height>}{<mark end height>}
%
\def\contourmark#1#2#3{%
\contourcontourpathcommand{#1}{([shift={(0,#2)}]\contourmarkstart) -- ([shift={(0,#3)}]\contourmarkend)}
}
\makeatother
% Separator.
\contourcontourpathcommand{.}{}
\contourmark{0}{0}{0}
\contourmark{1}{1}{1}
\contourmark{2}{2}{2}
\contourmark{3}{3}{3}
\contourmark{4}{4}{4}
\contourmark{5}{5}{5}
\contourmark{+}{0}{1}
\contourcontourpathcommand{!}{
(\contourmarkstart) .. controls ++(0,2) and ++(0,2) .. (\contourmarkend)
}
\contourcontourpathcommand{?}{
(\contourmarkstart) .. controls ++(0,-1) and ++(0,-1) .. ([shift={(0,2)}]\contourmarkend)
}
\contourcontourpathcommand{|}{
% Continue previous path
-- ([shift={(0, 3)}]\contourmarkend)
}
\begin{document}
\begin{tabular}{c}
\begin{tikzpicture}
\contour[contour/.append style={rounded corners=0}, contour raise=-0.75cm,
contour marks={0.55.0..0.55.?..3.2..+..0..0..5|..!..3.2..3.33.+}]
{ibuuna basiidi kilumbu ki-bakweenda kuna-kiziitu};
\end{tikzpicture}
\\[0.5cm]
in line marking: ibuuna [\tikz[baseline={(0,0.25ex)}]%
\contour[contour only, contour scale=2ex/6,
contour marks={0.55.0}]
{ibuuna};]
\end{tabular}
\end{document}