Main index Other Papers index About author

Glasses placemat: how to avoid confusion at a port tasting

Julian D. A. Wiseman

Contents: Publication history; example output (and in PDF); How to control the PostScript program; Other easy parameters; Non-easy parameters; Code within parameters; Errors: causation and avoidance; How to comment; Who to invite?; Recent changes.

Publication history: only at www.jdawiseman.com. Usual disclaimer and copyright terms apply. Also see the PostScript program itself, and the example PDF output.


This is the ‘documentation’, such as it is, for the latest version, dated June 2010, which prior precedent suggests will not be the last. The code is mostly debugged, but errors surely remain. It is provided as-is, without liability—it is free.

There are separate pages describing: the choosing of the page size; the obscure parameters; and how to use code in parameters. Further, PostScript programmers are invited to peruse the list of re-usable routines.

Introduction

So you and your lucky guests are to enjoy a port tasting. Of course, there will be many glasses, each person having one for each port. But it is important to avoid the what-is-in-this-glass confusion: each person will need a wine tasting placemat, clearly labelling each glass’s spot.

The author has devised a PostScript program to create such pages, and matching decanter labels, and pages for tasting notes. Pages are set as in the PDF example, the first page of which is also rendered immediately below.

Example of an 8-glass port tasting placemat

 As further examples, the following link to placemats from actual tastings, or draft placemats for future tastings. Most of these were made with earlier versions of the software; some required expert use of the program’s features. ◦ 12th November 2010, Köln, Niepoort vertical; ◦ 7th September 2010, Dow; ◦ 9th July 2010, Utrecht, Fonseca and Guimaraens; ◦ 21st June 2010, horizontal of 1982; ◦ 19th May 2010, horizontal of 1960; ◦ 14th May 2010, horizontal of 1978; ◦ 6th May 2010, blind port from election years; ◦ 17th April 2010, Warre in Sussex; ◦ 16th April 2010, exercises ahead of Warre in Sussex; ◦ 10th April 2010, a recent delivery from the SMWS; ◦ 22nd March 2010, Malvedos; ◦ 16th March 2010, a near-minimal horizontal of 1970; ◦ 23rd February 2010, Vesuvio; ◦ 11th February 2010, blind; ◦ 1st February 2010, bring a bottle; ◦ 30th January 2010, CUTwC’s decanter labels; ◦ 5th January 2010, 1985 or 1970; ◦ 13th November 2009, bring a bottle; ◦ 13th November 2009, partially blind double vertical; ◦ 28th October 2009, Portal restaurant; ◦ 23rd October 2009, Paris; ◦ 14th October 2009, AHB’s birthday; ◦ 2nd October 2009, Warre; ◦ 21st July 2009, eighties night; ◦ 29th June 2009, best mature ports; ◦ 27th June 2009, at Quinta St Luiz; ◦ 26th June 2009, decent drinking; ◦ 26th June 2009, Sandeman; ◦ 13th June 2009, Fonseca mini-vertical; ◦ 18th April 2009, Taylor Fonseca Warre; ◦ 13th February 2009, Graham; ◦ 30th January 2009, horizontal of 1970; ◦ 3rd January 2009, emergency port.

Making Your First Placemat: Advice for Beginners

A code editor, a good text editor, is a boon, and it should be one that understands PostScript. On a Mac Alpha X is excellent, and Aquamacs Emacs is suitable for Emacs experts. On a PC the specification of NotePad++ looks encouraging—user feedback welcomed. The basic text editor that came pre-installed on your computer will make life harder than it needs to be. A code editor that understands PostScript will prevent many errors and save much labour.

Bookmark this manual, and download to your machine a copy of the PostScript code (update this copy every time: new versions fix bugs; add features; improve default settings). Store it in a directory named something like “placemats”. As a test convert the unedited unchanged PostScript to PDF, perhaps by using PS2PDF.com.

Make a copy of the original PostScript. Give it a name which will make sense in aeons to come: perhaps YYYYMMDD.ps, or YYYYMMDD_TastingName.ps. Use the text editor to edit this copy of the PostScript, changing to values appropriate for your tasting the:

Do these one at a time, converting to PDF between each.

Now test some of the more exuberant features described in the rest of this manual. Play and experiment. Convert to PDF after each significant change, and admire the results. Choose a small subset of the decorative features to go in the final placemats. Too many flamboyant features looks cluttered and horrible, so be parsimonious. Convert to PDF.

If the tasting is being arranged via ThePortForum or another wine bulletin board, upload the PDF to the web, and post in an appropriate thread a link labelled something like “First draft of the placemats”. Allow some time for comments and corrections and changes. Update if appropriate (and post “Second…”).

Perhaps send to the author a copy of the PS and PDF for comment. Time and convenience permitting, help might be forthcoming. Please send the URLs of the uploaded .PS and .PDF files, rather than filling email with large enclosures. Allow some days for a response.

The day before the tasting print the mats using a toner printer.

Construct the decanter labels:

  1. cut a neat rectangle around each;
  2. paste to the back of a business card (typically one from a former employer—keep them when changing jobs);
  3. allow the glue to dry;
  4. punch holes top-left and top-right;
  5. hang on the decanter, perhaps using a 30″ metal bead chain (filling an unlabelled decanter risks needless confusion, so hang before filling).

Enjoy the tasting.

How to control the PostScript program

PostScript programs are in the form of a text file, which can be interpreted by Adobe Distiller, by Preview on the Mac OS X, by GNU Ghostscript, or by any PostScript printer (though sending raw PostScript to a printer might require some technical knowledge). Several websites offer free PS→PDF conversion; the author has successfully used PS2PDF.com (fonts that can be used if distilling at PS2PDF.com). The text file can be edited in any text editor, though it is easier to use a text editor that has been configured to edit PostScript files—see box on right.

After some opening comments (after a “%” character the remainder of a line is a comment), the program defines three arrays, called Titles, Subtitles, and Circlearrays. Each of these arrays has the same length, typically equal to the number of glass-settings on the page (eight in the example above), and the program copes with any sensible number of glasses.

In the example provided, Titles is defined thus:

/Titles [
	(G70)
	(G77)
	(G85)
	(G63)
	(G85)
	(S70)
	(S77)
	(S85)
] def

Observe that the array is delimited with square parentheses [], and that each of the strings is delimited with round parentheses (). White space outside strings is ignored. The page looks best if each of these titles is short, ideally ≤3 characters.

(Throughout this manual PostScript is shown in monospace with a pale grey background. Further, the preferred code editor of the author, Alpha X, helpfully colours the different types of element. That colouring is echoed here: /names; operators; array and code parentheses [ ] { }; and % comments.)

Subtitles is an array of the same length, though, in the example, most of the strings are empty:

/Subtitles [
	()
	()
	(Single)
	()
	(Magnum)
	()
	()
	()
] def

