Inter-Office MemorandumToWhom it May ConcernDateApril 17, 1980FromLyle RamshawLocationPalo AltoSubjectKerned Strike Fonts (Revised version)OrganizationCSLXEROX Filed on:[Maxc1]KenrnedStrikes.bravo[Maxc1]KenrnedStrikes.pressIt's time for a new font format! The Strike format for font files was devised to permit the gracefuluse of BITBLT for writing characters onto the Alto screen; the authoritative description of thisoriginal Strike format can be found in the memo Font Representations and Formats by Bob Sproull,filed on[Maxc1]FontFormats.Press.The original Strike format, however, has a serious difficulty: it does not distinguish between thespacing width of a character, and the width of that character's bounding box. Let us say that acharacter kerns to the left if its raster includes bits in columns to the left of the character's origin. Acharacter is said to kern to the right if its raster includes bits in columns to the right of the end ofits width vector (the origin of the next character). The original Strike format is incapable ofhandling characters that kern in either direction. The newer PARC fonts contain lots of zero-widthaccent characters that are intended to overprint the following character. These accent charactersoverhang the ends of their width vectors by quite a bit, that is, they kern heavily to the right;hence, conventional Strike format can't handle them.There are basically two ways to adjust Strike format so that it can handle characters that kern.Consider left kerning, for example. One possibility might be called the padding approach. The ideahere is to pad every character raster in the strike body with enough blank columns so that all of theoverhanging bits fit into those padding columns.A padding approach to the left kerning problem would work like this. We would look through theentire font, and determine the size of the largest left kern of any character; say that it is fourcolumns. Thus, at least one character's bounding box includes four columns to the left of theorigin, while no character overhangs to the left of the origin by more than four columns. Whenputting character rasters into the Strike array, then, we include four columns for every character tothe left of that character's origin. We also find a field somewhere early in the file to put thenumber 4'. A user of the resulting file would paint a character on the display by BitBlt'ing theentire character raster, padding columns and all. The first column of the destination of the BitBltwould be given by the formula (4).A symmetric padding strategy could be used to handle right kerning. But any padding strategy hasproblems. The padding columns appear in every character's raster; they take up space in the file,and in memory, and they slow down the process of painting the character, since they are includedin the BitBlt's.The other approach to the kerning problem might be called the auxiliary table approach. In thisscheme, we store the character rasters into the strike body by their bounding box dimensions, andthen we use an auxiliary table of small integers to tell the location of the origin relative to the]gpi c8q]rX-q7Br ]q]r -q7Br Yq]r%-q 7BrSsr M"L{" I-R Ga E0tr D7B' ?Ac =3- ; tr2 :Ktr& 8A 6c 5U>$ 3P 24 .4, -:tr +ie )0 &sN $E #$1- !}F 9, .D b (< 83 H B.5 Z  )trtr M V U  >^9KernedStrikes (revised version)2bounding box, and the length of the width vector. The auxiliary table approach seems to be abetter choice than a padding approach. The purpose of this memo is propose a new Strike fileformat that uses the auxiliary table approach to handle both left and right kerning. If you object tothe following plan, or have suggestions to improve it, please get in touch with me as soon aspossible. History:The definition of Strike file format in Sproull's memo Font Representations and Formats suggeststhe use of a padding scheme to handle left kerning. As I read it, this memo states that a negativeinteger in the xoffset word implies that every character raster in the strike is padded by (xoffset)columns on the left. To the best of my knowledge, no one ever wrote any programs that wouldcorrectly produce or consume such a left-padded strike font. In addition, left kerning doesn'thappen to be nearly as common in PARC fonts as right kerning anyway. We could, of course,legislate against left kerning completely, and start devoting the xoffset word to a right kerningscheme. In fact, this is what the current version of PrePress does when the Kerned flag is set inMakeStrike. But thinking things over, it seems to be a better plan to take advantage of the fact that no paddingscheme has been widely used, and drop all such schemes in favor of a format based on the auxiliarytable approach. From now on, if you want to handle kerning, you should use the newKernedStrike format, and its auxiliary tables. Some terminology:The following section is a substitute for section 7.2 of the Font Representations and Formats memo.Before we start on that, though, let me review a little terminology from that memo, in case thereader is rusty. The origin of a charcter is a reference point located at the corner where four pixelstouch. The width vector of a character is a two-dimensional vector that specifies the desireddisplacement from the origin of the current character to the origin of the next character in a string.The components of the width vector are written Wx and Wy. Wx is always nonnegative; all of thefont formats intended for the Alto screen assume in addition that Wx is an integral number ofpixels, and that all characters have a Wy of zero. The bounding box of the black pixels in thecharacter raster is a rectangle with width BBdx and height BBdy. These numbers are alwaysnonnegative. They are both zero if the character has no black bits in its raster (such characters arecalled empty characers), and are both positive in all other cases. If we use the origin to define aCartesian coordinate system on the plane, the lower left corner of the bounding box is located atthe point . Thus, the left edge of the bounding box is located BBox units to the rightof the origin (left if BBox is negative), while the bottom of the bounding box is located BBoy unitsabove the origin (below if BBoy is negative). Empty charcters have BBox and BBoy equal to zero,by convention. Finally, if all of the characters in the font are superimposed with their originscoincident, the dimensions of the resulting bounding box are called FBBdx, FBBdy, FBBox, andFBBoy respectively.7.2 (New version) STRIKE format:There are four kinds of files in the Strike class: a PlainStrike file (conventional extension .Strike), aKernedStrike file (conventional extension .KS), a PlainStrikeIndex file (conventional extension.StrikeX), and a KernedStrikeIndex file (conventional extension .KSX). In a PlainStrike file, theindividual rasters of the characters are assembled in ascending order of character code into one largeraster, called the strike. The baselines of the characters are aligned, and the origin of each characteris made coincident with the end of the width vector of the preceding character. The PlainStrike filealso contains a table indexed by character code that points to the leftmost column of the raster foreach character in the strike. Warning: since the rasters in a PlainStrike file are positioned by their fu rGu brH `v'6 ^7/ ](R [ X2u Tr7tr S<G QW O$8 NF@ LD JY IPH G DZ13 BL A 3 ?d1 <u 8r#t!r 7M 5x^ 3V 2)C# 0O .D -3O +*0 )F (=trL &F $,7 #GN !"> &; QJ  [u  r55 eB J (> o trP :+ ;) ytrK 2>]sKernedStrikes (revised version)3origins and width vectors, it must be the case that all of the black bits of the character lie betweenthese two bounds. No character may include bits to the left of its origin (left-kerning) or the rightof the end of its width vector (right-kerning).A KernedStrike file handles kerned characters, and does so in the following way: the individualrasters are put into the strike by their bounding box widths. Just think about taking the boundingboxes of all of the characters, lining up their baselines, and packing them tightly into one longraster array; in this format, there are no blank columns between characters in the strike. AKernedStrike file has three additional tables, indexed by character code. One gives the position inthe strike of the first column of the character's raster, which is also the leftmost column of itsbounding box. The other two tables consist of small integers that specify the left-to-right locationof the origin with respect to the bounding box, and the length of the width vector. A StrikeIndex is essentially a table that maps character codes into pairs, together withthe associated strikes. An index can be used to achieve sharing if several character codes map tothe same pair, and hence refer to the same raster. Or it can help to save space, bygrouping the rasters into several strikes to save top and bottom scanlines. [By the way, to the bestof my knowledge, no one has ever used StrikeIndex format.]PlainStrike and KernedStrike files have the following format:structure PlainStrike: [ @StrikeHeader// header common to all Strike files @StrikeBody// the actual strike ]structure KernedStrike: [ @StrikeHeader// header common to all Strike files @BoundingBoxBlock// dimensions of the font bounding box @StrikeBody// the actual strike @WidthBody// table of width data ]structure StrikeHeader: [ format word = [ oneBit bit// always =1, meaning new style'' index bit// =1 means StrikeIndex, =0 otherwise fixed bit// =1 if all characters have same value of Wx, else =0 kerned bit// =1 if KernedStrike, =0 if PlainStrike blank bit 12 ] min word// mimimum character code max word// maximum character code maxwidth word// maximum spacing width of any character = max{Wx} ]structure BoundingBoxBlock: [ FBBox// as defined above FBBoy// as defined above fu rGu br.8 `v] ^/ [2. Y(; X2F V1- TI S<K Q#B OT LL J[ IPL G14 F: B= ?dX = <?$ :n ? 8 5x 3 2)?$ 0?& . ? -3 ? + (= & $ #G ! ?# ?& Q?6  ?(  [  ?  ? e?3  o  ? y? l 2=])KernedStrikes (revised version)4 FBBdx// as defined above FBBdy// as defined above ]structure StrikeBody: [ length word// total number of words in the StrikeBody ascent word// number of scan-lines above the baseline, which is// normally max{BBdy+BBoy} over the chars in this strike descent word// number of scan-lines below the baseline, which is// normally max{(BBoy)} over the chars in this strike xoffset word// always =0 [used to be used for padding schemes] raster word// number of words per scan-line in the strike bitmap word raster*height// the bit map, where height=ascent+descent=FBBdy xinsegment ^ min, max+2 word// pointers into the strike, indexed by code ]structure WidthBody: [ widthtable ^ min, max+1 @WidthEntry// spacing information, indexed by code ]structure WidthEntry: [ spacing word =// the entire spacing word will be =(1) (both bytes =377b)// to flag a non-existent character, else the bytes are:[offset byte// =BBoxFBBoxwidth byte// =Wx] ]The bitmap'' entry is one large bit map; there are height=ascent+descent scanlines in thebitmap, each of which is raster words long. Unless something funny is going on, ascent will besimply FBBdy+FBBoy, while descent will be simply (FBBoy).The font includes characters for some of the ASCII codes from min through max inclusive. Thebitmap includes a dummy character associated with the charcter code (max+1), which can bedisplayed for any non-existent character. A PlainStrike works as follows: Given a character code c, in the range [min, max], we firstcompute:xLeft _ xinsegment ^ c;xRight _ xinsegment ^ (c+1);.If xLeft=xRight, then c is a non-existent character in the current font, and should be replaced bythe raster with code (max+1). Otherwise, the columns of the bitmap from xLeft through(xRight1) inclusive contain the raster for character c, and the width of charcter c isWx=(xRightxLeft).A KernedStrike works a little differently. We first compute xLeft and xRight as above, and alsocomputeSpacing _ WidthTable ^ c;.If Spacing=(1), then c is a non-existent character in the current font, and should be replaced by fu rGu brX? `v? ^ [ Y X2 $* V $4$T: S<$4$Q8 O$3 NF $. L$1 J$, IP F DZ B&,' A  = < :n?<?8875x $ 3 $2) 0 +\ )@ (=: $= #GV !+ QF [ H  9 e,8-  o R   y_f 2=]KernedStrikes (revised version)5the dummy character at (max+1). Otherwise, the columns of the bitmap from xLeft through(xRight1) constitute the bounding box of the raster of character c. In this case, we decomposethe Spacing value into its two bytes:Offset _ Spacing< pairs, dummy at max+1 bodies ^ 1, nStrikeBodies @StrikeBody// the strike bodies themselves ]structure KernedStrikeIndex: [ @StrikeHeader// common header @BoundingBoxBlock// bounding box data for the entire font maxascent word// maximum ascent of all the strikes// [probably =FBBdy+FBBoy] maxdescent word// maximum descent of all the strikes// [probably =(FBBoy)] nStrikeBodies word// the number of strike bodies map ^ min,max+1 @mapEntry// table of pairs, dummy at max+1 bodies ^ 1, nStrikeBodies @StrikeBody// the strike bodies themselves @WidthBody// table of width data ]structure mapEntry: fu rGu br9 `v)7 ^%]($[# Y<& X21- V= T8# S<P QI OF NF4 JN IPI G+< F9+ DZ"B B7) A P ?d P =I :nY 8 5xX 3 2)$ 0$$,. -3$%,+ )$ (=$0 &($ $ !  Q$ $( $$,[ $%,  e$ $0 ($ o $  y 2?]:KernedStrikes (revised version)6 [ missing bit 1// =1 if character is non-existent, else =0 strike bit 7//which strike in range [0:127] code byte// which code ]In a StrikeIndex font, all of the StrikeBodies have implicit min values of zero; the max value isunimportant, as the map will never generate a reference outside the range. The individualStrikeBodies do not have separate pictures for illegal characters; instead, the (max+1) entry in theglobal map defines a single dummy picture. Non-existent characters in the range [min, max] areindicated in the global map by a mapEntry that specifies a strike number larger than 127=177b,that is, by the sign bit of the map entry being 1. In KernedStrikeIndex fonts, non-existentcharacters will also be indicated by having a WidthEntry of (1).In StrikeIndex fonts, the ascent and descent words in each StrikeBody give the dimensions of thatparticular StrikeBody; thus, they probably are the y dimensions of the bounding box of thosecharacters that are included in that StrikeBody, rather than of the entire font. BitBlt modes:There are evidently lots of programs in the world that paint charcters on the screen by calling BitBltin Replace mode, in which the new bits simply smash whatever used to be at the destination. Ifyou want to handle characters that kern, you simply can't do this! The bounding boxes ofsuccessive characers may actually overlap, and hence a Replace Blt might overwrite valuable bits. Ifyou want kerning specified in a KernedStrike font to work, you must use one of the other BitBltmodes: Paint, Erase, or Invert. Conversion issues:I propose the following plan. In the near future, some combination of Doug Wyatt and myself willmodify PrePress 1.12 to produce a PrePress 1.13. This new PrePress will include a MakeKScommand, that converts a font from .AC format to .KS format, and a ReadKS command, thatconverts in the opposite direction. The MakeStrike command will remain, to convert from .ACformat to the original Strike format. However, the Kerned flag will be replaced by a new flagcalled Clipped'. And the code that implements the MakeStrike command will be altered to treatoverhanging characters as follows. If any character of the .AC font kerns to the left, the MakeStrikecommand will fail, as it does currently. Characters will be allowed to kern to the right. If theClipped flag is true, the portion of the bounding box that overhangs the end of the width vectorwill be ignored. If the Clipped flag is false, the width of any right-kerned characters will beartificially increased just enough to eliminate the overhang. Thus, calling MakeStrike on a font withright kerning will have one of two effects: if Clipped is true, the resulting Strike font will spacecorrectly but the overhanging portions of characters won't print. If Clipped is false, theoverhanging portions will print, but the characters will be spaced too far apart. Neither of thesetwo possibilities is very pleasant, of course; but if you want kerned characters to work, you shoulduse .KS format.Note that the xoffset word of all StrikeBodies produced under the new rules will always be zero, nomatter what file format is involved. Non-zero values of xoffset were originally reserved forhandling kerning by padding schemes; since padding is now handled by the auxiliary tableapproach, the xoffset word is not needed.PrePress 1.13 will also include new code to handle the exotic face byte values that are beingintroduced as part of the upcoming font cataclysm. fu rGu brX `v?, ^? ]( ? [ X2R VC TR S<+4 QC OD NFA JH IPP GS DZu A rF ?dE =9 <.7 :n1. 8! 5xu 2)r*7 0C .R -3(4 +U )_ (=Q &9) $H #G(8 !>( "C Q N 8+ e [  c eD %4 ) 6' 2 =\2IKernedStrikes (revised version)7Once PrePress 1.13 is up and running, we will take all of the .AL fonts on [Ivy] andproduce a .KS version for each of them, sticking all of those fonts on [Ivy] as well.That should give us plenty of KernedStrike fonts to play with, as people start to produce softwarethat uses the new format. fu rGu br%: `v S ^3/ ]( Y V` VC>9 TIMESROMAN  TIMESROMAN TIMESROMAN LOGO TIMESROMAN  TIMESROMAN !) 24j/75&6kernedStrikes.bravo Ramshaw, LyleApril 17, 1980 1:58 PM