<> <> <> <> <> <> <<>> DIRECTORY CardTable, Imager, ImagerBox, ImagerPath, ImagerFont, IKOps, Rope, ImagerTypeface, RuntimeError, FS; ImagerIKTypefaceImpl: CEDAR PROGRAM IMPORTS CardTable, Imager, ImagerBox, IKOps, ImagerTypeface, RuntimeError ~ BEGIN XChar: TYPE ~ ImagerFont.XChar; nullXChar: XChar ~ ImagerFont.nullXChar; VEC: TYPE ~ Imager.VEC; ROPE: TYPE ~ Rope.ROPE; IKFontData: TYPE ~ IKOps.IKFontData; Typeface: TYPE ~ ImagerTypeface.Typeface; CharCodeMapper: TYPE ~ CardTable.Ref; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ ikFontData: IKOps.IKFontData, charCodeMapper: CharCodeMapper, unitsPerEm: REAL ]; Ord: PROC [x: XChar] RETURNS [CARDINAL] ~ INLINE {RETURN [x.set*256+x.code]}; IKContains: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ { data: Data ~ NARROW[self.data]; mapped: REF CARDINAL ~ NARROW[CardTable.Fetch[data.charCodeMapper, Ord[char]].val]; RETURN [char = [0, 40B] OR mapped # NIL AND IKOps.Contains[data.ikFontData, mapped^]] }; IKNextChar: PROC [self: Typeface, char: XChar] RETURNS [XChar] ~ { Val: PROC [c: CARDINAL] RETURNS [XChar] ~ INLINE {RETURN [[set: c/256, code: c MOD 256]]}; next: XChar _ IF char = nullXChar THEN [0, 0] ELSE Val[Ord[char]+1]; UNTIL next = nullXChar OR IKContains[self, next] DO next _ Val[Ord[next]+1] ENDLOOP; RETURN [next]; }; defaultWidth: VEC ~ [0.5, 0.0]; wordSpaceWidth: VEC ~ [0.3333, 0.0]; IKWidth: PROC [self: Typeface, char: XChar] RETURNS [VEC] ~ { data: Data ~ NARROW[self.data]; mapped: REF CARDINAL ~ NARROW[CardTable.Fetch[data.charCodeMapper, Ord[char]].val]; IF char = [0, 40B] THEN { RETURN [wordSpaceWidth] }; IF mapped # NIL AND IKOps.Contains[data.ikFontData, mapped^] THEN { charInfo: IKOps.CharacterInfo ~ IKOps.GetCharacterInfo[data.ikFontData, mapped^]; RETURN [[x: charInfo.totalSetWidth/data.unitsPerEm, y: 0.0]] }; RETURN [defaultWidth]; }; IKAmplified: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ { IF char = [0, 40B] THEN RETURN [TRUE]; RETURN [FALSE] }; IKCorrection: PROC [self: Typeface, char: XChar] RETURNS [ImagerFont.CorrectionType] ~ { IF char = [0, 40B] THEN RETURN [space]; RETURN [mask] }; IKBoundingBox: PROC [self: Typeface, char: XChar] RETURNS [ImagerFont.Extents] ~ { data: Data ~ NARROW[self.data]; mapped: REF CARDINAL ~ NARROW[CardTable.Fetch[data.charCodeMapper, Ord[char]].val]; IF mapped # NIL AND IKOps.Contains[data.ikFontData, mapped^] THEN { charInfo: IKOps.CharacterInfo ~ IKOps.GetCharacterInfo[data.ikFontData, mapped^]; xMin: REAL ~ (charInfo.xMin+charInfo.leftSideBearing)/data.unitsPerEm; xMax: REAL ~ (charInfo.xMax+charInfo.leftSideBearing)/data.unitsPerEm; yMin: REAL ~ (charInfo.yMin)/data.unitsPerEm; yMax: REAL ~ (charInfo.yMax)/data.unitsPerEm; RETURN [ImagerBox.ExtentsFromBox[[xmin: xMin, ymin: yMin, xmax: xMax, ymax: yMax]]] }; RETURN [[leftExtent: -0.05, rightExtent: 0.45, descent: 0, ascent: 0.6]]; }; IKFontBoundingBox: PROC [self: Typeface] RETURNS [ImagerFont.Extents] ~ { data: Data ~ NARROW[self.data]; bb: ImagerBox.Box _ [xmin: 0.05, ymin: 0, xmax: 0.45, ymax: 0.6]; Action: PROC [characterCode: CARDINAL, byteOffsetOfCharacterData: INT] ~ { charInfo: IKOps.CharacterInfo ~ IKOps.GetCharacterInfo[data.ikFontData, characterCode]; xMin: REAL ~ (charInfo.xMin+charInfo.leftSideBearing)/data.unitsPerEm; xMax: REAL ~ (charInfo.xMax+charInfo.leftSideBearing)/data.unitsPerEm; yMin: REAL ~ (charInfo.yMin)/data.unitsPerEm; yMax: REAL ~ (charInfo.yMax)/data.unitsPerEm; bb _ ImagerBox.BoundingBox[bb, [xmin: xMin, ymin: yMin, xmax: xMax, ymax: yMax]]; }; IKOps.EnumerateCharacters[data.ikFontData, Action]; RETURN [ImagerBox.ExtentsFromBox[bb]]; }; IKLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; IKNextLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; IKKern: PROC [self: Typeface, char, successor: XChar] RETURNS [VEC] ~ { RETURN[[0, 0]]; }; IKNextKern: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ { RETURN[nullXChar]; }; IKMask: PROC [self: Typeface, char: XChar, context: Imager.Context] ~ { data: Data ~ NARROW[self.data]; mapped: REF CARDINAL ~ NARROW[CardTable.Fetch[data.charCodeMapper, Ord[char]].val]; IF mapped # NIL AND IKOps.Contains[data.ikFontData, mapped^] THEN { path: ImagerPath.PathProc ~ { IKOps.GetPath[data.ikFontData, mapped^, moveTo, lineTo, curveTo]; }; charInfo: IKOps.CharacterInfo ~ IKOps.GetCharacterInfo[data.ikFontData, mapped^]; Imager.ScaleT[context, 1.0/data.unitsPerEm]; Imager.TranslateT[context, [x: charInfo.xMin+charInfo.leftSideBearing, y: charInfo.yMin]]; Imager.MaskFill[context: context, path: path, parity: TRUE]; RETURN; }; IF char # [0, 40B] THEN Imager.MaskBox[context, [xmin: 0.05, ymin: 0.0, xmax: 0.45, ymax: 0.6]]; }; ikClass: ImagerTypeface.TypefaceClass ~ NEW[ImagerTypeface.TypefaceClassRep _ [ type: $IkarusFont, Contains: IKContains, NextChar: IKNextChar, Width: IKWidth, Amplified: IKAmplified, Correction: IKCorrection, BoundingBox: IKBoundingBox, FontBoundingBox: IKFontBoundingBox, Ligature: IKLigature, NextLigature: IKNextLigature, Kern: IKKern, NextKern: IKNextKern, Mask: IKMask ]]; FindCharCodeMapper: PROC [ikFontData: IKFontData] RETURNS [CharCodeMapper] ~ { RETURN [bigelowAndHolmesCharCodeMapper] -- for now }; FindUnitsPerEm: PROC [ikFontData: IKFontData] RETURNS [REAL] ~ { IF ikFontData.bodySize # 0.0 THEN RETURN [ikFontData.bodySize]; RETURN [16800.0] -- for now }; bigelowAndHolmesCharCodeMapper: CharCodeMapper ~ MakeBigelowAndHolmesCharCodeMapper[]; MakeBigelowAndHolmesCharCodeMapper: PROC RETURNS [CharCodeMapper] ~ { c: CardTable.Ref ~ CardTable.Create[199]; C: PROC [xSet: [0B..377B), xChar: [0B..377B), bChar: CARDINAL] ~ { [] _ CardTable.Store[c, xSet*256+xChar, NEW[CARDINAL _ bChar]]; }; C[xSet: 46B, xChar: 141B, bChar: 51]; C[xSet: 46B, xChar: 142B, bChar: 52]; C[xSet: 46B, xChar: 144B, bChar: 53]; C[xSet: 46B, xChar: 145B, bChar: 54]; C[xSet: 46B, xChar: 146B, bChar: 55]; C[xSet: 46B, xChar: 151B, bChar: 56]; C[xSet: 46B, xChar: 152B, bChar: 57]; C[xSet: 46B, xChar: 153B, bChar: 58]; C[xSet: 46B, xChar: 154B, bChar: 59]; C[xSet: 46B, xChar: 155B, bChar: 60]; C[xSet: 46B, xChar: 156B, bChar: 61]; C[xSet: 46B, xChar: 157B, bChar: 62]; C[xSet: 46B, xChar: 160B, bChar: 63]; C[xSet: 46B, xChar: 161B, bChar: 64]; C[xSet: 46B, xChar: 162B, bChar: 65]; C[xSet: 46B, xChar: 163B, bChar: 66]; C[xSet: 46B, xChar: 165B, bChar: 67]; C[xSet: 46B, xChar: 166B, bChar: 68]; C[xSet: 46B, xChar: 170B, bChar: 69]; C[xSet: 46B, xChar: 171B, bChar: 70]; C[xSet: 46B, xChar: 172B, bChar: 71]; C[xSet: 46B, xChar: 173B, bChar: 72]; C[xSet: 46B, xChar: 174B, bChar: 73]; C[xSet: 46B, xChar: 175B, bChar: 74]; C[xSet: 46B, xChar: 147B, bChar: 75]; C[xSet: 0B, xChar: 101B, bChar: 101]; C[xSet: 0B, xChar: 102B, bChar: 102]; C[xSet: 0B, xChar: 103B, bChar: 103]; C[xSet: 0B, xChar: 104B, bChar: 104]; C[xSet: 0B, xChar: 105B, bChar: 105]; C[xSet: 0B, xChar: 106B, bChar: 106]; C[xSet: 0B, xChar: 107B, bChar: 107]; C[xSet: 0B, xChar: 110B, bChar: 108]; C[xSet: 0B, xChar: 111B, bChar: 109]; C[xSet: 0B, xChar: 112B, bChar: 110]; C[xSet: 0B, xChar: 113B, bChar: 111]; C[xSet: 0B, xChar: 114B, bChar: 112]; C[xSet: 0B, xChar: 115B, bChar: 113]; C[xSet: 0B, xChar: 116B, bChar: 114]; C[xSet: 0B, xChar: 117B, bChar: 115]; C[xSet: 0B, xChar: 120B, bChar: 116]; C[xSet: 0B, xChar: 121B, bChar: 117]; C[xSet: 0B, xChar: 122B, bChar: 118]; C[xSet: 0B, xChar: 123B, bChar: 119]; C[xSet: 0B, xChar: 124B, bChar: 120]; C[xSet: 0B, xChar: 125B, bChar: 121]; C[xSet: 0B, xChar: 126B, bChar: 122]; C[xSet: 0B, xChar: 127B, bChar: 123]; C[xSet: 0B, xChar: 130B, bChar: 124]; C[xSet: 0B, xChar: 131B, bChar: 125]; C[xSet: 0B, xChar: 132B, bChar: 126]; C[xSet: 0B, xChar: 341B, bChar: 127]; C[xSet: 0B, xChar: 352B, bChar: 128]; C[xSet: 0B, xChar: 351B, bChar: 129]; C[xSet: 0B, xChar: 350B, bChar: 130]; C[xSet: 46B, xChar: 131B, bChar: 139]; C[xSet: 46B, xChar: 104B, bChar: 140]; C[xSet: 46B, xChar: 105B, bChar: 141]; C[xSet: 46B, xChar: 113B, bChar: 142]; C[xSet: 46B, xChar: 116B, bChar: 143]; C[xSet: 46B, xChar: 121B, bChar: 144]; C[xSet: 46B, xChar: 123B, bChar: 145]; C[xSet: 46B, xChar: 126B, bChar: 146]; C[xSet: 46B, xChar: 132B, bChar: 147]; C[xSet: 46B, xChar: 134B, bChar: 148]; C[xSet: 46B, xChar: 135B, bChar: 149]; C[xSet: 0B, xChar: 140B, bChar: 150]; C[xSet: 0B, xChar: 301B, bChar: 150]; C[xSet: 0B, xChar: 5B, bChar: 150]; --temporary substitution for Subhana C[xSet: 0B, xChar: 302B, bChar: 151]; C[xSet: 0B, xChar: 13B, bChar: 151]; --temporary substitution for Subhana C[xSet: 0B, xChar: 136B, bChar: 152]; C[xSet: 0B, xChar: 303B, bChar: 152]; C[xSet: 0B, xChar: 317B, bChar: 153]; C[xSet: 0B, xChar: 312B, bChar: 154]; C[xSet: 0B, xChar: 307B, bChar: 155]; C[xSet: 0B, xChar: 310B, bChar: 156]; C[xSet: 0B, xChar: 176B, bChar: 157]; C[xSet: 0B, xChar: 305B, bChar: 157]; C[xSet: 0B, xChar: 304B, bChar: 158]; C[xSet: 0B, xChar: 306B, bChar: 159]; C[xSet: 0B, xChar: 315B, bChar: 160]; C[xSet: 0B, xChar: 316B, bChar: 161]; C[xSet: 0B, xChar: 313B, bChar: 170]; C[xSet: 361B, xChar: 55B, bChar: 270]; C[xSet: 0B, xChar: 141B, bChar: 301]; C[xSet: 0B, xChar: 142B, bChar: 302]; C[xSet: 0B, xChar: 143B, bChar: 303]; C[xSet: 0B, xChar: 144B, bChar: 304]; C[xSet: 0B, xChar: 145B, bChar: 305]; C[xSet: 0B, xChar: 146B, bChar: 306]; C[xSet: 0B, xChar: 147B, bChar: 307]; C[xSet: 0B, xChar: 150B, bChar: 308]; C[xSet: 0B, xChar: 151B, bChar: 309]; C[xSet: 0B, xChar: 152B, bChar: 310]; C[xSet: 0B, xChar: 153B, bChar: 311]; C[xSet: 0B, xChar: 154B, bChar: 312]; C[xSet: 0B, xChar: 155B, bChar: 313]; C[xSet: 0B, xChar: 156B, bChar: 314]; C[xSet: 0B, xChar: 157B, bChar: 315]; C[xSet: 0B, xChar: 160B, bChar: 316]; C[xSet: 0B, xChar: 161B, bChar: 317]; C[xSet: 0B, xChar: 162B, bChar: 318]; C[xSet: 0B, xChar: 163B, bChar: 319]; C[xSet: 0B, xChar: 164B, bChar: 320]; C[xSet: 0B, xChar: 165B, bChar: 321]; C[xSet: 0B, xChar: 166B, bChar: 322]; C[xSet: 0B, xChar: 167B, bChar: 323]; C[xSet: 0B, xChar: 170B, bChar: 324]; C[xSet: 0B, xChar: 171B, bChar: 325]; C[xSet: 0B, xChar: 172B, bChar: 326]; C[xSet: 0B, xChar: 361B, bChar: 327]; C[xSet: 0B, xChar: 372B, bChar: 328]; C[xSet: 0B, xChar: 371B, bChar: 329]; C[xSet: 0B, xChar: 373B, bChar: 330]; C[xSet: 360B, xChar: 41B, bChar: 331]; C[xSet: 360B, xChar: 44B, bChar: 332]; C[xSet: 360B, xChar: 45B, bChar: 333]; C[xSet: 360B, xChar: 42B, bChar: 334]; C[xSet: 360B, xChar: 43B, bChar: 335]; C[xSet: 0B, xChar: 365B, bChar: 336]; C[xSet: 0B, xChar: 370B, bChar: 337]; C[xSet: 0B, xChar: 345B, bChar: 338]; <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <<>> C[xSet: 361B, xChar: 255B, bChar: 470]; C[xSet: 0B, xChar: 60B, bChar: 500]; C[xSet: 0B, xChar: 61B, bChar: 501]; C[xSet: 0B, xChar: 62B, bChar: 502]; C[xSet: 0B, xChar: 63B, bChar: 503]; C[xSet: 0B, xChar: 64B, bChar: 504]; C[xSet: 0B, xChar: 65B, bChar: 505]; C[xSet: 0B, xChar: 66B, bChar: 506]; C[xSet: 0B, xChar: 67B, bChar: 507]; C[xSet: 0B, xChar: 70B, bChar: 508]; C[xSet: 0B, xChar: 71B, bChar: 509]; C[xSet: 357B, xChar: 260B, bChar: 520]; C[xSet: 357B, xChar: 261B, bChar: 521]; C[xSet: 0B, xChar: 321B, bChar: 521]; C[xSet: 357B, xChar: 262B, bChar: 522]; C[xSet: 0B, xChar: 262B, bChar: 522]; C[xSet: 357B, xChar: 263B, bChar: 523]; C[xSet: 0B, xChar: 263B, bChar: 523]; C[xSet: 357B, xChar: 264B, bChar: 524]; C[xSet: 357B, xChar: 265B, bChar: 525]; C[xSet: 357B, xChar: 266B, bChar: 526]; C[xSet: 357B, xChar: 267B, bChar: 527]; C[xSet: 357B, xChar: 270B, bChar: 528]; C[xSet: 357B, xChar: 271B, bChar: 529]; C[xSet: 0B, xChar: 275B, bChar: 540]; C[xSet: 0B, xChar: 274B, bChar: 542]; C[xSet: 357B, xChar: 257B, bChar: 545]; C[xSet: 357B, xChar: 241B, bChar: 570]; C[xSet: 357B, xChar: 245B, bChar: 576]; C[xSet: 0B, xChar: 56B, bChar: 600]; C[xSet: 0B, xChar: 72B, bChar: 601]; C[xSet: 0B, xChar: 54B, bChar: 602]; C[xSet: 0B, xChar: 73B, bChar: 603]; C[xSet: 0B, xChar: 251B, bChar: 604]; C[xSet: 0B, xChar: 140B, bChar: 604]; --temporary substitution for Subhana C[xSet: 0B, xChar: 47B, bChar: 605]; C[xSet: 0B, xChar: 271B, bChar: 605]; C[xSet: 0B, xChar: 252B, bChar: 606]; C[xSet: 0B, xChar: 42B, bChar: 607]; C[xSet: 0B, xChar: 272B, bChar: 607]; C[xSet: 357B, xChar: 50B, bChar: 608]; C[xSet: 0B, xChar: 41B, bChar: 609]; C[xSet: 0B, xChar: 241B, bChar: 610]; C[xSet: 0B, xChar: 77B, bChar: 611]; C[xSet: 0B, xChar: 277B, bChar: 612]; C[xSet: 43B, xChar: 262B, bChar: 613]; C[xSet: 0B, xChar: 134B, bChar: 620]; C[xSet: 0B, xChar: 57B, bChar: 621]; C[xSet: 0B, xChar: 50B, bChar: 622]; C[xSet: 0B, xChar: 51B, bChar: 623]; C[xSet: 0B, xChar: 133B, bChar: 624]; C[xSet: 0B, xChar: 135B, bChar: 625]; C[xSet: 0B, xChar: 173B, bChar: 626]; C[xSet: 0B, xChar: 175B, bChar: 627]; C[xSet: 357B, xChar: 52B, bChar: 628]; C[xSet: 357B, xChar: 53B, bChar: 629]; C[xSet: 0B, xChar: 253B, bChar: 630]; C[xSet: 0B, xChar: 273B, bChar: 631]; C[xSet: 357B, xChar: 60B, bChar: 650]; C[xSet: 357B, xChar: 61B, bChar: 651]; C[xSet: 0B, xChar: 247B, bChar: 652]; C[xSet: 0B, xChar: 266B, bChar: 653]; C[xSet: 41B, xChar: 76B, bChar: 670]; C[xSet: 357B, xChar: 44B, bChar: 671]; C[xSet: 0B, xChar: 55B, bChar: 671]; -- neutral C[xSet: 0B, xChar: 30B, bChar: 671]; --temporary substitution for Subhana C[xSet: 0B, xChar: 55B, bChar: 670]; --temporary substitution for Subhana C[xSet: 357B, xChar: 45B, bChar: 672]; C[xSet: 0B, xChar: 137B, bChar: 673]; C[xSet: 0B, xChar: 137B, bChar: 672]; -- questionable duplication C[xSet: 0B, xChar: 52B, bChar: 674]; C[xSet: 0B, xChar: 174B, bChar: 675]; C[xSet: 0B, xChar: 244B, bChar: 700]; C[xSet: 0B, xChar: 242B, bChar: 701]; C[xSet: 0B, xChar: 243B, bChar: 702]; C[xSet: 0B, xChar: 245B, bChar: 703]; C[xSet: 357B, xChar: 242B, bChar: 704]; C[xSet: 0B, xChar: 44B, bChar: 705]; C[xSet: 0B, xChar: 44B, bChar: 700]; --(questionable duplication) C[xSet: 0B, xChar: 43B, bChar: 710]; C[xSet: 0B, xChar: 45B, bChar: 711]; C[xSet: 0B, xChar: 260B, bChar: 712]; C[xSet: 0B, xChar: 323B, bChar: 713]; C[xSet: 0B, xChar: 100B, bChar: 714]; C[xSet: 0B, xChar: 46B, bChar: 715]; C[xSet: 0B, xChar: 265B, bChar: 716]; C[xSet: 0B, xChar: 322B, bChar: 717]; C[xSet: 0B, xChar: 324B, bChar: 718]; <> <> C[xSet: 357B, xChar: 0B, bChar: 721]; C[xSet: 357B, xChar: 146B, bChar: 722]; <<>> <> <<>> C[xSet: 0B, xChar: 53B, bChar: 750]; C[xSet: 365B, xChar: 55B, bChar: 751]; -- (minus sign code) C[xSet: 0B, xChar: 75B, bChar: 752]; C[xSet: 0B, xChar: 261B, bChar: 753]; C[xSet: 0B, xChar: 74B, bChar: 754]; C[xSet: 0B, xChar: 76B, bChar: 755]; C[xSet: 356B, xChar: 176B, bChar: 756]; C[xSet: 357B, xChar: 266B, bChar: 757]; C[xSet: 0B, xChar: 267B, bChar: 758]; <> C[xSet: 0B, xChar: 264B, bChar: 760]; C[xSet: 0B, xChar: 270B, bChar: 761]; C[xSet: 41B, xChar: 142B, bChar: 762]; C[xSet: 357B, xChar: 174B, bChar: 775]; RETURN [c] }; IKCreator: ImagerTypeface.CreateProc ~ { <> ikFontData: IKOps.IKFontData _ NIL; ikFontData _ IKOps.OpenFromOpenFile[file ! RuntimeError.UNCAUGHT => CONTINUE]; IF ikFontData = NIL THEN ERROR Imager.Error[[$formatError, "Format error in IK font file"]]; RETURN [NEW[ImagerTypeface.TypefaceRep _ [ class: ikClass, data: NEW [DataRep _ [ikFontData, FindCharCodeMapper[ikFontData], FindUnitsPerEm[ikFontData]]] ]]]; }; ImagerTypeface.Register[extension: "ik", create: IKCreator]; END.