If an auction house is hosting the tasting, Subtitles might contain lot numbers: (123) or even [(123) /arrowright (129)] (“123→129”).

And Circlearrays, which is an array of arrays, thus:

/Circlearrays [
	[ (Graham) (1970) ]
	[ (Graham) (1977) ]
	[ (Graham) (1985) (Single) ]
	[ (Graham) (1963) ]
	[ (Graham) (1985) (Magnum) ]
	[ (Sandeman) (1970) ]
	[ (Sandeman) (1977) ]
	[ (Sandeman) (1985) ]
] def

Each of the sub-arrays of Circlearrays contains strings; glyphs; or sub-sub-arrays arrays of these. The program calculates how many copies of the sub-arrays can be spaced around the circle, and then does so with equal spacing between the elements of the sub-arrays.

PostScript names of glyphs

Accents and modifiers: Á /Aacute; á /aacute;  /Acircumflex; â /acircumflex; À /Agrave; à /agrave; Å /Aring; å /aring; à/Atilde; ã /atilde; Ä /Adieresis; ä /adieresis; Ç /Ccedilla; ç /ccedilla; É /Eacute; é /eacute; Ê /Ecircumflex; ê /ecircumflex; È /Egrave; è /egrave; Ë /Edieresis; ë /edieresis; Í /Iacute; í /iacute; Π/Icircumflex; î /icircumflex; Ì /Igrave; ì /igrave; Ï /Idieresis; ï /idieresis; Ñ /Ntilde; ñ /ntilde; Ó /Oacute; ó /oacute; Ô /Ocircumflex; ô /ocircumflex; Ò /Ograve; ò /ograve; Õ /Otilde; õ /otilde; Ö /Odieresis; ö /odieresis; Ú /Uacute; ú /uacute; Û /Ucircumflex; û /ucircumflex; Ù /Ugrave; ù /ugrave; Ü /Udieresis; ü /udieresis.

Ligatures and punctuation: fi /fi; fl /fl; Æ /AE; æ /ae; Œ /OE; œ /oe; … /ellipsis; – /endash; — /emdash; ‘ /quoteleft; ’ /quoteright; “ /quotedblleft; ” /quotedblright; ‹ /guilsinglleft; › /guilsinglright; ‚ /quotesinglbase; „ /quotedblbase.

Other: ≈ /approxequal; £ /sterling; € /Euro; ¥ /yen; ¢ /cent; ½ /onehalf; ¼ /onequarter; ¾ /threequarters; ⅛ /oneeighth; ⅜ /threeeighths; ⅝ /fiveeighths; ⅞ /seveneighths; ⅓ /onethird; ⅔ /twothirds; × /multiply; ≥ /greaterequal; ≤ /lessequal; • /bullet; · /periodcentered; ◊ /lozenge; † /dagger; ‡ /daggerdbl; ♠ /spade; ♥ /heart; ♦ /diamond; ♣ /club; ® /registered; ™ /trademark; → /arrowright; ← /arrowleft; ↑ /arrowup; ↓ /arrowdown; ↔ /arrowboth.

Any string may be replaced with an array of strings and other characters called glyphs, each beginning with a forward slash (“/”). Examples of glyphs include accented characters such as /atilde, and the likes of /daggerdbl, as well as ligatures such as that in [(Quinta do Bom) /fi (m)]. Most of the characters one might need are in the box on the left. Others are listed in appendix E.5 of the PostScript Language Reference Manual, third edition; a still fuller list is at www.jdawiseman.com/​papers/​trivia/​character-entities.html. (But most fonts do not contain all the glyphs listed, so check the output carefully.) Any string parameter may be replaced with an array of any of: strings; glyphs; other like arrays; and indeed pieces of PostScript code.

Each place settings is named (e.g., the author’s “JDAW” initials are on the page shown above), and these names are listed in yet another array, not necessarily of the same length as the previous three:

/Names [
	(JDAW)
	[/Gdotaccent /uacute /ecircumflex /scaron /tcommaaccent ( ) /Odieresis /ntilde /egrave]
	(Guest Two)
	()
	(Decanter Priming)
] def

As with the other parameters, strings may be replaced with arrays of glyphs and strings, in this case to make the silly but didactic “Ġúêšţ Öñè”. Including a blank name (()) is very strongly recommended: last-minute changes to the guest list do happen.

Other parameters

Black “Fonseca” overlapping grey “F”

OverlapSubtitlesOnTitles

◊ The parameter OverlapSubtitlesOnTitles may be deffed to false, as in the PDF example rendered above; alternatively /OverlapSubtitlesOnTitles true def, which overlaps the sub-titles on the titles, as in the diagram on the right.

Fonts

◊ The fonts in which the various text pieces are rendered are contained in the parameters TitlesFont, SubtitlesFont, FillTextFont, CircletextFont, and NamesFont. But PostScript uses font names that are not always obvious. Help is at hand: distilling fonts_illustrated.ps produces a PDF with a list of the available fonts, their PostScript names, and formatted example text. If distilling on a different machine or with a different program, a different set of fonts might be available: re-test by re-distilling fonts_illustrated.ps.

The program was designed for left-to-right alphabets, and only Roman fonts have been tested. Users with knowledge of PostScript who are able to assist with testing in other scripts—including right-to-left—are invited to contact the the author, perhaps after reading this request for assistance rendering “泉十段”.

PaperType and Orientation

◊ Two parameters control the page size and the page orientation:

/PaperType /A4 def  % /A4 /A3 /B4 /USL /USLegal /USL2 [SmallerPts LargerPts]
/Orientation /Landscape def  % /Landscape /Portrait

In the first line allowed values include /A4 (8.28″×11.70″), /USL (8½″×11″), /A3 (11.70″×16.55″), /USLegal (8½″×14″), /USL2 (11″×17″), or a non-standard page size expressed in points as an array of length two. For convenience of copy-pasting, these allowed values appear in the comment at the end of the line—after the “%”. In the second line allowed values are /Landscape and /Portrait.

Also see the separate manual page Glasses placemat: choosing a paper size.

Around the edge of the page is an invisible margin, the circles lying inside the area at least the margin away from the edge of the page. The margin equals the parameters MarginL (left), MarginR (right), MarginT (top), and MarginB (bottom), each defaulting to 30.

Decorating the Titles and Subtitles

ColourSchemeTitles and ColourSchemeSubtitles

By default, the Titles are black if OverlapSubtitlesOnTitles is true, and grey otherwise; the Subtitles always being black. But the colour scheme is controlled by two parameters ColourSchemeTitles and ColourSchemeSubtitles, each of which can take values /Black or /MidGrey. These control the colouring both of plain text and of decorated text. It might be that, in future, new colour schemes are introduced. There is also the analogous parameter ColourSchemePlaceNames, used to control the colour of Place Names.

Second example of CrossHatchingTitles and CrossHatchingSubtitles

