DIRECTORY Basics USING [BYTE, bytesPerWord], CountedVM USING [Allocate, Handle], FS USING [OpenFile, StreamFromOpenFile], Imager USING [Context, MaskFill], ImagerFont USING [CorrectionType, Extents, nullXChar, XChar], ImagerPath USING [PathProc], ImagerTypeface USING [Register, Typeface, TypefaceClass, TypefaceClassRep, TypefaceRep], IO USING [Close, SetIndex, STREAM, UnsafeGetBlock], PrePressFontFormat USING [CardFromBcpl, DirectoryArray, IntFromBcpl, IXHeader, missingFilePos, missingSpline, NameIndexEntry, RelFilePos, SplineCode, SplineCommand, SplineCoords, SplineData, SplineDataArray, StdIndexEntry], RealConvert USING [BcplToIeee], Vector2 USING [Add, Div, VEC]; ImagerSDTypefaceImpl: CEDAR PROGRAM IMPORTS CountedVM, FS, Imager, ImagerTypeface, IO, PrePressFontFormat, RealConvert, Vector2 ~ BEGIN OPEN ImagerTypeface, ImagerFont; BYTE: TYPE ~ Basics.BYTE; VEC: TYPE ~ Vector2.VEC; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ bc, ec: BYTE _ 0, splineData: LONG POINTER TO PrePressFontFormat.SplineDataArray _ NIL, directory: LONG POINTER TO PrePressFontFormat.DirectoryArray _ NIL, vm: CountedVM.Handle _ NIL ]; MalformedSDFont: ERROR ~ CODE; ReadWords: UNSAFE PROC [stream: IO.STREAM, base: LONG POINTER, words: INT] ~ UNCHECKED { count: INT ~ words*Basics.bytesPerWord; IF IO.UnsafeGetBlock[stream, [base: LOOPHOLE[base], count: count]]=count THEN NULL ELSE ERROR MalformedSDFont; -- data too short }; SDCreate: PROC [file: FS.OpenFile] RETURNS [Typeface] ~ { OPEN PrePressFontFormat; stream: IO.STREAM ~ FS.StreamFromOpenFile[file]; data: Data ~ NEW[DataRep _ []]; ix: IXHeader; ixSize: NAT ~ SIZE[IXHeader]; name: NameIndexEntry; index: StdIndexEntry; nameFound, indexFound: BOOL _ FALSE; segmentIndex, segmentWords: INT _ 0; DO -- read the index part TRUSTED { ReadWords[stream, @ix, SIZE[IXHeader]] }; SELECT ix.type FROM end => EXIT; name => { IF nameFound THEN ERROR MalformedSDFont; -- more than one name entry IF (ix.length-ixSize)=SIZE[NameIndexEntry] THEN TRUSTED { ReadWords[stream, @name, SIZE[NameIndexEntry]] } ELSE ERROR MalformedSDFont; -- wrong ix.length nameFound _ TRUE; }; spline => { IF indexFound THEN ERROR MalformedSDFont; -- more than one char index entry IF (ix.length-ixSize)=SIZE[StdIndexEntry] THEN TRUSTED { ReadWords[stream, @index, SIZE[StdIndexEntry]] } ELSE ERROR MalformedSDFont; -- wrong ix.length indexFound _ TRUE; }; ENDCASE => ERROR MalformedSDFont; -- unexpected ix type ENDLOOP; IF nameFound AND indexFound AND name.code=index.family THEN NULL ELSE ERROR MalformedSDFont; -- index part has wrong form IF index.bc>index.ec THEN ERROR MalformedSDFont; -- bc exceeds ec data.bc _ index.bc; data.ec _ index.ec; segmentIndex _ CardFromBcpl[index.segmentSA]; -- in words! segmentWords _ CardFromBcpl[index.segmentLength]; data.vm _ CountedVM.Allocate[words: segmentWords]; IO.SetIndex[stream, segmentIndex*Basics.bytesPerWord]; TRUSTED { -- read segment base: LONG POINTER ~ data.vm.pointer; ReadWords[stream, base, segmentWords]; data.splineData _ LOOPHOLE[base]; data.directory _ LOOPHOLE[base+SIZE[SplineDataArray[index.ec-index.bc+1]]]; }; IO.Close[stream]; RETURN[NEW[TypefaceRep _ [class: sdClass, data: data]]]; }; SDContains: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ { data: Data ~ NARROW[self.data]; IF char.set=0 AND char.code IN[data.bc..data.ec] THEN { index: NAT ~ char.code-data.bc; sd: PrePressFontFormat.SplineData; TRUSTED { sd _ data.splineData[index] }; RETURN[sd.wx#PrePressFontFormat.missingSpline]; }; RETURN[FALSE]; }; SDNextChar: 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.codefxmax THEN fxmax _ xmax; IF ymax>fymax THEN fymax _ ymax; }; count _ count+1; }; ENDLOOP; RETURN[[leftExtent: -fxmin, rightExtent: fxmax, descent: -fymin, ascent: fymax]]; }; SDKern: PROC [self: Typeface, char, successor: XChar] RETURNS [VEC] ~ { RETURN[[0, 0]]; }; SDNextKern: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; SDLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; SDNextLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; SDMask: PROC [self: Typeface, char: XChar, context: Imager.Context] ~ { data: Data ~ NARROW[self.data]; IF char.set=0 AND char.code IN[data.bc..data.ec] THEN { index: NAT ~ char.code-data.bc; sd: PrePressFontFormat.SplineData; TRUSTED { sd _ data.splineData[index] }; IF sd.wx#PrePressFontFormat.missingSpline THEN { base: LONG POINTER _ NIL; path: ImagerPath.PathProc ~ { next: LONG POINTER _ base; lp: VEC _ [0, 0]; GetCode: PROC RETURNS [PrePressFontFormat.SplineCode] ~ TRUSTED { p: LONG POINTER TO PrePressFontFormat.SplineCommand ~ LOOPHOLE[next]; next _ next+SIZE[PrePressFontFormat.SplineCommand]; RETURN[p.code]; }; GetCoords: PROC RETURNS [VEC] ~ TRUSTED { p: LONG POINTER TO PrePressFontFormat.SplineCoords ~ LOOPHOLE[next]; next _ next+SIZE[PrePressFontFormat.SplineCoords]; RETURN[[RealConvert.BcplToIeee[p.x], RealConvert.BcplToIeee[p.y]]]; }; DO SELECT GetCode[] FROM $moveTo => { p: VEC ~ GetCoords[]; moveTo[p]; lp _ p; }; $drawTo => { p: VEC ~ GetCoords[]; lineTo[p]; lp _ p; }; $drawCurve => { c1: VEC ~ GetCoords[]; c2: VEC ~ GetCoords[]; c3: VEC ~ GetCoords[]; b1: VEC ~ lp.Add[c1.Div[3]]; b2: VEC ~ b1.Add[c1.Add[c2].Div[3]]; b3: VEC ~ lp.Add[c1].Add[c2].Add[c3]; curveTo[b1, b2, b3]; lp _ b3; }; $endDefinition => EXIT; $newObject => ERROR MalformedSDFont; -- not implemented ENDCASE => ERROR MalformedSDFont; -- undefined ENDLOOP; }; TRUSTED { filePos: PrePressFontFormat.RelFilePos ~ data.directory[index]; offset: INT ~ PrePressFontFormat.IntFromBcpl[filePos]; IF filePos=PrePressFontFormat.missingFilePos THEN ERROR MalformedSDFont; base _ LOOPHOLE[data.directory+offset]; }; Imager.MaskFill[context: context, path: path, parity: TRUE]; }; }; }; sdClass: TypefaceClass ~ NEW[TypefaceClassRep _ [ type: $SD, Contains: SDContains, NextChar: SDNextChar, Width: SDWidth, Amplified: SDAmplified, Correction: SDCorrection, BoundingBox: SDBoundingBox, FontBoundingBox: SDFontBoundingBox, Ligature: SDLigature, NextLigature: SDNextLigature, Kern: SDKern, NextKern: SDNextKern, Mask: SDMask ]]; ImagerTypeface.Register["SD", SDCreate]; END. ΐImagerSDTypefaceImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Doug Wyatt, May 29, 1985 10:39:42 am PDT { -- convert name to rope i: NAT _ 0; p: PROC RETURNS [CHAR] ~ { RETURN[VAL[name.chars[i _ i+1]]] }; family _ Rope.FromProc[len: name.chars[0], p: p]; }; SDRegister: PROC ~ { scratch: REF TEXT ~ NEW[TEXT[200]]; DoName: FS.NameProc ~ { cp: FS.ComponentPositions; start, stop: INT; text: REF TEXT _ scratch; [fullFName: fullFName, cp: cp] _ FS.ExpandName[fullFName]; start _ cp.subDirs.start; stop _ cp.base.start+cp.base.length; text.length _ 0; text _ RefText.AppendRope[to: text, from: "Xerox/PressFonts/"]; text _ RefText.AppendRope[to: text, from: fullFName, start: start, len: stop-start]; FOR i: NAT IN[0..text.length) DO IF text[i]='> THEN text[i] _ '/ ENDLOOP; Register[name: Rope.FromRefText[text], fileName: fullFName, create: SDCreate]; RETURN[continue: TRUE]; }; FS.EnumerateForNames[pattern: "[Indigo]*.sd!H", proc: DoName]; Alias["Xerox/XC82-0-0/Classic", "Xerox/PressFonts/Classic-MRR"]; Alias["Xerox/XC82-0-0/Classic-Bold", "Xerox/PressFonts/Classic-BRR"]; Alias["Xerox/XC82-0-0/Classic-Italic", "Xerox/PressFonts/Classic-MIR"]; Alias["Xerox/XC82-0-0/Modern", "Xerox/PressFonts/Modern-MRR"]; Alias["Xerox/XC82-0-0/Modern-Bold", "Xerox/PressFonts/Modern-BRR"]; Alias["Xerox/XC82-0-0/Modern-Italic", "Xerox/PressFonts/Modern-MIR"]; Alias["Xerox/XC82-0-0/Logotypes-Xerox", "Xerox/PressFonts/LOGO-MRR"]; }; Κ \˜codešœ™Kšœ Οmœ7™BK™(—K™šΟk ˜ Kšœžœžœ˜"Kšœ žœ˜#Kšžœžœ ˜(Kšœžœ˜!Kšœ žœ-˜=Kšœ žœ ˜KšœžœD˜XKšžœžœžœ˜3KšœžœΗ˜ίKšœ žœ˜Kšœžœ žœ˜—K˜KšΠblœžœž˜#Kšžœ žœžœ*˜[Kšœžœžœ˜(K˜Kšžœžœ žœ˜Kšžœžœ žœ˜K˜Kšœžœžœ ˜šœ žœžœ˜Kšœžœ˜Kš œ žœžœžœ&žœ˜EKš œ žœžœžœ%žœ˜CKšœž˜K˜K˜—K˜Kšœžœžœ˜K˜šΟn œžœžœ žœžœžœžœ žœž œ˜XKšœžœ˜'Kš žœžœžœžœž˜RKšžœžœΟc˜-K˜K˜—š œžœžœ žœ˜9Kšžœ˜Kšœžœžœžœ˜0Kšœ žœ˜K˜ Kšœžœžœ ˜Kšœ˜Kšœ˜Kšœžœžœ˜$Kšœžœ˜$šžœ‘˜Kšžœžœ˜3šžœ ž˜Kšœžœ˜ šœ ˜ Kšžœ žœžœ‘˜Dšžœžœžœžœ˜9Kšœžœ˜0—Kšžœžœ‘˜.šœ‘™Kš œžœ žœžœžœžœžœ™JKšœ1™1K™—Kšœ žœ˜K˜—šœ ˜ Kšžœ žœžœ‘!˜Kšžœžœžœžœ˜8Kšœžœ˜0—Kšžœžœ‘˜.Kšœ žœ˜K˜—Kšžœžœ‘˜7—Kšžœ˜—Kš žœ žœ žœžœž˜@Kšžœžœ‘˜8Kšžœžœžœ‘˜AKšœ'˜'Kšœ.‘ ˜:Kšœ1˜1Kšœ2˜2Kšžœ4˜6šžœ‘˜Kšœžœžœ˜%Kšœ&˜&Kšœžœ˜!Kšœžœžœ(˜KK˜—Kšžœ˜Kšžœžœ.˜8K˜K˜—K˜š  œžœžœžœ˜AKšœ žœ ˜šžœ žœ žœžœ˜7Kšœžœ˜Kšœ"˜"Kšžœ!˜(Kšžœ)˜/K˜—Kšžœžœ˜K˜K˜—š  œžœžœ˜HKšœ žœ ˜Kšœžœ˜Kšžœžœž˜Kšžœžœ žœžœ˜AKšžœžœ ˜š žœžœžœžœž˜2Kšœžœ˜Kšœ"˜"Kšžœ!˜(Kšžœ(žœžœ˜LKšžœ˜—Kšžœ ˜K˜K˜—š œžœžœžœ˜=Kšœ žœ ˜šžœ žœ žœžœ˜7Kšœžœ˜Kšœ"˜"Kšžœ!˜(šžœ(žœ˜0Kšœžœ!˜)Kšœžœ!˜)Kšžœ ˜K˜—K˜—Kšžœ ˜K˜K˜—š  œžœžœžœ˜BKšžœ žœ˜%K˜K˜—š  œžœžœ˜MKšœ žœ ˜šžœ žœ žœžœ˜7Kš žœžœžœžœžœ˜6K˜—Kšžœ˜ K˜K˜—š  œžœžœ˜GKšœ žœ ˜šžœ žœ žœžœ˜7Kšœžœ˜Kšœ"˜"Kšžœ!˜(šžœ(žœ˜0Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-KšžœG˜MK˜—K˜—Kšžœ˜K˜K˜—š œžœžœ˜>Kšœ žœ ˜Kšœžœ˜Kšœžœ˜%šžœžœžœž˜&Kšœžœ˜Kšœ"˜"Kšžœ!˜(šžœ(žœ˜0Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-Kšžœ žœ;˜Jšžœ˜Kšžœ žœ˜ Kšžœ žœ˜ Kšžœ žœ˜ Kšžœ žœ˜ K˜—K˜K˜—Kšžœ˜—KšžœK˜QK˜K˜—š œžœ*žœžœ˜GKšžœ ˜K˜K˜—š  œžœ*žœ ˜MKšžœ ˜K˜K˜—š  œžœ*žœ ˜MKšžœ ˜K˜K˜—š œžœ*žœ ˜QKšžœ ˜K˜K˜—š œžœ;˜GKšœ žœ ˜šžœ žœ žœžœ˜7Kšœžœ˜Kšœ"˜"Kšžœ!˜(šžœ(žœž˜0Kšœžœžœžœ˜šœ˜Kšœžœžœ˜Kšœžœ ˜š œžœžœ#žœ˜AKš œžœžœžœ$žœ˜EKšœ žœ#˜3Kšžœ ˜K˜—š   œžœžœžœžœ˜)Kš œžœžœžœ#žœ˜DKšœ žœ"˜2Kšžœ=˜CK˜—šžœžœ ž˜˜ Kšœžœ˜K˜ K˜K˜—˜ Kšœžœ˜K˜ K˜K˜—šœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜$Kšœžœ˜%K˜K˜K˜—Kšœžœ˜Kšœžœ‘˜7Kšžœžœ‘ ˜.Kšžœ˜—K˜—šžœ˜ Kšœ?˜?Kšœžœ+˜6Kšžœ+žœžœ˜HKšœžœ˜'K˜—Kšœ6žœ˜™>K™K™?KšœT™TKšžœžœžœžœžœ žœžœ™IK™NKšžœ žœ™K™—KšžœH™JK™@K™EK™GK™>K™CK™EKšœE™EK™K™—Kšœ(˜(K˜Kšžœ˜—…—"$4@