DIRECTORY ImagerTransform, UFont, Real USING [MinusZero, SqRt], RefText USING [ObtainScratch, ReleaseScratch], Rope USING [FromRefText, ROPE], UFTfm, UFFileManager USING [FontFile, GetData, InBounds, InitProc, Open, Pointer], UFTfmReader; UFTfmReaderImpl: CEDAR PROGRAM IMPORTS ImagerTransform, UFont, Real, RefText, Rope, UFTfm, UFFileManager EXPORTS UFTfmReader = BEGIN OPEN UFTfmReader; TwoToTheTenth: INT = 2*2*2*2*2 * 2*2*2*2*2; TwoToTheTwentieth: INT = TwoToTheTenth*TwoToTheTenth; RealTwoToTheTwentieth: REAL = TwoToTheTwentieth; FixedToReal: PROCEDURE [x: UFTfm.Fixed] RETURNS [REAL] = {RETURN[UFTfm.Long[x]/RealTwoToTheTwentieth]}; Ord: PROCEDURE [c: CHAR] RETURNS [[0..256)] = INLINE {RETURN[LOOPHOLE[c]]}; Data: TYPE = REF DataRec; DataRec: TYPE = RECORD [ characterCodingScheme: Rope.ROPE, family: Rope.ROPE, dirPtr: LONG POINTER TO UFTfm.Directory, headerPtr: LONG POINTER TO UFTfm.Header, fInfoDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.FInfoEntry, widthDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.Fixed, heightDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.Fixed, depthDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.Fixed, charIcDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.Fixed, ligKernDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.LigKernEntry, kernDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.Fixed, extenDesc: LONG DESCRIPTOR FOR ARRAY OF UFTfm.ExtRecipe, paramPtr: LONG POINTER TO UFTfm.Param ]; OpenInit: UFFileManager.InitProc = TRUSTED { base: LONG POINTER _ fontFile.Pointer[]; dir: LONG POINTER TO UFTfm.Directory _ base; data: Data _ NEW[DataRec]; curPtr: LONG POINTER _ base; Next: UNSAFE PROC [size: NAT] RETURNS [p: LONG POINTER] = UNCHECKED {p _ curPtr; curPtr _ curPtr + size}; s: NAT = SIZE[UFTfm.Word]; IF NOT fontFile.InBounds[dir, SIZE[UFTfm.Directory]] THEN ERROR UFont.BadFontFileFormat; IF NOT UFTfm.ValidDirectory[dir^] THEN ERROR UFont.BadFontFileFormat; IF NOT fontFile.InBounds[base, dir.lf] THEN ERROR UFont.BadFontFileFormat; data.dirPtr _ Next[SIZE[UFTfm.Directory]]; data.headerPtr _ Next[s*dir.lh]; data.fInfoDesc _ DESCRIPTOR[Next[s*(dir.ec-dir.bc+1)], s*(dir.ec-dir.bc+1)]; data.widthDesc _ DESCRIPTOR[Next[s*dir.nw], s*dir.nw]; data.heightDesc _ DESCRIPTOR[Next[s*dir.nh], s*dir.nh]; data.depthDesc _ DESCRIPTOR[Next[s*dir.nd], s*dir.nd]; data.charIcDesc _ DESCRIPTOR[Next[s*dir.ni], s*dir.ni]; data.ligKernDesc _ DESCRIPTOR[Next[s*dir.nl], s*dir.nl]; data.kernDesc _ DESCRIPTOR[Next[s*dir.nk], s*dir.nk]; data.extenDesc _ DESCRIPTOR[Next[s*dir.ne], s*dir.ne]; data.paramPtr _ Next[s*dir.np]; BEGIN temp: REF TEXT _ RefText.ObtainScratch[40]; temp.length _ Ord[data.headerPtr.characterCodingScheme[0]]; FOR i: NAT IN [0..temp.length) DO temp[i] _ data.headerPtr.characterCodingScheme[i+1]; ENDLOOP; data.characterCodingScheme _ Rope.FromRefText[temp]; temp.length _ Ord[data.headerPtr.externalFontIdentifier[0]]; FOR i: NAT IN [0..temp.length) DO temp[i] _ data.headerPtr.externalFontIdentifier[i+1]; ENDLOOP; data.family _ Rope.FromRefText[temp]; RefText.ReleaseScratch[temp]; END; RETURN[data]; }; CheckSum: PUBLIC PROCEDURE [key: Key] RETURNS [checkSum: UFTfm.Word] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; checkSum _ data.headerPtr.checkSum; }; CharacterCodingScheme: PUBLIC PROCEDURE [key: Key] RETURNS [characterCodingScheme: Rope.ROPE] = { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; characterCodingScheme _ data.characterCodingScheme; }; Family: PUBLIC PROCEDURE [key: Key] RETURNS [family: Rope.ROPE] = { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; family _ data.family; }; DesignSize: PUBLIC PROCEDURE [key: Key] RETURNS [designSize: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; designSize _ FixedToReal[data.headerPtr.designSize]; }; Face: PUBLIC PROCEDURE [key: Key] RETURNS [face: [0..256)] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; face _ data.headerPtr.extraInfo.parcFaceByte; }; Range: PUBLIC PROCEDURE [key: Key] RETURNS [bc, ec: CHAR] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; bc _ '\000+data.dirPtr.bc; ec _ '\000+data.dirPtr.ec; }; NullFInfoEntry: UFTfm.FInfoEntry = [0, 0, 0, 0, none[]]; Contains: PUBLIC PROCEDURE [key: Key, char: CHAR] RETURNS [BOOLEAN] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char]>= data.dirPtr.bc AND Ord[char] <= data.dirPtr.ec) THEN RETURN [FALSE]; RETURN[data.fInfoDesc[Ord[char]-data.dirPtr.bc] # NullFInfoEntry]; }; Width: PUBLIC PROCEDURE [key: Key, char: CHAR] RETURNS [width: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char] IN [data.dirPtr.bc..data.dirPtr.ec]) THEN RETURN [Real.MinusZero]; width _ FixedToReal[data.widthDesc[data.fInfoDesc[Ord[char]-data.dirPtr.bc].widthIndex]]; }; Height: PUBLIC PROCEDURE [key: Key, char: CHAR] RETURNS [height: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char] IN [data.dirPtr.bc..data.dirPtr.ec]) THEN RETURN [Real.MinusZero]; height _ FixedToReal[data.heightDesc[data.fInfoDesc[Ord[char]-data.dirPtr.bc].heightIndex]]; }; Depth: PUBLIC PROCEDURE [key: Key, char: CHAR] RETURNS [depth: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char] IN [data.dirPtr.bc..data.dirPtr.ec]) THEN RETURN [Real.MinusZero]; depth _ FixedToReal[data.depthDesc[data.fInfoDesc[Ord[char]-data.dirPtr.bc].depthIndex]]; }; ItalicCorrection: PUBLIC PROCEDURE [key: Key, char: CHAR] RETURNS [italicCorrection: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char] IN [data.dirPtr.bc..data.dirPtr.ec]) THEN RETURN [Real.MinusZero]; italicCorrection _ FixedToReal[data.charIcDesc[data.fInfoDesc[Ord[char]-data.dirPtr.bc].charIcIndex]]; }; LigKern: PUBLIC PROCEDURE [key: Key, char1, char2: CHAR] RETURNS [ligOrKern: LigatureOrKern] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; IF NOT (Ord[char1] IN [data.dirPtr.bc..data.dirPtr.ec] AND Ord[char2] IN [data.dirPtr.bc..data.dirPtr.ec]) THEN RETURN [[neither[]]]; WITH data.fInfoDesc[Ord[char1]-data.dirPtr.bc] SELECT FROM ligFInfoEntry: UFTfm.FInfoEntry[lig] => { FOR i: NAT _ ligFInfoEntry.ligKernStart, i+1 DO ligKernEntry: UFTfm.LigKernEntry _ data.ligKernDesc[i]; IF ligKernEntry.nextChar = char2 THEN RETURN[ WITH ligKernEntry SELECT FROM ligEntry: UFTfm.LigKernEntry[lig] => [ligature[ligatureCode: ligEntry.ligCode]], kernEntry: UFTfm.LigKernEntry[kern] => [kern[kernAmount: FixedToReal[data.kernDesc[kernEntry.kernIndex]]]], ENDCASE => ERROR ]; IF ligKernEntry.stop THEN RETURN[[neither[]]]; ENDLOOP }; ENDCASE => RETURN[[neither[]]]; }; Slant: PUBLIC PROCEDURE [key: Key] RETURNS [numerator, denominator: INT] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; numerator _ UFTfm.Long[data.paramPtr[slant].ValueTimesTwoToTheTwentieth]; denominator _ TwoToTheTwentieth; }; Parameter: PUBLIC PROCEDURE [key: Key, index: UFTfm.ParamIndex] RETURNS [parameterValue: REAL] = TRUSTED { file: UFFileManager.FontFile _ UFFileManager.Open[key,OpenInit]; data: Data _ NARROW[file.GetData[]]; parameterValue _ IF LOOPHOLE[index, CARDINAL] > data.dirPtr.np THEN 0.0 ELSE FixedToReal[data.paramPtr[index]]; }; FONT: TYPE = UFont.FONT; LigatureOrKern: TYPE = UFont.LigatureOrKern; Box: TYPE = UFont.Box; VecMag: PROC [x, y: REAL] RETURNS [REAL] = {RETURN[Real.SqRt[x*x + y*y]]}; TFMLigKern: PROCEDURE [font: FONT, char1, char2: CHAR] RETURNS [ligatureOrKern: LigatureOrKern] = { ligKern: LigatureOrKern _ LigKern[font.formattingKey, char1, char2]; WITH lg: ligKern SELECT FROM kern => { scale: REAL _ IF font.actualTransformation.Contents.b = 0 THEN font.actualTransformation.Contents.e ELSE VecMag[font.actualTransformation.Contents.b, font.actualTransformation.Contents.e]; RETURN[[kern[lg.kernAmount*scale]]] }; ENDCASE => RETURN[ligKern]; }; TFMFormattingBox: PROCEDURE [font: FONT, char: CHAR] RETURNS [box: Box] = { s: REAL _ IF font.actualTransformation.Contents.b = 0 THEN font.actualTransformation.Contents.e ELSE VecMag[font.actualTransformation.Contents.b, font.actualTransformation.Contents.e]; box.xmin _ 0; box.xmax _ Width[font.formattingKey, char]*s; box.ymin _ - Depth[font.formattingKey, char]*s; box.ymax _ Height[font.formattingKey, char]*s; }; TFMFormattingMetric: PROCEDURE [font: FONT, metric: ATOM, char: CHAR] RETURNS [REAL] = { RETURN[0.0]; }; TFMObjectInit: PROCEDURE [font: FONT] = { font.fontFormattingClass _ TFMClass; }; TFMClass: REF UFont.FontFormattingClassRec _ NEW[UFont.FontFormattingClassRec _ [ formattingBoxProc: TFMFormattingBox, ligKernProc: TFMLigKern, formattingMetricProc: TFMFormattingMetric ]]; UFont.RegisterFontFormattingClass[$Tfm, TFMObjectInit]; END. UFTfmReaderImpl.mesa Copyright c 1983, 1984, Xerox Corporation. All rights reserved. Last changed by Michael Plass, February 15, 1984 8:48:33 am PST Last changed by Doug Wyatt, August 6, 1984 11:55:01 am PDT Make some ropes FontFormattingClass interface Ê ü˜šœ™Jšœ Ïmœ5™@Jšœ?™?Jšœ:™:—J™šÏk ˜ J˜Jšœ˜Jšœžœ˜Jšœžœ!˜.Jšœžœžœ˜Jšœ˜Jšœžœ8˜KJšœ ˜ J˜—Jšœž ˜JšžœB˜IJšžœ˜Jšžœžœ ˜J˜Jšœžœ˜+Jšœžœ˜5Jšœžœ˜0J˜šÏn œž œžœžœ˜8Jšœžœ'˜.J˜—JšŸœž œžœžœžœžœžœ˜KJ˜Jšœžœžœ ˜šœ žœžœ˜Jšœžœ˜!Jšœ žœ˜Jšœžœžœžœ˜(Jšœ žœžœžœ˜(Jš œ žœž œžœžœžœ˜9Jš œ žœž œžœžœžœ ˜4Jš œ žœž œžœžœžœ ˜5Jš œ žœž œžœžœžœ ˜4Jš œ žœž œžœžœžœ ˜5Jš œ žœž œžœžœžœ˜=Jš œ žœž œžœžœžœ ˜3Jš œ žœž œžœžœžœ˜8Jšœ žœžœžœ ˜%Jšœ˜J˜—šœ#žœ˜,Jšœžœžœ˜(Jšœžœžœžœ˜,Jšœ žœ ˜Jšœžœžœ˜JšŸœžœžœžœžœžœžœž œ&˜iJšœžœžœ ˜Jš žœžœžœžœžœ˜XJšžœžœžœžœ˜EJšžœžœ!žœžœ˜JJšœžœ˜*Jšœ ˜ Jšœž œ1˜LJšœž œ˜6Jšœž œ˜7Jšœž œ˜6Jšœž œ˜7Jšœž œ˜8Jšœž œ˜5Jšœž œ˜6Jšœ˜™Jšž˜Jšœžœžœ˜+Jšœ;˜;šžœžœžœž˜!Jšœ4˜4Jšž˜—Jšœ4˜4Jšœ<˜<šžœžœžœž˜!Jšœ5˜5Jšž˜—Jšœ%˜%Jšœ˜Jšž˜—Jšžœ˜ Jšœ˜J˜—š Ÿœžœž œ žœžœ˜PJšœ@˜@Jšœ žœ˜$Jšœ#˜#Jšœ˜J˜—š Ÿœžœž œ žœžœ˜aJšœ@˜@Jšœ žœ˜$Jšœ3˜3Jšœ˜J˜—š Ÿœžœž œ žœžœ˜CJšœ@˜@Jšœ žœ˜$Jšœ˜Jšœ˜J˜—š Ÿ œžœž œ žœžœžœ˜NJšœ@˜@Jšœ žœ˜$Jšœ4˜4Jšœ˜J˜—š Ÿœžœž œ žœžœ˜FJšœ@˜@Jšœ žœ˜$Jšœ-˜-Jšœ˜J˜—š Ÿœžœž œ žœ žœžœ˜EJšœ@˜@Jšœ žœ˜$Jšœ˜Jšœ˜Jšœ˜J˜—Jšœ8˜8J˜šŸœžœž œžœžœžœžœ˜OJšœ@˜@Jšœ žœ˜$Jš žœžœžœžœžœžœ˜XJšžœ<˜BJšœ˜J˜—šŸœžœž œžœžœ žœžœ˜PJšœ@˜@Jšœ žœ˜$Jš žœžœ žœ#žœžœ˜TJšœY˜YJšœ˜J˜—šŸœžœž œžœžœ žœžœ˜RJšœ@˜@Jšœ žœ˜$Jš žœžœ žœ#žœžœ˜TJšœ\˜\Jšœ˜J˜—šŸœžœž œžœžœ žœžœ˜PJšœ@˜@Jšœ žœ˜$Jš žœžœ žœ#žœžœ˜TJšœY˜YJšœ˜J˜—šŸœžœž œžœžœžœžœ˜fJšœ@˜@Jšœ žœ˜$Jš žœžœ žœ#žœžœ˜TJšœf˜fJšœ˜J˜—JšŸœžœž œžœ˜8šžœžœ˜/Jšœ@˜@Jšœ žœ˜$Jšžœžœ žœ"žœ žœ#žœžœ˜…šžœ+žœž˜:šœ)˜)šžœžœ#ž˜/Jšœ7˜7šžœž œ˜-šžœžœž˜JšœP˜PJšœk˜kJšžœž˜—Jšœ˜—Jšžœžœžœ˜.Jšž˜—Jšœ˜—Jšžœžœ˜—Jšœ˜J˜—š Ÿœžœž œ žœžœžœ˜TJšœ@˜@Jšœ žœ˜$JšœI˜IJšœ ˜ Jšœ˜J˜—š Ÿ œžœž œ%žœžœžœ˜jJšœ@˜@Jšœ žœ˜$Jš œžœžœžœžœžœ#˜oJšœ˜J˜—šÏbŸ  ™J™Jšžœžœ žœ˜Jšœžœ˜,Jšœžœ ˜J˜š Ÿœžœžœžœžœžœ˜JJ˜—š Ÿ œž œžœžœžœ%˜cJšœD˜Dšžœ žœž˜šœ ˜ Jš œžœžœ*žœ&žœT˜¼Jšžœ˜#Jšœ˜—Jšžœžœ ˜—Jšœ˜J˜—š Ÿœž œžœžœžœ˜KJš œžœžœ*žœ&žœT˜¸J˜ Jšœ-˜-Jšœ/˜/Jšœ.˜.Jšœ˜J˜—šŸœž œžœ žœžœžœžœ˜XJšžœ˜ Jšœ˜J˜—šŸ œž œžœ˜)Jšœ$˜$Jšœ˜J˜—šœ žœ žœ!˜QJšœ$˜$Jšœ˜Jšœ)˜)J˜J˜—Jšœ7˜7J˜—Jšžœ˜—…—$t0x