CrossHatchingTitles and CrossHatchingSubtitles

◊ The example on the right, and the CirclifyTitles example below, are both filled with a check pattern. This check is activated by booleans CrossHatchingTitles and CrossHatchingSubtitles. The polar gridlines originate from a point with x coordinate CrossHatchingCentreX which can take values of /Name, /Left, /Center, or /Right; and y coordinate CrossHatchingCentreY with possible values /Name, /Bottom, /Middle, or /Top. Lines are formatted and stroked by the code in CrossHatchingTitlesStrokeCode and CrossHatchingSubtitlesStrokeCode (the code must include the stroke, this requirement permitting the likes of “gsavestroke grestorestroke”). The number of straight lines is CrossHatchingNumRadialLines, defaulting to 180 so 2° apart. The radial gaps start at CrossHatchingRadialGapStart (this is the diameter of the inner-most circle), the gaps between the radii tending to CrossHatchingRadialGapAtInfinity with decay CrossHatchingRadialGapDecay. The author believes that CrossHatching… looks quite stylish when OverlapSubtitlesOnTitles is false and hence the text in black and the lines defaulting to white.

Example of outlined titles

Stars and flowers

◊ In the 2× diagram on the left the Titles and Subtitles contain small random stars and flowers. This feature is activated by setting to true the boolean parameters ShapesInTitles and ShapesInSubtitles, and setting the array ShapesToUse to [/Flower /Star] (for both shapes: obviously just one item for just one).

The radius of each shapes’s enclosing circle is random in the range ShapesEnclosingCircleRadiusMin to ShapesEnclosingCircleRadiusMax. An approximation to the typical separation between the shapes is ShapesAverageSeparation; a parameter controlling how far stars are moved from a regular grid is ShapesAverageMaxTweakPlusMinus. The shape is filled with the code ShapesTitlesFill (or ShapesSubtitlesFill), which, if the shapes are filled, should end with a fill. The shape is then stroked with ShapesTitlesStroke (or ShapesSubtitlesStroke) which should end with a stroke. For the stars, the numbers of points and the step between points are chosen randomly from within ShapesStarsPointsAndStepsArray, the default [[5 2] [6 2] [7 2] [7 3] [8 3]] being small 5/2 star small 6/2 star small 7/2 star small 7/3 star small 8/3 star. A possible alternative value for ShapesStarsPointsAndStepsArray is [[3 1.318] [4 1.792] [5 2.278] [6 2.77]], being pointier and less polygonal: small sharp 3-pointed star small sharp 4-pointed star small sharp 5-pointed star small sharp 6-pointed star. (Mathematicians might be interested in an open question about such stars.) For the flowers the number of petals is chosen randomly from ShapesFlowersNumPetalsMin to ShapesFlowersNumPetalsMax, and, as a proportion of 360° divided by the number of petals, the angular width of each is chosen randomly from the range ShapesFlowersAngularWidthMin to ShapesFlowersAngularWidthMax.

OutlineTitles

◊ The Titles can be outlined by setting /OutlineTitles true def, as in the example with flowers and stars. The innermost white and black outlines have width OutlineTitlesInnerWidthWhite and OutlineTitlesInnerWidthBlack, and these widths grow in successive outlines by factors of OutlineTitlesMultiplierWhite (defaulting to (1+√5)/2 = the golden ratio) and OutlineTitlesMultiplierBlack (defaulting to unity). Subject to there being not more than OutlineTitlesMaxNum black ripples, the number of black ripples is chosen such that the total width of the ripples is at least OutlineTitlesTargetTotalDistanceProportionRadius radii. This parameter can be relevant if a title is something like “L”, as the top-right of the circle can then be more than 1 radius from the title.

If OutlineTitlesAlsoSubtitles is true then Subtitles are also outlined; if false then Subtitles sit plainly atop the lines. Generally it helps if the decanter labels fit onto a rectangular business card, so the default value of OutlineTitlesSuppressForDecanterLabels suppresses the outlines on the decanter labels. OutlineTitles does not impose as high a burden on a printer as does FillTexts, but can still be difficult for some. Again, test your printer.

Example of inlined titles

InlineTitles

◊ A more architectural form of decoration is activated by the booleans InlineTitles and InlineSubtitles, being in some sense a reversal of OutlineTitles—the lines being on the inside. In the Titles the lines have widths of InlineTitlesBlackWidth and InlineTitlesWhiteWidth, and in the Subtitles of InlineSubtitlesBlackWidth and InlineSubtitlesWhiteWidth, all these defaulting to 1. If the colour scheme is /MidGrey then “black” means the darker of the two shades, and “white” the lighter.

It would be difficult for the code to compute correctly how many contours are needed. So instead the code makes an estimate, which will typically be a great overestimate, and then caps that estimate at InlineTitlesMaxNumberContours/InlineSubtitlesMaxNumberContours. Setting carefully these Inline…itlesMaxNumberContours parameters reduces file size and complexity, which can help some printers.

InlineTitles and InlineSubtitles do not mix well with other decoration: the text can be illegibly cluttered. Self-restraint is beautiful.

Example of titles circlified

CirclifyTitles

◊ Another flamboyant option that can be set is controlled by the booleans CirclifyTitles and CirclifySubtitles, which apply a transformation to either or both pieces of text, such that what would otherwise have been their joint bounding box vertically fills the circle. In the example on the right CirclifyTitles and OverlapSubtitlesOnTitles are both true.

CirclifyTitles looks far better if the characters have exactly the same height above the baseline, and do not have descenders. If using a “J” good typefaces include /ArialRoundedMTBold, /AmericanTypewriter-CondensedLight and /Braggadocio. If not using a “J” other candidates include /GillSans, /GillSans-Light, /GillSans-Bold, /EurostileRegular, /EurostileBold, /Modern-Regular, /Onyx, /Stencil, and, though lacking a glyph for the “fi” ligature, /AmosExtendedNormal and /AmosThinNormal.

If using CirclifyTitles it is recommended that SameSizeTitlesIfAllOf be set to [/False], and that one-at-a-time size constraints be set to large values.

Using CirclifyTitles or CirclifySubtitles with FillTitles or FillSubtitles is even harder on many printers.

FillTitles and FillSubtitles

Example of titles filled with text

◊ If FillTitles or FillSubtitles is true, then the program accesses another array called FillTexts, which is of the same length as Titles. This is used to ‘fill’ the Titles (or Subtitles) with repeated small copies of the FillTexts, outlined FillTextNumOutlines times. Depending on the values of ColourSchemeTitles and ColourSchemeSubtitles, the colours are either black and white, or 40% grey and white. The additional parameter FillTextAngle may be deffed to a number (30 being a good choice), this being the angle at which the FillTexts are shown. Alternatively, FillTextAngle may be one of /LowerLeft, /LowerCenter, /LowerRight, /MiddleLeft, /MiddleCenter, /MiddleRight, /UpperLeft, /UpperCenter or /UpperRight such that the text will be 90° to a line drawn from the centre of the circle to that corner or edge or centre of the page. Or FillTextAngle may be /Name, making the angle perpendicular to a line drawn to the positioning of the Names. Each rendering of an item of FillTexts is suffixed with FillTextNumSpaces spaces.

