Comportamiento extraño de \sbox

Comportamiento extraño de \sbox

Esta pregunta consta de dos partes relacionadas. Ya resolví el problema original pero todavía no entiendo de dónde vino ni por qué funciona la solución.

Utilizo el subcaptionpaquete para poder colocar dos subtablas una al lado de la otra. Cada subtabla requiere el ancho deseado, por lo que también uso a saveboxpara crear primero la tabla, luego mido el ancho del cuadro para obtener el ancho óptimo de la subtabla y, por último, pero no menos importante, imprimo el contenido del cuadro.

\newsavebox{\tablebox}
\sbox{\tablebox}{
  \begin{tabular}{ccc}
      1st & 2nd & 3rd \\
      1   & 2   & 3   \\
      4   & 5   & 6   \\
      7   & 8   & 9   \\
  \end{tabular}
}
% create fitting subtable
\begin{subtable}{\wd\tablebox}
  \usebox{\tablebox}
  \caption{Subable}
\end{subtable}

Sin embargo, pdflatexcomenzó a darme la siguiente advertencia.

Underfull \hbox (maldad 10000) en el párrafo de las líneas 24--25

donde 24 es la línea en la \useboxque está.

Esto no tiene sentido porque la subtabla debería tener exactamente el ancho correcto. A través de prueba y error descubrí que la advertencia solo ocurre cuandotodose cumple alguna de las siguientes tres condiciones:

  1. La construcción dada se utiliza en el apéndice (es decir, después de \appendix).
  2. El cleverefpaquete está cargado.
  3. No hay ningún %al final de la \useboxlínea.

No entiendo por qué alguno de estos tiene alguna influencia...

Mi segunda pregunta surgió al intentar localizar el error. Reemplacé la segunda mesa por una \ruledel mismo tamaño, o al menos eso es lo que intenté lograr. Si bien el ancho ( {\wd\tablebox}) me parece bien, la altura del reemplazo ( {\ht\tablebox}) es incorrecta. Es demasiado estrecho. ¿Por qué?

Finalmente, un MWE que demuestra todos los efectos descritos. Tenga en cuenta que no hay ninguna advertencia para la tabla real debido a que %hay una para el reemplazo \rulecon el mismo ancho:

\documentclass[english]{scrreprt}
\usepackage{babel}
\usepackage{subcaption}
\usepackage{cleveref}

\begin{document}
\appendix

\newsavebox{\tablebox}
\begin{table}
  % prepare table
  \sbox{\tablebox}{
    \begin{tabular}{ccc}
        1st & 2nd & 3rd \\
        1   & 2   & 3   \\
        4   & 5   & 6   \\
        7   & 8   & 9   \\
    \end{tabular}
  }
  % create fitting subtable
  \begin{subtable}{\wd\tablebox}
    \usebox{\tablebox}% no warning for this table
    \caption{Left Table}
  \end{subtable}
  %
  \hspace{2ex}
  %
  % create fitting subtable
  \begin{subtable}{\wd\tablebox}
    \rule{\wd\tablebox}{\ht\tablebox}
    \caption{Right Table}
  \end{subtable}

  \caption{Two Tables}
\end{table}

\end{document}

Respuesta1

\hbox insuficientemente lleno

El problema es el paquete cleverefque establece un espacio no deseado. La línea comienza con un objeto que llena la línea completa. Por lo general, las siguientes \captionllamadas \parfinalizan el párrafo anterior y eliminan el último espacio en el proceso. Sin embargo, si hay un espacio en \captionalgún código \cleverefanterior, entonces solounoel espacio se elimina al final del párrafo. El otro espacio provoca un salto de línea y se elimina al comienzo de la nueva línea. Pero la nueva línea ya ha comenzado y está bastante vacía y LaTeX se queja Underfull \hbox.

Un ejemplo para un modelo TeX simple:

\showboxdepth=1000
\showboxbreadth=1000
\tracingonline=1
\setbox0=\vbox{%
  \noindent
  \vrule height 1pt width \hsize\relax
  \space\space
}
\showbox0
\csname @@end\endcsname\end

TeX imprime como advertencia:

Underfull \hbox (badness 10000) in paragraph at lines 5--8

\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0

Y el cuadro 0 contiene:

> \box0=
\vbox(13.0+0.0)x469.75499
.\hbox(1.0+0.0)x469.75499
..\rule(1.0+*)x469.75499
..\glue(\rightskip) 0.0
.\penalty 300
.\glue(\baselineskip) 12.0
.\hbox(0.0+0.0)x469.75499
..\glue(\rightskip) 0.0

! OK.
l.9 \showbox0

Dentro del cuadro vertical ( \vbox) \noindentcomienza un nuevo párrafo sin sangría. Al final del cuadro, TeX finaliza el párrafo (implícito \par). Luego, TeX elimina un último espacio (implícito \unskip) para eliminar el último espacio. En este caso, el segundo \spacey agrega el espacio \parfillskip. Entonces el párrafo antes de romper contiene:

<\vrule ...> <\space> <\hskip\parfillskip>

La regla llena la línea completa, por lo que TeX rompe la línea después de la regla antes del espacio. Al comienzo de la nueva línea se eliminan los espacios, por lo que se eliminan tanto <\space>y . <\hskip\parfillskip>La línea solo contiene el componente insertado automáticamente \rightskipque no contiene extensible, consulte el cuadro de advertencia:

\hbox(0.0+0.0)x469.75499
.\glue(\rightskip) 0.0

Por lo tanto, el cuadro no contiene nada que pueda llenar la línea, la línea esinsuficientemente lleno.

Soluciones alternativas:

  • Comentando el final de línea (ya lo has encontrado).
  • \paral final, los espacios posteriores se ignoran en modo vertical.
  • Cargando cleverefa través de:

    \edef\RestoreEndlinechar{\endlinechar=\the\endlinechar\relax}
    \endlinechar=-1 %
    \usepackage{cleveref}
    \RestoreEndlinechar
    

    (Es posible que falten espacios en los mensajes de advertencia).

El final de línea no deseado de cleveref.sty2013/03/22 v0.18.9 se encuentra en la definición de \refstepcounter@noargslas líneas 196 y 242.

regla incompleta

Simplemente has olvidado que una caja puede tener profundidad. El comportamiento predeterminado de a tabulares la línea base en el medio. Pero también con la opción [b]puedes tener una profundidad generalmente pequeña, si el último elemento es una fila normal y no un archivo \hline.

\raiseboxpuede ayudar a crear una profundidad:

    \raisebox{-\dp\tablebox}{%
      \rule{\wd\tablebox}{\dimexpr\ht\tablebox+\dp\tablebox\relax}%
    }%

información relacionada