% \iffalse meta-comment % % Copyright (C) 2013 by Scott Pakin % ------------------------------------------------------- % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3c or later is part of all distributions of LaTeX % version 2006/05/20 or later. % % \fi % % \iffalse %<*driver> \ProvidesFile{dashrule.dtx} % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{dashrule} %<*package> [2013/03/28 v1.3 Dashed rules] % % %<*driver> \documentclass{ltxdoc} \usepackage{dashrule} \usepackage{titlesec} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{dashrule.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{64} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.0}{2001/04/23}{Initial version} % % \GetFileInfo{dashrule.dtx} % % \DoNotIndex{\addtocounter,\csname,\DeclareRobustCommand,\def,\else,\empty} % \DoNotIndex{\endcsname,\expandafter,\fi,\hbox,\hskip,\hspace,\ifodd,\ifx} % \DoNotIndex{\let,\mbox,\newcounter,\relax,\setcounter} % % ^^A Precede every section title with a dashed rule. % \titleformat{\section} % {\unskip\vskip 2.3ex plus 0.2ex % \vbox{\noindent\hdashrule[0pt][x]{\fill}{1pt}{5pt}\rule{5pt}{1pt}} % \vskip 2.3ex plus 0.2ex} % {\normalfont\Large\bfseries\thesection} % {1em} % {\normalfont\Large\bfseries} % % % \title{The \textsf{dashrule} package\thanks{This document % corresponds to \textsf{dashrule}~\fileversion, dated \filedate.}} % \author{Scott Pakin \\ \texttt{scott+dash@pakin.org}} % % \maketitle % % \begin{abstract} % The \textsf{dashrule} package makes it easy to draw a huge variety % of dashed rules (i.e., lines) in \LaTeX. \textsf{dashrule} provides % a command, |\hdashrule|, which is a cross between \LaTeX's |\rule| % and PostScript's |setdash| command. |\hdashrule| draws horizontally % dashed rules using the same syntax as |\rule| but with an % additional, |setdash|-like parameter that specifies the pattern of % dash segments and the space between those segments. Because % \textsf{dashrule}'s rules are constructed internally using |\rule| % (as opposed to, e.g., PostScript |\special|s) they are fully % compatible with every \LaTeX{} back-end processor. % \end{abstract} % % % \section{Usage} % % \DescribeMacro{\hdashrule} % \LaTeX's |\rule| command draws a rectangular blob of ink with a given % width, height, and distance above the baseline. The % \textsf{dashrule} package introduces an analogous command, % |\hdashrule|, which draws the same blob of ink, but horizontally % dashed. |\hdashrule| takes five parameters, two of which are % optional: % % \bigskip % \noindent\hspace{-\leftmargini}% % \fbox{\texttt{\string\hdashrule} % \oarg{raise} \oarg{leader} \marg{width} \marg{height} \marg{dash}} % \bigskip % % The \meta{raise}, \meta{width}, and \meta{height} parameters have the % same meaning as in \LaTeX's |\rule| macro: the distance to raise the % rule above the baseline and the width and height of the rule. % % Because |\hdashrule| is implemented in terms of \TeX's primitive % leader commands (|\leaders|, |\cleaders|, and |\xleaders|), the dash % pattern must be repeated an integral number of times. \meta{leader} % specifies what to do with the extra whitespace (always less than the % width of the dash pattern) that this requirement introduces. The % default, which corresponds to \TeX's |\leaders| command, adds space to % both ends of the rule so the dash patterns from multiple |\hdashrule|s % line up. If \meta{leader} is~|c|, which corresponds to \TeX's % |\cleaders| command, an equal amount of whitespace is added to both % ends of the rule. If \meta{leader} is~|x|, which corresponds to % \TeX's |\xleaders| command, the whitespace is divided up, and the same % amount of whitespace separates each repetition of the dash pattern. % % The \meta{dash} argument specifies the dash pattern and is analogous % to the \textit{array} argument to PostScript's |setdash| function. % That is, it is a list of space-separated \meta{dimen}s that alternate % ``on'' and ``off'' distances. For instance, ``|2pt 1pt|'' means a % 2\,pt.\ rule, followed by a 1\,pt.\ gap, followed by a 2\,pt.\ rule, % followed by a 1\,pt.\ gap, and so forth. An odd number of % \meta{dimen}s is no different; ``|2pt|'' alternates 2\,pt.\ rules and % 2\,pt.\ gaps, and ``|1pt 2pt 3pt|'' repeats ``1\,pt.\ rule, % 2\,pt.\ gap, 3\,pt.\ rule, 1\,pt.\ gap, 2\,pt.\ rule, 3\,pt.\ gap.'' % As a special case, an empty \meta{dash} argument draws a solid rule. % % % \section{Examples} % % The following are some typical ways to use |\hdashrule|. Each example % changes from the previous in only one parameter. For clarity, % underlines are used to indicate modified text, and the rule is % bracketed by an upper- and lowercase~``X''. % % \begin{center} % \renewcommand{\arraystretch}{1.5} % \newcommand{\chg}[1]{\underbar{\texttt{#1}}} % \begin{tabular}{l@{\qquad}l} % |\rule{2cm}{1pt}| & % X\rule{2cm}{1pt}x \\ % % |\|\chg{hdashrule}|{2cm}{1pt}|\chg{\char`\{\char`\}} & % X\hdashrule{2cm}{1pt}{}x \\ % % |\hdashrule{2cm}{1pt}{|\chg{1pt}|}| & % X\hdashrule{2cm}{1pt}{1pt}x \\ % % |\hdashrule{|\chg{4cm}|}{1pt}{1pt}| & % X\hdashrule{4cm}{1pt}{1pt}x \\ % % |\hdashrule|\chg{[0.5ex]}|{4cm}{1pt}{1pt}| & % X\hdashrule[0.5ex]{4cm}{1pt}{1pt}x \\ % % |\hdashrule[0.5ex]{4cm}{1pt}{|\chg{3mm}|}| & % X\hdashrule[0.5ex]{4cm}{1pt}{3mm}x \\ % % |\hdashrule[0.5ex]{4cm}{|\chg{1mm}|}{3mm}| & % X\hdashrule[0.5ex]{4cm}{1mm}{3mm}x \\ % % |\hdashrule[0.5ex]{4cm}{1mm}{3mm |\chg{3pt}|}| & % X\hdashrule[0.5ex]{4cm}{1mm}{3mm 3pt}x \\ % % |\hdashrule[0.5ex]{4cm}{1mm}{%| \\[-1.5ex] % | 3mm 3pt |\chg{1mm 2pt}|}| & % X\hdashrule[0.5ex]{4cm}{1mm}{3mm 3pt 1mm 2pt}x \\ % \end{tabular} % \end{center} % % \bigskip % \noindent % These next examples show the effect of using different leader types. % Each leader is used with both a 4\,cm~wide rule and a 3\,cm~wide rule. % % \begin{center} % \renewcommand{\arraystretch}{1.25} % \newcommand{\chg}[1]{\underbar{\texttt{#1}}} % \begin{tabular}{l@{\qquad}l} % |\hdashrule[0.5ex]{4cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex]{4cm}{1mm}{8mm 2pt}x \\ % % |\hdashrule[0.5ex]{3cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex]{3cm}{1mm}{8mm 2pt}x \\[2ex] % % |\hdashrule[0.5ex]|\chg{[c]}|{4cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex][c]{4cm}{1mm}{8mm 2pt}x \\ % % |\hdashrule[0.5ex]|\chg{[c]}|{3cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex][c]{3cm}{1mm}{8mm 2pt}x \\[2ex] % % |\hdashrule[0.5ex][|\chg{x}|]{4cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex][x]{4cm}{1mm}{8mm 2pt}x \\ % % |\hdashrule[0.5ex][|\chg{x}|]{3cm}{1mm}{8mm 2pt}| & % X\hdashrule[0.5ex][x]{3cm}{1mm}{8mm 2pt}x \\ % \end{tabular} % \end{center} % % \noindent % Notice how the dashes in the first pair of |\hdashrule|s line up; the % rules in the second pair each have an equal amount of whitespace on % either side of the rule; and the rules in the third pair have extra % spaces within the dash pattern itself instead of around it. The % |x|~qualifier is rarely useful for dashed rules because it alters the % pattern itself. However, |x| does enable rules with long dashes to % better fill a comparatively small width, as in the following example: % % \begin{center} % \renewcommand{\arraystretch}{1.25} % \begin{tabular}{l@{\qquad}l} % |\hdashrule[0.5ex][x]{3in}{2pt}{2cm 0pt}| \\ % X\hdashrule[0.5ex][x]{3in}{2pt}{2cm 0pt}x % \end{tabular} % \end{center} % % \noindent % The gaps in the above are clearly wider than~|0pt|, but they \emph{are} % evenly spaced. % % % \section{Differences from \texttt{setdash}} % % |\hdashrule| is different from PostScript's |setdash| command in the % following ways: % % \begin{itemize} % \item |setdash| takes on/off values in terms of PostScript points % (\TeX{} ``big points'' or~``|bp|''), while |\hdashrule| requires % explicit units. % % \item There is no equivalent of |setdash|'s \textit{offset} % parameter to specify a starting offset into the pattern. If you're % desperate you can fake \textit{offset} with a leading |\rule| and % |\hspace|. % \end{itemize} % % % \StopEventually{^^A % \section{Future Work} % % \textsf{dashrule} \fileversion{} supports only horizontally dashed % rules. Future versions (if any) may support vertically dashed rules % as well. For the time being, the \textsf{graphicx} package's % \texttt{\string\rotatebox} can be used to define a % \texttt{\string\vdashrule} in terms of a rotated % \texttt{\string\hdashrule}. % % The next logical step after adding a \texttt{\string\vdashrule} is % to support dashed rectangles, which would be composed of % \texttt{\string\hdashrule}s and \texttt{\string\vdashrule}s. Other % possible enhancements would be a way of drawing dotted lines, % presumably composed from the limited set of circle characters % available in \LaTeX's fonts. % } % % % \section{Implementation} % % We load the \textsf{ifmtarg} package to help check if the final % argument to |\hdashrule| is empty. % \begin{macrocode} \RequirePackage{ifmtarg} % \end{macrocode} % % \begin{macro}{\hdr@do@rule} % This macro is exactly like \LaTeX's |\rule| except that the optional % argument is required, and it has the side effect of pointing % |\hdr@do@something| to |\hdr@do@skip|. % \begin{macrocode} \def\hdr@do@rule[#1]#2#3{% \rule[#1]{#2}{#3}% \let\hdr@do@something=\hdr@do@skip } % \end{macrocode} % \end{macro} % % \begin{macro}{\hdr@do@skip} % This macro takes the same arguments as |\hdr@do@rule|, but instead of % drawing a rule, it inserts an equivalent amount of horizontal % whitespace. Additionally, it points |\hdr@do@something| to % |\hdr@do@rule| as a side effect. % \begin{macrocode} \def\hdr@do@skip[#1]#2#3{% \hspace*{#2}% \let\hdr@do@something=\hdr@do@rule } % \end{macrocode} % \end{macro} % % \begin{macro}{\c@hdr@segments} % \begin{macro}{\hdr@tally@segments} % Dash patterns containing an odd number of segments are treated % differently from dash patterns containing an even number of segments. % We therefore define a macro, |\hdr@tally@segments|, which counts the % number of space-separated segments in a dash pattern and stores the % tally in the |hdr@segments| counter. Note that |hdr@segments| should % be initialized to~|0| before invoking |\hdr@tally@segments|. % \begin{macrocode} \newcounter{hdr@segments} \def\hdr@tally@segments#1 {% \ifx#1!% \else \addtocounter{hdr@segments}{1}% \expandafter\hdr@tally@segments \fi } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\hdashrule} % This is the only macro in \textsf{dashrule}'s external interface. % (|\hdashrule@ii| does most of the work for |\hdashrule|, though.) All % |\hdashrule| itself does is invoke |\hdashrule@i| with its first % optional argument or~|0.0pt| if none was provided. |\hdashrule@i|, in % turn, invokes |\hdashrule@ii| with the two optional arguments, % supplying |\empty| as the default value of the second optional % argument. % \changes{v1.1}{2008/04/27}{Preceded the invocation of % \texttt{\string\string\string\@testopt} with an empty box so that % \texttt{\string\string\string\hdashrule} can now begin a paragraph} % \begin{macrocode} \DeclareRobustCommand{\hdashrule}{\mbox{}\@testopt{\hdashrule@i}{0pt}} % \end{macrocode} % \end{macro} % % \begin{macro}{\hdashrule@i} % Supply |\empty| as the default second argument and call % |\hdashrule@ii|. % \begin{macrocode} \def\hdashrule@i[#1]{\@testopt{\hdashrule@ii[#1]}\empty} % \end{macrocode} % \end{macro} % % \begin{macro}{\hdashrule@ii} % Now we can do the real work for |\hdashrule|. |\hdashrule@ii| takes % the following parameters: % % \begin{center} % \begin{tabular}{ccccc} % |#1| & |#2| & |#3| & |#4| & |#5| \\ % \oarg{raise} & \oarg{leader} & \marg{width} & \marg{height} & \marg{dash} % \end{tabular} % \end{center} % % \noindent % The \meta{raise}, \meta{width}, and \meta{height} parameters have the % same meaning as in \LaTeX's |\rule| macro. \meta{leader} specifies % the \TeX\ leader function to use to fill \meta{width} amount of % space. It should be |c| for |\cleaders|, |x| for |\xleaders|, or % nothing for ordinary |\leaders|. The \meta{dash} argument specifies % the dash pattern and is analogous to the \textit{array} argument to % PostScript's |setdash| function. That is, it is a list of % space-separated \meta{dimen}s that alternate ``on'' and ``off'' % distances. % \begin{macrocode} \def\hdashrule@ii[#1][#2]#3#4#5{% % \end{macrocode} % \end{macro} % % If the final argument, \meta{dash}, is empty, we fall back to using an % ordinary |\rule| command. This is not terribly useful in practice but % does make |\hdashrule| behave more like PostScript's |setdash|. % \begin{macrocode} \@ifmtarg{#5}{% \rule[#1]{#3}{#4}% }{% % \end{macrocode} % Here begins the common case, in which the \meta{dash} argument is % nonempty. % % \begin{macro}{\hdr@do@something} % The |\hdr@do@something| alias alternates between |\hdr@do@rule| % and |\hdr@do@skip|, starting with |\hdr@do@rule|. % \begin{macrocode} \let\hdr@do@something=\hdr@do@rule % \end{macrocode} % \end{macro} % % \begin{macro}{\hdr@parse@dash} % For every space-separated \meta{dimen} in \meta{dash}, we invoke % |\hdr@do@something| to draw a rule or a space, as appropriate. We % define |\hdr@parse@dash| within |\hdashrule@ii| so we don't have to % pass in |\hdashrule@ii|'s~|#1| and~|#4| on every invocation. % \begin{macrocode} \def\hdr@parse@dash##1 {% \ifx##1!% \else \hdr@do@something[#1]{##1}{#4}% \expandafter\hdr@parse@dash \fi }% % \end{macrocode} % We now count the number of segments in the dash pattern so we can % determine if we have an even or odd number of them. % \begin{macrocode} \setcounter{hdr@segments}{0}% \hdr@tally@segments#5 ! % \end{macrocode} % Finally, we invoke |\leaders|, |\cleaders|, or |\xleaders| to draw the % dashed line, repeating the pattern until \meta{width} space is filled. % The trick here is that odd-lengthed pattern descriptions must be % repeated to yield the complete pattern. For instance, the pattern % ``|1pt|'' is actually short for ``1\,pt.\ rule, 1\,pt.\ space,'' and % ``|2pt 4pt 6pt|'' is an abridged version of ``2\,pt.\ rule, 4\,pt.\ % space, 6\,pt.\ rule, 2\,pt.\ space, 4\,pt.\ rule, 6\,pt.\ space.'' % Although it is valid to repeat even-lengthed patterns as well---an % earlier draft of |\hdashrule@ii| did just that---this produces % inferior results because \TeX's various leader commands do not split % boxes. The longer the pattern, the less likely it will fit snugly % into the given width. % \changes{v1.2}{2009/08/08}{Ended the rule with an empty box to enable % \texttt{\string\string\string\hdashrule} to work within a % \texttt{tabular} cell. Thanks to Piazza Luca for the bug report} % \changes{v1.3}{2013/03/28}{Prevented spurious spaces from being introduced % into the output. Thanks to Halil \c{S}en for the bug report} % \begin{macrocode} \ifodd\c@hdr@segments \csname#2leaders\endcsname \hbox{\hdr@parse@dash#5 #5 ! }% \hskip#3% \else \csname#2leaders\endcsname \hbox{\hdr@parse@dash#5 ! }% \hskip#3% \fi \mbox{}% }% } % \end{macrocode} % \end{macro} % % \Finale \endinput