The FillTexts are set in the font FillTextFont, at a size of at least FillTextMinFontSizeAbsolute, and of a size of at least FillTextMinFontSizeProportionLargerTitlesSubtitles × the larger of the font size of the Titles and of the Subtitles.

In the example on the right the relevant item of Titles is (S); of Subtitles is (Sandeman); of Circlearrays is [(Sandeman) (1985)]; of FillTexts is (1985), with FillTextNumSpaces being 2 and FillTextAngle being 30, and all the typefaces being /HelveticaNeue-CondensedBold. The default value of FillTextAngle is complicated, but natural. If GlassesOnSheets specifes a two-page layout, then to /LowerRight on the first sheet, and /LowerLeft on the second. If not a two-page layout, then if NamesAtTop is true to /LowerCenter, otherwise to /Name.

Use of FillTexts greatly slows distillation time. If distilling the PostScript via the web (e.g. via PS2PDF.com), the browser might time out before the PDF is returned. If this happens the best course is to deactivate FillTexts by setting both FillTitles and FillSubtitles to false. If used with PlaceNames… distillation is excruciatingly slow, and if done over the web, will almost certainly time out.

As well as slowing distillation time, use of FillTexts and can also make the PDF files very large and complicated. Such files can be too complicated for some printers. Test your printer; do not assume that anything will work first time—and it is not always true that larger more expensive printers cope better.

It also appears that Adobe does not always distill or render perfectly these FillTexts. This problem can be fixed by opening the PostScript file with Preview on the Mac OS X, and then printing from Preview or saving the PDF file Preview makes and subsequently printing from Acrobat (technical demonstration of error).

Page-level settings

Example of use of Rays

Rays

To connect circles with pseudo-electrical field lines, as in the example on the right, set Rays to true. Then from each glass setting there emanates RaysLinesPerGlass lines, the first being offset from vertical by RaysAngleOffset°. It is strongly recommended that RaysLinesPerGlass be an integer multiple of 4. Rays can be straight lines, or, as in the example, curves, this being controlled by the boolean RaysUseCurves. The lines or curves can be truncated at the margin, or at the edge of the paper: RaysLinesToPaperEdge. If this is true, it is even more important to ensure that printing is done at 100% with no scaling. Lines shorter than RaysCollidingCircleMinLength that collide with a circle (rather than meeting one of its rays) are suppressed. The formatting of the stroke can be controlled within RaysStrokeCode.

Imperfections in the algorithm can cause crossovers or missed intersections, either of which can be aesthetically detrimental. Typically the problem can be fixed by tweaking RaysLinesPerGlass and RaysAngleOffset: for several PermittedPackingStyles vertical and horizontal lines seem to cause particular problems.

Example of watercounts

H2O

◊ Particularly at a tasting of a sweet fortified wine, drinking water is important. If WaterCounts is true, then there are a set of little glass icons (see lower-right of figure on left) with which to record water consumption: check one for each glass of water downed. Even better, use a diagonal slash (I drank half a glass of water) for a half glass of water, and a cross (I drank a whole glass of water) for a whole.

The number of these boxes is usually at least WaterCountTarget, each of size WaterCountSize and separated by gaps of width WaterCountGap. These should appear on the lower-right of the page for right-handed drinkers, and lower-left for left-handers, this being controlled by NamesHandedness, an array of the same length as Names, each item of the array being one of /Left or /Right.

If there are multiple pages of glasses (see GlassesOnSheets below), then on which of these pages should they appear? For the right handers this is controlled by the array of booleans WaterCountShowRight; and for the lefties WaterCountShowLeft. Nota Bene: WaterCountShowRight and WaterCountShowLeft must be the same length as GlassesOnSheets; whereas NamesHandedness must be the same length as Names. The default values of WaterCountShowRight and WaterCountShowLeft refer to PageOrderingNonDecanterLabelGlasses, which is implicitly assumed to specify sessions. Naturally enough, WaterCountShowRight defaults to true for the last page in each ‘session’, and WaterCountShowLeft for the first.

Headers and footers

◊ It is possible to define a header to title a tasting. Headers have texts HeaderLeftText, HeaderCenterText, and HeaderRightText, which are rendered left-aligned to the page, centered and right-aligned. These are shown in font HeaderFont, at size HeaderFontSize, with the baseline of the characters a distance HeaderBaselineFromPageTop from the top of the page (which should be inside the top margin). Likewise FooterLeftText, FooterCenterText, and FooterRightText are shown in FooterFont at size FooterFontSize, with the top of the footer a distance FooterTopFromPageBottom from page bottom (which should be inside the bottom margin). Using all of six of these text positions would be very cluttered. Also, to have different headers on glass sheets and tasting-note sheets set the text parameters to suitable code: {TypeOfPagesBeingRendered /TastingNotes eq {(Tasting-note header)} {(Glass-sheet header)} ifelse}.

Usually elegance is enhanced by having left and right headers of approximately equal length.

Layout

There are several types of layout for the glasses, and which may be used is controlled by the array PermittedPackingStyles, which should contain the permitted styles in order of preference. The code chooses the style from those in PermittedPackingStyles, and chooses the parameters for that style, to maximise the permitted circle radius (whilst ignoring MaxRadius), draws being resolved by order. Below are some examples of the packing styles.

/PseudoHexagonal: circles in each row and column lie midway between those in neighbouring rows and columns.

5 glasses, /PseudoHexagonal on /A4 /Portrait
/PseudoHexagonal on /A4, /Portrait
8 glasses, /PseudoHexagonal on /A4 /Portrait
/PseudoHexagonal on /A4, /Portrait
13 glasses, /PseudoHexagonal on /A3 /Landscape
/PseudoHexagonal on /A3, /Landscape
16 glasses, /PseudoHexagonal on /A3 /Landscape
/PseudoHexagonal on /A3, /Landscape
5 glasses, /PseudoHexagonal on /USL=8½″×11″ /Portrait
/PseudoHexagonal on /USL, /Portrait
9 glasses, /PseudoHexagonal on /USLegal=8½″×14″ /Landscape
/PseudoHexagonal on /USLegal, /Landscape

/SquareGrid: circles lie in a square grid, in which the distance to vertical neighbours equals that to horizontal neighbours.

5 glasses, /SquareGrid on /A4 /Portrait
/SquareGrid on /A4, /Portrait
15 glasses, /SquareGrid on /A3 /Landscape
/SquareGrid on /A3, /Landscape

