% \iffalse % % EPSDICE.DTX by Thomas Heim (thomas.heim@unibas.ch) % % LICENSE: LPPL % % a small package to include dice faces in .eps format % % provides the command \epsdice{#1} % taking one mandatory argument, an integer from 1 to 6 % and one optional argument: 'black' (for black background, with white dots); % default is white background with black dots) % % HISTORY: % ======== % % 2001/02/11 -- first release, for dvips only % % 2001/02/13 -- now works under pdfLaTeX, too % (with Rolf Niepraschk's help) % % 2001/09/04 -- "program encapsulated" by introducing "@" in counter name % -- distributed as .dtx and .ins files, plus binary .pdf file % -- some modifications in documentation % -- NO CHANGES IN USER INTERFACE (tah) % % 2007/02/11 -- added OPTIONAL argument [black] to user interface, for % reversed colors (extension suggested and drawings provided % by Christoph Zurnieden, czurnieden@gmx.de) % % 2007/02/15 -- removed spurious comment line from generated EPS file % (thanks to Christoph for spotting the bug) % \fi %<*sampledoc> \documentclass[11pt]{article} \usepackage{epsdice} % \title{Package `epsdice' --- a scalable dice font} \author{2007/02/15 -- Version 2.1 \\[.5ex] Thomas Heim \\[.5ex] (thomas.heim@unibas.ch)} \date{} \begin{document} \maketitle \section{Introduction} Dice fonts are already available in \textsc{metafont} format. (I should know, I wrote one myself: \texttt{dice3d.mf}.) For some applications it seems preferable, however, to have the fonts in scalable form. The package \texttt{epsdice} fills this gap. \texttt{epsdice.sty} provides a single command, \verb+\epsdice{#1}+, taking one mandatory argument, an integer from 1 to 6, and recognising one optional argument, namely \verb+[black]+ for a black die with white dots.\footnote{Thanks to Chrisoph Zurnieden for suggesting the extension with reversed colors, and for adjusting the drawings to this purpose.} The default behavior (i.e., with \emph{no} optional argument or with \emph{any optional argument other} than \verb+[black]+) results in a white die with black dots. The mandatory argument may also be the value of a counter. Thus automatic representation of (generated or input) data is possible as well. Of course, values outside the range 1--6 will not be represented as die faces. Depending on the value of the argument, \verb+\epsdice+ includes the appropriately clipped region from a file containing simple drawings of die faces. The drawings scale with the current font because the height of the included graphics file is set in terms of `ex' units. % \section{Requirements and limitations} \texttt{epsdice} relies on the \texttt{graphicx} package to include the drawings. It also uses the \texttt{ifthen} package to validate the arguments (error checking). The package has been tested with two widely used package drivers for \texttt{graphicx}: \verb+[dvips]+ and \verb+[pdftex]+. By default, the command \verb+\epsdice+ includes \texttt{epsdice.eps} under \LaTeXe, and \texttt{epsdice.pdf} under pdf\LaTeX, respectively\footnote{Many thanks to Rolf Niepraschk for his help with the latter!} (unless your \texttt{graphics.cfg} file specifies non-standard settings). Clipping is supported only in pdf\TeX\ versions $\ge 0.14$. You will also need an up-to-date version of \texttt{pdftex.def}: Clipping is not supported in versions \texttt{v0.03c} \texttt{[2000/09/04]} or earlier. If your pdf\TeX\ is up-to-date but you still receive error messages about clipping not being supported, get the latest \texttt{pdftex.def} here: \\[.5ex] \verb+http://www.tug.org/applications/pdftex/pdftex.def+ \\[.5ex] I tested the package successfully with pdf\TeX\ 0.14e and \texttt{pdftex.def} v0.03f \texttt{[2000/11/10]}. % \section{Configuring this package} To finish the installation of the package, simply move the following files somewhere in your ``local texmf tree'': \begin{verbatim} epsdice.sty, epsdice.cfg, dice.eps, dice.pdf \end{verbatim} e.g.\ to a new subdirectory \verb+/tex/latex/epsdice/+. Refresh the \TeX-system's file name database, and that's it, you're all set! The remainder of this section applies only if you want to change the default settings. The command \verb+\epsdice+ works by including an external file, so this file must be found by \LaTeXe. The package comes with a configuration file \texttt{epsdice.cfg} containing the file name in the variable \verb+\dicefile+. By default, this variable points to the file \verb+dice.{eps|pdf}+ (without file name extension). If you don't like my drawings and would like to ``roll your own'', a look at section~\ref{pscode} may give some hints. It contains the same PostScript code as \texttt{dice.eps}, with some comments about what's going on. Conversion to \textsc{pdf} format has been accomplished with \texttt{epstopdf} (using GhostScript), see pdf\TeX's web page. If you intend to keep the external file with the dice drawings in a different place or if you want to use your own version you have to edit the configuration file \texttt{epsdice.cfg} accordingly, by adding the path to the file name, or by changing the file name in the variable \verb+\dicefile+. If a configuration file does not exist, the external file is assumed to be located in the present working directory. % \section{Examples} Die faces in an 11pt environment: The pictures fit into the surrounding text, as in \epsdice{1} \epsdice[black]{2} \epsdice[black]{3} \epsdice[red]{4} \epsdice[black]{5} \epsdice[white]{6}. The code used to set these die faces was: \begin{verbatim} \epsdice{1} \epsdice[black]{2} \epsdice[black]{3} \epsdice[red]{4} \epsdice[black]{5} \epsdice[white]{6} \end{verbatim} The only effective option to the command \verb+\epsdice+ is \verb+[black]+. Anything else results in the default behavior with white background. \medskip {\Large Here is some \verb+\Large+ text. The die pictures scale accordingly:% \footnote{\ldots as they do in footnotes, \epsdice{\value{footnote}}, like this.} \epsdice{3} \epsdice[black]{5}. See?} \medskip Finally, note that the package works with standard counters, too: Here's the result of \verb+\epsdice{\value{section}}+ \epsdice{\value{section}}. % \section{Drawing dice in PostScript} \label{pscode} Something as simple as a ``square with dots on it'' is rather straightforward to draw in PostScript. The first line \begin{flushleft} \verb+%!PS-Adobe-2.0 EPSF-1.2+ \end{flushleft} is just a standard header. Next comes the bounding box: Each face measures $32\times 32$~pt, centered in a $43\times43$~pt box. For six faces in a row, this gives a bounding box of $258\times43$~pt. We have two rows of dice, the lower row containing the white dice with black dots, the upper one the black dice with white dots. So the total bounding box is $258\times86$~pt. The background color will be stored in the variable $bw=0$ or 1. \begin{verbatim} %%BoundingBox: 0 0 258 86 \end{verbatim} The \verb+/frame+ macro defines a simple box with rounded corners. It takes one argument, the face index $n$, and calculates a corresponding $x$-offset: $x_{\mathrm{off}}=43 (n-1)$. The point $(x_{\mathrm{off}},y_{\mathrm{off}})$ then becomes the origin of the coordinate system for this particular face. This macro uses the variable $bw$ to calculate the vertical offset $y_{\mathrm{off}}=43 bw$. The frame consists of straight lines separated by 5~pt from the outer margin, and of four quarter circles with radius $r$ ($r=5$~pt for black on white and $r=6$~pt for white on black) centered at $(10,10),\,(32,10),\,(10,32)$, and $(32,32)$. \begin{verbatim} /frame { /n exch def % take n off the stack, store it /xoffset n 1 sub 43 mul def % xoffset = 43*(n-1) gsave % save the graphics state newpath % start a new path xoffset yoffset translate % move origin to (xoffset,yoffset) 32 5 bw sub moveto % go to (32,5) or (32,4) in this system 32 10 r -90 0 arc % SE quarter circle around (32,10) 37 bw add 32 lineto % right line 32 32 r 0 90 arc % NE quarter circle around (32,32) 10 37 bw add lineto % top line 10 32 r 90 180 arc % NW quarter circle around (10,32) 5 bw add 10 lineto % left line 10 10 r 180 270 arc % SW quarter circle around (10,10) closepath % bottom line (closes the path) bw 0 eq { stroke } % either paint (lower row, bw=0) { fill } ifelse % or fill (upper row, bw=1) the path grestore % restore graphics state } def \end{verbatim} The dot positions are labelled within a face by $(x,y)$-coordinates running from $(1,1)$ for bottom left to $(3,3)$ for top right. The dot itself is a filled circle with radius $3.5$~pt. Change the dots' positions within the frame, or their radius, as you like. The \verb+/dot+ macro takes three arguments off the stack: (i) the face index, to determine the $x$-offset, (ii) the $x$-coordinate (1, 2, or 3) on the face, and (iii) the $y$-coordinate (1, 2, or 3) on the face. \begin{verbatim} /dot { /y exch def % take y-coordinate off the stack /x exch def % take x-coordinate off the stack /n exch def % take face index n off the stack /xoffset n 1 sub 43 mul def % xoffset = 43*(n-1) gsave % save the graphics state newpath % start a new path xoffset yoffset translate % move origin to (xoffset,yoffset) x 8 mul 5 add % the dot's x-position: 8*x+5 y 8 mul 5 add % the dot's y-position: 8*y+5 3.5 0 360 arc % a circle with radius 3.5 pt closepath % close the circle bw setgray % set the appropriate color fill % fill the circle grestore % restore graphics state } def \end{verbatim} Now choose a linewidth (2~pt) \begin{verbatim} 2 setlinewidth \end{verbatim} and loop over the background color (and hence the rows) from 0 to 1. The color counter is stored in $bw$ and used to determine $y_{\mathrm{off}}$ as well as the radius of the circles, $r=5+bw$~pt. \begin{verbatim} 0 1 1 { % set up loop from 0 to 1 /bw exch def % store loop index in bw /yoffset bw 43 mul def % yoffset = 43*bw /r 5 bw add def % radius r = 5+bw 0 setgray % set color to black for all frames \end{verbatim} All we have to do now is draw the six faces \begin{verbatim} 1 1 6 { frame } for % call /frame macro for n=1..6 \end{verbatim} and fill in the appropriate dots. The bottom left and top right dots appear on faces 2, 3, 4, 5, and 6. Thus there is an outer loop from 2 to 6 in steps of 1. For each of these face indices, we call the dot macro with $(x,y)$-argument equal to $(1,1)$ and $(3,3)$. This can be achieved with an inner loop running from 1 to 3 in steps of 2. Because the $x$- and $y$-coordinates coincide for these particular points, we obtain them by duplicating the inner loop index. The \verb+/dot+ macro gobbles not only the $x$- and $y$-coordinates but the face index as well. In order to draw \emph{two} dots on the same face, we thus have to duplicate the outer loop index, too. \begin{verbatim} 2 1 6 { % start loop 2 to 6 in steps of 1 dup % duplicate index (two dots on each face) 1 2 3 { % start loop 1 to 3 in steps of 2 dup % duplicate loop index -> 1 1 and 3 3 dot % call /dot macro, using three arguments } for % inner loop (dot positions) } for % outer loop (face index) \end{verbatim} The center dot appears on faces 1, 3, and 5. We get it in a simple loop from 1 to 5 in steps of 2, calling the \verb+/dot+ macro for each index together with the coordinate set $(2,2)$ corresponding to the center. \begin{verbatim} 1 2 5 { 2 2 dot } for % (2,2) dot on 1, 3, 5 \end{verbatim} The top left and the bottom right dots appear on faces 4, 5, and 6. Again, in order to draw \emph{two} dots on each face, we have to duplicate the loop index, i.e., the face index: \begin{verbatim} 4 1 6 { % start loop 4 to 6 in steps of 1 dup % duplicate index (two dots on each face) 1 3 dot % call /dot macro for (1,3) dot on this face 3 1 dot % call /dot macro for (3,1) dot on this face } for % loop over face index \end{verbatim} Finally, on face 6 we have two dots in positions $(1,2)$ and $(3,2)$. We can use a loop, but then we have to swap the loop index, i.e., the dot's $x$-coordinate, with the (constant) face index 6 inside the loop. \begin{verbatim} 1 2 3 { % start loop 1 to 3 in steps of 2 6 exch % swap loop index and constant face index 2 % push constant y-coordinate on stack dot % call /dot macro for (x,2) dot on face 6 } for % loop over x-coordinates 1 and 3 \end{verbatim} And this closes the loop over background colors: \begin{verbatim} } for % loop over bw 0 and 1 \end{verbatim} That's it! \begin{verbatim} %%EOF \end{verbatim} \section{Errors} Of course it doesn't make sense to ask for die faces with arguments other than 1, 2, 3, 4, 5, or 6. The package generates error messages and simply prints the offending argument in the \TeX\ output. % % This generates `benign' errors: \epsdice{99} and \epsdice{-3}. % The following is more serious, generating two different errors: % \epsdice{epsfoo}. Nevertheless, output continues with a fall-back % solution. \end{document} % % % %<*package> % % I don't think the package code needs much of an explanation; % it's really very simple\ldots % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{epsdice}[2007/02/15 by Thomas Heim (v. 2.1)] \RequirePackage{graphicx} \RequirePackage{ifthen} \InputIfFileExists{epsdice.cfg}{}{\def\dicefile{dice}} % \newcounter{eps@face} \newcommand*\epsdice[2][white]{% \setcounter{eps@face}{\number #2}% \ifthenelse{\value{eps@face}>6}{\theeps@face\setcounter{eps@face}{0}}{}% \ifthenelse{\value{eps@face}<0}{\theeps@face\setcounter{eps@face}{0}}{}% \ifthenelse {\equal{#1}{black}} {\addtocounter{eps@face}{6}} {}% \eps@dice{\value{eps@face}}} \newcommand*\eps@dice[1]{% \setcounter{eps@face}{\number #1}% \ifcase\value{eps@face}% \PackageError{EPSDICE}{% Argument is not a number, or its value\MessageBreak lies outside the allowed range for dice}{% Make sure the argument is either 1, 2, 3, 4, 5, or 6.\MessageBreak -- Just go on and I'll write whatever you typed;\MessageBreak the output may not make much sense, though}% \or \includegraphics[height=1.75ex,viewport= 3 4 38 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 46 4 81 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 89 4 124 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 132 4 167 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 175 4 210 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 218 4 253 39,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 3 47 38 82,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 46 47 81 82,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 89 47 124 82,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 132 47 167 82,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 175 47 210 82,% clip=true]{\dicefile}% \or \includegraphics[height=1.75ex,viewport= 218 47 253 82,% clip=true]{\dicefile}% \fi} % % % %\def\dicefile{dice} % %<*epsfile> % % Here's the PostScript code for the drawings: % %< \endinput