Как можно разместить содержимое в блоке нулевой ширины и указанной высоты, при необходимости вращая его, используя синтаксис expl3?

Как можно разместить содержимое в блоке нулевой ширины и указанной высоты, при необходимости вращая его, используя синтаксис expl3?

С использованиемОтвет Стивена Б. Сеглетеса, я могу центрировать что-то горизонтально, при желании вращая его, используя

\centering
\makebox[0pt]{\rotatebox{<angle>}{<contents>}}
\par

Однако я также хотел бы указать, что у ящика есть определенная высота. Более того, поскольку я делаю это с помощью команды, которая уже использует синтаксис expl3, я подумал, что, возможно, имеет смысл попробовать использовать функции expl3. (Однако я не привязан к этой идее — мои макросы уже представляют собой колдовское варево из TeX, LaTeX2e и синтаксиса expl3, так что немного больше на самом деле не повредит ничему, против чего я уже не оскорбляюсь.)

Я могу добиться желаемого эффекта, используя следующее:

\documentclass[a4paper]{article}
\usepackage{expl3,xparse,geometry}
\geometry{margin=20mm}
\ExplSyntaxOn
\tl_new:N \l_cfr_troibocs_tl
\bool_new:N \l_cfr_bocs_bool
\keys_define:nn { mycommand }
{
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .code:n = {
    \tl_set:Nn \l_cfr_troibocs_tl {#1}
    \bool_set_true:N \l_cfr_troi_bool },
  troi .bool_set:N = \l_cfr_troi_bool,
  troi .default:n = true,
  troibocs .tl_set:N = \l_cfr_troibocs_tl,
  troibocs .initial:n = 0,
}
\NewDocumentCommand\mycommand { o m }{
  \group_begin:
  \IfValueT{#1}{ \keys_set:nn { mycommand } { #1 } }
  % from Steven B. Segletes's answer at https://tex.stackexchange.com/a/162202/
    \bool_if:NTF \l_cfr_troi_bool
    {
      \hbox_set:Nn \g_tmpa_box {\rotatebox[]{\l_cfr_troibocs_tl}{\file_input:n {#2}}}
    }
    {
      \hbox_set:Nn \g_tmpa_box {\file_input:n {#2}}
    }
    \bool_if:NT \l_cfr_vfit_bool
    {
      \box_set_ht:Nn \g_tmpa_box {.8\textheight}
    }
    \centering
    \bool_if:NTF \l_cfr_hfit_bool
    {
      \makebox[0pt]{\box_use:N \g_tmpa_box}
    }{
      \box_use:N \g_tmpa_box
    }
    \par
  \group_end:
}
\ExplSyntaxOff
\usepackage{filecontents,tikz}
\begin{filecontents}{mytikz.tex}
  \begin{tikzpicture}
    \path [draw, fill] (0,0) rectangle +(265mm,175mm);
  \end{tikzpicture}
\end{filecontents}

\begin{document}
\mycommand[
  rotate=90,
  vfit,
  hfit
  ]{mytikz}
\end{document}

Есть ли лучший/более чистый способ сделать это?

Мои попытки перевести большую часть определения в синтаксис expl3 пока что потерпели полную неудачу. Я подозреваю, что мои трудности связаны сответ egregно я не уверен, и вообще не знаю, как изменить код.

Если я использую \hbox_to_zero:n, то блок не центрируется горизонтально, но я не могу просто поставить \leavemodeперед ним в этом контексте, так как это просто сломает все полностью. Я также не могу изменить ширину блока, как я изменяю высоту, так как это \box_set_wd:Nn \g_tmpa_box {0pt}не имеет никакого эффекта.

[Я также пытался заменить его \rotateboxновым экспериментальным расширением \box_rotate:Nn, но оно ведет себя странно по сравнению с моими ожиданиями, поэтому я отказался от этой идеи.]

решение1

Если я правильно понял ваши требования, то достаточно стандартных методов:

\documentclass{article}
\usepackage{graphicx,lipsum,color}

\newcommand\rotbox[3][\dimexpr\height+\depth\relax]{%
  % #1 is the final height, #2 is the angle, #3 the contents
  \raisebox{\depth}[#1][0pt]{%
    \makebox[0pt]{%
      \rotatebox{#2}{\color{red}#3}%
    }%
  }%
}

\begin{document}

\lipsum[3]
\begin{center}
XX\rotbox{45}{This text is rotated}XX
\end{center}
\lipsum*[2]
\begin{center}
XX\rotbox[4cm]{45}{This text is rotated}XX
\end{center}
\lipsum[2]

\end{document}

Я добавил красный цвет просто для большей ясности. Если вы хотите иметь естественную ширину (после поворота), опустите \makebox[0pt].

введите описание изображения здесь

Возможная expl3версия:

\documentclass{article}
\usepackage{graphicx,lipsum,color,xparse}

\ExplSyntaxOn
\NewDocumentCommand{\xrotbox}{O{}m}
 {
  \group_begin:
  \keys_set:nn { cfr/rotbox } { #1 }
  \cfr_xrotbox:n { #2 }
  \group_end:
 }

\keys_define:nn { cfr/rotbox }
 {
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .fp_set:N = \l_cfr_rotate_fp,
  rotate .initial:n = 0,
  %troi .bool_set:N = \l_cfr_troi_bool,
  %troi .default:n = true,
  %troibocs .tl_set:N = \l_cfr_troibocs_tl,
  %troibocs .initial:n = 0,
 }

\box_new:N \l_cfr_xrotbox_box

\cs_new_protected:Npn \cfr_xrotbox:n #1
 {
  \hbox_set:Nn \l_cfr_xrotbox_box { #1 }
  \fp_compare:nF { \l_cfr_rotate_fp = \c_zero_fp }
   {
    \box_rotate:Nn \l_cfr_xrotbox_box { \l_cfr_rotate_fp }
   }
  \hbox_set:Nn \l_cfr_xrotbox_box
   {
    \box_move_up:nn { \box_dp:N \l_cfr_xrotbox_box } { \box_use:N \l_cfr_xrotbox_box }
   }
  \bool_if:NF \l_cfr_hfit_bool
   {
    \hbox_set_to_wd:Nnn \l_cfr_xrotbox_box { 0pt }
     {
      \hss \box_use:N \l_cfr_xrotbox_box \hss
     }
   }
  \bool_if:NF \l_cfr_vfit_bool
   {
    \box_set_ht:Nn \l_cfr_xrotbox_box { 0pt }
   }
  \leavevmode\box_use:N \l_cfr_xrotbox_box
 }
\ExplSyntaxOn

\begin{document}

\lipsum[3]
\begin{center}
XX\xrotbox[rotate=45]{This text is rotated}XX
\end{center}
\lipsum*[2]
\begin{center}
XX\xrotbox[rotate=45,hfit,vfit]{This text is rotated}XX
\end{center}
\lipsum[2]

\end{document}

введите описание изображения здесь

решение2

Это основано наответ egregно адаптирован к тому, что я на самом деле хотел сделать. Боюсь, что мой изначальный вопрос недостаточно объяснил контекст и поэтому был неясен. Таким образом, я считаю ответ egreg вполне хорошим. Однако, если это будет полезно кому-то еще, я также публикую код, который я придумал, адаптировав этот ответ.

Суть кода в том, чтобы набрать изображение, которое на самом деле слишком велико для доступного пространства, но которое на самом деле подходит с человеческой (не TeX) точки зрения. Например, ментальная карта может немного выходить за пределы области страницы, не «выглядя» слишком большой, поскольку она содержит разумное количество пустого пространства.

Команда, которую я на самом деле использую для этого, вводит файл и опционально набирает заголовок и подзаголовок, запись для оглавления и библиографию. Обычно вводится в основном текст. Однако я хотел использовать ту же команду для набора одностраничного изображения с заголовком, чтобы обеспечить единообразие форматирования и т. д. В этом случае содержимое файла помещается в поле и далее обрабатывается, тогда как в стандартном случае это просто обычный ввод.

Код ниже касается только случая изображения. То есть он не беспокоится о различии обычного случая от случая изображения или о заголовке, оглавлении или библиографии.

\mycommand[]{}принимает необязательный аргумент, состоящий из 0–3 ключей:

  • rotate=<angle>если содержимое следует повернуть;
  • hfitесли содержимое должно быть размещено горизонтально, центрируя его в коробке шириной 0pt;
  • vfitесли содержимое должно быть размещено вертикально, путем помещения его в коробку высотой .8\textheightплюс половина разницы между естественной высотой коробки и .8\textheight.

Обязательным аргументом является имя файла, который необходимо ввести, например, имя файла, содержащего tikzpictureментальную карту.

Пример изображения немного шире \textheightи немного выше, чем \textwidth. Поэтому, даже если его повернуть, оно слишком велико с точки зрения TeX. (Поскольку это один черный ящик, оно также выглядит слишком большим для человека. Но дело в том, что его размеры достаточно близки к виду изображения, которое меня интересует.)

Я не уверен, что это действительно правильно, но полная версия, похоже, пока работает...

\documentclass[a4paper]{article}
\usepackage{expl3,xparse,geometry}
\geometry{margin=20mm}
\ExplSyntaxOn
\fp_new:N \l_cfr_troibocs_fp
\bool_new:N \l_cfr_bocs_bool
\dim_zero_new:N \l_cfr_width_dim
\box_new:N \l_cfr_bocs_box
\NewDocumentCommand\mycommand{O{}m}
 {
  \group_begin:
  \centering
  \keys_set:nn { cfr/rotbox } { #1 }
  \cfr_troibocs:n { 0pt } { .8\textheight } { #2 }
  \par
  \group_end:
 }

\keys_define:nn { cfr/rotbox }
 {
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .fp_set:N = \l_cfr_troibocs_fp,
  rotate .initial:n = 0,
 }
\cs_new_protected:Npn \cfr_troibocs:n #1 #2 #3
 {
  \hbox_set:Nn \l_cfr_bocs_box { #3 }
  \fp_compare:nF { \l_cfr_troibocs_fp = \c_zero_fp }
   {
    \box_rotate:Nn \l_cfr_bocs_box { \l_cfr_troibocs_fp }
   }
  \hbox_set:Nn \l_cfr_bocs_box
   {
    \box_move_up:nn { \box_dp:N \l_cfr_bocs_box } { \box_use:N \l_cfr_bocs_box }
   }
  \bool_if:NT \l_cfr_hfit_bool
   {
    \hbox_set_to_wd:Nnn \l_cfr_bocs_box { #1 }
     {
      \hss \box_use:N \l_cfr_bocs_box \hss
     }
   }
  \bool_if:NT \l_cfr_vfit_bool
   {
     \dim_set:Nn \l_cfr_width_dim { \box_ht:N \l_cfr_bocs_box }
     \dim_sub:Nn \l_cfr_width_dim { #2 }
     \dim_compare:nNnT {0pt} < \l_cfr_width_dim
     {
       \vbox_set_to_ht:Nnn \l_cfr_bocs_box { #2 + .5\l_cfr_width_dim }
         {
           \vss \box_use:N \l_cfr_bocs_box \vss
         }
     }
   }
  \leavevmode\box_use:N \l_cfr_bocs_box
 }
\ExplSyntaxOff
\usepackage{filecontents,tikz}
\begin{filecontents}{mytikz.tex}
  \begin{tikzpicture}
    \path [draw, fill] (0,0) rectangle +(265mm,175mm);
  \end{tikzpicture}
\end{filecontents}

\begin{document}
\mycommand[
  rotate=90,
  hfit,
  vfit
  ]{\input{mytikz}}
\end{document}

фиктивный выход

Связанный контент