/RectangularDislocation or /RectangularDislocationV: circles lie in a rectangular grid, filling the x and y space, so vertical neighbours not necessarily being the same distance away as horizontal neighbours. There can also be a horizontal “dislocation”, above and below which there is regular grid, but the meeting of which is offset by half a circle. For /RectangularDislocation, the upper block has one column fewer than the lower block. For /RectangularDislocationV this is reversed, the lower block being narrower.

4 glasses, /RectangularDislocation on /A4 /Portrait
/RectangularDislocation on /A4, /Portrait
5 glasses, /RectangularDislocation on /A4 /Portrait
/RectangularDislocation on /A4, /Portrait
6 glasses, /RectangularDislocation on /A4 /Portrait
/RectangularDislocation on /A4, /Portrait
10 glasses, /RectangularDislocation on /A3 /Landscape
/RectangularDislocation on /A3, /Landscape
11 glasses, /RectangularDislocation on /A3 /Landscape
/RectangularDislocation on /A3, /Landscape
5 glasses, /RectangularDislocation on /USL=8½″×11″ /Portrait
/RectangularDislocation on /USL, /Portrait

/Gaia or /GaiaElegant: inspired by a simpler design seen by the author in Vila Nova de Gaia, and leaving room for a substantial corporate message in the centre of the page—particularly useful to those skilled in Adobe Illustrator.) /Gaia looks less handsome in portrait pages: the default /GaiaElegant applies only when the gap between the vertical columns of circles is at least 1½ circles across, and adjacent glasses are equally spaced. If /GaiaElegant, and there isn’t an elegant /Gaia, treated as /PseudoHexagonal.

6 glasses, /Gaia on /A4 /Landscape
/Gaia on /A4, /Landscape
6 glasses, /Gaia on /USL=8½″×11″ /Landscape
/Gaia on /USL, /Landscape

/Irregular, /IrregularMirror, /IrregularPortrait, /IrregularLandscape, /IrregularMirrorPortrait or /IrregularMirrorLandscape: each of these is a special pattern for exactly five glasses. The …Mirror variants are a mirror image of the non-Mirror variants; the …Landscape variants are ignored unless Orientation is /Landscape; and likewise the …Portrait variants are ignored unless Orientation is /Portrait.

5 glasses, /Irregular on /A4 /Landscape
/Irregular on /A4, /Landscape
5 glasses, /IrregularMirror on /A4 /Landscape
/IrregularMirror on /A4, /Landscape

/TwoRowsOrTwoColumns: like /PseudoHexagonal, but with either the rows or the columns closer, and therefore of maximum number 2. Relevant when the number of glasses is very small or the non-margin page extremely non-square. If unusable, ignored.

2 glasses, /TwoRowsOrTwoColumns on /A4 /Landscape
/TwoRowsOrTwoColumns on /A4, /Landscape

The default value of PermittedPackingStyles tests each of /RectangularDislocation, /PseudoHexagonal, /SquareGrid, /TwoRowsOrTwoColumns, /IrregularLandscape, and, redundantly, /GaiaElegant. It then chooses whichever gives the largest radius. Obviously if an elegant /Gaia is wanted one should delete all but /GaiaElegant.

Further control of the layout is possible with RowsMinNum and RowsMaxNum, as the number of rows of glasses is restricted to lie between these two. (It is assumed that 1 ≤ RowsMinNum ≤ RowsMaxNum and RowsMinNum ≤ the number of glasses. If not so, the limits are adjusted sensibly.) RowsMinNum and RowsMaxNum are ignored for the /TwoRowsOrTwoColumns, /Irregular and /IrregularMirror packing styles.

As a convenience, there is also the parameter PackingDirectionVertical which can be set to /TopToBottom or /BottomToTop, and the parameter PackingDirectionHorizontal with possible values /LeftToRight or /RightToLeft. The same effect can be made, less easily, with GlassesOnSheets. PackingDirectionVertical is typically changed to from the default value to /BottomToTop when a tasting is in flights, starting with the front row; but the tasting-note sheets run in the opposite direction, top-to-bottom.

When there are few glasses on a page, the radius of the circles could become very large. Hence the radius of the circles is bounded above by MaxRadius. Further, if there are multiple pages of glass sheets, it can look neater if all the pages, or all the pages in the same session, have the same radius. This is controlled by ShrinkRadii, which can be /NotAtAll, so each page’s radius is determined independently; /ToSmallest, so all pages have the same radius; or /ToSmallestSamePageOrdering, so the radius of each page in the same session, presumed to be equivalent to having the same value of PageOrderingNonDecanterLabelGlasses, is shrunk to the smallest of that session’s radii. Alternatively, ShrinkRadii may be an array of integers of the same length as GlassesOnSheets, pages being grouped if they have matching values of the array (so the default value of ShrinkRadii, “/ToSmallestSamePageOrdering”, is equivalent to “{PageOrderingNonDecanterLabelGlasses}”).

The names appear at the top if NamesAtTop is true, and at the bottom if it is false. The names are rendered in the font NamesFont, at a size equal to the size of the Circlearrays (or rather, at the size at which the the Circlearrays would appear if CircletextsMinCopies were ignored), subject to a minimum of NamesFontSizeMin and a maximum of NamesFontSizeMax.

The making of decanter labels is controlled by the integer DecanterLabelsNumCopies. The sizes of the Titles and Subtitles can be reduced by the setting of DecanterLabelsNumCopies to a value above zero, as described in the section Type sizes. The decanter label pages include instructions along the lines of “Cut; paste to the back of a business card; allow to dry; punch holes; hang on decanter; fill decanter; wait; drink.” Two sets of decanter labels can be pasted to both sides of the business cards, sometimes affording those sitting ‘behind’ the labels a clue as to contents.

Bottle labels

Why both decanter labels and bottle labels? Decanter labels are ‘front of house’, intended to match very closely the design on the glasses sheets, and to be pasted to business cards and hung around decanters. Because of the desired close match between glasses sheets and decanter labels, the decanter labels are generated as a special type of glasses sheet, omitting the inappropriate elements.

So go back in time, to the start of decanting. Some bottles will be clearly labelled. Others might have little more than a capsule, so after opening, could be entirely unlabelled. To prevent confusion there should be, printed onto sheets of sticky labels, a means of avoiding the potential confusion. These are the bottle labels, and their specification largely requires describing the sheet of labels.

Bottle labels appear if BottleLabelsNumCopies exceeds zero, and multiple copies are permitted. The following are then defined assuming that the page is portrait.

The default parameters were fitted to the 25-sheet pack Ryman product 0220013460 (or equivalently the 100-sheet pack 0220023460), having on each A4 sheet eight labels, each 99mm×68mm. Those without access to this /A4 product will need to alter the bottle-label specification.

Side-by-side, right-Handed
Side-by-side, left-Handed

