A graphicx se lo suele tomar por un paquete de imágenes, pero la x de su nombre significa «extendido», no «solo gráficos». Sus comandos \rotatebox, \scalebox, \resizebox y \reflectbox giran, estiran y reflejan cualquier cosa que quepa en una caja: una palabra, una fórmula, un tabular entero. Las dimensiones de la caja, en cambio, no se comportan como uno espera. Medido, una Xg de 10pt tumbada a la derecha con \rotatebox{-90} devuelve una caja de altura 0pt y profundidad 12,50pt: todo queda colgando por debajo de la línea base. Justo por eso el interlineado de una tabla se desploma en cuanto pones una cabecera en vertical. Esta página recorre los comandos de LaTeX para rotar y escalar texto, junto con las dos trampas que atrapan a todo el mundo: las dimensiones y el controlador.
No solo para imágenes: las cuatro transformaciones de caja de graphicx
Basta una línea, \usepackage{graphicx}, para disponer de las cuatro transformaciones. Se reparten en dos grupos: las que se indican por factor (\scalebox, \reflectbox), la que se indica por tamaño objetivo (\resizebox), y \rotatebox, que se indica por un ángulo. \scalebox{0.8}{…} significa «0,8 veces el original»; \resizebox{5cm}{!}{…} significa «hazlo de 5 cm de ancho». Cuál usar depende de si el número que tienes es una proporción o una medida. Ajustar una figura al ancho del texto pide el segundo; agrandar un poco una palabra pide el primero.
| Comando | Qué hace | Forma |
|---|---|---|
\rotatebox | Gira el contenido en sentido antihorario | \rotatebox[origin=c]{45}{...}; en grados, negativo para sentido horario |
\scalebox | Escala por un factor | \scalebox{2}[1.5]{...}; el segundo argumento opcional es el factor vertical |
\reflectbox | Refleja de izquierda a derecha | \reflectbox{...}; internamente idéntico a \scalebox{-1}[1] |
\resizebox | Escala a un tamaño final indicado | \resizebox{ancho}{alto}{...}; un ! en uno de los campos conserva la proporción |
\rotatebox: grados, positivo significa antihorario
\rotatebox{ángulo}{contenido} mete el contenido en una caja y lo gira en sentido antihorario según el ángulo dado, en grados. Positivo gira a la izquierda, negativo a la derecha: \rotatebox{90}{...} pone el texto de pie, \rotatebox{-90} lo tumba al otro lado. Si prefieres escribir los ángulos en otra unidad, la clave opcional units= espera el número que corresponde a una vuelta completa: units=-360 da grados en sentido horario, units=6.283185 da radianes antihorarios. Si el convenio de signos te hace tropezar, envolverlo una vez en una macro del preámbulo lo resuelve.
This is \rotatebox{45}{slanted text} in a line of prose.
% clockwise degrees instead of the default anticlockwise:
\rotatebox[units=-360]{90}{tipped to the right}Vayamos a las dimensiones, que es donde casi todo el mundo tropieza. El ancho, el alto y la profundidad de una caja rotada se recalculan a partir del contorno del resultado girado. Mide una Xg de 10pt (ancho 12,50pt, alto 6,83pt, profundidad 1,94pt) y \rotatebox{90} devuelve ancho 8,78pt, alto 12,50pt, profundidad 0pt: el alto más la profundidad originales pasaron a ser el nuevo ancho, y el ancho original, el nuevo alto. \rotatebox{-90} da el mismo ancho pero alto 0pt y profundidad 12,50pt, con lo que toda la caja se hunde bajo la línea base. Y \rotatebox{45} vuelve con 15,05pt de ancho y 13,67pt de alto, mayor que el original en ambas direcciones. La rotación cambia la altura de la línea: sabiéndolo, el hueco que se abre de golpe justo después de añadir una rotación deja de ser un misterio.
origin=: en cuanto escribes los corchetes, cambia el valor por defecto
El centro de rotación se fija con el argumento opcional [origin=…]. Sus valores son una o dos letras entre l (izquierda), r (derecha), t (arriba), b (abajo), B (línea base) y c (centro): origin=lb pivota sobre la esquina inferior izquierda, origin=c sobre el centro de la caja. Y aquí está el detalle que despista a quien no lo conoce. Al leer graphicx.sty se descubre que, cuando el argumento opcional falta, el centro es (0,0) —el borde izquierdo, sobre la línea base, es decir, lo mismo que origin=lB—, mientras que en cuanto se escribe cualquier clave, el valor por defecto salta al centro de la caja, c. La medición lo confirma: \rotatebox{90}{Xg} y \rotatebox[origin=lB]{90}{Xg} coinciden exactamente en 8,78pt de ancho, 12,50pt de alto y 0pt de profundidad, mientras que \rotatebox[origin=c]{45}, con los mismos 45 grados, se reparte en 9,97pt de alto y 5,08pt de profundidad, a caballo sobre la línea base. «Solo añadí units= y todo se movió»: casi siempre es esto.
Además de origin= existen x= e y=, que dan el pivote como longitudes explícitas. Escribe \rotatebox[x=1cm,y=1cm]{90}{...} y el centro se sitúa en (1 cm, 1 cm) medido desde la esquina inferior izquierda de la caja. Es la herramienta para los ajustes finos que el puñado de palabras clave no alcanza a expresar.
% no optional argument: the pivot is the left edge on the baseline (= origin=lB)
\rotatebox{90}{upright}
% ANY key present: the default pivot becomes the box centre (origin=c)
\rotatebox[origin=c]{180}{upside down}
\rotatebox[x=1cm,y=1cm]{90}{pivot given as a length}Poner de pie una cabecera de tabla: más estrecha, pero la fila se hunde
El uso más práctico de \rotatebox es poner de pie nombres de columna largos para recuperar ancho. Funciona: \begin{tabular}{ll}Header&b\\ c&d\end{tabular} medía 60,42pt de ancho, y girar Header con \rotatebox{90}{...} lo redujo a 36,50pt. Pero tiene un precio. En la misma medición, la profundidad de la tabla creció de 9,50pt a 20,73pt. Las dimensiones de la sección anterior hacen exactamente lo que anunciaron: una cabecera puesta de pie crece hacia abajo, dentro de la fila. Si se deja así, acaba chocando con el texto o con la fila siguiente. Las soluciones son directas: mover el pivote con \rotatebox[origin=c]{90}{...}, levantar la celda con \raisebox, o reservar la altura con un puntal como \rule{0pt}{altura}. Colocar la tabla misma en la página —páginas apaisadas, sidewaystable, columnas de ancho declarado— es competencia de las páginas de tablas; consúltalas.
\begin{tabular}{lrr}
% rotating the pivot to the centre keeps the row from sinking
& \rotatebox[origin=c]{90}{Measured} & \rotatebox[origin=c]{90}{Predicted} \\
\hline
Sample A & 12.4 & 12.1 \\
Sample B & 9.8 & 10.0 \\
\end{tabular}Escalar por factor y reflejar: \scalebox y \reflectbox
\scalebox{factor}{contenido} escala ambas direcciones por igual y conserva la forma. \scalebox{2}{...} duplica, \scalebox{0.5}{...} reduce a la mitad. Para estirar las dos direcciones de forma distinta, pasa un factor vertical como segundo argumento opcional: \scalebox{horizontal}[vertical]{contenido}. Medido, \scalebox{2} duplicó ancho, alto y profundidad por igual, mientras que \scalebox{1}[2] dejó el ancho en 12,50pt y duplicó solo alto y profundidad. Así se condensa o achata la letra, pero recuerda que los gruesos del tipo se deforman con ella, así que úsalo con moderación en el texto corrido.
Un factor también puede ser negativo, lo que invierte a lo largo de ese eje. \scalebox{-1}[1]{...} es factor horizontal −1 y factor vertical 1: un espejo de izquierda a derecha. El caso es lo bastante frecuente como para tener su abreviatura, y en graphics.sty \reflectbox está definido como exactamente \Gscale@box-1[1]. La medición coincide: ambas cajas salen de 12,50pt de ancho, 6,83pt de alto y 1,94pt de profundidad. \reflectbox es, pues, un simple alias de \scalebox{-1}[1]. Refleja la mitad del palíndromo «Able was I ere I saw Elba» y el comportamiento del comando salta a la vista.
\scalebox{2}{bigger}\quad\scalebox{0.5}{smaller}\quad\scalebox{1}[2]{stretched}
% \reflectbox is literally \scalebox{-1}[1]
Able was I \reflectbox{Able was I}Escalar a un tamaño objetivo: \resizebox y el estrellado \resizebox*
\resizebox{ancho}{alto}{contenido} escala el contenido a un tamaño final indicado. Si pones un signo de exclamación ! en uno de los campos, esa dimensión toma el factor que implica la otra: se conserva la proporción. \resizebox{\textwidth}{!}{...} es la forma que más verás. Dentro de los argumentos de dimensión puedes usar \width, \height, \totalheight y \depth, que representan el tamaño propio del contenido. Medido, \resizebox{2\width}{!}{Xg} resultó idéntico a \scalebox{2}{Xg} hasta el último dígito: 25,00pt de ancho, 13,67pt de alto, 3,89pt de profundidad.
Un punto que se le escapa a casi todo el mundo: el argumento de altura de \resizebox es la altura, no altura más profundidad. Mide \resizebox{!}{1cm}{Xg} y la altura es 28,46pt —prácticamente 1 cm—, pero por debajo cuelgan otros 8,10pt de profundidad, así que la caja entera supera 1 cm. Cuando quieras la altura total, usa el \resizebox* estrellado. Medido, \resizebox*{!}{1cm}{Xg} dio 22,15pt de altura y 6,30pt de profundidad, sumando 28,45pt: exactamente 1 cm. Si algo que «redujiste a 1 cm» sigue asomando de su línea, sospecha de la estrella que falta.
% twice the original width, aspect ratio kept
\resizebox{2\width}{!}{double width}
% height only vs. height+depth
\resizebox{!}{1cm}{Tall} % height = 1cm, depth hangs below
\resizebox*{!}{1cm}{Tall} % height + depth = 1cmEl uso más frecuente de \resizebox es encoger una tabla demasiado ancha hasta que quepa en el texto. Envuelve todo el tabular en \resizebox{\textwidth}{!}{...} y el ancho siempre saldrá bien. Pero es un arma de doble filo, porque la letra de dentro de la tabla encoge con ella: una reducción fuerte deja caracteres más pequeños que el cuerpo del texto —a veces difíciles de leer— y desentonados con su entorno. Redefinir después un tamaño de fuente para la tabla no sirve de nada, ya que al final se escala toda la caja. Cuánto encoge exactamente una tabla, y de forma cuán alarmante se hincha una tabla demasiado estrecha al pasarla al mismo comando, está medido en detalle en la página de tablas anchas. El primer movimiento correcto es hacer que la tabla misma quepa —ajustar anchos de columna, quitar columnas— y dejar \resizebox como último recurso.
Cuando nada gira: un controlador que no corresponde
\rotatebox no hace que TeX dibuje letras giradas. TeX solo incrusta una instrucción en el archivo de salida —«gira lo que sigue este ángulo»— y el giro real lo ejecuta el controlador de la etapa siguiente. Por eso, nombrar el controlador equivocado hace que la rotación desaparezca sin error ni aviso. Ahí va la medición. Compila con pdfLaTeX un documento que diga \usepackage[dvips]{graphicx} y termina limpiamente, cero errores; y sin embargo el flujo de contenido del PDF resultante no contiene ni una sola matriz de transformación cm. El texto se queda ahí, recto. Quita la opción de controlador del mismo documento y el registro informa Package graphics Info: Driver file: pdftex.def, mientras el PDF gana .70709 .70709 -.70709 .70709 0 0 cm: el coseno y el seno de 45 grados.
La conclusión es simple: no nombres ningún controlador. graphicx detecta automáticamente pdfLaTeX, XeLaTeX y LuaLaTeX, así que escribir [dvips] o [pdftex] a mano es justo la manera de fabricar un desajuste. La vía DVI es la excepción: con latex, graphicx toma por defecto el controlador dvips y el DVI acaba llevando PostScript en bruto (ps: gsave currentpoint currentpoint translate 45 neg rotate …). dvipdfmx entiende lo bastante de esos especiales PostScript como para girar de hecho, pero la vía limpia es escribir explícitamente \usepackage[dvipdfmx]{graphicx}, tras lo cual el DVI lleva en su lugar una instrucción orientada a PDF: pdf:btrans rotate 45. Qué entrega realmente un DVI a su controlador se trata a fondo en la página sobre la conversión de DVI a PDF.
adjustbox y max width=: solo reducir, nunca agrandar
Los comandos de graphicx son simples y potentes, pero al combinarlos se anidan mucho. adjustbox, cargado con \usepackage{adjustbox}, es la alternativa de más alto nivel que los reúne en una sola interfaz clave-valor al estilo de \includegraphics. \adjustbox{angle=45,scale=0.8}{…} fija de una vez la rotación (angle=), el factor (scale=), el tamaño objetivo (width=/height=) y el reflejo (reflect), y existe además un entorno adjustbox homónimo. Medido, la caja de \adjustbox{angle=45}{Xg} coincidió con \rotatebox{45}{Xg} hasta el último decimal: la maquinaria de debajo es la misma. Lo que cambia es la comodidad de escritura y la idea de un tope, descrita a continuación.
La clave verdaderamente útil es max width=\textwidth (junto con max totalheight= y similares). El \resizebox{\textwidth}{!}{...} de la sección anterior agranda de buena gana un contenido más estrecho que el texto, mientras que max width= está hecho para reducir solo si hay desbordamiento y dejar en paz lo que ya cabe. Medido: un pequeño tabular de una columna, de 17,00pt de ancho, salió de max width=\textwidth todavía con 17,00pt, mientras que entregar la misma tabla a \resizebox{\textwidth}{!} la estiró hasta unos 345,00pt completos. Así que si por costumbre de \includegraphics aplicas \resizebox a todas las tablas, son las estrechas las que se convierten en monstruos. Haz que «reducir cuando haga falta, nunca agrandar» sea tu ajuste por defecto: en la práctica es el que provoca menos accidentes.
\usepackage{adjustbox}
% ...
\adjustbox{angle=45,scale=0.8}{rotate and scale in one go}
% shrinks only when the content overflows; leaves narrow tables alone
\adjustbox{max width=\textwidth}{%
\begin{tabular}{lrr} ... \end{tabular}%
}