--Maureen Stone April 16, 1984 4:00:46 pm PST DIRECTORY StyleDefs, GriffinFontDefs, ScreenDefs USING [DrawChar, EraseBox], Graphics USING [Context], PointDefs USING [ScrPt,ObjPt, ObjToScr, ObjValToScrVal, X, Y], Rope USING [ROPE,Equal,Map,ActionType, Cat], Font, ImagerTransform, GriffinDefs USING [AppendNumber, UserMessage], ControllerMenuDefs USING [AddFontName]; GriffinFont: PROGRAM IMPORTS Rope, ScreenDefs, Font, ImagerTransform, ControllerMenuDefs, GriffinDefs, PointDefs EXPORTS GriffinFontDefs = BEGIN OPEN GriffinFontDefs; X: CARDINAL = PointDefs.X; Y: CARDINAL = PointDefs.Y; fontVersion: CARDINAL = 7; fontPassword: CARDINAL = 143000B + fontVersion; GriffinFontHandle: TYPE = REF GriffinFont; GriffinFont: TYPE = RECORD [ next: GriffinFontHandle, fd: FontDescriptorHandle, maxHeight,maxPosExtent,maxWidth: REAL, --metrics in object coordinates font: Font.FONT ]; FontError: PUBLIC SIGNAL = CODE; StartupFontError: PUBLIC SIGNAL[type: ErrorType] = CODE; gFontHead, currentFont, lastFont: GriffinFontHandle _ NIL; DisplayString: PUBLIC PROCEDURE [string: Rope.ROPE, anchorPt: PointDefs.ObjPt, anchor: StyleDefs.Anchor, orientation: StyleDefs.Orientation, fd: FontDescriptorHandle, dc: Graphics.Context] = BEGIN DeduceRotation: PROC [t: ImagerTransform.Transformation] RETURNS [rot: REAL _ 0.0] = { trec: ImagerTransform.TransformationRec _ ImagerTransform.Contents[t]; }; rotation: CARDINAL=fd.rotation; height, width: REAL; tl,br: PointDefs.ScrPt; org: PointDefs.ObjPt; maxWidth, maxHeight, baseline: REAL; sr,fr: REAL; doProc: Rope.ActionType; dn,dv: RECORD [x,y: REAL]; EasyString: Rope.ActionType = TRUSTED { ScreenDefs.DrawChar[currentFont.font,PointDefs.ObjToScr[org],c, dc]; org[X] _ org[X]+dv.x*FormatWidth[c]; org[Y] _ org[Y]+dv.y*FormatWidth[c]; }; BackwardString: Rope.ActionType = TRUSTED { org[X] _ org[X]+dv.x*FormatWidth[c]; org[Y] _ org[Y]+dv.y*FormatWidth[c]; ScreenDefs.DrawChar[currentFont.font,PointDefs.ObjToScr[org],c, dc]; }; Stack: Rope.ActionType = TRUSTED { showPt: PointDefs.ObjPt; showPt[X] _ org[X]+dn.x*(maxWidth+FormatWidth[c])/2; --center it showPt[Y] _ org[Y]+dn.y*(maxWidth+FormatWidth[c])/2; ScreenDefs.DrawChar[currentFont.font,PointDefs.ObjToScr[showPt],c, dc]; org[X] _ org[X]+dv.x*maxHeight; org[Y] _ org[Y]+dv.y*maxHeight; }; BackwardStack: Rope.ActionType = TRUSTED { showPt: PointDefs.ObjPt; showPt[X] _ org[X]+dn.x*(maxWidth-FormatWidth[c])/2; --center it showPt[Y] _ org[Y]+dn.y*(maxWidth-FormatWidth[c])/2; ScreenDefs.DrawChar[currentFont.font,PointDefs.ObjToScr[showPt],c, dc]; org[X] _ org[X]+dv.x*maxHeight; org[Y] _ org[Y]+dv.y*maxHeight; }; SetUpFont [fd]; height _ StringHeight[string, fd, orientation]; width _ StringWidth[string, fd, orientation]; org _ TopLeft[anchorPt, height,width, anchor, orientation, rotation]; tl _ PointDefs.ObjToScr[org]; br _ [tl[X]+PointDefs.ObjValToScrVal[width], tl[Y]+PointDefs.ObjValToScrVal[height]]; ScreenDefs.EraseBox [tl, br, dc]; SELECT orientation FROM or0 => {dv _ [1,0]; sr _ 0}; or90 => {dv _ [0,1]; org[Y] _ org[Y] - height; sr _ 90}; or180 => {dv _ [-1,0]; org[Y] _ org[Y] - height; org[X] _ org[X] + width; sr _ 180}; or270 => {dv _ [0,-1]; org[X] _ org[X] + width; sr _ 270}; ENDCASE => ERROR; dn _ [dv.y, -1*dv.x]; fr _ rotation/60.0; maxWidth _ currentFont.maxWidth; maxHeight _ currentFont.maxHeight; baseline _ currentFont.maxPosExtent; IF fr { org[X] _ org[X]+dn.x*baseline; org[Y] _ org[Y]+dn.y*baseline; doProc _ EasyString; }; 90 => { org[X] _ org[X]+dv.x*baseline; org[Y] _ org[Y]+dv.y*baseline; doProc _ Stack; }; 180 => { org[X] _ org[X]+dn.x*(maxHeight-baseline); org[Y] _ org[Y]+dn.y*(maxHeight-baseline); doProc _ BackwardString; }; 270=> { org[X] _ org[X]+dv.x*(maxHeight-baseline); org[Y] _ org[Y]+dv.y*(maxHeight-baseline); doProc _ BackwardStack; }; ENDCASE => ERROR; [] _ Rope.Map[action: doProc, base: string]; END; TopLeft: PUBLIC PROCEDURE [anchorPt: PointDefs.ObjPt, height, width: REAL, --same coordinates as anchorPt anchor: StyleDefs.Anchor, orientation: StyleDefs.Orientation, rotation: CARDINAL] RETURNS [tl: PointDefs.ObjPt]= BEGIN vertical, aligned, reverse: BOOLEAN; shift, amount: REAL; tl _ anchorPt; vertical _ orientation = or90 OR orientation = or270; reverse _ orientation=or90 OR orientation=or180; aligned _ IF vertical THEN rotation = Rot0Degrees OR rotation = Rot180Degrees ELSE rotation = Rot90Degrees OR rotation = Rot270Degrees; amount _ IF vertical THEN height ELSE width; shift _ SELECT anchor FROM right => IF reverse THEN 0 ELSE amount, left => IF reverse THEN amount ELSE 0, ENDCASE --center-- => amount/2; IF vertical --adjust for Anchor: THEN tl [Y] _ tl [Y] + shift ELSE tl [X] _ tl [X] - shift; IF aligned THEN BEGIN shift _ (IF vertical THEN width ELSE height)/2; IF vertical THEN tl [X] _ tl [X] - shift ELSE tl [Y] _ tl [Y] + shift; END; END; BltChar: PUBLIC PROCEDURE [char: CHARACTER, tl: PointDefs.ObjPt, fd: FontDescriptorHandle]= BEGIN SetUpFont [fd]; tl[Y] _ tl[Y]+currentFont.maxPosExtent; ScreenDefs.DrawChar[currentFont.font,PointDefs.ObjToScr[tl],char, NIL]; END; Width: PUBLIC PROCEDURE [c: CHARACTER, fd: FontDescriptorHandle] RETURNS [REAL] = BEGIN SetUpFont [fd]; RETURN [FPWidth[c]]; END; StringWidth: PUBLIC PROCEDURE [string: Rope.ROPE, fd: FontDescriptorHandle, orientation: StyleDefs.Orientation] RETURNS [w: REAL] = BEGIN DoChar: Rope.ActionType = TRUSTED{ w_w + FPWidth[c]; RETURN[FALSE]}; SetUpFont [fd]; SELECT orientation FROM or0, or180 => BEGIN IF string=NIL THEN RETURN [0]; w _ 0; [] _ Rope.Map[base: string, action: DoChar]; END; or90, or270 => w _ MaxHeight[fd]; ENDCASE; END; MaxWidth: PUBLIC PROCEDURE [fd: FontDescriptorHandle] RETURNS [REAL] = BEGIN SetUpFont [fd]; RETURN [SELECT currentFont.fd.rotation FROM Rot0Degrees, Rot180Degrees => currentFont.maxWidth, ENDCASE => currentFont.maxHeight]; END; Height: PUBLIC PROCEDURE [c: CHARACTER, fd: FontDescriptorHandle] RETURNS [REAL] = BEGIN SetUpFont [fd]; RETURN [FPHeight[c]]; END; StringHeight: PUBLIC PROCEDURE[string: Rope.ROPE, fd:FontDescriptorHandle, orientation: StyleDefs.Orientation] RETURNS [h: REAL] = BEGIN DoChar: Rope.ActionType = TRUSTED {h _ h + FPHeight[c]; RETURN[FALSE]}; SetUpFont [fd]; SELECT orientation FROM or0, or180 => h _ MaxHeight[fd]; or90, or270 => BEGIN IF string=NIL THEN RETURN [0]; h _ 0; [] _ Rope.Map[base: string, action: DoChar]; END; ENDCASE; END; MaxHeight: PUBLIC PROCEDURE [fd: FontDescriptorHandle] RETURNS [REAL] = BEGIN SetUpFont [fd]; RETURN [SELECT currentFont.fd.rotation FROM Rot0Degrees, Rot180Degrees => currentFont.maxHeight, ENDCASE => currentFont.maxWidth]; END; FPWidth: PROCEDURE [char: CHARACTER] RETURNS [REAL] = INLINE BEGIN -- returns actual x dimension of char rot: CARDINAL = currentFont.fd.rotation; RETURN [IF rot = Rot0Degrees OR rot = Rot180Degrees THEN PointsToMicas[Font.Width[currentFont.font, char]] ELSE currentFont.maxHeight ]; END; FormatWidth: PROCEDURE [char: CHARACTER] RETURNS [REAL] = BEGIN RETURN [PointsToMicas[Font.Width[currentFont.font, char]]]; END; FPHeight: PROCEDURE [char: CHARACTER] RETURNS [REAL] = INLINE BEGIN -- returns actual y dimension of char for the display rot: CARDINAL = currentFont.fd.rotation; RETURN [IF rot = Rot0Degrees OR rot = Rot180Degrees THEN currentFont.maxHeight ELSE PointsToMicas[Font.Width[currentFont.font, char]] ]; END; MaxPosExtent: PUBLIC PROCEDURE [fd: FontDescriptorHandle] RETURNS [REAL] = BEGIN SetUpFont [fd]; RETURN [currentFont.maxPosExtent]; END; ForAllFonts: PUBLIC PROCEDURE[do: PROCEDURE[font: FontDescriptorHandle]] = BEGIN rover: GriffinFontHandle; FOR rover _ gFontHead, rover.next UNTIL rover = NIL DO do[rover.fd] ENDLOOP; END; SetUpFont: PROCEDURE [fd: FontDescriptorHandle] = BEGIN rover: GriffinFontHandle; sameface, samerotation: BOOLEAN; foundFont: BOOLEAN _ FALSE; IF currentFont=NIL THEN {AddGFont[fd]; RETURN}; IF currentFont.fd.rotation = fd.rotation AND currentFont.fd.points = fd.points AND currentFont.fd.face= fd.face AND Rope.Equal[currentFont.fd.name, fd.name, FALSE] THEN RETURN; rover _ gFontHead; WHILE rover # NIL DO IF NOT (Rope.Equal[rover.fd.name, fd.name, FALSE] AND rover.fd.points = fd.points) THEN BEGIN rover _ rover.next; LOOP END; sameface _ rover.fd.face = fd.face; samerotation _ rover.fd.rotation = fd.rotation; IF sameface AND samerotation THEN BEGIN currentFont _ rover; foundFont _ TRUE; EXIT END; rover _ rover.next; ENDLOOP; IF ~foundFont THEN AddGFont[fd]; END; AddGFont: PROCEDURE [fd: FontDescriptorHandle] = BEGIN font: Font.FONT; name: Rope.ROPE _ GriffinDefs.AppendNumber[fd.name,fd.points]; --name in default.fontDir maxHeight,maxPosExtent, maxWidth: REAL _ 0; angle: REAL _ (SELECT fd.rotation FROM Rot0Degrees => 0, Rot90Degrees => 90, Rot180Degrees => 180, Rot270Degrees => 270, ENDCASE => 0); IF fd.face#Regular THEN name _ Rope.Cat[name,SELECT fd.face FROM Italic => "I", Bold => "B", BoldItalic => "BI", ENDCASE =>""]; font _ Font.Create[fontName: name, transformation: ImagerTransform.PreScale[s: fd.points, m: ImagerTransform.Rotate[degrees: angle]], deviceType: $Ideal]; IF font=NIL THEN SIGNAL GriffinDefs.UserMessage[Rope.Cat[name, " not found"]]; IF gFontHead = NIL THEN gFontHead _ lastFont _ NEW[GriffinFont] ELSE lastFont _ lastFont.next _ NEW[GriffinFont]; currentFont _ lastFont; currentFont.fd _ fd; currentFont.font _ font; currentFont.next _ NIL; FOR char: CHAR IN [font.bc..font.ec] DO box: Font.Box _ Font.BoundingBox[font,char]; boxHeight: REAL _ ABS[box.ymax] + ABS[box.ymin]; boxWidth: REAL _ ABS[box.xmax] + ABS[box.xmin]; IF box.ymax > maxPosExtent THEN maxPosExtent _ box.ymax; IF boxHeight > maxHeight THEN maxHeight _ boxHeight; IF boxWidth>maxWidth THEN maxWidth _ boxWidth; ENDLOOP; currentFont.maxPosExtent _ PointsToMicas[maxPosExtent]; currentFont.maxHeight _ PointsToMicas[maxHeight]; currentFont.maxWidth _ PointsToMicas[maxWidth]; ControllerMenuDefs.AddFontName[fd,TRUE]; END; PointsToMicas: PROC [points: REAL] RETURNS [micas: REAL] = { RETURN[(points*2540)/72.0]; }; END. Ê ‹˜J˜-J˜šÏk ˜ J˜ J˜Jšœ œ˜&Jšœ œ ˜Jšœ œ)œœ˜>Jšœœœ˜,J˜J˜Jšœ œ˜.Jšœœ˜'J˜—Jšœ˜JšœT˜[Jšœ˜Jšœœ˜J˜Jšœœ œ˜Jšœœ œ˜J˜Jšœ œ˜Jšœœ˜/J˜J˜Jšœœœ ˜*J˜šœ œ˜J˜J˜J˜Jšœ!œÏc˜IJšœ ˜J˜—J˜Jšœ œœœ˜ Jšœœœœ˜8J˜Jšœ6œ˜:J˜šÏn œœ œœŒ˜¾Jš˜šŸœœ%œœ ˜VJ˜FJ˜—Jšœ œ ˜Jšœœ˜J˜J˜Jšœœ˜$Jšœœ˜ J˜Jšœœœ˜šœœ˜'J˜DJšœœœ˜$Jšœœœ˜$J˜—šœ"œ˜+Jšœœœ˜$Jšœœœ˜$J˜DJ˜—šœœ˜"J˜Jšœœœ$ž ˜@Jšœœœ#˜4J˜GJšœœœ˜Jšœœœ˜J˜—šœ!œ˜*J˜Jšœœœ$ž ˜@Jšœœœ#˜4J˜GJšœœœ˜Jšœœœ˜J˜—J˜J˜/J˜-J˜EJ˜Jšœ œ&œ$˜U˜!Jšœ ˜J˜Jšœœœ˜8Jš œœœœœ˜TJšœœœ˜:Jšœœ˜—J˜J˜J˜ J˜#J˜$Jšœœ ˜šœ˜˜Jšœœœ˜Jšœœœ˜J˜J˜—˜Jšœœœ˜Jšœœœ˜J˜J˜—˜Jšœœœ˜*Jšœœœ˜*J˜J˜—˜Jšœœœ˜*Jšœœœ˜*J˜J˜—Jšœœ˜—J˜,Jšœ˜J˜—J˜šŸœœ œ˜5Jšœœž˜3J˜J˜#Jšœ œ˜Jšœ˜Jš˜Jšœœ˜$Jšœœ˜J˜J˜Jšœœ˜5Jšœœ˜0šœ œ ˜Jšœœ˜7Jšœœ˜9—Jšœ œ œœ˜,šœœ˜Jšœ œ œœ˜'Jšœœ œœ˜&Jšœž œ ˜—šœ ž˜ Jšœœœ ˜Jšœœœ ˜—J˜šœ ˜Jš˜Jšœ œ œœ ˜/Jšœ ˜ Jšœœœ ˜Jšœœœ ˜Jšœ˜—Jšœ˜—J˜šŸœœ œ œ˜@J˜Jš˜J˜Jšœœœ˜'JšœBœ˜GJšœ˜—šŸœœ œ œ˜@Jšœœ˜Jš˜J˜Jšœ˜Jšœ˜—J˜JšŸ œœ œœ?˜ošœœ˜Jš˜Jšœœœœ˜DJ˜šœ ˜˜ Jš˜Jšœœœœ˜J˜J˜,Jšœ˜—J˜!Jšœ˜—J˜Jšœ˜—J˜JšŸœœ œ˜5šœœ˜Jš˜J˜šœœ˜+J˜3Jšœ˜"—Jšœ˜—J˜š Ÿœœ œ œœœ˜RJš˜J˜Jšœ˜Jšœ˜—J˜JšŸ œœ œœ˜1J˜J˜#šœœ˜Jš˜Jšœœœœ˜GJ˜šœ ˜J˜ ˜Jš˜Jšœœœœ˜J˜J˜,Jšœ˜—Jšœ˜—Jšœ˜—J˜JšŸ œœ œ˜6šœœ˜Jš˜J˜šœœ˜+J˜4Jšœ˜!—Jšœ˜—J˜Jš Ÿœ œ œœœ˜<šœž%˜+Jšœœ˜(šœœœ˜3Jšœ2˜6Jšœ˜J˜—Jšœ˜—J˜š Ÿ œ œ œœœ˜9Jš˜Jšœ5˜;Jšœ˜—J˜š Ÿœ œ œœœ˜=Jšœž5˜;Jšœœ˜(šœœœ˜3Jšœ˜Jšœ2˜6J˜—Jšœ˜—J˜JšŸ œœ œ˜9šœœ˜Jš˜J˜Jšœ˜"Jšœ˜—J˜JšŸ œœ œ œ ˜Kš˜J˜Jšœœ ˜3Jšœœ˜Jšœ˜J˜—šŸ œ œ˜1Jš˜J˜Jšœœ˜ Jšœ œœ˜Jšœ œœœ˜/Jšœ'œ#˜RJšœ˜ Jšœ)œœœ˜=J˜šœ œ˜Jšœœ%œ˜1Jšœ˜ Jšœœœœ˜(J˜#J˜/šœ œœ˜'J˜Jšœ œ˜Jš˜Jšœ˜—J˜Jšœ˜—Jšœ œ˜ Jšœ˜—J˜J˜šŸœ œ˜0Jš˜Jšœ œ˜Jšœ œ0ž˜XJšœ"œ˜+Jšœœœ œ˜8Jšœ@œ˜NJš œœœ œ1œ˜J˜šJšœœœœ7˜NJš œ œœœ˜DJšœœ˜,J˜J˜J˜Jšœœ˜šœœœœ˜(J˜,Jšœ œœ œ ˜0Jšœ œœ œ ˜0Jšœœ˜8Jšœœ˜4Jšœœ˜.Jšœ˜—J˜7J˜1J˜/Jšœ"œ˜(Jšœ˜—J˜š Ÿ œœ œœ œ˜