Side-by-side Glasses and TastingNotes

◊ If having a mini tasting of only three wines, one might wish to print everything on one sheet. For right handers the three glasses would be on the left of the tasting-notes; for lefties, glasses to the right—as in the images on the right. This small-tasting layout is enabled by setting the boolean constant SideBySideGlassesTastingNotes to true. Between the two sides of the paper is a gutter, an internal margin, of size SideBySideGlassesTastingNotesWidthGutter; the proportion of the page occupied by the glasses (from the edge of the paper to the middle of the gutter) being SideBySideGlassesTastingNotesProportionPageGlasses. The handedness of the people is specified in NamesHandedness (an array of the same length as Names, each item being one of /Left or /Right).

When SideBySideGlassesTastingNotes is true several of the tasting-note parameters are ignored, action being determined by the glasses equivalent. Ignored parameters include TastingNotesPaperType and TastingNotesOrientation; PageOrderingTastingNotePages; and MirrorPagesTastingNotePages.

Type sizes and controls

Type sizes

This section describes the non-obscure parameters for type sizes. A fuller list can be found in the page of obscure parameters.

The type sizes of Titles and Subtitles is controlled by a two-stage process. First, one at a time, various maximum-size constraints are applied. Second, all the circles are considered together, and various subsets are required to be the same size, that is, the size of the smallest in that subset.

One-at-a-time constraints include the following.

In general, it looks nicer if most of the Titles (and likewise Subtitles) have matching type sizes. Which of Titles (Subtitles) are the same size is controlled by SameSizeTitlesIfAllOf (SameSizeSubtitlesIfAllOf), being an array of ‘condition flags’, the items of Titles (Subtitles) being the same size if all the conditions are met. So an empty set of conditions is always true: all the Titles (Subtitles) would then be the same size. Permitted conditions include the following.

How big is the circle text? In points, not bigger than CircletextMaxFontSizeAbsolute; and as a proportion of the circles’ radius not bigger than CircletextMaxFontSizeProportionRadius. If, in a font size equal to the lesser of these two, a particular item in Circlearrays is too long to fit at least CircletextsMinCopies times, then the font size is reduced for that circle such that it does. The number of copies is also bounded above by CircletextsMaxCopies; and the minimum separation (measured in space-widths) between the items of the sub-arrays of Circlearrays is CircletextsMinNumSpacesBetween.

Tasting-note pages

◊ By default there are also tasting-note pages (controlled by GlassesOnTastingNotePages), these pages being of size TastingNotesPaperType and orientation TastingNotesOrientation. The tasting-note pages are lightly divided into columns, the number of columns and the column headings being determined by the array TastingNotesColumnHeadings, by default this being [ (Times) (Eye) (Nose) (Mouth) (Score) ] (the “Times” column being intended to hold the times of decanting and sampling). These column headings are rendered in the font NamesFont at a size not exceeding TastingNotesColumnHeadingsMaxFontSize. The columns have widths proportionate to TastingNotesColumnRelativeWidths, an array of the same length as TastingNotesColumnHeadings. TastingNotesColumnStrokeCode formats and strokes the lines that separate the columns. Technical aside: whilst these tasting-note pages are being rendered the program sets TypeOfPagesBeingRendered to /TastingNotes. Many parameters may be set to code that checks this flag.

On the tasting-notes page the vertical separation between the Circlearrays and Titles, and between the Titles and Subitles, is TastingNotesLineGap.

Example of a place-name sheet

Place Names

◊ At a large formal tasting it is appropriate to label each person’s place-setting, so everybody knows who everybody else is, even late in the tasting. Pages to facilitate this are produced using the PlaceNamesNumCopies parameter, being an integer containing the number of such pages for each person. The pages are formatted to match the Titles: example on right. Generally PlaceNamesNumCopies is deffed to 0 or 1, though might be larger for tastings over multiple sessions.

Pages require three folds. First, fold in half; then fold and press hard along the faint dashed lines (so preventing the corners curling). The side with the small-writing header and footer should face the named person; the side without should face away. Whilst these are being rendered TypeOfPagesBeingRendered is /PlaceName, and the variable PlaceNameSheetNum is the number of the place-name page. So 0 ≤ PlaceNameSheetNum < PlaceNamesNumCopies. The headers and footers can be set to code that refers to these variables.

These place-name pages are set on pages of size PlaceNamesPaperType (defaulting to TastingNotesPaperType), and orientation PlaceNamesOrientation (default /Landscape). The lines marking the anti-curling folds are a distance PlaceNamesFirstAndThirdFoldsFromEdge away from the top and bottom edges (defaulting to 36 = ½″). The Names are set in font PlaceNamesFont (defaulting to TitlesFont), at the largest size that fits subject to an upper bound of PlaceNamesMaxFontSizeAbsolute (defaulting to 192). The colour scheme used is ColourSchemePlaceNames, this functioning in the same manner as ColourSchemeTitles and ColourSchemeSubtitles. Because these names are usually larger than the Titles, various details such as line-widths are set larger by a factor of PlaceNamesDetailsScalingFactor; but this parameter is used partly in the code, and partly in the default values of other parameters.

Caution: if used with FillTitles distillation is excruciatingly slow. Distillation over the web will almost certainly time out: use local conversion.

Example of a pre-pour sheet

Pre-Pour Sheets

◊ Tastings arranged on ThePortForum are for a maximum of fourteen people, in order to give a 5cl portion to each person (75cl bottle, less the angels’ share and less a little loss during decanting leaves only an edge more than 14×5cl = 70cl). At a tasting attended by eight people, decanters can circulate and people help themselves. But when there are fourteen people and so only 5cl each, portions need to be pre-poured. Typically this necessitates many trays holding fourteen glasses, and, to avoid confusion, these trays should be labelled: a sheet of paper on each tray. These are on paper type PrePourPaperType defaulting to TastingNotesPaperType, with orientation PrePourOrientation defaulting to /Landscape.

The number of copies of these pre-pour sheets is PrePourNumCopies, by default 0. If pre-pour sheets are wanted this should be set to a higher value: usually /PrePourNumCopies 1 def is sufficient. If trays are too small to hold 14 glasses then 2 might be needed. Alternatively, if glasses are to be transferred from one place to another, 2 or even 3 might be required.

Points: The Vote Recorder

◊ At the end of a tasting there is typically a vote for the Wine Of The Night (WOTN), and for large tastings there might also be a vote after each flight or page. The vote is not usually secret, people being asked to declare 1st, 2nd, and 3rd places (scoring 3, 2, 1). To assist the ‘returning officer’ there are VoteRecorderNumCopies copies of a single sheet of paper on which votes can be recorded. It is the points that should be recorded, rather than the ranks, as doing so simplifies the addition of the totals. (There is also benefit in there being agreement as to what is recorded: if you record, but I retain the vote-recorder sheet and enter it into a description of the tasting, it is useful that “3” be unambiguously first place three points.)

