DIRECTORY Basics USING [bytesPerWord], BasicTime USING [GMT], CountedVM USING [Allocate, Handle], ImagerFont USING [BYTE, CorrectionType, Extents, nullXChar, XChar], ImagerTypeface USING [Register, Typeface, TypefaceClass, TypefaceClassRep, TypefaceRep], FS USING [OpenFile, StreamFromOpenFile], Imager USING [Context, MaskBits], IO USING [Close, EndOfStream, STREAM, UnsafeGetBlock], Rope USING [ROPE], StrikeFontFormat USING [Body, BoundingBox, Header, nullWidthEntry, WidthEntry, WTable, XTable], Vector2 USING [VEC]; ImagerStrikeTypefaceImpl: CEDAR PROGRAM IMPORTS CountedVM, FS, Imager, ImagerTypeface, IO ~ BEGIN OPEN ImagerTypeface, ImagerFont; ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector2.VEC; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ min, max: BYTE _ 0, left, right, ascent, descent: INTEGER _ 0, -- font extents strike: LONG POINTER _ NIL, raster, lines: NAT _ 0, xtable: LONG POINTER TO StrikeFontFormat.XTable _ NIL, wtable: LONG POINTER TO StrikeFontFormat.WTable _ NIL, vm: CountedVM.Handle _ NIL ]; MalformedStrikeFont: ERROR ~ CODE; Assert: PROC [pred: BOOL] ~ { IF pred THEN NULL ELSE ERROR MalformedStrikeFont }; ReadWords: UNSAFE PROC [stream: IO.STREAM, base: LONG POINTER, words: INT] ~ UNCHECKED { count: CARDINAL ~ words*Basics.bytesPerWord; IF IO.UnsafeGetBlock[stream, [base: base, count: count]]=count THEN NULL ELSE ERROR IO.EndOfStream[stream]; -- file too short }; StrikeCreate: PROC [file: FS.OpenFile] RETURNS [Typeface] ~ { OPEN StrikeFontFormat; stream: IO.STREAM ~ FS.StreamFromOpenFile[file]; data: Data _ NIL; header: Header; box: BoundingBox _ [0, 0, 0, 0]; body: Body; left, right, descent, ascent, lines: INTEGER _ 0; vm: CountedVM.Handle _ NIL; strikeWords, xtableWords, wtableWords: NAT _ 0; vmWords: INT _ 0; strike, xtable, wtable: LONG POINTER _ NIL; TRUSTED { ReadWords[stream, @header, SIZE[Header]] }; Assert[header.oneBit=T AND header.index=F AND header.unused=0]; Assert[header.min<=header.max AND header.max<=BYTE.LAST]; IF header.kerned=T THEN TRUSTED { ReadWords[stream, @box, SIZE[BoundingBox]] }; TRUSTED { ReadWords[stream, @body, SIZE[Body]] }; descent _ body.descent; ascent _ body.ascent; Assert[(lines _ descent+ascent)>0]; IF header.kerned=T THEN { left _ -box.fbbox; right _ box.fbbox+box.fbbdx; Assert[box.fbboy=-descent AND box.fbbdy=lines AND box.fbbdx>0] } ELSE { left _ 0; right _ header.maxwidth }; strikeWords _ body.raster*lines; xtableWords _ header.max-header.min+3; Assert[CARDINAL[SIZE[Body]+strikeWords+xtableWords]<=body.length]; IF header.kerned=T THEN wtableWords _ header.max-header.min+2; vmWords _ LONG[strikeWords+xtableWords]+wtableWords; vm _ CountedVM.Allocate[words: vmWords]; IF vm.wordsx0 THEN RETURN[index]; } ELSE TRUSTED { w: StrikeFontFormat.WidthEntry ~ data.wtable[index]; IF w#StrikeFontFormat.nullWidthEntry THEN RETURN[index]; }; }; RETURN[data.max-data.min+1]; }; StrikeContains: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ { data: Data ~ NARROW[self.data]; RETURN[Index[data, char]<=(data.max-data.min)]; }; StrikeNextChar: PROC [self: Typeface, char: XChar] RETURNS [next: XChar] ~ { data: Data ~ NARROW[self.data]; start: BYTE _ 0; IF char=nullXChar THEN NULL ELSE IF char.set=0 AND char.codex0 THEN RETURN[[leftExtent: 0, rightExtent: (x1-x0), descent: data.descent, ascent: data.ascent]]; } ELSE TRUSTED { w: StrikeFontFormat.WidthEntry ~ data.wtable[index]; IF w#StrikeFontFormat.nullWidthEntry THEN { x0: INTEGER ~ data.xtable[index]; x1: INTEGER ~ data.xtable[index+1]; left: INTEGER ~ data.left-w.offset; RETURN[[leftExtent: left, rightExtent: (x1-x0)-left, descent: data.descent, ascent: data.ascent]]; }; }; RETURN[[0, 0, 0, 0]]; }; StrikeFontBoundingBox: PROC [self: Typeface] RETURNS [Extents] ~ { data: Data ~ NARROW[self.data]; RETURN[[leftExtent: data.left, rightExtent: data.right, descent: data.descent, ascent: data.ascent]]; }; StrikeWidth: PROC [self: Typeface, char: XChar] RETURNS [VEC] ~ { data: Data ~ NARROW[self.data]; index: NAT ~ Index[data, char]; IF data.wtable=NIL THEN TRUSTED { x0: INTEGER ~ data.xtable[index]; x1: INTEGER ~ data.xtable[index+1]; IF x1>x0 THEN RETURN[[x1-x0, 0]]; } ELSE TRUSTED { w: StrikeFontFormat.WidthEntry ~ data.wtable[index]; IF w#StrikeFontFormat.nullWidthEntry THEN RETURN[[w.width, 0]]; }; RETURN[[0, 0]]; }; spaceChar: XChar ~ [set: 0, code: 40B]; StrikeAmplified: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ { RETURN[char=spaceChar]; }; StrikeCorrection: PROC [self: Typeface, char: XChar] RETURNS [CorrectionType] ~ { RETURN[IF char=spaceChar THEN space ELSE mask]; }; StrikeKern: PROC [self: Typeface, char, successor: XChar] RETURNS [VEC] ~ { RETURN[[0, 0]]; }; StrikeNextKern: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; StrikeLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; StrikeNextLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; StrikeMask: PROC [self: Typeface, char: XChar, context: Imager.Context] ~ TRUSTED { data: Data ~ NARROW[self.data]; index: NAT ~ Index[data, char]; x0: INTEGER ~ data.xtable[index]; x1: INTEGER ~ data.xtable[index+1]; IF x0<=x1 AND NAT[x1]<=NAT[data.raster*16] THEN NULL ELSE ERROR MalformedStrikeFont; -- xtable inconsistent IF data.wtable=NIL THEN { IF x1>x0 THEN Imager.MaskBits[context: context, base: data.strike, wordsPerLine: data.raster, fMin: x0, fSize: x1-x0, sMin: 0, sSize: data.lines, tx: 0, ty: data.ascent]; } ELSE { w: StrikeFontFormat.WidthEntry ~ data.wtable[index]; IF w#StrikeFontFormat.nullWidthEntry AND x1>x0 THEN Imager.MaskBits[context: context, base: data.strike, wordsPerLine: data.raster, fMin: x0, fSize: x1-x0, sMin: 0, sSize: data.lines, tx: w.offset-data.left, ty: data.ascent]; }; }; strikeClass: TypefaceClass ~ NEW[TypefaceClassRep _ [ type: $Strike, Contains: StrikeContains, NextChar: StrikeNextChar, Width: StrikeWidth, Amplified: StrikeAmplified, Correction: StrikeCorrection, BoundingBox: StrikeBoundingBox, FontBoundingBox: StrikeFontBoundingBox, Ligature: StrikeLigature, NextLigature: StrikeNextLigature, Kern: StrikeKern, NextKern: StrikeNextKern, Mask: StrikeMask ]]; ImagerTypeface.Register["strike", StrikeCreate]; ImagerTypeface.Register["ks", StrikeCreate]; END. ImagerStrikeTypefaceImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Doug Wyatt, May 24, 1985 7:00:35 pm PDT Κ ’˜codešœ™Kšœ Οmœ7™BK™'—K™šΟk ˜ Kšœžœ˜Kšœ žœžœ˜Kšœ žœ˜#Kšœ žœžœ-˜CKšœžœD˜XKšžœžœ ˜(Kšœžœ˜!Kšžœžœžœ˜6Kšœžœžœ˜KšœžœI˜_Kšœžœžœ˜—K˜KšΠblœžœž˜'Kšžœ žœž˜1Kšœžœžœ˜(K˜Kšžœžœžœ˜Kšžœžœ žœ˜K˜Kšœžœžœ ˜šœ žœžœ˜Kšœ žœ˜KšœžœΟc˜:Kšœžœžœžœ˜Kšœžœ˜Kš œžœžœžœžœ˜6Kš œžœžœžœžœ˜6Kšœž˜K˜K˜—Kšœžœžœ˜"K˜KšΟnœžœžœžœžœžœžœžœ˜QK˜š‘ œžœžœ žœžœžœžœ žœž œ˜XKšœžœ˜,Kšžœžœ:žœž˜HKšžœžœžœ ˜4K˜K˜—š‘ œžœžœ žœ˜=Kšžœ˜Kšœžœžœžœ˜0Kšœ žœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ%žœ˜1Kšœžœ˜Kšœ'žœ˜/Kšœ žœ˜Kšœžœžœžœ˜+Kšžœžœ ˜5Kš œžœžœžœžœ˜?Kšœžœ žœžœ˜9Kš žœžœžœžœžœ˜OKšžœžœ ˜1Kšœ-˜-Kšœ#˜#šžœžœžœ2˜IKšœžœžœ˜@—Kšžœ'˜+K˜ K˜&Kšœžœžœ.˜BKšžœžœžœ'˜>Kšœ žœ&˜4Kšœ(˜(Kšžœžœžœ ˜5šžœžœ 5˜DKšœžœžœ˜ Kšœ!˜!K˜Kšœ˜Kšžœžœ˜2K˜—Kšžœ˜šœžœ-˜7KšœE˜EKšœ\˜\—Kšžœžœ2˜