ImagerFontFilterImpl.mesa
Copyright Ó 1985, 1989, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, September 15, 1989 1:14:45 pm PDT
Last changed by Pavel on January 18, 1988 2:52:37 pm PST
Jean-Marc Frailong January 20, 1988 11:56:16 am PST
Willie-s, April 2, 1992 7:30 pm PST
DIRECTORY
Imager USING [ClassRep, Context, ContextRep, GetProp, SetFont, Show, Warning],
ImagerFont USING [Find, Font, MapText, Modify, XChar, XStringProc, Name],
ImagerFontFilter USING [CharacterCodeMap, FontMap, OutputMap],
ImagerPrivate USING [Class, ClassRep],
Prop USING [Put, PropList],
IO,
RefTab USING [Create, Fetch, Ref, Store],
Rope;
ImagerFontFilterImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerFont, Prop, IO, RefTab, Rope
EXPORTS ImagerFontFilter, Imager
~ BEGIN OPEN ImagerFontFilter;
ROPE: TYPE ~ Rope.ROPE;
Font: TYPE ~ ImagerFont.Font;
XChar: TYPE ~ ImagerFont.XChar;
XStringProc: TYPE ~ ImagerFont.XStringProc;
Context: TYPE ~ Imager.Context;
Class: TYPE ~ ImagerPrivate.Class;
ClassRep: PUBLIC TYPE ~ ImagerPrivate.ClassRep; -- export to Imager
BoundOutputMap: TYPE ~ LIST OF BoundOutputMapEntry;
BoundOutputMapEntry: TYPE ~ RECORD [newFont: ImagerFont.Font, charMap: CharacterCodeMap];
Data: TYPE ~ REF DataRep;
DataRep: TYPE ~ RECORD[
c: Imager.Context,
curFont: Font ¬ NIL,
curBoundOutputMap: BoundOutputMap ¬ NIL,
curMappedFont: Font ¬ NIL,
fontMap: FontMap,
fontTable: RefTab.Ref,
saveStack: LIST OF SaveEntry,
msg: IO.STREAM,
verbose: BOOL
];
SaveEntry: TYPE ~ RECORD [
curFont: Font,
curBoundOutputMap: BoundOutputMap,
curMappedFont: Font,
ref: REF
];
FilterFonts: PUBLIC PROC [c: Imager.Context, fontMap: FontMap, msg: IO.STREAM, verbose: BOOL] RETURNS [context: Imager.Context] ~ {
oldClass: Class ~ c.class;
data: Data ~ NEW[DataRep ¬ [c: c, fontMap: fontMap, fontTable: RefTab.Create[], msg: msg, verbose: verbose]];
props: Prop.PropList ~ Prop.Put[c.propList, $FontFilter, data];
class: Class ~ NEW[ClassRep ¬ oldClass­];
class.type ¬ $FontFilter;
class.Save ¬ MySave;
class.Restore ¬ MyRestore;
class.SetFont ¬ MySetFont;
class.GetFont ¬ MyGetFont;
class.Show ¬ MyShow;
class.ShowText ¬ MyShowText;
context ¬ NEW[Imager.ContextRep ¬ [class: class, state: c.state, data: c.data, propList: props]];
};
MySetFont: PROC[context: Context, font: Font] ~ {
data: Data ~ NARROW[Imager.GetProp[context, $FontFilter]];
subst: BoundOutputMap ¬ NARROW[data.fontTable.Fetch[font].val];
IF subst = NIL THEN {
oldName: ROPE ~ ImagerFont.Name[font];
outputMap: OutputMap ¬ NIL;
h: BoundOutputMap ~ LIST[[NIL,NIL]];
t: BoundOutputMap ¬ h;
canPrint: BOOL ~ data.msg#NIL;
printing: BOOL ¬ canPrint AND data.verbose;
warn: BOOL ¬ FALSE;
FOR p: FontMap ¬ data.fontMap, p.rest UNTIL p=NIL DO
IF Rope.Equal[oldName, p.first.inputName, FALSE] THEN {
outputMap ¬ p.first.output;
warn ¬ p.first.warn;
EXIT;
};
ENDLOOP;
IF outputMap = NIL THEN {
charMap: CharacterCodeMap ~ LIST[[bc: 0, ec: WORD.LAST, newbc: 0]];
outputMap ¬ LIST[[newName: oldName, charMap: charMap]];
};
IF warn AND canPrint THEN printing ¬ TRUE;
IF warn AND printing THEN data.msg.PutRope[" WARNING:"];
IF printing THEN data.msg.PutF1[" (%g =>", IO.rope[oldName]];
FOR o: OutputMap ¬ outputMap, o.rest UNTIL o=NIL DO
newFont: Font;
note: ROPE ¬ NIL;
IF printing THEN data.msg.PutF1[" %g", IO.rope[o.first.newName]];
newFont ¬ ImagerFont.Find[o.first.newName ! Imager.Warning =>
{IF printing THEN data.msg.PutF1[" {%g}", IO.rope[error.explanation]]; RESUME}];
newFont ¬ ImagerFont.Modify[newFont, font.charToClient];
t.rest ¬ LIST[[newFont: newFont, charMap: o.first.charMap]];
t ¬ t.rest;
ENDLOOP;
IF printing THEN data.msg.PutRope[")"];
subst ¬ h.rest;
[] ¬ data.fontTable.Store[font, subst];
};
data.curFont ¬ font;
IF subst = NIL THEN ERROR;
data.curBoundOutputMap ¬ subst;
data.curMappedFont ¬ NIL;
};
MapChar: PROC [data: Data, charCode: WORD] RETURNS [f: Font, tchar: WORD] ~ {
boundMap: BoundOutputMap ~ data.curBoundOutputMap;
FOR b: BoundOutputMap ¬ boundMap, b.rest UNTIL b = NIL DO
FOR c: CharacterCodeMap ¬ b.first.charMap, c.rest UNTIL c = NIL DO
IF charCode IN [c.first.bc..c.first.ec] THEN {
f ¬ b.first.newFont;
tchar ¬ c.first.newbc+(charCode-c.first.bc);
RETURN;
};
ENDLOOP;
ENDLOOP;
f ¬ boundMap.first.newFont;
tchar ¬ charCode;
IF data.msg#NIL THEN data.msg.PutF[" WARNING: (%03BB|%03BB) not in %g", IO.int[charCode/256], IO.int[charCode MOD 256], IO.rope[ImagerFont.Name[data.curFont]]];
};
MyShow: PROC[context: Context, string: XStringProc, xrel: BOOL] ~ {
data: Data ~ NARROW[Imager.GetProp[context, $FontFilter]];
short: NAT ~ 100;
long: NAT ~ NAT15.LAST;
buf: ARRAY [0..short) OF WORD;
xbuf: REF ARRAY [short..long) OF WORD ¬ NIL;
nChars: NAT ¬ 0;
i: NAT ¬ 0;
myCharAction: PROC [char: XChar] ~ {
IF nChars = short THEN xbuf ¬ NEW[ARRAY [short..long) OF WORD];
IF nChars < short THEN buf[nChars] ¬ LOOPHOLE[char]
ELSE {
IF xbuf = NIL THEN xbuf ¬ NEW[ARRAY [short..long) OF WORD];
xbuf[nChars] ¬ LOOPHOLE[char];
};
nChars ¬ nChars + 1;
};
C: PROC [index: NAT] RETURNS [WORD] ~ INLINE {RETURN [IF index < short THEN buf[index] ELSE xbuf[index]]};
deltaChars: NAT ¬ 0;
f: Font ¬ NIL;
myString: XStringProc ~ {
c: WORD;
[f, c] ¬ MapChar[data, C[i]];
deltaChars ¬ 0;
DO
ff: Font;
charAction[LOOPHOLE[c]];
deltaChars ¬ deltaChars + 1;
IF i+deltaChars = nChars THEN EXIT;
[ff, c] ¬ MapChar[data, C[i+deltaChars]];
IF ff # f THEN EXIT;
ENDLOOP;
};
string[myCharAction];
UNTIL i = nChars DO
[f, ----] ¬ MapChar[data, C[i]];
IF f # data.curMappedFont THEN {
Imager.SetFont[data.c, f];
data.curMappedFont ¬ f;
};
Imager.Show[data.c, myString, xrel];
i ¬ i + deltaChars;
ENDLOOP;
};
MyShowText: PROC [context: Context,
text: REF READONLY TEXT, start, len: NAT, xrel: BOOL] ~ {
string: XStringProc ~ { ImagerFont.MapText[text, start, len, charAction] };
Imager.Show[context, string, xrel];
};
MySave: PROC[context: Context, all: BOOL] RETURNS [REF] ~ {
data: Data ~ NARROW[Imager.GetProp[context, $FontFilter]];
cClass: Class ~ data.c.class;
data.saveStack ¬ CONS[[
curFont: data.curFont,
curBoundOutputMap: data.curBoundOutputMap,
curMappedFont: data.curMappedFont,
ref: cClass.Save[context, all]
], data.saveStack];
RETURN [data.saveStack]
};
MyRestore: PROC[context: Context, ref: REF] ~ {
data: Data ~ NARROW[Imager.GetProp[context, $FontFilter]];
cClass: Class ~ data.c.class;
IF NOT (ref=NIL OR ref = data.saveStack) THEN ERROR;
cClass.Restore[context, data.saveStack.first.ref];
data.curMappedFont ¬ data.saveStack.first.curMappedFont;
data.curBoundOutputMap ¬ data.saveStack.first.curBoundOutputMap;
data.curFont ¬ data.saveStack.first.curFont;
data.saveStack ¬ data.saveStack.rest;
};
MyGetFont: PROC[context: Context] RETURNS[Font] ~ {
data: Data ~ NARROW[Imager.GetProp[context, $FontFilter]];
RETURN [data.curFont]
};
END.