Я пытаюсь создать документ для сравнения набора шрифтов. Я хотел бы разобрать массив, чтобы загрузить и попробовать их все.
Вот что я сделал:
\documentclass{article}
\usepackage{lipsum}
\usepackage{pgffor}
\usepackage{fontspec}
\def\LoadFont#1{\expandafter\newfontface\csname#1\endcsname{#1}}
\def\UseFont#1{\csname#1\endcsname}
\def\FontList{Charter,Lato,Linux Libertine O}
% these work just fine
%\LoadFont{Charter}
%\LoadFont{Lato}
%\LoadFont{Linux Libertine O}
% THIS DOES NOT WORK
\foreach \FontName in \FontList {\LoadFont\FontName}
\begin{document}
\foreach \FontName in \FontList {\UseFont\FontName\lipsum[1]}
\end{document}
Цикл с \UseFont
работает нормально, а вот с — \LoadFont
нет. Сам по себе \LoadFont
делает то, что и ожидается.
Думаю, это может быть проблема расширения, но я не уверен, в чем именно она заключается; слепые попытки ни к чему не привели.
Что не так с циклом загрузки?
решение1
Как уже объяснялось, наблюдаемое вами поведение обусловлено устоявшейся особенностью \foreach
выполнения итераций внутри групп, ограничивающих область действия.
Вот с \xintFor
. Я переключился на другой шрифт, так как у меня не установлен Lato.
\documentclass{article}
\usepackage{lipsum}
\usepackage{xinttools}
\usepackage{fontspec}
\def\LoadFont#1{\expandafter\newfontface\csname#1\endcsname{#1}}
\def\UseFont#1{\csname#1\endcsname}
% original
% \def\FontList{Charter,Lato,Linux Libertine O}
% as I don't have Lato:
\def\FontList {Charter, TeX Gyre Heros, Linux Libertine O}
\xintFor #1 in \FontList \do {\LoadFont {#1}}
\begin{document}
\xintFor #1 in \FontList \do {\UseFont {#1}\lipsum[1]}
\end{document}
% Local Variables:
% TeX-engine: xetex
% End:
решение2
Когда ты это сделаешь
\foreach \FontName in \FontList {\LoadFont\FontName}
инструкция \newfontface
выполняется внутри группы, поэтому определение шрифта теряется, как только группа заканчивается. Это особенность \foreach
.
Вот набор макросов, expl3
которые могут дать вам некоторые идеи по их расширению.
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}
\ExplSyntaxOn
\NewDocumentCommand{\LoadFont}{m}
{
\exp_args:Nc \newfontface { #1 } { #1 }
}
\NewDocumentCommand{\LoadFonts}{m}
{
\clist_map_inline:nn { #1 }
{
\LoadFont{##1}
}
}
\NewDocumentCommand{\UseFont}{m}
{
\use:c { #1 }
}
\NewDocumentCommand{\UseFonts}{m +m}
{
\clist_map_inline:nn { #1 }
{
\group_begin:
\UseFont{##1} ##1:~#2
\group_end:
}
}
\ExplSyntaxOff
\LoadFonts{Charter,Lato,Linux Libertine O}
\begin{document}
\UseFonts{Charter,Lato,Linux Libertine O}{\lipsum[2]}
\end{document}
Обратите внимание, что \exp_args:Nc \newfontface { #1 } { #1 }
по сути это то же самое, что
\expandafter\newfontface\csname #1\endcsname{#1}
Если вы хотите использовать символическое имя для списка, определите *-вариант:
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}
\ExplSyntaxOn
\NewDocumentCommand{\LoadFont}{m}
{
\exp_args:Nc \newfontface { #1 } { #1 }
}
\NewDocumentCommand{\LoadFonts}{sm}
{
\IfBooleanTF{#1}
{ \clist_map_inline:Nn #2 }
{ \clist_map_inline:nn { #2 } }
{
\LoadFont{##1}
}
}
\NewDocumentCommand{\UseFont}{m}
{
\use:c { #1 }
}
\NewDocumentCommand{\UseFonts}{s m +m}
{
\IfBooleanTF{#1}
{ \clist_map_inline:Nn #2 }
{ \clist_map_inline:nn { #2 } }
{
\group_begin:
\UseFont{##1} ##1:~#3
\group_end:
}
}
\ExplSyntaxOff
%\LoadFonts{Charter,Lato,Linux Libertine O}
\newcommand\FontList{Charter,Lato,Linux Libertine O}
\LoadFonts*{\FontList}
\begin{document}
%\UseFonts{Charter,Lato,Linux Libertine O}{\lipsum[2]}
\UseFonts*{\FontList}{\lipsum[2]}
\end{document}