Получить высоту/ширину родительского блока

Получить высоту/ширину родительского блока

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

Пример ввода. Вопросительные знаки (?) для замены (Lua или TeX).

The width of the parent box is ?

The height of the parent box is ?

Несколько возможных шаблонов:

\ruledhbox to 10cm{\vbox to 4cm{ \input input }} % 10cm by 4cm
\ruledvbox to 4cm{\hsize=10cm \input input } % 10cm by 4cm
\framed
    [width=10cm,
     height=4cm,
     align={middle,lohi},
     offset=0.5cm]
    { \input input } % 9cm by 3cm

Размеры не имеют смысла, пока коробка не будет отправлена ​​на хранение, так что, вероятно, с этого и следует начать.


Мое расширение \aftergroup+\lastbox отвечать:

\typeset{\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{\vbox to40pt{\hbox to30pt{width: \askparent }}}
}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{\vbox to40pt{\hbox to30pt{width: } \afterafter }}
}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{\vbox to40pt{\hbox to30pt{width: }} \after }
}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{
        \setbox\storelast=\vbox to40pt{\hbox to30pt{width: }}
        \xdef\parht{\the\ht\storelast}
        \xdef\parwd{\the\wd\storelast}
        \xdef\pardp{\the\dp\storelast}
        \ifvmode\nointerlineskip\fi\box\storelast}
}
{   \let\parht\askparent\let\parwd\askparent\let\pardp\askparent
    \setbox0=\hbox to50pt{\vbox to40pt{\hbox to30pt{width: \parwd }}}
    \hbox to50pt{
        \setbox\storelast=\vbox to40pt{\hbox to30pt{width: }}
        \xdef\parht{\the\ht\storelast}
        \xdef\parwd{\the\wd\storelast}
        \xdef\pardp{\the\dp\storelast}
        \vbox to40pt{\hbox to30pt{width: }}}
}

решение1

При использовании \framedдля текстов вы можете получить ширину содержимого в поле с помощью команд \framedwidthи \framedheight. Ограничением здесь является то, что вы получаете только полезное значение, когда настройки widthили heightсодержат длину больше 0pt.

\starttext

\startframed[width=200pt,height=80pt,offset=10pt,rulethickness=0.5pt]
     Width: \framedwidth \par
    Height: \framedheight
\stopframed

\stoptext

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

Чтобы получить значения ключей widthи heightвы можете использовать команды \localwidthи \localheight. Здесь вы должны быть осторожны, что ConTeXt выдает то значение, которое было установлено с ключом, т.е. когда вы устанавливаете width=fitкоманды \localwidth, выдает вам fitаргумент.

\starttext

\startframed[width=200pt,height=80pt,offset=10pt,rulethickness=0.5pt]
     Width: \localwidth \par
    Height: \localheight
\stopframed

\stoptext

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

Последнее возможное значение можно использовать для фона кадра, но в отличие от предыдущих методов вы получите правильный цвет widthкадра heightдаже с такими настройками, как width=fit.

\defineoverlay
  [boxdimensions]
  [\vbox\bgroup
     \hbox {Width: \overlaywidth}
     \hbox{Height: \overlayheight}
   \egroup]

\setupframed % don't make global framed settings in a document
  [background=boxdimensions]

\starttext

\startframed[width=200pt,height=80pt,offset=10pt,rulethickness=0.5pt]
    %
\stopframed

\stoptext

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

решение2

Это «решение», конечно, не универсально и не продумано, но оно работает у меня в простых случаях, с простым TeX:

\newbox\storelast
\def\after{\setbox\storelast=\lastbox
  {\globaldefs=1
  \edef\parht{\the\ht\storelast}
  \edef\parwd{\the\wd\storelast}
  \edef\pardp{\the\dp\storelast}}
  \ifvmode\nointerlineskip\fi\box\storelast}
\def\afterafter{\aftergroup\after}
\def\askparent{\aftergroup\afterafter}

\def\typeset#1{\let\parht\askparent\let\parwd\askparent\let\pardp\askparent
  {\globaldefs=-1 \setbox0#1}#1}

После этого вы можете набрать шаблон с помощью \typeset{...}. В качестве входных данных вы можете использовать \parwd, \parhtи \pardp, чтобы получить ширину, высоту и глубину родительского блока соответственно. Аргумент\typeset должен быть ящик(оно должно начинаться с \hbox, \vbox...).

Например, у меня есть файл, input.texкоторый содержит

width \parwd\ height \parht.

Затем, следующие строки

\typeset{\hbox to50pt{\vbox to40pt{\hbox to30pt{\input input }}}}
\typeset{\vbox to50pt{\hbox to40pt{\vbox to30pt{\input input }}}}

печать (за исключением множества переполненных/недополненных полей)

width 30.0pt height 40.0pt
width 40.0pt height 30.0pt

правильно. Однако,

  • Я понятия не имею, насколько хорошо это ведет себя для более сложных конструкций;
  • Редактировать:Как отметил Анри Менке в комментариях, набор поля дважды (с \setbox0#1последующим #1) может привести к неожиданным побочным эффектам, например, если счетчики увеличиваются в поле. Я попытался уменьшить эту проблему, оценивая \setbox0#1в группе с \globaldefs=-1, но это может изменить размеры поля, если используются пакеты, полагающиеся на глобальные определения, такие как tikz, давая неверные результаты;
  • предполагается, что команды \parhtи т. д.не используется внутри группыкроме тех, которые созданы ящиками;
  • это будет работать только если родительский блокне входит в основной вертикальный списоктак как он используется \lastboxдля определения размеров коробки, которая пуста во внешнем вертикальном режиме.

Для последнего пункта рассмотрим пример выше, но теперь нас интересуют размеры самого внешнего блока:

\typeset{\hbox to50pt{\vbox to40pt{\hbox to30pt{\input input }}}}
\typeset{\vbox to50pt{\hbox to40pt{\vbox to30pt{\input input }}}}

напечатал бы

width 0.0pt height 0.0pt
width 0.0pt height 0.0pt

потому что внешний блок установлен в режиме внешнего вертикального режима. В этом случае вам придется обернуть свой шаблон другим блоком, например

\typeset{\hbox{\hbox to50pt{\vbox to40pt{\hbox to30pt{}\input input }}}}
\typeset{\hbox{\vbox to50pt{\hbox to40pt{\vbox to30pt{}\input input }}}}

печать

width 50.0pt height 40.0pt
width 40.0pt height 50.0pt

как и ожидалось.

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