summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/magazines/mag-0010-mkiv.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/context/sources/general/magazines/mag-0010-mkiv.tex')
-rw-r--r--doc/context/sources/general/magazines/mag-0010-mkiv.tex531
1 files changed, 531 insertions, 0 deletions
diff --git a/doc/context/sources/general/magazines/mag-0010-mkiv.tex b/doc/context/sources/general/magazines/mag-0010-mkiv.tex
new file mode 100644
index 000000000..65c20180c
--- /dev/null
+++ b/doc/context/sources/general/magazines/mag-0010-mkiv.tex
@@ -0,0 +1,531 @@
+% language=uk
+
+% author : Hans Hagen
+% copyright : PRAGMA ADE & ConTeXt Development Team
+% license : Creative Commons Attribution ShareAlike 4.0 International
+% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions
+% origin : the ConTeXt distribution
+%
+% comment : Because this manual is distributed with TeX distributions it comes with a rather
+% liberal license. We try to adapt these documents to upgrades in the (sub)systems
+% that they describe. Using parts of the content otherwise can therefore conflict
+% with existing functionality and we cannot be held responsible for that. Many of
+% the manuals contain characteristic graphics and personal notes or examples that
+% make no sense when used out-of-context.
+%
+% comment : Some chapters might have been published in TugBoat, the NTG Maps, the ConTeXt
+% Group journal or otherwise. Thanks to the editors for corrections. Also thanks
+% to users for testing, feedback and corrections.
+
+\usemodule[mag-01,abr-02]
+
+\startbuffer[abstract]
+ The content of tenth magazine was written while listening to Tori Amos'
+ latest album, The Beekeeper. In the (nice) booklet the text flows in shapes
+ and here I will demonstrate that \TEX\ can do something similar. It's also a
+ nice example of applying \HZ\ optimization.
+\stopbuffer
+
+\startdocument
+ [title={Good looking shapes},
+ author=Hans Hagen,
+ affiliation=PRAGMA ADE,
+ date=March 2005,
+ number=10 \MKIV]
+
+Just as it takes while to get an understanding what \TEX\ is about, it takes a
+couple of listening loops to get a general picture about Tori Amos' Beekeeper.
+While browsing the rather nicely designed booklet I got puzzled |<|as usual when
+seeing such nice book(let)s|>| why everything looked okay except the text. High
+end design combined with rather low end typography. Don't get me wrong, apart
+from the typesetting it's a pretty good product! Tori being one of my favourite
+artists, you can imagine that I wrote quite some \CONTEXT\ code listening to her
+music.
+
+Now I will not argue that \TEX\ (or \CONTEXT) is the proper system for making
+\CD\ covers, but since most of such a booklet is a matter of pasting graphics
+components together, I can imagine that one should ask someone to typeset the
+text snippets using a proper engine. Anyway, most buyers (fans) won't notice it,
+but anyone familiar with \TEX\ will immediate get distracted by the strange
+intercharacter and interline spacing.
+
+Typesetting in a fixed shape is non||trivial. First of all lines should break in
+a pleasing way. If possible, hyphenation should be avoided. The gaps between
+characters must not become to large and the last line should not be too short.
+Doing this in \TEX\ is non trivial either, not so much because \TEX\ cannot do
+such things, but because one needs to control several mechanisms at once. On the
+other hand, one should know what one's dealing with anyway.
+
+Because the size of the shape is fixed, we can manipulate the number of lines
+and/or the line length and scale afterwards to the desired size. The font size is
+not fixed. This permits us to implement a semi||automated solution. The
+difference between the first version of the solution and current one is that we
+take into account an odd|/|even number of lines. Also, finding the best exit
+condition took some experiments. The final solution is not that complex and also
+shows a couple of tricks.
+
+\startbuffer
+\definecolor[BeeColorA][r=.4,g=.5,b=.6]
+\definecolor[BeeColorB][r=.5,g=.6,b=.4]
+\definecolor[BeeColorC][r=.6,g=.4,b=.5]
+
+\definecolor[BeeColor] [BeeColorA]
+
+\defineoverlay
+ [beecell]
+ [\uniqueMPgraphic{beecell}{offset=3mm,color=BeeColor}]
+
+\startuniqueMPgraphic{beecell}{offset,color}
+ fill
+ for i = 1 upto 6 : (0,OverlayHeight/2)
+ rotatedaround (center OverlayBox,i*60) --
+ endfor cycle
+ withpen pencircle scaled \MPvar{offset}
+ withcolor \MPvar{color} ;
+\stopuniqueMPgraphic
+\stopbuffer
+
+\getbuffer
+
+The shape we are dealing with looks as follows:
+
+\startlinecorrection
+\startMPcode
+ fill
+ for i = 1 upto 6 : (5cm,0)
+ rotatedaround(origin,i*60) --
+ endfor cycle
+ withpen pencircle scaled 2mm
+ withcolor \MPcolor{BeeColorC} ;
+ currentpicture := currentpicture xsized(5cm) ;
+\stopMPcode
+\stoplinecorrection
+
+We will will later put such a shape behind the text for which we define an
+overlay:
+
+\typebuffer
+
+Normally one will not put a shape behind the text, but in our case it illustrates
+the idea. We use an offset in order to get a more pleasing look.
+
+We will use the following two sample texts. The original linebreaks are visible
+in the source:
+
+\startbuffer
+\startbuffer[parasol]
+\title {PARASOL} when I come to
+terms to terms with this when
+I come to terms with this when I
+come to terms to terms with this my
+world will change for me I haven't moved
+since the call came since the call came I
+haven't moved I stare at the wall knowing on the
+other side the storm that waits for me then the
+Seated Woman with a Parasol may be the only one you
+can't Betray if I'm the Seated Women with a Parasol I will
+be safe in my frame I have no need for a sea view for a sea
+view I have no need I have my little pleasures this wall
+being one of these when I come to terms to terms
+with this when I come to terms with this when I
+come to terms with this whip lash of Silk on
+wool embroidery then the Seated Woman
+with a Parasol may be the only one you
+can't betray if I'm the Seated Woman
+with a Parasol I will be safe in my
+frame I will be safe in my frame
+in your House in your frame
+\stopbuffer
+
+\startbuffer[beekeeper]
+\title {THE BEEKEEPER} Flaxen hair
+blowing in the breeze It is time
+for the geese to head south I have
+come with my mustard seed I cannot
+accept that she will be taken from me
+``Do you know who I am'' she said ``I'm the
+one who taps you on the shoulder when it's
+your time Don't be afraid I promise that she
+will awake Tomorrow Somewhere Tomorrow
+Somewhere'' --- wrap yourself around the Tree of
+Life and the Dance of the Infinity of the Hive --- take
+this message to Michael I will comb myself into chains In
+between the tap dance clan and your ballerina gang I have
+come for the Beekeeper I know you want my You want
+my Queen --- Anything but this Can you use me instead?
+In your gown with your breathing mask Plugged into
+a heart machine As if you ever needed one I must
+see the Beekeeper I must see if she'll keep her
+alive Call Engine 49 I have come with my
+mustard seed Maybe I'm passing you by
+On my way On my way I'm just passing
+you by But don't be confused
+One day I'll be coming for you \unknown\space
+I must see the Beekeeper
+I must see the Beekeeper
+\stopbuffer
+\stopbuffer
+
+\typebuffer \getbuffer
+
+We will call these buffers indirectly (using setups is a convenient way to
+collect commands and definitions).
+
+\startbuffer
+\startsetups [beetext]
+ \getbuffer[parasol]
+\stopsetups
+\stopbuffer
+
+\typebuffer \getbuffer
+
+Now comes the dirty code. We assume that you know a bit of \CONTEXT. First of all
+we choose a font, in our case a Termes for the running text. We will use
+Hermann Zapf optimization, which is way more acceptable that intercharacter
+spacing and gives quite good results here.
+
+\startbuffer
+\definefontfeature[hzdefault][default][hz=quality]
+\definefont[BeeFont][file:texgyre-termes*hzdefault]
+\stopbuffer
+
+\typebuffer \getbuffer
+
+The core of the code is a loop wherein we try to figure out what the best width
+is. In principle this method can be used for similar shapes. Beforehand we define
+a few variables.
+
+\startbuffer
+\cldcontext{math.cosd(60)}
+\cldcontext{math.sind(60)}
+
+\newdimen\BeeEdge
+\newdimen\BeeLine
+\newdimen\BeeSize
+
+\newbox \BeeBox
+
+\def\BeeLines{17} % choose optimum odd/even
+\def\BeeStart{2cm} % set automatically
+\def\BeeStep {.5mm} % accurate enough
+\stopbuffer
+
+\typebuffer \getbuffer
+
+The loop starts with a rather small width and with increasing steps tries to find
+the solution where the number of used lines equals the asked number of lines. We
+could have used low level \TEX\ primitives, but using a few \CONTEXT\ wrappers
+makes more sense because that way struts and alike are set as well. In the end we
+stretch the interline spacing to match the height of the cell.
+
+\startbuffer
+
+\startsetups beeloop
+
+\def\title##1%
+ {{\ss\bf\kerncharacters[0.25]##1}%
+ \hskip.5em plus .5em minus .25em\relax
+ \ignorespaces}
+
+\setbox\scratchbox=\hbox{\setups[beetext]}
+
+\edef\BeeStart
+ {\the\dimexpr.5\wd\scratchbox/\BeeLines\relax}
+
+\def\BeeMax
+ {10000}
+
+\def\BeeShapeA
+ {\scratchdimen\numexpr\recurselevel-1\relax
+ \dimexpr\BeeEdge/\BeeLast\relax
+ \appendetoks
+ \the\dimexpr\BeeEdge- \scratchdimen\relax\space
+ \the\dimexpr\hsize +2\scratchdimen\relax\space
+ \to\scratchtoks}
+
+\def\BeeShapeB
+ {\appendetoks
+ \zeropoint\space
+ \the\dimexpr\hsize+2\BeeEdge\relax\space
+ \to\scratchtoks}
+
+\doloop
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \edef\BeeLast
+ {\the\numexpr(\BeeLines\ifodd\BeeLines-1\fi)/2\relax}%
+ \hsize\dimexpr\BeeStart+\recurselevel\dimexpr\BeeStep\relax\relax
+ \BeeEdge=\cldcontext{math.cosd(60)}\hsize
+ \BeeSize=\cldcontext{math.sind(60)}\hsize
+ \BeeLine=\dimexpr2\BeeSize/\numexpr2*\BeeLast+1\relax\relax
+ \setupinterlinespace[line=\BeeLine,stretch=.5]%
+ \setuptolerance[verytolerant]%
+ \setupalign[hz]%
+ \parfillskip\zeropoint
+ \scratchtoks\emptytoks
+ \ifodd\BeeLines
+ \dostepwiserecurse{1}{\BeeLast}{+1}{\BeeShapeA}%
+ \BeeShapeB
+ \dostepwiserecurse{\BeeLast}{1}{-1}{\BeeShapeA}%
+ \rightskip\zeropoint
+ \else
+ % we want to stay inside the shape, so we need
+ % to compensate the right side
+ \advance\hsize +\dimexpr\BeeEdge/\BeeLast\relax
+ \dostepwiserecurse{1}{\BeeLast}{+1}{\BeeShapeA}%
+ \dostepwiserecurse{\BeeLast}{1}{-1}{\BeeShapeA}%
+ \advance\hsize -\dimexpr\BeeEdge/\BeeLast\relax
+ \rightskip\dimexpr\BeeEdge/\BeeLast\relax
+ \fi
+ \setbox\scratchbox\vbox \bgroup
+ % we set it like this in case grid is turned on
+ \baselineskip=1\baselineskip plus 20pt minus 20pt
+ \parshape\numexpr\BeeLines\relax\the\scratchtoks
+ \begstrut
+ \ignorespaces\setups[beetext]\removeunwantedspaces
+ \endstrut
+ \endgraf
+ \xdef\BeeTotal{\number\prevgraf}%
+ \xdef\BeeRate {\number\badness }%
+ \egroup
+ \writestatus
+ {beestate}
+ { run: \recurselevel\space
+ target: \BeeLines \space
+ lines: \BeeTotal \space
+ badness: \BeeRate}%
+ \CheckBeeLines % sets 'done'
+ \ifdone
+ \vbox to 2\BeeSize
+ {\unvbox\ifvoid\BeeBox\scratchbox\else\BeeBox\fi}%
+ \egroup
+ \exitloop
+ \else
+ \egroup
+ \fi}
+
+\stopsetups
+\stopbuffer
+
+\getbuffer \typebuffer
+
+The end criterium is determined by:
+
+\startbuffer
+\def\CheckBeeLines
+ {\ifnum\BeeTotal>\BeeLines\relax
+ \donefalse
+ \else
+ \donetrue
+ \fi}
+\stopbuffer
+
+\getbuffer \typebuffer
+
+This solution is rather safe and, at the cost of the ugly saving of the number of
+lines as registered in \type {\prevgraf}, works better than measuring the height
+of the box.
+
+We could build the loop out of more isolated pieces of code like this but the
+reason why we do it for the checker is that we now can redefine it. At the cost
+of a few more tests, the following checker is better, because it goes on for a
+while and keeps looking for better solutions. If you have no idea what badness
+is, just skip the following code snippet.
+
+\startbuffer
+\def\CheckBeeLines
+ {\ifnum\BeeTotal>\BeeLines\relax
+ \donefalse
+ \else\ifnum\BeeTotal=\BeeLines\relax
+ \ifnum\BeeRate=\zerocount
+ \global\setbox\BeeBox=\box\scratchbox
+ \donetrue
+ \else\ifnum\BeeRate<\BeeMax\relax
+ \global\let\BeeMax\BeeRate
+ \global\setbox\BeeBox=\box\scratchbox
+ \donefalse
+ \else
+ \donefalse
+ \fi\fi
+ \else
+ \donetrue
+ \fi\fi}
+\stopbuffer
+
+\getbuffer \typebuffer
+
+Well, this is not the kind of code you want a designer to enter, but providing it
+as feature in a desk top publishing application is also non||trivial because each
+case differs and turning many knobs to get things done is not easy either, so
+basically it comes down to manual work (neglectable to the total amount of work
+involved in getting such a musical product done). Of course one can ask someone
+to typeset the text in \TEX\ and provide it as image, but that would make
+coordination the production more complex.
+
+The criterium (here \BeeStep) can be made smaller when you encounter problems. If
+we set it to 1mm, we get one case where the amount of lines jumps~2 and the loop
+is exit unexpected. Of course one can catch such cases but it does not make much
+sense in such a one||shot macro.
+
+The previous setup is applied as follows:
+
+\startbuffer
+\startsetups beeloner
+ \framed
+ [offset=overlay,
+ frame=off,
+ background=beecell,
+ foregroundstyle=\BeeFont]
+ {\setups[beeloop]}
+\stopsetups
+\stopbuffer
+
+\getbuffer \typebuffer
+
+We will now put several variants alongside. For this we use a layer:
+
+\startbuffer
+\startsetups beesample
+
+\definelayer
+ [beekeeper]
+ [width=13cm,
+ height=9cm]
+
+\setlayer
+ [beekeeper]
+ [preset=lefttop]
+ {\scale[width=5cm]{\def\BeeLines{16}\setups[beeloner]}}
+
+\setlayer
+ [beekeeper]
+ [preset=leftbottom]
+ {\scale[width=5cm]{\def\BeeLines{17}\setups[beeloner]}}
+
+\setlayer
+ [beekeeper]
+ [preset=righttop]
+ {\scale[width=5cm]{\def\BeeLines{18}\setups[beeloner]}}
+
+\setlayer
+ [beekeeper]
+ [preset=rightbottom]
+ {\scale[width=5cm]{\def\BeeLines{19}\setups[beeloner]}}
+
+\setlayer
+ [beekeeper]
+ [preset=middle]
+ {\scale[width=5cm]{\def\BeeLines{20}\setups[beeloner]}}
+
+\tightlayer[beekeeper]
+
+\stopsetups
+\stopbuffer
+
+\getbuffer \typebuffer
+
+\startbuffer[a]
+\startsetups [beetext]
+ \getbuffer[parasol]
+\stopsetups
+
+\definecolor[BeeColor][BeeColorA] \setups[beesample]
+\stopbuffer
+
+\startbuffer[b]
+\startsetups [beetext]
+ \getbuffer[beekeeper]
+\stopsetups
+
+\definecolor[BeeColor][BeeColorB] \setups[beesample]
+\stopbuffer
+
+\startpostponing
+
+\placefigure
+ [here]
+ [fig:parasol]
+ {Parasol}
+ {\getbuffer[a]}
+
+\placefigure
+ [here]
+ [fig:beekeeper]
+ {The Beekeeper}
+ {\getbuffer[b]}
+
+\page
+
+\stoppostponing
+
+The first samples, shown in \in {figure} [fig:parasol], will be typeset using:
+
+\typebuffer[a]
+
+The second example, shown in \in {figure} [fig:beekeeper], is done in a similar
+way. We redefine the \type {beetext} setup.
+
+\typebuffer[b]
+
+You can zoom in on cells using your viewer. An enlarged example is shown in \in
+{figure} [fig:big].
+
+\startbuffer
+\definecolor[BeeColor][BeeColorC]%
+\startcombination
+ {\scale
+ [width=.475\textwidth]
+ {\startsetups[beetext]\getbuffer[parasol]\stopsetups
+ \def\BeeLines{17}\setups[beeloner]}}
+ {Parasol}
+ {\scale
+ [width=.475\textwidth]
+ {\startsetups[beetext]\getbuffer[beekeeper]\stopsetups
+ \def\BeeLines{20}\setups[beeloner]}}
+ {The Beekeeper}
+\stopcombination
+\stopbuffer
+
+\typebuffer
+
+Choosing the best alternative is a matter of taste. If you ever get a change to
+see the \CD\ (a good buy anyway) you will note the difference. It is possible to
+improve the spacing at the top and bottom but we leave this as an exercise.
+
+\placefigure
+ [here]
+ [fig:big]
+ {An few enlarged examples.}
+ {\getbuffer}
+
+The downside of this exercise was that in the process my laptop suddenly made
+some funny noises and made me end up with a cracked \CD. So in the end the
+message may be not to bother too much about badly typeset paragraphs in \CD\
+booklets.
+
+\vbox to \vsize \bgroup
+
+ \vfil
+
+ \hbox to \hsize \bgroup \hss
+ \scale
+ [height=.45\textheight]
+ {\startsetups[beetext]\getbuffer[parasol]\stopsetups
+ \defineoverlay[beecell][]\def\BeeLines{17}\setups[beeloner]}%
+ \hss \egroup
+
+ \vfil \vfil
+
+ \hbox to \hsize \bgroup \hss
+ \scale
+ [height=.45\textheight]
+ {\startsetups[beetext]\getbuffer[beekeeper]\stopsetups
+ \defineoverlay[beecell][]\def\BeeLines{20}\setups[beeloner]}%
+ \hss \egroup
+
+ \vfil
+
+\egroup
+
+\stopdocument