From 873660d1a83ece926fe7206288dda9c36b349c1b Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 12 Jan 2006 23:46:03 +0000 Subject: generic 1 git-svn-id: svn://tug.org/texlive/trunk@613 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/generic/shapepar/Canflagshape.def | 33 + .../texmf-dist/tex/generic/shapepar/TeXshape.def | 37 + .../tex/generic/shapepar/candleshape.def | 37 + .../texmf-dist/tex/generic/shapepar/shapepar.sty | 1325 ++++++++++++++++++++ 4 files changed, 1432 insertions(+) create mode 100644 Master/texmf-dist/tex/generic/shapepar/Canflagshape.def create mode 100644 Master/texmf-dist/tex/generic/shapepar/TeXshape.def create mode 100644 Master/texmf-dist/tex/generic/shapepar/candleshape.def create mode 100644 Master/texmf-dist/tex/generic/shapepar/shapepar.sty (limited to 'Master/texmf-dist/tex/generic/shapepar') diff --git a/Master/texmf-dist/tex/generic/shapepar/Canflagshape.def b/Master/texmf-dist/tex/generic/shapepar/Canflagshape.def new file mode 100644 index 00000000000..114014b60cc --- /dev/null +++ b/Master/texmf-dist/tex/generic/shapepar/Canflagshape.def @@ -0,0 +1,33 @@ +\def\Canflagshape{% +{32.0} +{0}b{0}\\ +{0}t{0}{16}\\ +{32}t{0}{16}\\ +{32}e{0}\\ +% +{2.800} b{32.000}\\ +{6.250} b{27.000} t{30.160}{3.680} b{37.000}\\ +{7.300} t{27.217}{1.654} t{29.600}{4.800} t{35.128}{1.654}\\ +{7.400} t{27.238}{1.812} j t{29.050}{5.900} j t{34.950}{1.812}\\ +{10.450} b{24.500} t{27.869}{8.262} b{39.500}\\ +{11.800} b{19.900} t{23.984}{1.768} t{28.148}{7.703} t{38.248}{1.768} b{44.100}\\ +{12.150} t{20.005}{2.651} t{23.850}{2.227} t{28.221}{7.559} t{37.923}{2.227} t{41.344}{2.651}\\ +{12.200} t{20.021}{3.029} j t{23.050}{3.073} t{28.231}{7.538} t{37.877}{3.073} j t{40.950}{3.029}\\ +{13.500} t{20.412}{6.917} t{28.500}{7.000} t{36.671}{6.917}\\ +{13.900} t{20.533}{7.167} j t{27.700}{8.600} j t{36.300}{7.167}\\ +{15.450} t{21.000}{22.000}\\ +{16.000} t{21.000}{22.000}\\ +{17.000} t{19.550}{24.900}\\ +{22.050} t{25.900}{12.200}\\ +{22.600} t{25.900}{12.200}\\ +{23.550} t{25.489}{5.961} s t{31.450}{1.100} s t{32.550}{5.961}\\ +{24.000} t{25.295}{2.980} t{31.600}{0.800} t{35.725}{2.980}\\ +{24.450} e{25.100} t{31.593}{0.815} e{38.900}\\ +{30.000} t{31.500}{1.000}\\ +{30.000} e{32.0}\\ +% +{0}b{48}\\ +{0}t{48}{16}\\ +{32}t{48}{16}\\ +{32}e{48} +} diff --git a/Master/texmf-dist/tex/generic/shapepar/TeXshape.def b/Master/texmf-dist/tex/generic/shapepar/TeXshape.def new file mode 100644 index 00000000000..bf98bb8970c --- /dev/null +++ b/Master/texmf-dist/tex/generic/shapepar/TeXshape.def @@ -0,0 +1,37 @@ +\def\TeXshape{% +{3.8}% + {0}b{0}\\% + {0}t{-6.35}{7.03}\\% + {2.5}t{-6.35}{7.03}\\% + {2.5}t{-4.1}{2.58}\\% +{10.11}t{-4.1}{2.58}\\% +{10.11}e{-5}\\% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + {4.03}b{0}\\% + {4.03}t{0}{6.39}\\% + {6.52}t{0}{6.39}\\% + {6.52}t{0}{2.48}\\% + {8.0}t{0}{2.48}\\% + {8.0}t{0}{5.27}\\% +{10.23}t{0}{5.27}\\% +{10.23}t{0}{2.48}\\% +{11.69}t{0}{2.48}\\% +{11.69}t{0}{6.4}\\% +{14.19}t{0}{6.4}\\% +{14.19}e{0}\\% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + {0}b{7}b{13}\\% + {0}t{6.68}{2.5}t{11.96}{2.58}\\% + {1.39}t{6.68}{2.5}t{11.96}{2.58}\\% + {2.5}t{6.68}{3.6}t{10.89}{3.65}\\% + {2.8}t{7}{3.6}jt{10.6}{3.65}\\% + {4.23}t{8.37}{4.44}\\% + {5.1}t{9.19}{2.8}\\% + {6.72}t{7.54}{6.12}\\% + {7.32}t{6.99}{3.65}st{10.64}{3.62}\\% + {7.64}t{6.68}{3.59}t{10.95}{3.6}\\% + {8.2}t{6.68}{3}t{11.48}{3.07}\\% + {8.68}t{6.68}{2.5}t{11.97}{2.58}\\% +{10.11}t{6.68}{2.5}t{11.97}{2.58}\\% +{10.11}e{7}e{13}% +} diff --git a/Master/texmf-dist/tex/generic/shapepar/candleshape.def b/Master/texmf-dist/tex/generic/shapepar/candleshape.def new file mode 100644 index 00000000000..3fe8e60a41d --- /dev/null +++ b/Master/texmf-dist/tex/generic/shapepar/candleshape.def @@ -0,0 +1,37 @@ +% From: "Timothy C. Burt" +% ====- Definition of a candle shape -=========================== +\def\candle{% + {3.1}% Horizontal center + {0}b{3}\\% Tip of flame + {0.2}t{2.9}{0.1}\\% + {0.4}t{2.9}{0.2}\\% + {0.6}t{2.8}{0.4}\\% + {0.8}t{2.7}{0.6}\\% + {1.0}t{2.6}{0.8}\\% + {1.2}t{2.5}{1.0}\\% + {1.4}t{2.4}{1.3}\\% + {1.6}t{2.3}{1.5}\\% + {1.8}t{2.2}{1.6}\\% + {2.0}t{2.1}{1.8}\\% + {2.2}t{2.0}{2.0}\\% + {2.4}t{2.0}{2.1}\\% + {2.6}t{2.0}{2.1}\\% + {2.8}t{1.9}{2.1}\\% + {3.0}t{2.2}{1.8}\\% + {3.2}t{2.5}{1.4}\\% + {3.4}t{3.1}{0.3}\\% Bottom of flame + {3.6}t{3.3}{0.1}\\% Wick + {3.8}t{2.1}{2}\\% Top of candlestick + {9.6}t{2.1}{2}\\% Bottom of candlestick + {9.8}t{0.15}{6}\\% Top of candleholder + {10.0}t{0.05}{6.1}\\% + {10.2}t{0.00}{6.2}\\% + {10.4}t{0.00}{6.3}\\% + {10.6}t{0.05}{6.1}\\% + {10.8}t{0.15}{6.0}\\% + {11.0}t{0.30}{5.7}\\% + {11.2}t{0.50}{5.3}\\% + {11.4}t{1.00}{4.3}\\% + {11.4}e{3.1}% Bottom of the candleholder ended on the centerline +}% End of candle definition. +% ====- End candle -======================================== diff --git a/Master/texmf-dist/tex/generic/shapepar/shapepar.sty b/Master/texmf-dist/tex/generic/shapepar/shapepar.sty new file mode 100644 index 00000000000..c64fc6dccdc --- /dev/null +++ b/Master/texmf-dist/tex/generic/shapepar/shapepar.sty @@ -0,0 +1,1325 @@ +% S H A P E P A R . S T Y +% +% Typeset paragraphs in various shapes. +% +% Version 2.0 (Dec 2002) +% +% Copyright (c) 1993,2002 Donald Arseneau +% These definitions may be freely transmitted, reproduced, or modified +% provided that any modifications are clearly identified and this notice +% is left intact. +% +% \shapepar: a macro to typeset paragraphs in a specific shape. The +% size is adjusted automatically so that the entire shape is filled +% with text. There can be no displayed math, and no "\vadjust" +% material (no "\vspace"). These macros work for both LaTeX and Plain +% TeX. For LaTeX, specify \usepackage{shapepar}, or for Plain, +% \input shapepar.sty . Configuration parameters are set just +% below here. Instructions for use are given in the LaTeX document +% shapepar.tex; a short summary is given after \endinput below. +% +% ToDo: +% Vertical correction for character height applied to shape. +% Shape-based bounding box and reference point for exact placement +% Allow multiple paragraphs and displayed math in shape +% Typeset shape text directly when fixed scale (or even always) (register conflicts) +% Allow text overflow from fixed scale shapes (for magazine style) +% More assertive \cutout processing +% +%--------------------- +% make file load whatever status of @ (hold codes in \squarepar temporarily) +\edef\squarepar + {\catcode\string `\string @ \the\catcode `\@ + \catcode\string `\string $ \the\catcode `$ + \catcode\string `\string * \the\catcode `\* + \catcode\string `\string ^ \the\catcode `\^} +\catcode\string`\@=11 \catcode\string`\$=11 +\catcode\string`\^=14 \catcode\string`\*=10 + +% ------ Configuration parameters ------ + +% horizontal separation between shaped par and cut-out text +\newskip\cutoutsep +\cutoutsep=12pt + +% smallest gap allowed; smaller will be eliminated +\def\SmallestGap{.4em} + +% small gap; smaller will be enlarged +\def\SmallGap{1em} + +% smallest segment allowed; smaller will be omitted +\def\SmallestSegment{.2em} + +% How many times will \shapepar try to get the size of the paragraph? +\chardef\ScaleMaxTries=9 + +% fineness of cutout matching to lines (number of reference points +% per line of text) +\chardef\RefineBaselines=3 + +% Vertical extension of cutout gap (fraction of \baselineskip) +\def\cutoutsepstretch{.5} + +% -------------------------------------- +\ifx\DeclareOption\undefined\else + + \ProvidesPackage{shapepar}[2002/12/30 v 2.0, Shaped paragraphs] + \DeclareOption{quiet}{\catcode`\*=14} + \DeclareOption{noisy}{\catcode`\^=10} + \ProcessOptions + +\fi +% -------------------------------------- + +% Define variables. Use LaTeX names for some, and use aliases to +% LaTeX allocations and TeX parameters for many others. +% In the future, the descriptive names may disappear altogether. + +\newdimen\SH@scale +\mathchardef\@dxii=512 + +\def\@empty{} +\long\def\@gobble#1{} +\ifx\@tempdima\undefined \csname newdimen\endcsname \@tempdima \fi +\ifx\@tempdimb\undefined \csname newdimen\endcsname \@tempdimb \fi +\ifx\@tempcnta\undefined \csname newcount\endcsname \@tempcnta \fi +\ifx\@tempcntb\undefined \csname newcount\endcsname \@tempcntb \fi +\ifx\@tempboxa\undefined \csname newbox\endcsname \@tempboxa \fi + +\def\@tempa#1#2#3{% {"count"|"dimen"|"box"|"skip"}{\myname}{\realname} + \ifx\undefined#3\csname new#1\endcsname#2% allocate new one + \else\let#2#3\fi % alias is defined, so use it + } + +\@tempa{box}\SH@boxa\rootbox +\newbox\SH@boxb % global +\@tempa{count}\SH@ntries\@cla % global +\@tempa{dimen}\spec@bot\p@renwd +\@tempa{dimen}\spec@top\jot +\@tempa{dimen}\spec@height\@wholewidth +\@tempa{dimen}\spec@incr\@halfwidth +\@tempa{dimen}\spec@position\@picht +\@tempa{dimen}\spec@nextpos\@ovxx +\@tempa{dimen}\spec@prevpos\@ovyy +\@tempa{dimen}\spec@hcenter\@xdim +\@tempa{dimen}\SH@refbase\@ydim +\@tempa{dimen}\SH@dscale\dimen@i % global +\@tempa{dimen}\SH@tottext\@toproom % global +\@tempa{dimen}\SH@posseg\@ovro +\@tempa{dimen}\SH@widseg\@ovri +\@tempa{dimen}\SH@posold\@ovdx +\@tempa{dimen}\SH@widold\@ovdy +\@tempa{dimen}\SH@weight\@dashdim +\@tempa{count}\SH@npslines\interdisplaylinepenalty +\@tempa{count}\SH@nline\@savsf +\@tempa{count}\SH@lowline\delimiterfactor +\@tempa{count}\SH@highline\doublehyphendemerits + +\let\SH@margin\@empty +\let\SH@xoff\z@ +\let\SH@yoff\z@ + +% ------- Begin main definitions ------- + +\def\cutout#1#2{% #1 = r|l #2 = ( or something else + \par \endgraf + \lowercase{\def\SH@margin{#1}}% + \def\@tempa{#2}\def\@tempb{(}% + \ifx\@tempa\@tempb \let\@tempb\SH@cutopt + \else \def\@tempb{\SH@cutopt \z@,\z@)#2}% + \fi \@tempb +} + +\def\SH@cutopt #1,#2){% #1 = x-offset, #2 = y-offset + \def\SH@xoff{#1}\def\SH@yoff{#2}% + \edef\SH@cutoutbase{\the\baselineskip}% + \ifx\SH@margin\@empty\else + \def\@tempa{l}\ifx\SH@margin\@tempa\else \def\@tempa{r}\fi + \ifx\SH@margin\@tempa\else + \errhelp{The \string\cutout\space is ignored; the \string\shapepar\space + will continue. }\errmessage{Shaped Paragraph Error: + Cutout side \string"\SH@margin\string" not valid; should be l or r.}% + \let\SH@margin\@empty + \fi\fi + \ifx\SH@margin\@empty\else \begingroup \fi +} + +\def\Shapepar{\ifx\SH@margin\@empty \let\SH@usebox\box \fi \shapepar} +\let\SH@usebox\unvbox + +\def\shapepar#1{\relax % #1 = shape specification or "[" + \begingroup + \ifx\SH@margin\@empty \let\SH@xoff\z@ \let\SH@yoff\z@ \fi + \if [\noexpand#1\relax \expandafter\SH@scaledshape + \else \SH@scale\z@ \SH@start{#1}\fi +} + +\def\SH@scaledshape #1]{\SH@scale #1\relax \SH@start} + +\def\SH@start#1{% #1 = shape specification. May be a macro. + \edef\SH@restog{\global\SH@ntries\the\SH@ntries + \global\SH@dscale\the\SH@dscale \global\SH@tottext\the\SH@tottext}% + \ifx\SH@usebox\box\else \par \endgraf \fi + \xdef\SH@pd{\ifvmode \the\prevdepth \else \z@ \fi}% + \let\\\relax \xdef\SH@spec{#1}% + \expandafter\SH@checkspec\SH@spec $% check spec. $ + \hyphenpenalty10 \exhyphenpenalty10 % optimise + \doublehyphendemerits10 \adjdemerits10 + \hfuzz\maxdimen + \setbox\SH@boxa\vbox\bgroup % set whole text on one line + \parindent\z@ \leftskip\z@skip % \rightskip set below + % \spaceskip .333333emplus.8emminus.15em % optimise stretch + \parfillskip\z@ plus\@ne fil + \begingroup + \linepenalty\@m + \def\\{\unskip\penalty-200 \hskip1em plus\@m\p@ \penalty-60 }% + \let\par\SH@endpar \hsize\maxdimen \rightskip\spaceskip + \pretolerance\m@ne \hyphenpenalty 9000 % make discretionaries + \ifx\textwidth\undefined\else \textwidth\hsize + \linewidth\hsize \columnwidth\hsize \fi + \def\vadjust{{\def\SH@dm{special vertical material}\the\everydisplay}}% + \everydisplay{\errhelp{Press RETURN, and hope.}\errmessage + {Shaped Paragraph Error: \SH@dm\space is illegal in a shaped paragraph}}% + \noindent \penalty\@M \hskip\z@skip % allow hyphenation of first word + \ignorespaces} + +\def\SH@dm{display-math} + +\def\SH@endpar{% Insert filler for fixed-scale paragraphs + \ifdim\SH@scale>\z@ \def~{\hfil\null\hfil\null\hfil\null\hfil\null}% + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\fi + \xdef\SH@baseset{\noexpand\baselineskip\the\baselineskip \relax}% + \endgraf \endgroup % still inside \vbox and \begingroup + \SH@baseset + \global\SH@dscale\z@ +% get tottext = total length / 256 because total length may be > \maxdimen + \setbox\@tempboxa\box\voidb@x \global\SH@tottext\z@ + \SH@sumlines % combine multiple lines -> \@tempboxa; width/256 ->\SH@tottext +^ \message{total length = 256 times \the\SH@tottext; +^ \string\baselineskip=\the\baselineskip; +^ and spec height = \Pointless\spec@height. }% + \unskip\unkern\unpenalty\unskip\unkern\unpenalty + \setbox\SH@boxa\box\@tempboxa % all the text + \ifdim\SH@scale>\z@ % for specified fixed scale: only format once + \global\SH@ntries\ScaleMaxTries + \else % Automatic scaling. Get a first-guess scale + % Get 1/256 of total segment length into \@tempdima + \@tempdima\z@ \spec@prevpos\z@ +^ {\let\\relax\message{Measure area of spec: \SH@spec}}% + \expandafter\SH@measline\SH@spec \\\delimiter +^ \message{Spec area/256 = \Pointless\@tempdima}% +% scale = 1.02 * sqrt( [text_length/256]*\baselineskip / [spec_area/256] ) + \SH@scale \Pointless\SH@tottext\baselineskip + \fpdivide\SH@scale\@tempdima + \sqrtofdim\SH@scale + \SH@scale 1.0\SH@scale % optimize +^ \message{Initial scale = \the\SH@scale}% + \global\SH@ntries\z@ % will count maximum \ScaleMaxTries trial scales + \fi + \SH@parpars \SH@tryparshape} + +% Measure the area covered by segments in the shape spec. Accumulate +% as length \@tempdima + +\def\SH@measline#1#2\\#3{% #1 = this pos, #2 = segments, #3 = next pos + \ifx\delimiter#3\expandafter\@gobble\else + % Vertical space multiplier -> tempdimb -> \@tempa (temporarily) + \@tempdimb #3\p@ \advance\@tempdimb-\spec@prevpos \divide\@tempdimb\@dxii + \edef\@tempa{\Pointless\@tempdimb}% + \SH@measseg #2t\fam\fam + \spec@prevpos#1\p@ + \expandafter\SH@measline + \fi {#3}} + +\def\SH@measseg#1t#2#3{% + \ifx \fam #3\else + \@tempdimb #3\p@ + \advance\@tempdima\@tempa\@tempdimb + \expandafter\SH@measseg + \fi} + +% \SH@tryparshape: try a parshape with scale factor \SH@scale for \SH@spec +% For a given scale, it would take x lines of text to cover the shape, +% but only an integer number of lines (counted by \SH@nline) will be +% used. The excess is evenly distributed at the top and bottom to preserve +% the symmetry of shapes. The starting point is thus: +% +% spec_top + 1/2 * { spec_height - floor[ (spec_height-delta)/incr ]*incr } +% + +\def\SH@tryparshape{% + \advance\SH@scale\SH@dscale % shift scale factor by delta +^ \message{------------------------------------------------------------------------}% +* \message{(\the\SH@ntries) Try shape with scale \the\SH@scale. \space +* (Delta = \Pointless\SH@dscale). \space }% + \spec@incr\baselineskip \fpdivide\spec@incr\SH@scale + \spec@position\spec@height \advance\spec@position-.3\spec@incr % height-delta + \SH@nline\spec@position \divide\SH@nline\spec@incr % number of lines + \spec@position-\SH@nline\spec@incr % - height of n lines + \advance\spec@position\spec@height % difference from desired height + \divide\spec@position\tw@ % half the excess + \advance\spec@position\spec@top % starting position + \xdef\spec@firstposition{\the\spec@position}% + \SH@widold-\maxdimen + \SH@makeparshape} + +\def\SH@makeparshape{% + \advance\spec@position-\spec@incr % pre-decrement + \SH@nline\z@ % initialize counter for lines + \spec@prevpos \spec@top % -\maxdimen% \spec@position + \let\SH@Prevspec\@empty + \let\@elt\relax % simply accumulate lines (reverse order) + \gdef\SH@parshape{}\gdef\SH@lines{}\SH@npslines\z@ +% \message{Parsing spec, starting at \Pointless\spec@position. }% + \expandafter \SH@doaline \SH@spec \\\delimiter $\\$} +% this macro ends instead of continuing with \SH@done so TeX will use +% tail-recursion as \SH@tryparshape is iterated. + +\def\SH@doaline{\SH@updps \SH@widold-\maxdimen + \advance\SH@nline\@ne \advance\spec@position\spec@incr + \let\\\SH@findpos \\} + +% Get spec lines appropriate for given position (\spec@position): +% \SH@prevspec,\spec@prevpos for spec line above +% \SH@nextspec,\spec@nextpos for spec line below +% (lines may contain several segments) +% +\def\SH@findpos#1#2\\{% #1 = spec line vert position, #2 = segments + \ifx\delimiter#1\let\\\SH@dopara + \else + \ifdim#1\p@<\spec@prevpos \SH@backup{#1}\fi % handle backspace + \ifdim#1\p@>\spec@position + \def\SH@nextspec{#2{}}\spec@nextpos#1\p@ \def\\{\SH@found{#1}#2\\}% + \expandafter\def\expandafter\SH@prevspec\expandafter{\SH@Prevspec}% + \else + \def\SH@Prevspec{#2{}}\spec@prevpos#1\p@ + \fi\fi \\} + +\def\SH@found{% calculate weights to interpolate +% \message{ -- \number\SH@nline\space-- SH@found \the\spec@position\space +% between \the\spec@prevpos\space and \the\spec@nextpos. }% + \ifdim\spec@position<\spec@prevpos + \let\SH@next\SH@doaline + \else + \SH@weight\spec@position \advance\SH@weight-\spec@prevpos + \@tempdimb\spec@nextpos \advance\@tempdimb-\spec@prevpos + \fpdivide\SH@weight\@tempdimb % weight = interpolation factor + \let\SH@next\SH@dosegment + \fi + \SH@next} + +\def\SH@backup#1{%\tracingall +% \message{Backup for #1 after \Pointless\spec@prevpos, seeking \Pointless\spec@position. }% + \ifdim#1\p@<\spec@position + \advance\SH@nline\m@ne + \advance\spec@position-\spec@incr + \advance\spec@prevpos-\spec@incr + \SH@backup{#1}% + \fi} + +% Get the position and width of a segment of text by taking the weighted +% average of the specifications from above and below (weighted by nearness). +% We iterate \SH@dosegment while it handles the segments +% Most of the confusing bits here are hueristics to deal with narrow gaps. +% If a gap between two texts is less than a space, the texts are joined +% over the gap. If the gap is less than 1em, the gap is increased to the +% average of 1em and the given gap. + +\def\SH@dosegment{% do a segment of text on this line + \SH@posseg\z@ \SH@widseg\z@ + \advance\SH@weight-\p@ \SH@weight-\SH@weight % w1 = 1 - w2 + \SH@getseg A\SH@prevspec % Above + \advance\SH@weight-\p@ \SH@weight-\SH@weight % w2 = 1 - w1 + \SH@getseg B\SH@nextspec % Below + \ifdim\SH@widseg>10sp + \SH@widseg\Pointless\SH@scale\SH@widseg + \advance\SH@posseg-\spec@hcenter + \SH@posseg\Pointless\SH@scale\SH@posseg + \advance\SH@posseg.5\hsize +% Here are the small-gap heuristics. \@tempdima is the gap and the shift + \ifdim\SH@widold>10sp + \@tempdima\SH@posseg + \advance\@tempdima-\SH@posold \advance\@tempdima-\SH@widold %gap + \ifdim\@tempdima<\SmallestGap % gap too small; eliminate +^ \message{Gap is \the\@tempdima--eliminate. }% + \advance\SH@widold\@tempdimb \advance\SH@widold\SH@widseg % no update + \else + \ifdim\@tempdima<\SmallGap % gap small; enlarge it if text not too small + \ifdim\SH@widold>\SmallGap \ifdim\SH@widseg>\SmallGap +^ \message{Gap is \the\@tempdima--enlarge}% + \@tempdima-.25\@tempdima \advance\@tempdima.25em +^ \message{by 2 x \the\@tempdima. }% + \advance\SH@widold-\@tempdima + \advance\SH@widseg-\@tempdima + \advance\SH@posseg \@tempdima + \fi\fi\fi + \SH@updps + \fi + \else % no previous, so no update. Just hold. + \SH@widold\SH@widseg \SH@posold\SH@posseg + \fi\fi + \ifx\SH@prevspec\@empty \let\SH@next\SH@doaline \fi + \ifx\SH@nextspec\@empty \let\SH@next\SH@doaline \fi + \SH@next} + +\def\SH@updps{% Update parshape with `new' info +^\message{Segment \Pointless\SH@posold, \Pointless\SH@widold}% +\ifdim\SH@widold>\SmallestSegment +* \message{.}% + \xdef\SH@parshape{\SH@parshape\the\SH@posold\the\SH@widold\space}% + \xdef\SH@lines{\@elt{\the\SH@nline}{\the\SH@posold}{\the\SH@widold}\SH@lines}% + \advance\SH@npslines\@ne +\fi \SH@widold\SH@widseg \SH@posold\SH@posseg} + +\def\SH@getseg#1#2{% A/B, spec + \ifx#2\@empty \SH@sperror \fi + \expandafter \SH@GetseG #2$#1#2} + +\def\SH@GetseG#1#2$#3#4{% command, rest of spec, $, A/B, spec + \expandafter \ifx\csname spec#3$#1\endcsname \relax + \SH@sperror + \else + \csname spec#3$#1\endcsname #2$#4% + \fi} + +% b{pos} begin text at a point at horizontal position pos. +% e{pos} end text at a point at horizontal position pos. +% t{pos}{len} make a block of text at position pos with length len +% s split text (begin whitespace) +% j join two text blocks (end a gap) + +% Behavior of specs Above: +\def\specA$b#1{\specA$t{#1}{0}}% b(pos) -> t(pos)(0) +\def\specA$e#1#2{\csname specA$#2\endcsname}% e(pos) ignore +\def\specA$s#1{\csname specA$#1\endcsname}% s ignore % should never happen +\def\specA$t#1{\advance\SH@posseg#1\SH@weight \@spec$t jt{#1}} + +% Behavior of specs Below: +\def\specB$e#1{\specB$t{#1}{0}} +\def\specB$b#1#2{\csname specB$#2\endcsname} +\def\specB$j#1{\csname specB$#1\endcsname} +\def\specB$t#1{\advance\SH@posseg#1\SH@weight \@spec$t st{#1}} + +\def\@spec$t#1#2#3#4#5{% j|s t pos wid next + \if t#2\else \SH@sperror \fi + \advance\SH@widseg#4\SH@weight + \if#1#5\relax % next is s (below) or j (above): unite two t + \let\@tempa\@spec$t \else \let\@tempa\SH@redefine \fi + \@tempa #5} + +\def\SH@redefine#1$#2{\def#2{#1}} +\let\specA$\SH@redefine % bug fix to allow disjoint pieces +\let\specB$\SH@redefine + +\def\SH@dopara#1${% eat remaining spec and test parshape $ +\global\setbox\SH@boxb\vbox{% + \advance\SH@npslines\@ne + \parshape\the\SH@npslines\space \SH@parshape \z@ \maxdimen + \advance\SH@npslines\m@ne +* \message{Formatting. }% + \noindent \unhcopy\SH@boxa \endgraf +* \message{Expected \the\SH@npslines\space lines; +* got \the\prevgraf\space lines}% + \ifnum\prevgraf=\SH@npslines % maybe right size; check last line + \ifdim\SH@widseg>\z@ % yes, we can check + \ifnum\SH@ntries<\ScaleMaxTries % safe to screw around with \SH@npslines + \SH@grablast \@tempdima\wd\SH@boxa \advance\@tempdima 20\p@ + \ifdim\@tempdima<.8\SH@widseg % final line underfull % optimise +* \message{but the last line is too empty. }% + \advance\SH@npslines\@ne % flag underfullness + \fi\fi\fi\fi + \ifnum\prevgraf=\SH@npslines % right size, done + \aftergroup\SH@done \global\SH@dscale\z@ + \else % Try a new scale factor + \ifdim\SH@dscale=\z@ % no previous step. Try to guess a good one + \ifnum\prevgraf<\SH@npslines % underfull +^ \message{First underfull. }% + \@tempdima\prevgraf\p@ + \divide\@tempdima\SH@npslines + \else % overfull +^ \message{First overfull. }% + \SH@grablast + \@tempdimb-\wd\SH@boxa \advance\@tempdimb-20\p@ + \divide\@tempdimb\@cclvi + \@tempdima\SH@tottext \advance\@tempdimb\@tempdima + \fpdivide\@tempdima\@tempdimb +^ \message{overfullness: \the\wd\SH@boxa; ratio: \Pointless\@tempdima}% + \fi + \sqrtofdim\@tempdima + \advance\@tempdima-\p@ + \divide\@tempdima\tw@ + \global\SH@dscale\Pointless\@tempdima\SH@scale + \gdef\SH@fac{1}% % optimise + \else % Not first step, scale from previous + \ifnum\prevgraf>\SH@npslines % overflow now + \ifdim\SH@dscale>\z@ % previous Overflow + \global\SH@dscale \SH@fac\SH@dscale + \else % overflow now, but previous underflow + \gdef\SH@fac{.53}% % optimise + \global\SH@dscale -\SH@fac\SH@dscale + \fi + \else % underflow now + \ifdim\SH@dscale>\z@ % previous Overflow + \gdef\SH@fac{.54}% % optimise + \global\SH@dscale -\SH@fac\SH@dscale + \else % overflow now, but previous underflow + \global\SH@dscale \SH@fac\SH@dscale + \fi + \fi + \fi + \ifdim-\SH@dscale>.6\SH@scale + \global\SH@dscale -.6\SH@scale % avoid scale --> 0 ! + \fi + \global\advance\SH@ntries\@ne + \ifdim\AbsVal\SH@dscale <.005\p@ \global\SH@ntries\@cclv \fi + \ifnum \SH@ntries>\ScaleMaxTries \aftergroup\SH@done + \else \aftergroup\SH@tryparshape + \fi\fi +}}% end \vbox, end macro. Must not insert anything between braces! + +% Get last hbox off list; rebox it into \SH@boxa, omitting final glue +% +\def\SH@grablast{\unskip\unkern\unskip\unpenalty + \setbox\SH@boxa\lastbox + \ifhbox\SH@boxa + \setbox\SH@boxa\hbox{\unhbox\SH@boxa\unskip\unskip\unpenalty}% + \fi} + +\def\SH@parpars{% + \lineskiplimit-99\p@ \linepenalty\thr@@ + \tolerance9999 + \ifx\emergencystretch\undefined % TeX2 + \rightskip\z@ plus.5emminus.2em % optimise + \else \rightskip\z@skip \emergencystretch 3em % TeX 3 + \fi \pretolerance\m@ne \hbadness\@MM % avoid error messages + \SH@baseset +} + +\def\SH@done{\SH@parpars + \skip@ 1spplus2\p@ minus\p@ + \parfillskip.5\maxdimen % this will drag text to the bottom point. + \advance\SH@npslines\@ne +% \message{Parshape: \parshape\the\SH@npslines\space \SH@parshape 0 .5\maxdimen. }% + \SH@reform % reformat paragraph with new parfillskip + \ifx\SH@usebox\box % boxed \Shapepar: find min pos + \let\@elt\SH@measureh \SH@posold\maxdimen \SH@lines + \else + \SH@posold\z@ + \fi +% {\let\@elt\relax \message{SH@lines: \SH@lines. }}% + \SH@nline\m@ne \SH@highline-\@m \SH@lowline\m@ne \let\@elt\SH@restack +* \message{Restacking.}% + % re-stack segments and re-justify lines; put in \vtop or \vbox appropriately + \global\setbox\SH@boxb \ifx\SH@margin\@empty \vbox \else \vtop \fi {% + \setbox\SH@boxa\vbox{}\leftskip\z@ plus55sp minus5\p@ % optimise + \unvbox\SH@boxb + \SH@lines \unvbox\SH@boxa + \ifnum\SH@highline<\SH@lowline + \nobreak + % \message{After restack, \the\SH@highline<\the\SH@lowline,} + \advance\SH@lowline-\SH@highline + % \message{so skip down \the\SH@lowline\space lines. }% + \vskip\SH@lowline\baselineskip + \fi + }% Now we have final \SH@boxb + \ifx\SH@margin\@empty % stand-alone + \egroup % end original \setbox\SH@boxa\vbox\bgroup; but \SH@boxa is useless + \ifx\SH@usebox\unvbox % ordinary \shapepar + \unvbox\SH@boxb \prevdepth\SH@pd + \else % boxed \Shapepar + \vtop{\unvbox\SH@boxb}% + \ifvmode + \hrule height-\SH@pd width\z@ + \hbox{\vrule depth\SH@pd width\z@}% + \fi + \fi + \SH@restog % restore global registers + \endgroup % forgets many local parameters. \prevdepth is global + \else % \cutout\shapepar Placed on margin of cutout text + \SH@docutout + \fi + \let\SH@usebox\unvbox % completely finished! + \let\SH@margin\@empty + \SH@ignorepar +} + +% Note on height and depth: +% Ordinary \shapepar uses \unvbox, which ignores ordinary \baselineskip +% figuring, so we start the final formatting of the shape with the +% prevdepth from outside and above. We use the depth of the \vbox +% to set the \prevdepth after unboxing it. We can't record \prevdepth +% from inside because we strip off a box from the bottom. +% \Shapepar emits the shape in a box. The best way to do that is to +% record the depth of the \vbox, rebox it as a \vtop (emitted) and then, +% if vertical mode, make a strut with the proper depth. (Merely setting +% \prevdepth gets the inter-line skips right, but not the placement at +% the bottom of a page.) + +% Finally, \cutout requires a \smashed \vtop (only depth removed due to +% the strange behavior of \vtop). + +\def\SH@reform{% +\global\setbox\SH@boxb\vbox\bgroup +* \message{Reformat paragraph with \string\rightskip = \the\rightskip.}% + \advance\parfillskip-\rightskip \advance\parfillskip-\leftskip + \parshape\the\SH@npslines\space \SH@parshape \z@ .5\maxdimen + %% Maybe use prevdepth from outside, penalty puts \parskip and favors breaks + \ifx\SH@margin\@empty \ifx\SH@usebox\unvbox + \prevdepth\SH@pd \ifdim\SH@pd>-\@m\p@ \penalty-50 \fi + \fi \fi + \noindent \unhcopy\SH@boxa \unskip\unskip\unpenalty\strut + \penalty-\@M\hbox{\kern\maxdimen}\endgraf + \ifnum\prevgraf=\SH@npslines % good, it worked. + \setbox\SH@boxa\lastbox \unskip\unpenalty % remove mongo last box + \egroup % end \SH@boxb, just above + \xdef\SH@pd{\the\dp\SH@boxb}% + \else % something wrong, increase flexibility and try again + \egroup % end \SH@boxb, just above + \ifnum\skip@<64 % try again + \advance\rightskip\skip@ + \multiply\skip@\tw@ + \expandafter\expandafter\expandafter \SH@reform + \fi\fi} + +\def\SH@measureh#1#2#3{% line num, shift, width + \ifdim#2<\SH@posold \SH@posold#2\relax \fi +} + +\def\SH@restack#1#2#3{% line num, shift, width + \unpenalty \skip@\lastskip \unskip \unpenalty + \advance\skip@\lastskip \unskip \unpenalty\unpenalty + \setbox\@tempboxa\lastbox + \setbox\SH@boxa\vbox{% + \ifhbox\@tempboxa + \advance\SH@posold-#2% Trim box for \Shapepar + \moveright-\SH@posold \hbox to#3 + {\hskip\leftskip \unhbox\@tempboxa \unskip \hskip\leftskip}% + \nobreak + \fi + \vskip\skip@ + \ifnum\SH@nline>\z@ \begingroup + \count@=#1 \advance\count@-\SH@nline \advance\count@\@ne + \vskip-\count@\baselineskip + \endgroup\fi + \unvbox\SH@boxa}% + \SH@nline#1\relax + % Keep track of line num for last box (\SH@highline) and + % lowest box on page (\SH@lowline) + \ifnum\SH@highline=-\@m \SH@highline\SH@nline \fi + \ifnum\SH@lowline<\SH@nline \SH@lowline\SH@nline \fi +} + +% Find and record parameters about the shape spec: +% \spec@hcenter: Horizontal center of spec +% \spec@top: Vertical position at top of spec +% \spec@bot: Vertical position at bottom of spec +% \spec@height: difference between them +% \spec@left: Horizontal position at leftmost point of spec (macro) +% \spec@width: Total width of spec (macro) +% \spec@area: Area covered by spec +% All in whatever units are used by the spec itself. +% +\def\SH@checkspec#1#2#3#4${% h-center, v-origin, "b", rest of spec + \ifx b#3\else \SH@sperror \fi + \spec@hcenter#1\p@ \spec@top#2\p@ + \spec@bot-\maxdimen \spec@prevpos-\maxdimen + \gdef\SH@spec{{#2}b#4}% + % Measure vertical extrema and check for valid backspacing + \let\\\SH@CheckSpecLine + \\{#2}b#4\\{-12345.6}\\[$% + \ifdim\spec@bot<-\@M\p@ \SH@sperror \fi + % Measure horizontal extrema + \spec@height\spec@bot \advance\spec@height-\spec@top + \SH@posold\maxdimen \SH@widold-\maxdimen\relax + \SH@CheckSpecSeg b#4\delimiter + \edef\spec@left{\Pointless\SH@posold}% + \advance\SH@widold-\SH@posold \edef\spec@width{\Pointless\SH@widold}% +^ \message{Spec top: \Pointless\spec@top, bottom: \Pointless\spec@bot, height: +^ \Pointless\spec@height, left: \spec@left, width: \spec@width. }% +} + +% Record vertical positions. + +\def\SH@CheckSpecLine#1#2\\{\ifdim#1\p@<-\@M\p@ % finished + \def\\[${}% $ + \else + \ifdim#1\p@>\spec@bot \spec@bot #1\p@\relax \fi + \ifdim#1\p@<\spec@prevpos % allow backspace only between pieces + \if\SH@only@b#2;\@empty \spec@prevpos#1\p@ + \else \SH@sperror + \spec@bot-\p@ \def\\##1[${}% $ eat rest + \fi + \else \spec@prevpos#1\p@ + \fi\fi \\} + +\def\SH@only@b #1#2{% return bb if only "b" specs until ";" + \if b\noexpand#1\expandafter\SH@only@b + \else \if ;\noexpand#1bb\else ab\fi + \fi} + +% Record horizontal positions. These are not used, but they anticipate +% a shape-based bounding box. + +\def\SH@CheckSpecSeg#1#2#3{% + \ifx t#1\relax \SH@SaveSpecSeg{#2}{#3}\else + \ifx b#1\relax \SH@SaveSpecSeg{#2}0\else + \ifx e#1\relax \SH@SaveSpecSeg{#2}0\fi\fi\fi + \ifx\delimiter#3\def\SH@CheckSpecSeg##1##2{}\fi + \SH@CheckSpecSeg{#2}{#3}} + +\def\SH@SaveSpecSeg#1#2{% + \SH@posseg#1\p@\relax + \ifdim\SH@posseg<\SH@posold \SH@posold\SH@posseg \fi + \advance\SH@posseg#2\p@\relax + \ifdim\SH@posseg>\SH@widold \SH@widold\SH@posseg \fi + \relax +} + +% Grab all the hboxes in the preceding list, combine their contents in +% \@tempboxa (removing \rightskip, separating with space), and give +% SH@tottext = total_width / 256 (note that the total width may be +% greater than \maxdimen) +% +\def\SH@sumlines{\SH@grablast +\ifhbox\SH@boxa + \@tempdima\wd\SH@boxa \divide\@tempdima\@cclvi + \global\advance\SH@tottext\@tempdima + \setbox\@tempboxa\hbox{% + \ifvoid\@tempboxa\else \unhbox\@tempboxa\space \fi + \unhbox\SH@boxa}% + \expandafter\SH@sumlines +\fi} + +\def\SH@sperror{\errhelp{It would be amazing if you can continue after + this error.}\errmessage + {Shaped Paragraph Error: Error in specification. Check carefully!}}% + +% Do the cutout in the surrounding text. Do so by regenerating +% the a \parshape (\SH@lines actually) with a smaller line spacing. +% Whichever of those lines fall near each line in the outer cutout +% text contribute to the outer parshape. + +\def\SH@docutout{% + % \message{\string\SH@docutout, with initial y-pos=\the\spec@position, scale=\the\SH@scale. }% + \spec@position-\SH@yoff\relax \fpdivide\spec@position\SH@scale + \advance\spec@position\spec@firstposition + % \message{Spec position of first outer line is \the\spec@position. }% + % line spacing of surrogate is fraction of the outer baselines. + % Determine surrogate's "refined" baseline-skip (\SH@refbase), + % its shape-spec increment (\spec@incr) and the number of lines + % corresponding to the vertical (expanded) cutout-sep (\SH@highline) + % Temporarily, \SH@posold is "shoulder" - height of octagon's corner. + \SH@refbase\SH@cutoutbase + \@tempdima\cutoutsep + \SH@posold.414\cutoutsep + \advance\@tempdima\cutoutsepstretch\SH@refbase % not refbase but cutoutbase + \advance\SH@posold\cutoutsepstretch\SH@refbase + \divide\SH@refbase\RefineBaselines % examine multiple positions per line + % \message{Vertical gap \the\@tempdima, with refined spacing \the\SH@refbase. }% + \divide\@tempdima\SH@refbase + \SH@highline\@tempdima \SH@lowline-\SH@highline + \spec@incr\SH@refbase + \fpdivide\spec@incr\SH@scale + % Pre-calculate excluded octagon shape (\SH@posold is "shoulder") + \begingroup + \gdef\SH@octcase{}\let\or\relax \SH@nextoctcase + \xdef\SH@octcase{\noexpand\ifcase\SH@highline\SH@octcase\z@\noexpand\fi}% + %\toks@\expandafter{\SH@octcase}\message{Octagon cases are: \the\toks@ }% + \endgroup + \SH@lowline-\SH@highline + %\message{Range of lines of interest: \the\SH@lowline\space to \the\SH@highline. }% + \advance\SH@lowline\@ne \advance\SH@highline\@ne + % Generate the surrogate refined-lines shape + \def\SH@dopara##1${}% Don't typeset the refined shape; just gobble to $ + \SH@makeparshape % Get \SH@lines + % Record highest line number in \SH@lines + \let\@elt\SH@getmaxline \SH@nline\z@ \SH@lines + % Use \SH@widold ("hold") to retain: x_off +/- (.5 hsize) + \SH@widold\SH@xoff \advance\SH@widold\if l\SH@margin-\fi .5\hsize + % Use \SH@posold ("hold") for initialization for outermost position + \if l\SH@margin\relax + \def\@tempb##1##2{##1##2}% + \SH@posold -\SH@widold + \else + \def\@tempb##1##2{\z@##1}% + \SH@posold\hsize \advance\SH@posold-\SH@widold + \fi + % Build cutout's parshape in \SH@parshape + \gdef\SH@parshape{\@empty\@empty\@empty}\SH@npslines\z@ + \expandafter\let\expandafter\@elt\csname SH@mostopposite\SH@margin\endcsname + \SH@cutoutline % Builds parshape + % Pull out indentation of first line + \afterassignment\SH@dopara % a type of "gobble", see a bit above + \@tempdima\SH@parshape $% the $ terminates gobble + \advance\@tempdima-\SH@xoff + \xdef\SH@xoff{-\the\@tempdima}% + % Now finalize the parshape lines + \advance\SH@npslines\@ne + \xdef\SH@parshape{\number\SH@npslines\space\SH@parshape \z@\hsize}% + \egroup % end original \setbox\SH@boxa\vbox\bgroup; but \SH@boxa is useless + \SH@restog % restore global registers + \endgroup% Have the parshape; end group started by \shapepar + \global\setbox\SH@boxb\rlap{% + \kern\if\SH@margin l-\fi.5\hsize + \kern\SH@xoff + \lower\SH@yoff \box\SH@boxb + }% + % Encourage page break above + \@tempdima\dp\SH@boxb + \advance\@tempdima-\SH@cutoutbase + \advance\@tempdima\cutoutsep + \dp\SH@boxb\z@ + \vskip \z@ plus .3\@tempdima % optimize + \penalty \@cclv % optimize + \vskip \z@ plus -.3\@tempdima % undo above skip + \ifdim20\p@<\@tempdima % optimize + \vskip \@tempdima plus 9\p@ % optimize + \penalty \@m % optimize + \vskip -\@tempdima plus -9\p@ % undo above skip + \fi + \noindent % Outer text is not indented. To indent, use \indent. + \vadjust{\penalty\@M \vskip\@tempdima + \penalty9999 % exercise page builder + \vskip-\@tempdima}% + \endgroup % end group started by \cutout; out of all groups + %\message{Parshape: \noexpand\parshape\SH@parshape }% + \parshape\SH@parshape + \box\SH@boxb +} + +% for r indent = 0pt (done by \@tempb) +% width = leftmost_pos + x_offset + ( .5\hsize - gap ) +% for l indent = rightmost_pos + x_offset - ( .5\hsize - gap ) +% width = \hsize - indent +% Because I allow backspacing, I can't go through the spec, building +% the parshape. Instead, I have to scan the whole spec, or rather, its +% instantiation in \SH@lines, for every line of the \parshape... +% Well, I *could* sort the instantiation first; then I could move +% though it sequentially. +% +% Here I am re-using some scratch variables: +% \SH@posold = +/- \maxdimen -- starting value of rightmost/leftmost +% \SH@widold = x_offset +/- ( .5\hsize ) +% \SH@posseg = leftmost/rightmost position +% \SH@nline = highest number of \@elt lines in \SH@lines + +\def\SH@cutoutline{% + \ifnum\SH@lowline>\SH@nline + \let\SH@cutoutline\relax + \else + \SH@posseg\SH@posold + \advance\SH@npslines\@ne + %\message{SH@cutoutline \the\SH@npslines\space between \the\SH@lowline\space and \the\SH@highline. }% + \SH@lines % Use \@elt to get leftmost/rightmost at this line + %\message{ posseg \the\SH@posseg, posold \the\SH@posold. }% + \advance\SH@posseg \SH@widold + {\advance\hsize-\SH@posseg + \xdef\SH@parshape{\SH@parshape \@tempb{\the\SH@posseg}{\the\hsize}}}% + \fi + \advance\SH@highline\RefineBaselines \advance\SH@lowline\RefineBaselines + \SH@cutoutline} + +% choose leftmost position among \SH@posseg and lines near \SH@nline +\def\SH@mostoppositer#1#2#3{% #1: line, #2: indent, #3: width + \ifnum #1<\SH@lowline\else + \ifnum #1>\SH@highline\else + \advance\SH@highline-#1 + % \message{Compare #2 #3 at #1. Case \the\SH@highline: \SH@octcase}% + \dimen@#2\advance\dimen@-\SH@octcase\relax + \ifdim \dimen@<\SH@posseg \SH@posseg\dimen@\fi + \advance\SH@highline#1 + \fi\fi} + +% choose rightmost position among \SH@posseg and lines near \SH@nline +\def\SH@mostoppositel#1#2#3{% #1: line, #2: indent, #3: width + \ifnum #1<\SH@lowline\else + \ifnum #1>\SH@highline\else + \advance\SH@highline-#1 + \dimen@#2\advance\dimen@#3\advance\dimen@\SH@octcase\relax + % \message{Compare #2 #3 at #1. Case \the\SH@highline=\SH@octcase: \the\dimen@}% + \ifdim \dimen@>\SH@posseg \SH@posseg\dimen@\fi + \advance\SH@highline#1 + \fi\fi} + +%\def\SH@updCOlines{% Update list of lines for cut-out +%\message{.}% +% \xdef\SH@lines{\SH@lines\@elt{\the\SH@nline}{\the\SH@posold}{\the\SH@widold}}% +% \advance\SH@npslines\@ne +% \SH@widold\SH@widseg \SH@posold\SH@posseg} + +\def\SH@getmaxline#1#2#3{\ifnum#1>\SH@nline \SH@nline#1\relax\fi} + +\def\SH@nextoctcase{% + \SH@posseg\AbsVal\SH@lowline\SH@refbase + \SH@widseg\cutoutsep + \ifdim\SH@posseg>\SH@posold + \advance\SH@widseg-\SH@posseg + \advance\SH@widseg \SH@posold + \fi + \xdef\SH@octcase{\SH@octcase \the\SH@widseg \or}% + \advance\SH@lowline\@ne + \ifnum\SH@lowline>\SH@highline\else + \expandafter\SH@nextoctcase \fi} + +% Ignore following spaces and \par +\def\SH@ignorepar{\afterassignment\SH@ignorepaR \let\SH@next=} +\def\SH@ignorepaR{%\show\SH@next + \edef\SH@nextspec{\noexpand\SH@next}% Hide \outer macros + \ifx\par\SH@next \let\SH@nextspec\SH@ignorepar \fi + \expandafter\ifx\space\SH@next \let\SH@nextspec\SH@ignorepar \fi + \SH@nextspec} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Take a square root of counter \sqrtcount using Newton's method. +% Usage: \sqrtcount= \sqrtofcount; gives square root in \sqrtcount +% To take sqrt of a dimen, do: +% \sqrtcount=\thedimen \sqrtofcount +% \multiply\sqrtcount by 256 \thedimen=\sqrtcount sp +% -- see \sqrtofdim +% +% (\@tempcnta and \@tempcntb are used and modified.) +\newcount\sqrtcount +\def\sqrtofcount{\relax\ifnum\sqrtcount>\z@ + \@tempcnta\sqrtcount \sqrtcount\@ne + \expandafter\squinitial\the\@tempcnta\relax\relax\relax + \squiterate +\else + \sqrtcount\@ne +\fi} +\def\squinitial#1#2{\ifx#1\relax \else + \ifx #2\relax \multiply\sqrtcount \thr@@ % 3 ~ sqrt(10) + \else \multiply\sqrtcount 10 + \fi \expandafter \squinitial + \fi} +\def\squiterate{\@tempcntb\@tempcnta \divide\@tempcntb\sqrtcount + %\message{sqrt(\the\@tempcnta) guess: \the\sqrtcount. }% + \advance\sqrtcount\@tempcntb \divide\sqrtcount\tw@ + \advance \@tempcntb -\sqrtcount + \ifnum \AbsVal\@tempcntb>\thr@@ % approximate, use 1 for exact + \expandafter \squiterate \fi}% expandafter to avoid stack overflows + +% Take sqrt of dimen register, as described above. +\def\sqrtofdim#1{% #1 = dimen register + \sqrtcount#1\sqrtofcount \multiply\sqrtcount\@cclvi #1=\sqrtcount sp\relax} + + + +\newcount\FPD@hi \FPD@hi=67108863 + +% Approximate Fixed Point Division of two dimensions +% 3.14159/2.71828 = 1.15573 +% Two parameters: Numerator and denominator. The answer is returned +% in the numerator (which must be a register). The denominator is +% unchanged, but it should also be a dimen register. (It may be given +% as an explicit *integer* string, "123", which is treated as 0.001877 +% = 123/65536.) % \@tempcntb is used and altered. +% +\def\fpdivide#1#2{\let\FPD@nume#1\@tempcntb#2\relax + \FPD@scale\FPD@scale\FPD@scale\FPD@scale + \divide#1\@tempcntb} + +% Rescale numbers to preserve accuracy. The number 16 is the level of +% uncertainty. Use a lower power of 2 for more accuracy (2 is most precise). +% But if you change it, you must change the repetions of \FPD@scale in +% \fpdivide above: magic_number^repetitions = 65536 (16^4 = 65536). +% +\def\FPD@scale{\ifnum\AbsVal\FPD@nume<\FPD@hi + \multiply\FPD@nume\sixt@@n + \else + \divide\@tempcntb\sixt@@n + \fi} + +% take absolute value of TeX number or dimension (dimen must be a register) +\def\AbsVal#1{\ifnum#1<\z@-\fi#1} + +\def\Pointless#1{\expandafter\remove@PT\the#1} +{\catcode`p=12 \catcode`t=12 \gdef\remove@PT#1pt{#1}} + +\squarepar % restore catcodes + +% ---------------- Pre-defined shapes -------------------- +% If you have (computer) memory problems, the following shape +% definitions can be eliminated. + +\def\diamondshape{{3}{0}b{3}\\{4}t{0}{6}\\{8}e{3}} +\def\diamondpar#1{\shapepar\diamondshape $\diamondsuit$ {#1} $\diamondsuit$\par} + +\def\squareshape{% + {1}% centerline at x=1 + {0}b{0}\\% begin at (0,0) + {0}t{0}{2}\\% text at y=0, width=2 + {2}t{0}{2}\\% text at y=2, width=2 + {2}e{1}% end at (1,2) +} +\def\squarepar#1{\shapepar{\squareshape}#1\par} + +\def\heartshape{% +{20}{0}b{13.32}b{26.68}% +\\{.14}t{10.12}{4.42}t{25.46}{4.42}% +\\{.7}t{9.14}{7.16}t{23.7}{7.16}% +\\{1.4}t{8.4}{9.02}t{22.58}{9.02}% +\\{2.1}t{7.82}{10.42}t{21.76}{10.42}% +\\{2.8}t{7.36}{11.58}t{21.06}{11.58}% +\\{3.5}t{6.98}{12.56}t{20.46}{12.56}% +\\{4.2}t{6.68}{13.32}jt{20}{13.32}% +\\{4.9}t{6.48}{27.04}% +\\{5.6}t{6.34}{27.32}% +\\{6.3}t{6.28}{27.44}% +\\{7}t{6.26}{27.48}% +\\{7.7}t{6.27}{27.46}% +\\{8.4}t{6.32}{27.36}% +\\{9.1}t{6.4}{27.2}% +\\{9.8}t{6.52}{26.96}% +\\{10.5}t{6.68}{26.64}% +\\{11.9}t{7.12}{25.76}% +\\{13.3}t{7.72}{24.56}% +\\{14.7}t{8.51}{22.98}% +\\{16.1}t{9.5}{21}% +\\{17.5}t{10.69}{18.62}% +\\{18.9}t{12.08}{15.84}% +\\{20.3}t{13.7}{12.6}% +\\{21.7}t{15.62}{8.76}% +\\{22.4}t{16.7}{6.6}% +\\{23.1}t{17.87}{4.26}% +\\{24.6}e{20}% +} +\def\heartpar#1{\shapepar{\heartshape}#1\unskip\unskip\penalty-300 +\ \ $\heartsuit$\par} + +\def\circleshape{% +{0.0}% +{0.0}b{0}\\% +{0.017}t{-0.129}{0.259}\\% +{0.067}t{-0.250}{0.500}\\% +{0.146}t{-0.354}{0.707}\\% +{0.250}t{-0.433}{0.866}\\% +{0.371}t{-0.483}{0.966}\\% +{0.500}t{-0.500}{1.000}\\% +{0.629}t{-0.483}{0.966}\\% +{0.750}t{-0.433}{0.866}\\% +{0.854}t{-0.354}{0.707}\\% +{0.933}t{-0.250}{0.500}\\% +{0.983}t{-0.129}{0.259}\\% +{1.0}e{0} +} +\def\circlepar#1{\Shapepar\circleshape #1\par} + +\def\nutshape{% +{0}% +{0}b{0}\\% +{0}t{-12.5}{25}\\% +{11.65}t{-19.23}{19.23}st{0}{19.23}\\% +{11.99}t{-19.42}{16.835}t{2.59}{16.835}\\% +{12.99}t{-20}{15}t{5}{15}\\% +{14.58}t{-20.92}{13.85}t{7.07}{13.85}\\% +{16.65}t{-22.11}{13.45}t{8.66}{13.45}\\% +{19.06}t{-23.51}{13.85}t{9.66}{13.85}\\% +{21.65}t{-25}{15}t{10}{15}\\% +{24.24}t{-23.51}{13.85}t{9.66}{13.85}\\% +{26.65}t{-22.11}{13.45}t{8.66}{13.45}\\% +{28.72}t{-20.92}{13.85}t{7.07}{13.85}\\% +{30.31}t{-20}{15}t{5}{15}\\% +{31.31}t{-19.42}{16.835}t{2.59}{16.835}\\% +{31.65}t{-19.23}{19.23}jt{0}{19.23}\\% +{43.3}t{-12.5}{25}\\% +{43.3}e{0}% +} +\def\nutpar#1{\Shapepar\nutshape #1\par} + +\def\CDlabshape{% +{0}% +{-5.5}b{0}\\% +{-5.3}t{-1.47}{2.94}\\% +{-4.8}t{-2.685}{5.37}\\% +{-3.9}t{-3.878}{7.756}\\% +{-2.8}t{-4.734}{9.468}\\% +{-2.5}t{-4.899}{4.899}st{0}{4.899}\\% +{-2.2}t{-5.04}{3.853}t{1.187}{3.853}\\% +{-1.2}t{-5.376}{3.174}t{2.193}{3.174}\\% +{0}t{-5.5}{3}t{2.5}{3}\\% +{1.2}t{-5.376}{3.174}t{2.193}{3.174}\\% +{2.2}t{-5.04}{3.853}t{1.187}{3.853}\\% +{2.5}t{-4.899}{4.899}jt{0}{4.899}\\% +{2.8}t{-4.734}{9.468}\\% +{3.9}t{-3.878}{7.756}\\% +{4.8}t{-2.685}{5.37}\\% +{5.3}t{-1.47}{2.94}\\% +{5.5}e{0}% +} +\def\CDlabel#1{\Shapepar[1cm]{\CDlabshape}#1\par} + +\def\starshape{% +{0}% +{-3}b{0}\\% +{-.927}t{-.674}{1.348}\\% +{-.927}t{-2.853}{5.706}\\% +{.354}t{-1.09}{2.18}\\% +{1.146}t{-1.347}{1.347}st{0}{1.347}\\% +{2.427}e{-1.763}e{1.763}% +} +\def\starpar#1{\shapepar\starshape #1\par} + +\endinput + +%------------------------------------------------------------------- + + S H A P E P A R . S T Y -- Instructions + +\shapepar is a macro to typeset paragraphs of a specified shape. +The total size is adjusted automatically so that the entire shape is +filled with text. This is distinct from the normal \parshape command +which specifies a shape *and* a size, which may be only partially +filled, or over-filled, from top to bottom. In a \shapepar there +can be no displayed math, and no "\vadjust" material, (including +"\vspace"). \Shapepar (capital S) is just like \shapepar except the +paragraph is boxed and not centered. Shaping paragraphs this way is a +slow process, so this is mainly intended for cards, invitations etc., +not for whole books! Although short paragraphs process much faster, +only long paragraphs accurately fill complex shapes. + +These macros work for both LaTeX and plain TeX. For LaTeX, specify +\usepackage{shapepar}, or for either, \input shapepar.sty. + +The command \shapepar should be used at the beginning of a paragraph, +and it applies to the entire paragraph. There is one optional length +parameter -- a fixed scale, , and one required parameter -- a +description of the shape, . + +\shapepar []{} Text of the paragraph... + +The text of the paragraph is not literally a *parameter*, so verbatim +macros will work there. + +Ordinarily, the scale is calculated automatically so the pargaraph +fills the shape. If a scale length is given, then the shape is +reproduced so one unit of the equals the , and +the shape is filled with whitespace after the paragraph text. + +The parameter is very complex, but there are a few +shapes predefined as macros in this file: \diamondshape, \heartshape +and \nutshape, which are used as examples in the instructions below. +There are also commands to use these shapes: \diamondpar, \squarepar +and \heartpar; for example, \heartpar begins \shapepar{\heartshape}#1 +so you can use it like: + +\heartpar{This paragraph is too short to be recognized as a heart shape.} + +The syntax rules for are very specific, and must be +followed closely. (In these rules, { } mean explicit braces, [ ] +denote optional parts, < > surround a keyword that is defined (perhaps +loosely), and | means "or"; do not type [ ] < > or |, but do type { }.) + + = {} + + = [\\] + +That is, the shape is specified as a single number in braces, followed +by the specifications for the lines, with the lines separated by \\. The +final paragraph will have its position centered on the page. + is a number (like 10.5) of arbitrary units; whatever units +are used for lengths and positions in the , they just need to be +consistent. + +The lines in the spec are not lines of text; nor are they the lines +that you would use to draw the shape itself. They are horizontal +scans across the shape at irregular intervals. Curved shapes need +many scan lines for accurate rendering while simple shapes need only +a few. To determine the line specifications, start by drawing the +shape on paper, then draw a series of horizontal lines across it, +including lines that just touch the top and the bottom of the figure. +Each line crosses over pieces of the figure in some region. These +intersections of line and figure define a . + + = {} [ other s ] + +The is the vertical position of the line. Each must +usually have a position greater than or equal to that of the previous +line, and with all > -1000. The exception is that between consecutive +lines relating to completely disconnected parts of the figure the +may decrease (backspacing). Position is measured from top to bottom, and +always moving down. Each represents a region where text will +go in the final paragraph; it is the segment of the horizontal scan line +that overlaps the body of the figure. There are five types of segment: + + = t{pos}{len} | b{pos} | e{pos} | s | j + + b{pos} begin text at a point at horizontal position pos + e{pos} end text at a point at horizontal position pos + t{pos}{len} make a block of text at position pos with length len + s split text (begin whitespace) + j join two text blocks (end a gap) + +The most common type of segment is t (text). The other types are +degenerate in that they are single points rather than finite segments. +Types s and j have no explicit position, but they must appear between +text segments, and those texts should abut; e.g., t{3}{2}st{5}{4} +(text from 3 to 5 and text from 5 to 9). + +Let's jump right into a simple example, and the meanings will be +clearer. A "diamond" shape can have the four vertices: + + (x=1,y=0) + . + +---> x + ! (0,1) . . (2,1) + ! + V y . + (1,2) + + +This shape can be exactly specified by just three scan lines passing +through the vertices. The specification is: + +{1}% h_center: x = 1 +{0}b{1}\\% text block begins at point y=0, x=1 +{1}t{0}{2}\\% this scan (at y=1) crosses text (len=2) starting at x=0 +{2}e{1} text block ends at point y=2, x=1 + +Other specification lines, like + +{1.5}t{0.5}{1}\\% + +could be inserted, but would make no difference--the shape is +interpolated linearly between scan lines. + +Every block of text must start with a b specifier and end with an e +spec on some line below. Every segment specified by t must have a +length greater than zero. If two blocks of text merge to form one (like +at the notch of a heart shape) there should be a j spec at the point of +junction. If one block bifurcates (like at the top of a hole in a +doughnut) there should be an s spec. + +Thus, the first line for any valid shape description must consist +of only b segment descriptors; the last line can only have e type +descriptors. Although the definition of the units is arbitrary, the +numbers should range in magnitude from ~.1 - 100 to avoid numeric +overflows and underflows. + +If there are errors in the format of the specification, \shapepar +might complain with the error message + + Shaped Paragraph Error: Error in specification. Check carefully! + +At this point you may as well type x or e, as there is very little +chance that TeX will continue successfully. You might also get one +of TeX's regular error messages, like + + Illegal unit of measure (pt inserted). +or + Missing number, treated as zero. + +or you might get no error message at all, just ridiculous formatting. +Check shape syntax carefully against the rules and the examples before +running them through TeX. + +What to do if the figure does not start at a point--if it has a flat +top? It can start at a single point, but have the next scan line at +the same vertical position! A square paragraph is specified by: + + {1}% centerline at x=1 (x=1 is horizontally centered on page) + {0}b{0}\\% begin at (0,0) + {0}t{0}{2}\\% text at y=0, width=2 + {2}t{0}{2}\\% text at y=2, width=2 + {2}e{1}% end at (1,2) + +Both \diamondpar and \squarepar are defined above as paragraphs with +these shapes. + +Now let's get more ambitious. A heart shape must have two simultaneous +beginnings, a short stretch of separate text, ending with a join, +whereafter there is just one stretch of text leading to the final +bottom point. This shape has many scan lines so that the smooth +flowing curves are preserved. + +\def\heartshape{% +{20}{0}b{13.32}b{26.68}% +\\{.14}t{10.12}{4.42}t{25.46}{4.42}% +\\{.7}t{9.14}{7.16}t{23.7}{7.16}% +\\{1.4}t{8.4}{9.02}t{22.58}{9.02}% +\\{2.1}t{7.82}{10.42}t{21.76}{10.42}% +\\{2.8}t{7.36}{11.58}t{21.06}{11.58}% +\\{3.5}t{6.98}{12.56}t{20.46}{12.56}% +\\{4.2}t{6.68}{13.32}jt{20}{13.32}% +\\{4.9}t{6.48}{27.04}% +\\{5.6}t{6.34}{27.32}% +\\{6.3}t{6.28}{27.44}% +\\{7}t{6.26}{27.48}% +\\{7.7}t{6.27}{27.46}% +\\{8.4}t{6.32}{27.36}% +\\{9.1}t{6.4}{27.2}% +\\{9.8}t{6.52}{26.96}% +\\{10.5}t{6.68}{26.64}% +\\{11.9}t{7.12}{25.76}% +\\{13.3}t{7.72}{24.56}% +\\{14.7}t{8.51}{22.98}% +\\{16.1}t{9.5}{21}% +\\{17.5}t{10.69}{18.62}% +\\{18.9}t{12.08}{15.84}% +\\{20.3}t{13.7}{12.6}% +\\{21.7}t{15.62}{8.76}% +\\{22.4}t{16.7}{6.6}% +\\{23.1}t{17.87}{4.26}% +\\{24.6}e{20}% +} + +Look at \heartshape and find the two b specifiers at the beginning; find +the j a few lines below. Notice that above the j there are two segments +per line, but only one below it; the text to the left and right of the +join meet at the join point: 20. I drew this heart freehand, and measured +lengths from the sketch, so you should be able to do better! + +Text can have holes. For example, a doughnut-shape would have a b on +the first line, followed by some lines with a single t, then a line with +t s t at the start of the hole. The hole is represented by lines with two +t specs--the gap between them is the hole. A line with t j t ends the +hole. There are more lines with single t, and then an e line to end +with. Our final example is a nut. Not a doughnut, but a hex-nut (for a +machine screw) -- a regular hexagon with a circular hole in the center. +The hexagon is flat on top and bottom so the specification begins and +ends like the square shape. The circle is rendered as a 24-gon, beginning +with a split (s) of the surrounding text and ending with a join (j). If +the spacing of the scan lines looks odd, it is because the hexagon alone +would need few scans, but the circle needs many; the points on the circle +are at 15 degree intervals. + +\def\nutshape{% +{0}% +{0}b{0}\\% +{0}t{-12.5}{25}\\% +{11.65}t{-19.23}{19.23}st{0}{19.23}\\% +{11.99}t{-19.42}{16.835}t{2.59}{16.835}\\% +{12.99}t{-20}{15}t{5}{15}\\% +{14.58}t{-20.92}{13.85}t{7.07}{13.85}\\% +{16.65}t{-22.11}{13.45}t{8.66}{13.45}\\% +{19.06}t{-23.51}{13.85}t{9.66}{13.85}\\% +{21.65}t{-25}{15}t{10}{15}\\% +{24.24}t{-23.51}{13.85}t{9.66}{13.85}\\% +{26.65}t{-22.11}{13.45}t{8.66}{13.45}\\% +{28.72}t{-20.92}{13.85}t{7.07}{13.85}\\% +{30.31}t{-20}{15}t{5}{15}\\% +{31.31}t{-19.42}{16.835}t{2.59}{16.835}\\% +{31.65}t{-19.23}{19.23}jt{0}{19.23}\\% +{43.3}t{-12.5}{25}\\% +{43.3}e{0}% +} + +\shapepar cheats a bit when the horizontal gap between two bits of text +is small (like down in the notch of \heartpar). When the gap is less +than an interword space it is eliminated, and the texts are joined; when +it is somewhat larger it is expanded to give it more visibility. If you +want to eliminate this behavior, move the following definitions up into +the main part of the file. + +See shapepar.tex for more detailed instructions. + +%----------------------------------------- +Version 2.00 (Dec 2002) \cutout, disjoint parts, set scale, much rewrite +Version 1.01 (March 1993) Small changes from initial release. + +% +% Test integrity of file: +% brackets: round, square, curly, angle: () [] {} <> +% backslash, slash, vertical, at, dollar, and: \ / | @ $ & +% hat, grave, acute (apostrophe), quote, tilde: ^ ` ' " ~ -- cgit v1.2.3