The first of the VoteRecorderNumCopies copies is headed by large text “Wine Of The Night”; subsequent copies by “Q:” after which the returning officer should write the question posed. These strings are in the parameter VoteRecorderTopText.

The vote-recorder sheet contains the wines within GlassesClusteredOnVoteRecorders, which is a triple-depth array, so one deeper than GlassesOnTastingNotePages. The outermost array is one per vote-recorder page: voting on separate days, or with different people present, should be recorded on separate sheets. Within this are ‘clusters’, intended to align with tasting-note pages. Within this are integers pointing to wines. The default value is empty if GlassesOnTastingNotePages is empty, otherwise [GlassesOnTastingNotePages], so the cluster divisions (some 25% grey backgrounding) on the vote recorder are page divisions on the tasting-note pages.

Observe the different roles of GlassesClusteredOnVoteRecorders and VoteRecorderNumCopies: wines varying within the former; the top text (the question) within the latter.

Also ∃ obvious parameters VoteRecorderPaperType and VoteRecorderOrientation, with VoteRecorderSubtitleFontSizeProportionTitles controlling the relatives sizes of the Titles and Subtitles.

Non-easy parameters

GlassesOnSheets and GlassesOnTastingNotePages

◊ Imagine that sixteen wines are to be tasted—too many for one sheet of paper. What might be wanted is something like the diagram below: two sheets to hold the glasses, but one combined tasting-note page.

Stylised glasses sheet, 1 of 2 Stylised glasses sheet, 2 of 2 Stylised tasting-note sheet

This may be done using the complicated parameter GlassesOnSheets, which is an array of arrays, each of the inner arrays describing one page. Choose the wines that will or might be in the tasting, creating appropriate members of Titles, Subitles, Circlearrays, and FillTexts. Imagine that there are twenty-six such candidate wines, which are deemed to be numbered from 0 to 25 (emphasis: numbering always starts at zero). Then

/GlassesOnSheets [
	[ 0 1 2 3 4 5 6 7 ]
	[ 11 12 17 16 15 14 13 25 ]
] def

would specify two sheets: the first containing the first eight glass settings (from the arrays Titles etc); the second sheet containing the 12th, the 13th, the 18th, the 17th, the 16th, the 15th, the 14th, and the last, in that order. Thus GlassesOnSheets can be used to select glass settings from a too-large set, to control the order in which they appear on a page, and which appear on which page. The default value of /GlassesOnSheets is [ [0 1 2 … n–1] ], where n is the length of Titles, and therefore specifies a single page (outer array of length 1) containing all the settings defined in Titles etc in that order.

The parameter GlassesOnTastingNotePages works the same way, controlling the tasting-note pages. Its default is to equal GlassesOnSheets.

[ [/Left 3] [0 3] [/Top 3] ]    [ [/Top 4] [1 4] [/Widdershins 4] [/Bottom 4] ]    [ /Closed [/Right] [/Bottom] [/Clockwise 7] [/Widdershins 4] [/Clockwise 2] ]
[ /Closed [0 3] [1 3] [/HorizontalLeft 0 3 3 3] [4 1] [4 2] [4 7] [4 6] [/Widdershins 6] [3 6] [3 5] ]

Separating flights within a page

◊ It is often natural to split a tasting into ‘flights’ of a few wines. This can structure a balance between quietly contemplating the differences between wines, and subsequent sociable discussion. The parameters FlightSeparations and FlightSeparationLines allow the page to be divided into zones. However FlightSeparationLines is fiddly, and if one wine is added or taken away, will need to be completely reworked. Hence it is recommended that division into flights be saved until late in the planning.

FlightSeparations is a boolean: true to activate the line-drawing code, false de-activated. The real work is done by FlightSeparationLines, a set of nested arrays four deep. FlightSeparationLines is of the same length as GlassesOnSheets. Each item of FlightSeparationLines is an array, each of which holds line descriptions, as many as there are lines on that page. Each line description is an array, pieces of which can be as follows.

Several examples can be found at www.jdawiseman.com/papers/placemat/flightseparations.pdf, the header showing that page’s item of FlightSeparationLines (i.e., FlightSeparationLines is an array one deeper than the header).

The actual definition of FlightSeparationLines used to generate the two graphics shown above right is as follows.

/FlightSeparationLines
[
	[ % Start Sheet 0
		[ [/Left 3] [0 3] [/Top 3] ]
		[ [/Top 4] [1 4] [/Widdershins 4] [/Bottom 4] ]
		[ /Closed [/Right] [/Bottom] [/Clockwise 7] [/Widdershins 4] [/Clockwise 2] ]
	] % End Sheet 0
	[ % Start Sheet 1
		[ /Closed [0 3] [1 3] [/HorizontalLeft 0 3 3 3] [4 1] [4 2] [4 7] [4 6] [/Widdershins 6] [3 6] [3 5] ]
	] % End Sheet 1
] def  % /FlightSeparationLines

So, in the upper graphic, “[ [/Left 3] [0 3] [/Top 3] ]” causes the line to start at the left margin at the same y-value as circle 3; then to become the joint tangent of circles 0 and 3; then to run off the top of the page at the same x-value as circle 3. More complicatedly, “[ [/Top 4] [1 4] [/Widdershins 4] [/Bottom 4] ]” starts at the top above circle 4; runs between circles 1 and 4; then anti-clockwise around 4, where it meets a vertical line running to the bottom. “[ /Closed [/Right] [/Bottom] [/Clockwise 7] [/Widdershins 4] [/Clockwise 2] ]” is a closed loop running along the right margin, then along the bottom, clockwise around 7 until it meets 4 which it navigates anti-clockwise until it touches 2 which is done clockwise, and so back to the right margin. The lower diagram should now make sense: “[ /Closed [0 3] [1 3] [/HorizontalLeft 0 3 3 3] [4 1] [4 2] [4 7] [4 6] [/Widdershins 6] [3 6] [3 5] ]”.

The path can be stroked, clipped or filled by the code FlightSeparationPaintCode, which has a default stroke that is complicated but elegant. Use of fill is discouraged, as it impedes comparison of colours of the wines. If FlightSeparationPaintSeparately then FlightSeparationPaintCode is invoked after each line, the variable FlightSeparationLineNum being set to the appropriate integer ≥ 0. If not FlightSeparationPaintSeparately, then all the lines on the current page are drawn, after which is the single call of FlightSeparationPaintCode. The former is better if the format is not constant; the latter preferred if overlapping or crossing lines are to be double-stroked.

Some control over the radius of the arcs is sometimes possible. If any circles touch, the radius of the arcs equals that of the circles. If no circles touch (probably because of MaxRadius or ShrinkRadii) then FlightSeparationArcRadiusControl controls the radius. FlightSeparationArcRadiusControl should be both ≥0 and ≤1; the default being the maximum. If it is 0, the radius of the arcs is that of the circles. If 1, the radius is the half the distance between the closest circles. If between, between.

