diff options
Diffstat (limited to 'tex/context/base/supp-fun.mkiv')
-rw-r--r-- | tex/context/base/supp-fun.mkiv | 716 |
1 files changed, 716 insertions, 0 deletions
diff --git a/tex/context/base/supp-fun.mkiv b/tex/context/base/supp-fun.mkiv new file mode 100644 index 000000000..33bee0306 --- /dev/null +++ b/tex/context/base/supp-fun.mkiv @@ -0,0 +1,716 @@ +%D \module +%D [ file=supp-fun, +%D version=1995.10.10, +%D title=\CONTEXT\ Support Macros, +%D subtitle=Fun Stuff, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D Beware, these macros wil be replaced and at some point this +%D module will not be preloaded any more. + +%D This module implements some typographics tricks that can +%D be fun when designing document layouts. The examples use +%D macros that are typical to \CONTEXT, but non \CONTEXT\ +%D users can use the drop caps and first line treatment +%D macros without problems. This module will be extended +%D when the need for more of such tricks arises. + +\writestatus{loading}{ConTeXt Support Macros / Fun Stuff} + +%D \macros +%D {DroppedCaps, DroppedString, DroppedIndent, DroppedLines} +%D +%D \startbuffer +%D \DroppedCaps +%D {\color[green]} {SerifBold} +%D {\the\dimexpr2.2\baselineskip} {2pt} {\the\baselineskip} {2} +%D Let's start +%D \stopbuffer +%D +%D \getbuffer with dropped caps, those blown up first +%D characters of a paragraph. It's hard to implement a general +%D mechanism that suits all situations, but dropped caps are so +%D seldomly used that we can permit ourselves a rather user +%D unfriendly implementation. +%D +%D \typebuffer +%D +%D As we will see, there are 7 different settings involved. The +%D first argument takes a command that is used to do whatever +%D fancy things we want to do, but normally this one will be +%D empty. The second argument takes the font. Because we're +%D dealing with something very typographic, there is no real +%D reason to adopt complicated font switching schemes, a mere +%D name will do. Font encodings can bring no harm, because the +%D alphanumeric characters are nearly always located at their +%D natural position in the encoding vector. +%D +%D \startbuffer +%D \DroppedCaps +%D {\color[red]} {SerifBold} +%D {\the\baselineskip} {0pt} {0pt} {1} +%D This simple +%D \stopbuffer +%D +%D \getbuffer case shows us what happens when we apply minimal +%D values. Here we used: +%D +%D \typebuffer +%D +%D \startbuffer +%D \DroppedCaps +%D {\color[red]} {SerifBold} +%D {\the\dimexpr2\baselineskip} {0pt} {\the\baselineskip} {2} +%D Is this ugly +%D \stopbuffer +%D +%D \getbuffer example the third argument tells +%D this macro that we want a dropped capital scaled to the +%D baseline distance. The two zero point arguments are the +%D horizontal and vertical offsets and the last arguments +%D determines the hanging indentation. In this paragraph we +%D set the height to two times the baselinedistance and use +%D two hanging lines: +%D +%D \typebuffer +%D +%D Here, the first character is moved down one baseline. Here +%D we also see why the horizontal offset is important. The +%D first example (showing the~L) sets this to a few points and +%D also used a slightly larger height. +%D +%D Of course common users (typist) are not supposed to see this +%D kind of fuzzy definitions, but fortunately \TEX\ permits us +%D to hide them in macros. Using a macro also enables us to +%D garantee consistency throughout the document: +%D +%D \startbuffer +%D \def\MyDroppedCaps% +%D {\DroppedCaps +%D {\color[green]} {SerifBold} +%D {\the\dimexpr5\baselineskip} {3pt} {\the\dimexpr3\baselineskip} {4}} +%D +%D \MyDroppedCaps The implementation +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer of the general macro is rather simple and only +%D depends on the arguments given and the dimensions of the +%D strut box. We explicitly load the font, which is no problem +%D because \TEX\ does not load a font twice. We could have +%D combined some arguments, like the height, vertical offset +%D and the number of lines, but the current implementation +%D proved to be the most flexible. One should be aware of the +%D fact that the offsets depend on the design of the glyphs +%D used. + +\let\DroppedIndent\!!zeropoint \def\DroppedLines{0} + +\def\DroppedString{ABCDEFGHIJKLMNOPQRSTUVWXYZ} + +\let\globaldropcaps\global % will be an option, but on by default + +\def\localdropcaps{\let\globaldropcaps\relax} + +\chardef\DroppedStatus = 0 % 0=done 1=starting 2=doing 3=error +\chardef\DropMode = 0 % 1 == marginhang + +\ifx\keeplinestogether\undefined + \let\keeplinestogether\gobbleoneargument +\fi + +\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars + {\defconvertedargument\asciia{#7}% + \defconvertedcommand \asciib{\DroppedString}% + \doifinstringelse\asciia\asciib + {\noindentation + \dontleavehmode + \checkindentation % redo this one + %\ifhmode\hskip-\parindent\fi % sensitive for context mechanism + \keeplinestogether{#6}% + \setbox0\hbox{\definedfont[#2 at #3]#1{#7}\hskip#4}% + \ifdim\dp0>\strutdp % one of those Q's , will be option + \setbox2\hbox{\raise\dp0\hbox{\lower\strutdp\copy0}}% + \ht2\ht0 + \dp0\strutdp + \setbox0\box2 + \fi + \setbox0\hbox + {\ifnum\DropMode=\plusone + \hskip-\wd0\wd0\zeropoint + \fi + \lower#5\box0}% + \ht0\strutht + \dp0\strutdp + \ifnum\DropMode=\plusone + \globaldropcaps\let\DroppedIndent\!!zeropoint + \globaldropcaps\edef\DroppedLines{\number\maxdimen}% + \globaldropcaps\chardef\DroppedStatus\plusthree + \else + \globaldropcaps\edef\DroppedIndent{\the\wd0}% + \globaldropcaps\edef\DroppedLines {\number#6}% + \globaldropcaps\chardef\DroppedStatus\plustwo + \globaldropcaps\hangindent\DroppedIndent + \globaldropcaps\hangafter-\DroppedLines +% \noindent + \noindentation + \checkindentation % redo this one + \hskip-\DroppedIndent + \fi + \vbox{\forgetall\box0}% + \nobreak + \let\next\ignorespaces} % Could be a one character word ! + {\globaldropcaps\let\DroppedIndent\!!zeropoint + \globaldropcaps\edef\DroppedLines{\number\maxdimen}% + \globaldropcaps\chardef\DroppedStatus\plusthree + \def\next{#7}}% + \let\globaldropcaps\global + \next} + +%D Before we go to the next topic, we summarize this command: +%D +%D \starttyping +%D \DroppedCaps +%D {command} {font} +%D {height} {hoffset} {voffset} {lines} +%D \stoptyping +%D +%D Sometimes you need to make sure that the global settings are +%D kept local, as in: +%D +% %D \startbuffer +% %D \defineparagraphs[SomePar][n=2,rule=on] +% %D \setupparagraphs [SomePar][1][width=.5\textwidth] +% %D \setupparagraphs [SomePar][2][width=.5\textwidth] +%D \startbuffer +%D \defineparagraphs[SomePar][n=2,rule=on] +%D \setupparagraphs [SomePar][1][width=.5\textwidth] +%D \setupparagraphs [SomePar][2][width=.5\textwidth] +%D +%D \startSomePar +%D \localdropcaps\NiceDroppedCaps{}{cmr12}{0pt}{2}Here we need +%D to explicitly keep the hanging indentation local, like it or +%D not. +%D \SomePar +%D \localdropcaps\NiceDroppedCaps{}{cmr12}{0pt}{2}Here we need +%D to explicitly keep the hanging indentation local, like it or +%D not. +%D \stopSomePar +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {AutoDroppedCaps, CheckDroppedCaps} +%D +%D {\em To be documented.} + +% example usage +% +% \def\bpar{\ifvmode\CheckDroppedCaps\fi} +% \def\epar{\ifhmode\par\fi\CheckDroppedCaps} + +\newcount\lastprevgraf +\newcount\droppedlines + +\def\CheckDroppedCaps + {\global\lastprevgraf\prevgraf} + +\def\AutoDroppedCaps % will be proper core stuff since it + {\globaldropcaps\chardef\DroppedStatus\plusone + \global\lastprevgraf\zerocount + \global\droppedlines\zerocount + \EveryPar{\doAutoDroppedCaps}} + +\let\AutoDroppedNext\relax + +\ifx\AutoDroppedCapsCommand\undefined + \def\AutoDroppedCapsCommand{\NiceDroppedCaps{}{SerifBold}{.125em}{3}} +\fi + +\def\doAutoDroppedCaps + {\ifcase\DroppedStatus % done + \let\next\relax + \or % starting + % \ifnum\lastprevgraf>0 % tricky, probably a wrong par + % \globaldropcaps\chardef\DroppedStatus=3 % and inhibits dropped + % \let\next\relax % caps after titles and more than once + % \else % so let's nill this rubishly code fragment + \let\next\AutoDroppedCapsCommand + % \fi % and hope for the best + \or % doing + \global\advance\droppedlines \lastprevgraf + \ifnum\droppedlines=\zerocount + \globaldropcaps\chardef\DroppedStatus\zerocount + \let\next\relax + \else\ifnum\droppedlines>\zerocount + \ifnum\droppedlines<\DroppedLines\relax + \globaldropcaps\hangindent\DroppedIndent + \globaldropcaps\hangafter-\DroppedLines + \globaldropcaps\advance\hangafter \droppedlines + \hskip-\parindent % brrr + \let\next\AutoDroppedNext + \else + \globaldropcaps\chardef\DroppedStatus\zerocount + \let\next\relax + \fi + \else + \globaldropcaps\chardef\DroppedStatus\zerocount + \let\next\relax + \fi\fi + \or % error + \globaldropcaps\chardef\DroppedStatus\zerocount + \let\next\relax + \fi + \next} + +%D \macros +%D {LineDroppedCaps, NiceDroppedCaps} +%D +%D To save definitions, we also provide: +%D +%D \starttyping +%D \LineDroppedCaps {command} {font} {hoffset} {lines} +%D \NiceDroppedCaps {command} {font} {hoffset} {lines} +%D \stoptyping +%D +%D The first command scales the font to the exact height, while +%D the second command scales the font to a nice 2.5 times the +%D line height, a value that gives a pleasant grayness. + +\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines + {\scratchcounter#5% + \advance\scratchcounter \minusone + \scratchdimen\scratchcounter\baselineskip + \advance\scratchdimen #1% + \NormalizeFontHeight\DummyFont{W}\scratchdimen{#3}% + \DroppedCaps{#2}{#3}\TheNormalizedFontSize{#4} + {\scratchcounter\baselineskip}{#5}} + +\def\LineDroppedCaps% command font offset lines + {\DoLineDroppedCaps{\strutht}} + +\def\NiceDroppedCaps% command font offset lines + {\DoLineDroppedCaps{.5\baselineskip}} + +%D \macros +%D {TreatFirstLine} +%D +%D \startbuffer +%D \TreatFirstLine {\sc} {} {} {} +%D Instead of limiting its action to one token, the next macro +%D treats the whole first line. This paragraph was typeset by +%D saying: +%D \stopbuffer +%D +%D \getbuffer +%D +%D \typebuffer +%D +%D \startbuffer +%D \TreatFirstLine {\startcolor[red]\bf} {\stopcolor} {} {} +%D The combined color and font effect is also possible, +%D although one must be careful in using macros that accumulate +%D grouping, but the commands used here are pretty save in that +%D respect. +%D \stopbuffer +%D +%D \getbuffer +%D +%D \typebuffer +%D +%D Before we explain the third and fourth argument, we show the +%D implementation. Those who know a bit about the way \TEX\ +%D treats tokens, will probably see in one glance that this +%D alternative works all right for most text||only situations +%D in which there is enough text available for the first line, +%D but that more complicated things will blow. One has to live +%D with that. A workaround is rather trivial but obscures the +%D principles used. + +\def\TreatFirstLine#1#2#3#4% before, after, first, next + {\leavevmode + \bgroup + \forgetall + \bgroup + #1% + \setbox0\emptybox + \setbox2\emptybox + \def\grabfirstline##1 % + {\setbox2\hbox + {\ifvoid0 + {#3{\ignorespaces##1}}% + \else + \unhcopy0\ {#4{##1}}% + \fi}% + \ifdim\wd2=\zeropoint + \setbox0\emptybox + \setbox2\emptybox + \@EA\grabfirstline + \else\ifdim\wd2>\hsize + \hbox to \hsize{\strut\unhbox0}#2\egroup + \break##1\ + \egroup + \else + \setbox0\box2 + \@EAEAEA\grabfirstline + \fi\fi}% + \grabfirstline} + +%D \startbuffer +%D \gdef\FunnyCommand +%D {\getrandomfloat\FunnyR{0}{1}% +%D \getrandomfloat\FunnyG{0}{1}% +%D \getrandomfloat\FunnyB{0}{1}% +%D \definecolor[FunnyColor][r=\FunnyR,g=\FunnyG,b=\FunnyB]% +%D \color[FunnyColor]} +%D +%D %\TreatFirstLine {\bf} {} {\FunnyCommand} {\FunnyCommand} +%D The third and fourth argument can be used to gain special +%D effects on the individual words. Of course one needs ... +%D \stopbuffer +%D +%D \getbuffer +%D to know a bit more about the macro package used to get real +%D nice effects, but this example probably demonstrates the +%D principles well. +%D +%D \typebuffer +%D +%D Like in dropped caps case, one can hide such treatments in a +%D macro, like: +%D +%D \starttyping +%D \def\MyTreatFirstLine% +%D {\TreatFirstLine{\bf}{}{\FunnyCommand}{\FunnyCommand}} +%D \stoptyping + +%D \macros +%D {reshapebox} +%D +%D \startbuffer +%D \beginofshapebox +%D When using \CONTEXT, one can also apply this funny command +%D to whole lines by using the reshape mechanism. Describing +%D this interesting mechanism falls outside the scope of this +%D module, so we only show the trick. This is an example of +%D low level \CONTEXT\ functionality: it's all there, and it's +%D stable, but not entirely meant for novice users. +%D \endofshapebox +%D +%D \reshapebox{\FunnyCommand{\box\shapebox}} \flushshapebox +%D \stopbuffer +%D +%D \getbuffer +%D +%D \typebuffer +%D +%D This mechanism permits hyphenation and therefore gives +%D better results than the previously discussed macro +%D \type{\TreatFirstLine}. + +%D \macros +%D {TreatFirstCharacter} +%D +%D \startbuffer +%D \TreatFirstCharacter{\bf\color[green]} Just to be +%D \stopbuffer +%D +%D \getbuffer complete we also offer a very simple one +%D character alternative, that is not that hard to understand: + +\def\TreatFirstCharacter#1#2% command, character + {{#1{#2}}} + +%D A previous paragraph started with: +%D +%D \typebuffer + +%D \macros +%D {StackCharacters} +%D +%D The next hack deals with vertical stacking. + +\def\StackCharacters#1#2#3#4% sequence vsize vskip command + {\vbox #2 + {\forgetall + \baselineskip\zeropoint + \def\StackCharacter##1{#4{##1}\cr\noalign{#3}}% + \halign + {\hss##\hss&##\cr + \handletokens#1\with\StackCharacter\cr}}} + +%D \startbuffer +%D \StackCharacters{CONTEXT}{}{\vskip.2ex}{\FunnyCommand} +%D \stopbuffer +%D +%D Such a stack looks like: +%D +%D \startlinecorrection +%D \hbox to \hsize +%D {$\hss\bfd +%D \vcenter{\StackCharacters{TEX} {}{\vskip.2ex}{\FunnyCommand}}% +%D \hss +%D \vcenter{\StackCharacters{CON} {}{\vskip.2ex}{\FunnyCommand}} +%D \hss +%D \vcenter{\StackCharacters{TEXT} {}{\vskip.2ex}{\FunnyCommand}} +%D \hss +%D \vcenter{\StackCharacters{CONTEXT}{}{\vskip.2ex}{\FunnyCommand}} +%D \hss$} +%D \stoplinecorrection +%D +%D and is typeset by saying: +%D +%D \typebuffer +%D +%D An alternative would have been +%D +%D \starttyping +%D \StackCharacters {CONTEXT} {to 5cm} {\vfill} {\FunnyCommand} +%D \stoptyping + +%D \macros +%D {processtokens} +%D +%D At a lower level horizontal and vertical manipulations are +%D already supported by: +%D +%D \starttyping +%D \processtokens {begin} {between} {end} {space} {text} +%D \stoptyping +%D +%D \startbuffer[a] +%D \processtokens +%D {\hbox to .5\hsize\bgroup} {\hfill} +%D {\egroup} {\space} {LET'S HAVE} +%D \stopbuffer +%D +%D \startbuffer[b] +%D \processtokens +%D {\vbox\bgroup\raggedcenter\hsize1em} +%D {\vskip.25ex} {\egroup} {\strut} {FUN} +%D \stopbuffer +%D +%D This macro is able to typeset: +%D +%D \leavevmode\hbox to \hsize +%D {$\hfil\hfil +%D \vcenter{\bf\getbuffer[a]}% +%D \hfil +%D \vcenter{\bfd\getbuffer[b]}% +%D \hfil\hfil$} +%D +%D which was specified as: +%D +%D \typebuffer[a] +%D \typebuffer[b] + +%D \macros +%D {NormalizeFontHeight, NormalizeFontWidth, +%D TheNormalizedFontSize} +%D +%D Next we introduce some font manipulation macros. When we +%D want to typeset some text spread in a well defined area, it +%D can be considered bad practice to manipulate character and +%D word spacing. In such situations the next few macros can be +%D of help: +%D +%D \starttyping +%D \NormalizeFontHeight \name {sample text} {height} {font} +%D \NormalizeFontWidth \name {sample text} {width} {font} +%D \stoptyping +%D +%D These are implemented using an auxilliary macro: + +\def\NormalizeFontHeight{\NormalizeFontSize\ht} +\def\NormalizeFontWidth {\NormalizeFontSize\wd} + +\def\NormalizeFontSize#1#2#3#4#5% + {\bgroup + \dimen0=#4% #4 can be \ht0 or so + \setbox0\hbox{\definedfont[#5 at 5pt]#3}% 10pt + \ifdim\wd0>\zeropoint + \dimen2=#10 % #1 is \wd or \ht + \dimen4=\maxdimen % 10000pt + \divide\dimen4 \dimen2 + \divide\dimen0 1638 % 1000 + \dimen0=\number\dimen4\dimen0 + \divide \dimen0 \plustwo % ... + \xdef\TheNormalizedFontSize{\the\dimen0}% + \else + \dimen0\bodyfontsize + \fi + \normalexpanded{\egroup\def\noexpand#2{\definedfont[#5 at \the\dimen0]}}} + +%D Afterwards, we have access to the calculated size by: + +\let\TheNormalizedFontSize\!!zeropoint + +%D Extra: + +\def\WidthSpanningText#1#2#3% text width font + {\hbox{\NormalizeFontWidth\temp{#1}{#2}{#3}\temp\the\everydefinedfont#1}} + +%D Consider for instance: +%D +%D \startbuffer +%D \NormalizeFontHeight \tmp {X} {2\baselineskip} {cmr10} +%D +%D {\tmp To Be Or Not To Be} +%D \stopbuffer +%D +%D \typebuffer +%D +%D This shows up as (we also show the baselines): +%D +%D {\showbaselines\getbuffer} +%D +%D The horizontal counterpart is: +%D +%D \startbuffer +%D \NormalizeFontWidth \tmp {This Line Fits} {\hsize} {cmr10} +%D +%D \hbox{\tmp This Line Fits} +%D \stopbuffer +%D +%D \typebuffer +%D +%D The calculated font scale is avaliable in the macro +%D \type{\NormalizedFontSize}. +%D +%D \startlinecorrection +%D \ruledhbox{\getbuffer} +%D \stoplinecorrection +%D +%D One can of course combine these macros with the ones +%D described earlier, like in: +%D +%D \starttyping +%D \NormalizeFontHeight {text} \DroppedFont {2\baselineskip} {cmbx12} +%D +%D \def\NicelyDroppedCaps +%D {\DroppedCaps +%D {\color[green]} +%D {\DroppedFont} +%D {2pt} +%D {\baselineskip} +%D {2}} +%D \stoptyping +%D +%D It's up to the reader to test this one. + +\unexpanded\def\FirstNCharacters#1#2% \FirstNCharacters{3}{fr{\"o}beln} + {\bgroup + \scratchcounter\zerocount + \def\docommand##1% + {\ifnum\scratchcounter=#1\else + ##1\relax % catches ##1 = \"e and alike + \advance\scratchcounter\plusone + \fi} + \handletokens#2\with\docommand + \egroup} + +%D \macros +%D {FittingText} +%D +%D First used in Pascal (demo-bbv): +%D +%D \startbuffer +%D \ruledvbox{\FittingText{3cm}{1cm}{Serif}{24pt}{1pt}{1} +%D {\veryraggedright +%D \hangindent1em\hangafter1\relax +%D \begstrut \dorecurse{8}{Bram Marta }\unskip \endstrut}} +%D +%D \ruledvbox{\FittingText{3cm}{1cm}{Serif}{24pt}{1pt}{1} +%D {\raggedleft\begstrut Bram\\Marta \unskip\endstrut}} +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection + +% #1 width #2 height #3 font #4 size #5 step #6 interlinie #7 text + +\long\def\FittingText#1#2#3#4#5#6#7% + {\bgroup + \forgetall + \dontcomplain + \setuptolerance[\v!verytolerant]% == \tolerance4500 + \hsize#1% + \def\\{\softbreak}% + \!!heighta#4% + \!!heightb#2% + \doloop + {\ifdim\!!heighta>\onepoint + \expanded{\definefont[\s!dummy][#3 at \the\!!heighta][\c!interlinespace=#6]}% + \getvalue\s!dummy + \setbox\scratchbox\vbox{#7\endgraf}% + \ifdim\ht\scratchbox>\!!heightb + \advance\!!heighta-#5% + \else + \beginshapebox + \unvcopy\scratchbox + \endshapebox + \global\dimen1\hsize + \reshapebox + {\setbox\shapebox\hbox{\unhbox\shapebox}% + \ifdim\wd\shapebox>\dimen1 + \global\dimen1\wd\shapebox + \fi}% + \ifdim\dimen1>\hsize + \advance\!!heighta-#5% + \else + \exitloop + \fi + \fi + \else + \exitloop + \fi}% + %\writestatus{\strippedcsname\FittingText}{height: \the\!!heighta}% + \unvbox\scratchbox + \egroup} + +%D New: + +% \font width gap font spec text + +\def\NormalizeFontWidthSpread#1#2#3#4#5#6% + {\global\setfalse\NFSpread + \scratchdimen#3% + \scratchdimen-.5\scratchdimen + \advance\scratchdimen#2\relax + \NormalizeFontWidth + #1% + {\def\+{\global\settrue\NFSpread\gobbleuntil\relax}% + \def\\{\gobbleuntil\relax}% newline + \setupspacing + #6\relax}% + {\scratchdimen}% + {#4}% + \ifconditional\NFSpread + % de gap valt in de binding + \else + \definefont[\strippedcsname#1][#4 #5]% + \fi} + +\def\SpreadGapText#1#2% + {{\def\+{\kern#1}#2}} + +\def\GapText#1#2#3#4#5% width distance font spec title + {\bgroup + \NormalizeFontWidthSpread\DummyFont{#1}{#2}{#3}{#4}{#5}% + \DummyFont\setupspacing\SpreadGapText{#2}{#5}\endgraf + \egroup} + +\protect \endinput |