35

Using the graphicx package, I can make any arbitrary box rotated using the \rotatebox{...}{...} command. Is there a comparable command in any package that lets me shear a box, i.e., producing a kind of general slanting?

5 Answers5

36

With a slightly more recent pdfTeX than in David's answer, you can more directly do affine transforms using \pdfsetmatrix. I don't claim to know anything about this, but here is roughly what graphicx does under the hood in \rotatebox (with a different matrix, of course).

\documentclass{article}
\newsavebox{\foobox}
\newcommand{\slantbox}[2][.5]
  {%
    \mbox
      {%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
      }%
  }
\begin{document}
\slantbox{Hello, world!}

\slantbox[-2]{Hello, world!} \slantbox[-1]{Hello, world!} \slantbox[-.8]{Hello, world!} \slantbox[-.6]{Hello, world!} \slantbox[-.4]{Hello, world!} \slantbox[-.2]{Hello, world!}

\slantbox[.2]{Hello, world!} \slantbox[.4]{Hello, world!} \slantbox[.6]{Hello, world!} \slantbox[.8]{Hello, world!} \slantbox[1]{Hello, world!} \slantbox[2]{Hello, world!}

\end{document}

Result of the code above: text that is slanted by various amounts

EDIT: as pointed out by quark67, to use this code with LuaLaTeX, you just need to first load the package luatex85, which provides the commands \pdfsave, \pdfsetmatrix, \pdfrestore (see section 2.5 of the manual).

  • 7
    Do we want this for LaTeX3? It should be pretty easy to code as I've already got the basics sorted. – Joseph Wright Jul 13 '12 at 17:10
  • I'm still a bit confused. How do those four numbers correspond to a transformation matrix? Is it just a list of elements of the matrix left to right, row by row? Would \slantbox[0]{} amount to the identity transformation? – Seamus Jul 13 '12 at 17:15
  • 1
    @Seamus: yes, the four numbers 1, 0, #1, and 1 are the entries in the 2×2 matrix defining the linear transformation. David's answer with \pdfliteral allows arbitrary affine transformation (so the 4 coefficients for the linear part, and 2 coefficients for the offset, I think). – Bruno Le Floch Jul 13 '12 at 17:47
  • 1
    @Joseph: I was thinking of it (I didn't upvote your comment, so at least one other person would like that), but I'm not sure whether we should give \box_linear_transform:Nnnnn for arbitrary parameters, or \box_vertical_shear:Nn and \box_horizontal_shear:Nn, or... – Bruno Le Floch Jul 13 '12 at 17:59
  • 1
    @BrunoLeFloch If we provide a mechanism here, we should have the 'general case' shear, something like \box_shear:Nnn or even as you say a totally-general transformation (\box_affine:Nnnnn?). One for LaTeX-L – Joseph Wright Jul 13 '12 at 18:40
  • @JosephWright Yes, for LaTeX-L, and probably after the CTAN upload. I'd say linear is better than affine. – Bruno Le Floch Jul 13 '12 at 19:41
  • @BrunoLeFloch If the offset is present it's in my opinion better to call it affine to emphasize the difference between y=ax and y=ax+b – percusse Jul 14 '12 at 11:05
  • @percusse If the offset is present, you need 6 arguments: 4 for the matrix, 2 for the offset vector. I have to admit that I'm not sure around which corner/center of the box we should rotate/scale/shear/do a linear transform, nor what the size of the box should be as a result (there is more than just affine transformations at play, since the box is not just defined by one of its points). – Bruno Le Floch Jul 14 '12 at 14:55
  • 1
    Indeed I was thinking of \pdfliteral. I've confused your answer with David's probably. But maybe it is possible to use directly that command in your case too. Great answer anyway and I hope it goes into the L3 magic. – percusse Jul 14 '12 at 17:48
  • Was this function added to LaTeX3? If so what is its current form? – Simon Jul 28 '18 at 10:20
  • @Simon: No idea, but I can't find such a function. – Bruno Le Floch Aug 05 '18 at 10:50
  • @JosephWright: Can you say whether we have a shear function? – Bruno Le Floch Aug 05 '18 at 10:50
  • @BrunoLeFloch We do not have a dedicated interface for a shear: one can of course use scalings and rotations in combination. We could provide such an interface of course. – Joseph Wright Aug 05 '18 at 12:55
  • In fact, shears cannot be expressed in terms of scalings and rotations (for instance both of these preserve angles while shears don't), so maybe that's an argument for providing some interface. – Bruno Le Floch Aug 11 '18 at 21:35
  • 1
    For use this code with LuaLaTeX, you just need to first load the package luatex85, which provides the commands \pdfsave, \pdfsetmatrix, \pdfrestore (see section 2.5 of the manual). Perhaps this information can be added in your answer. – quark67 Aug 17 '23 at 20:37
  • @quark67 Done, thanks. – Bruno Le Floch Aug 17 '23 at 21:36
20

Aha, TikZability opportunity!

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\begin{scope}[cm={1,0,1,1,(0,0)}] % Sets the coordinate trafo matrix entries.
\node[transform shape] at (0,0) {ABC};
\end{scope}
\begin{scope}[cm={1,0,-1,1,(0,0)}]
\node[transform shape] at (3,0) {Hello};
\end{scope}
\begin{scope}[cm={1,0,-1,-1,(0,0)}]
\node[transform shape] at (2,2) {World};
\end{scope}
\begin{scope}[cm={1,0,1,-1,(0,0)}]
\node[transform shape] at (1,2) {FOObar?};
\end{scope}
\end{tikzpicture}
\end{document}

You can put into nodes instead of boxes (with less risk :P).

enter image description here

percusse
  • 157,807
19

enter image description here

You can mess with the coordinate matrix, but at your own risk...

\documentclass{article}

\begin{document}


ABC\pdfliteral{ q 2 0.1 0.6 .4 0 0 cm}\rlap{XYZ}\pdfliteral{ Q}


\end{document}
David Carlisle
  • 757,742
  • 1
    q (\pdfsave) and Q (\pdfrestore) should be used at the same place. Otherwise the coordinate system of TeX and its output device get indeed messed up. – Heiko Oberdiek Jun 19 '14 at 15:36
  • @HeikoOberdiek ah yes I wrote some driver graphics back end files once, clearly I forgot everything, I'll add an rlap.... – David Carlisle Jun 19 '14 at 15:49
15

A little late, but perhaps useful. An easier solution is the use of xslant and yslant in the node options.

Example 1

\documentclass{standalone}
\usepackage{tikz}
\begin{tikzpicture}
    \node[yslant=0.5, draw] (1) {Latex};
    \node[xslant=0.5, draw, anchor=south] at ([yshift=10]1.north) {Latex};
\end{tikzpicture}

Result 1

Result example 1

Then I wanted to use it for a 3D view of a box, where on one plane I project an external *.png image.

Example 2

\documentclass[convert]{standalone}
\usepackage{tikz}

\newcommand{\w}{4 cm} % width of the box
\newcommand{\dep}{1 cm} % depth of the box
\newcommand{\h}{0.7 cm} % height of the box

\begin{document}
\begin{tikzpicture}
    % Front side of the box
    \node[minimum width = \w, minimum height=\h, fill=gray, outer sep =0] (front) {};
    \begin{scope}       
        \pgftransformxslant{1}
        \pgfset{minimum width=\w, minimum height= \dep, outer sep = 0}
        \pgftransformshift{\pgfpointanchor{front}{north}}
        \pgfnode{rectangle}{south}{}{clip}{\pgfusepath{clip}}
        % Image on top of the box
        \node[anchor=south, inner sep =0, xslant=1, outer sep = 0] (img) at (front.north) 
            {\includegraphics[width=\w, height=\dep]{Example_image.png}}; 
    \end{scope}
    % Side of the box
    \node[anchor=west, yslant=1, minimum height =\h, minimum width=\dep,
          inner sep=0, outer sep=0, fill=black!70] at (front.east) {};
\end{tikzpicture}
\end{document}

Result 2

Result example 2

Roald
  • 1,245
7

Shear transforms can be decomposed into scalings and rotations.

% \hshearbox{vertical_prescale_times_shearfactor}{one_divide_by_shearfactor}{content}
% an initial vertical downscale is often necessary for a 3d projection
\newcommand{\hshearbox}[3]{\scalebox{0.866025}[#2]{\rotatebox{210}%
{\scalebox{1.73205}[-0.57735]{\rotatebox{60}{\scalebox{-1.1547}[#1]{#3}}}}}}
% \vshearbox{horizontal_prescale_times_shearfactor}{one_divide_by_shearfactor}{content}
% an initial horizontal downscale is often necessary for a 3d projection
\newcommand{\vshearbox}[3]{\scalebox{#2}[0.866025]{\rotatebox{210}%
{\scalebox{-0.57735}[1.73205]{\rotatebox{60}{\scalebox{#1}[-1.1547]{#3}}}}}}
brac37
  • 71
  • 1
  • 1