Page order

◊ The order of the pages is controlled by seven arrays of integers.

Array nameLengthDefault
entries
Default explained
PageOrderingNonDecanterLabelGlassessame as GlassesOnSheets0 Sorted into order by the algorithm: for simplicity of table setting starting with interleaved glasses sheets and tasting-note sheets; then the vote-recording page(s) to be placed with the returning officer’s tasting-note sheets; then pre-pour pages.
PageOrderingTastingNotePagessame as GlassesOnTastingNotePages0
PageOrderingVoteRecorderssame as GlassesClusteredOnVoteRecorders0
PageOrderingPrePourPagessame as GlassesOnSheets0
PageOrderingPlaceNamesPlaceNamesNumCopies99Separated from 0s to facilitate pre-tasting folding.
PageOrderingDecanterLabelssame as GlassesOnSheets999Separated from above to facilitate pre-tasting gluing.
PageOrderingBottleLabelssame as GlassesOnSheets65535Separated from above so there is a single switch of printer paper to the labels.

Draws are resolved in a manner that separates pages on different paper types, perhaps simplifing printer loading, as described by the following algorithm (in which “matching” means matching the page ordering and the paper type).

For a tasting over multiple sessions it can be helpful to have a page order more complicated than the default. For example, imagine a tasting split over afternoon and evening sessions, each session having three glasses pages and two tasting-note pages per person (example of such a tasting, inspiring but pre-dating these page-order controls). Managing such a tasting will be enough work and spare on the day: simplifying the task of table setting, thus reducing the likelihood of error, is worthwhile. One might set:

/PageOrderingNonDecanterLabelGlasses [ 10 10 10  20 20 20 ] def
/PageOrderingDecanterLabels [ 0 0 0  0 0 0 ] def
/PageOrderingTastingNotePages [ 10 10  20 20 ] def
/PageOrderingPlaceNames [ 1 2 ] def
/PageOrderingVoteRecorder  [ 10 ] def
/PageOrderingPrePourPages [ 10 10 10  20 20 20 ] def
/PageOrderingBottleLabels [ 65535 65535 65535  65535 65535 65535 ] def

First out of the printer are the decanter labels, which can be cut and pasted to business cards in advance (integer: 0). Next are place-name pages for the two sessions, collated, to be folded before the day (1 and 2). Next are the glasses and tasting-note pages for the afternoon, with each person’s five pages together (10), followed by the vote recorder for the day (10), and the pre-pour sheets for that session (10). Then the glasses and tasting-note pages for the evening, with each person’s five pages together (20) followed by pre-pour sheets (20). Finally the bottle labels at the end (65535) for ease of paper-changing in the printer.

The values in PageOrderingNonDecanterLabelGlasses are used by ShrinkRadii as they are presumed to define sessions; and ShrinkRadii is then used by the /RadiiShrunkToBeSame value of SameSizeTitlesIfAllOf and SameSizeSubtitlesIfAllOf. The values in PageOrderingNonDecanterLabelGlasses are also used to determine the default values of WaterCountShowRight and WaterCountShowLeft.

Page mirroring

◊ Generally one should print using toner not ink, as a single drop of wine or water causes ink to smudge. Alternatively, one could print the glasses mats onto acetate, and use the non-printed side. This requires mirroring the page, this being controlled by the seven arrays MirrorPagesNonDecanterLabelGlasses, MirrorPagesDecanterLabels, MirrorPagesTastingNotePages, MirrorPagesPlaceNames, MirrorPagesVoteRecorder, MirrorPagesPrePour, and MirrorPagesBottleLabels. These are of the same length as the arrays PageOrdering…, though contain booleans. By default all values are false.

Use of page mirroring should be accompanied by use of PageOrdering…, to ensure that the acetates are consecutive.

CopiesMultiplier

For some subset of the pages one might wish to have multiple copies, or even zero copies. This is controlled by CopiesMultiplier, which defaults to the seemingly-complicated value of {ThisName (Decanter Priming) eq TypeOfPagesBeingRendered /Glasses ne and {0} {1} ifelse}. If using decanters, it is best to prime them: load with 1 to 3cm³ of the wine, and firmly holding down the stopper, shake vigorously before discarding the liquid. Solely for quality-control purposes, one can ‘discard’ into a glass, each of these being placed on a glasses sheet. These glasses are then nosed and tasted for contaminants (of course, never for pleasure). But the ‘person’ with name (Decanter Priming) does not need tasting-note sheets, nor a place name, so the number of copies of these is set to 0.

Code within parameters

It is possible to vary the parameters by sheet or by glass, as described at www.jdawiseman.com/papers/placemat/placemat-code.html. The same page also describes how to add code inside compound strings, and gives examples of why this might be done.

Errors: causation and avoidance

This is a PostScript program, and its various parameters are entered directly in PostScript. The program does very little error checking. If parameters are malformed (e.g., non-matching parentheses), or if the parameters have nonsense values, then the output might be inelegant or non-existent.

If it just won’t work, then start again with the code as published at www.jdawiseman.com. Does that distill correctly? Then change the Titles and Subtitles, and set the Circlearrays to be something simple of the same length. Does that distill correctly? Then add any required complexity to the Circlearrays, and re-test, before setting the other parameters one at a time. If you believe yourself to be coping competently, and it still won’t work, contact the author, enclosing in the email a link to the PostScript file and the log file produced by the distiller, and saying which program you use for the ps→pdf conversion.

The program outputs to a log file. This can contain various ‘Error’s, ‘Warning’s, and ‘Advice’s, as well as values of variables and other diagnostics. Perusal of this file might help. But some ps→pdf converters don’t produce a log file. If it is wanted nonetheless, set OutputLogToPage to true which will cause them to appear on an extra page at the end of the PDF file.

Comment

The avatar of jdaw1

The author welcomes comment on this program, which may be by email or in the appropriate threads on The Port Forum, For The Love Of Port, CellarTracker, or WineBerserkers.com. The avatar of the author is a stylised placemat.

Who to invite?

Permission is given to make non-commercial use of this program as you see fit, and to distribute its output. But not to distribute the code: refer interested parties to the latest version via this page (www.jdawiseman.com/papers/​placemat/​placemat.html). Those with improvements to the code are invited to send them to the author.

It hardly needs saying that the finest way to thank me for this excellent product would be an invitation to your tasting! I’m particularly fond of port and Madeira, and to a lesser extent of whisky and beer, but am willing to have my horizons broadened. Let me check my diary… yes, that evening is good. Thank you very much indeed—what should I wear, and should I bring cheese?

Julian D. A. Wiseman


Recent changes

June 2010

May 2010

April 2010

March 2010


Main index Top About author