CDTextsImpl.mesa
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 29, 1983 11:17 am
Last Edited by: Christian Jacobi, December 16, 1986 12:59:06 pm PST
DIRECTORY
Atom,
CDBasics,
CDTexts,
CDTextsBackdoor,
CDEvents,
CDLayers,
CDPrivate,
CDProperties,
CD,
CDIO,
FS,
Imager,
ImagerFont,
ImagerTransformation,
IO,
LRUCache,
NodeStyle,
NodeStyleFont,
Real,
Rope,
RuntimeError USING [UNCAUGHT],
SymTab,
TerminalIO,
TokenIO,
VFonts;
CDTextsImpl: CEDAR MONITOR
IMPORTS Atom, CD, CDBasics, CDIO, CDEvents, CDLayers, CDPrivate, CDProperties, CDTexts, FS, Imager, ImagerFont, ImagerTransformation, IO, LRUCache, NodeStyleFont, Real, Rope, RuntimeError, SymTab, TerminalIO, TokenIO, VFonts
EXPORTS CDTexts, CDTextsBackdoor =
BEGIN
TextSpecific: TYPE = CDTexts.TextSpecific;
TextRec: TYPE = CDTexts.TextRec;
FontRec: TYPE = CDTexts.FontRec;
CDFont: TYPE = CDTexts.CDFont;
convertClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$Text, [
internalRead: ConvertRead
]];
rigidTextClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$RigidText, [
drawMe: FixDraw,
quickDrawMe: FixDraw,
internalRead: Read,
internalWrite: Write,
newLayer: ChangeLayer,
describe: Describe
]];
flipTextClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$FlipText, [
drawMe: FlipDraw,
quickDrawMe: FlipDraw,
internalRead: Read,
internalWrite: Write,
newLayer: ChangeLayer,
describe: Describe
]];
textClass: PUBLIC CD.ObjectClass ← flipTextClass;
lruQueue: LRUCache.Handle ← LRUCache.Create[127, CDPrivate.Hash, Equal];
free: CD.Object ← NIL;
GiveOb: ENTRY PROC [] RETURNS [ob: CD.Object] = {
ob ← free; free ← NIL;
IF ob=NIL THEN
ob ← NEW[CD.ObjectRep←[specific: NEW[TextRec]]];
};
Equal: PROC[x, y: REF] RETURNS [BOOL] = {
EqualSpec: PROC[x, y: CD.Object] RETURNS [BOOL] = {
tp1: TextSpecific = NARROW[x.specific];
tp2: TextSpecific = NARROW[y.specific];
RETURN [
Rope.Equal[tp1.text, tp2.text, TRUE] AND
Rope.Equal[tp1.cdFont.supposedKey, tp2.cdFont.supposedKey, TRUE]
]
};
ob1: CD.Object = NARROW[x];
ob2: CD.Object = NARROW[y];
RETURN [ob1.class=ob2.class AND ob1.bbox=ob2.bbox AND ob1.layer=ob2.layer AND EqualSpec[ob1, ob2]]
};
Up: PROC [r: REAL] RETURNS [i: INT] = {
-- returns integer i: i >= r; there exists no integer j such that j < i and j >= r
i ← Real.Fix[r];
IF Real.Float[i]#r THEN i ← i+1;
};
Create: PUBLIC PROC [text: Rope.ROPE, font: REF ANY, layer: CD.Layer, flip: BOOLTRUE] RETURNS [ob: CD.Object] = {
ENABLE UNWIND => NULL;
WITH font SELECT FROM
cdFont: CDFont => {
insert: BOOL; used: REF;
e: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[cdFont.font, text];
w: REAL ← ImagerFont.RopeWidth[cdFont.font, text].x;
ob ← GiveOb[];
NARROW[ob.specific, TextSpecific]^ ← [text: text, cdFont: cdFont];
ob.bbox ← [x1: -cdFont.origin.x, x2: Up[e.rightExtent], y1: -cdFont.origin.y, y2: cdFont.height-cdFont.origin.y];
ob.class ← IF flip THEN flipTextClass ELSE rigidTextClass;
ob.layer ← layer;
[insert: insert, used: used] ← LRUCache.Include[lruQueue, ob];
IF ~insert THEN {
free ← ob; ob ← NARROW[used];
};
};
ENDCASE => NULL
};
ImagerPrintFont: PUBLIC PROC [cdFont: CDTexts.CDFont] RETURNS [Imager.Font] = {
RETURN [InlineImagerPrintFont[cdFont]]
};
InlineImagerPrintFont: PROC [cdFont: CDTexts.CDFont] RETURNS [Imager.Font] = INLINE {
WITH cdFont.data SELECT FROM
printFont: Imager.Font => RETURN [printFont];
ENDCASE => {
printFont: Imager.Font ← SubstituteTiogaFonts[cdFont.font]; cdFont.data ← printFont;
RETURN [printFont];
};
};
FixDraw: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = {
WithContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
tp: CDTexts.TextSpecific = NARROW[ob.specific];
--don't clip: speed;
--Imager.ClipRectangle[context, [x: ob.bbox.x1, y: ob.bbox.y1, w: ob.bbox.x2-ob.bbox.x1, h: ob.bbox.y2-ob.bbox.y1]];
Imager.SetFont[context, (IF pr.specialFonts THEN InlineImagerPrintFont[tp.cdFont] ELSE tp.cdFont.font)];
Imager.SetXY[context, [0, 0]]; --always use original font offsets!
Imager.ShowRope[context, tp.text];
};
pr.drawContext[pr, WithContext, inst.ob, trans, inst.ob.layer]
};
FlipTransform: PUBLIC PROC [bbox: CD.Rect, orient: CD.Orientation] RETURNS [Imager.Transformation] = {
RETURN [InlineFlipTransform[bbox, orient]]
};
InlineFlipTransform: PROC [bbox: CD.Rect, orient: CD.Orientation] RETURNS [Imager.Transformation] = INLINE {
RETURN [SELECT orient FROM
--matrix multiplications done manually for speed
mirrorX, rotate90X => ImagerTransformation.Create[-1, 0, bbox.x2-bbox.x1, 0, 1, 0],
rotate180X, rotate270X => ImagerTransformation.Create[1, 0, 0, 0, -1, bbox.y2+bbox.y1],
rotate180, rotate90 => ImagerTransformation.Create[-1, 0, bbox.x2-bbox.x1, 0, -1, bbox.y2+bbox.y1],
original, rotate270 => ImagerTransformation.Create[1, 0, 0, 0, 1, 0],
--thats what it really means
original, rotate270 => ImagerTransformation.Scale[1],
mirrorX, rotate90X => ImagerTransformation.Concat[
ImagerTransformation.Translate[[bbox.x1-bbox.x2, 0]],
ImagerTransformation.Scale2[[-1, 1]]
],
rotate180X, rotate270X => ImagerTransformation.Cat[
ImagerTransformation.Translate[[bbox.x1-bbox.x2, -bbox.y2-bbox.y1]],
ImagerTransformation.Rotate[180],
ImagerTransformation.Translate[[bbox.x1-bbox.x2, 0]],
ImagerTransformation.Scale2[[-1, 1]]
],
rotate180, rotate90 => ImagerTransformation.Concat[
ImagerTransformation.Translate[[bbox.x1-bbox.x2, -bbox.y2-bbox.y1]],
ImagerTransformation.Rotate[180]
],
ENDCASE => ERROR
]
};
FlipDraw: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = {
WithContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
tp: CDTexts.TextSpecific = NARROW[ob.specific];
--don't clip: speed;
--Imager.ClipRectangle[context, [x: ob.bbox.x1, y: ob.bbox.y1, w: ob.bbox.x2-ob.bbox.x1, h: ob.bbox.y2-ob.bbox.y1]];
Imager.SetFont[context, (IF pr.specialFonts THEN InlineImagerPrintFont[tp.cdFont] ELSE tp.cdFont.font)];
SELECT trans.orient FROM
original, rotate270 => NULL;
mirrorX, rotate90X => {
Imager.Scale2T[context, [-1, 1]]; Imager.TranslateT[context, [ob.bbox.x1-ob.bbox.x2, 0]];
};
rotate180X, rotate270X => {
Imager.Scale2T[context, [-1, 1]]; Imager.TranslateT[context, [ob.bbox.x1-ob.bbox.x2, 0]];
Imager.RotateT[context, 180]; Imager.TranslateT[context, [ob.bbox.x1-ob.bbox.x2, -ob.bbox.y2-ob.bbox.y1]];
};
rotate180, rotate90 => {
Imager.RotateT[context, 180]; Imager.TranslateT[context, [ob.bbox.x1-ob.bbox.x2, -ob.bbox.y2-ob.bbox.y1]];
};
ENDCASE => Imager.ConcatT[context, InlineFlipTransform[ob.bbox, trans.orient]];
Imager.SetXY[context, [0, 0]]; --always use original font offsets!
Imager.ShowRope[context, tp.text];
};
pr.drawContext[pr, WithContext, inst.ob, trans, inst.ob.layer]
};
Describe: PROC[me: CD.Object] RETURNS [r: Rope.ROPE] = {
tp: TextSpecific = NARROW[me.specific];
r ← Rope.Cat["text [", tp.text, "]"];
IF me.class#flipTextClass THEN r ← Rope.Concat["X-", r];
};
Write: CD.InternalWriteProc = {
tp: TextSpecific = NARROW[ob.specific];
CDIO.WriteRect[h, ob.bbox];
TokenIO.WriteRope[h, tp.text];
WriteFont[h, tp.cdFont];
CDIO.WriteLayer[h, ob.layer];
IF ob.class=flipTextClass THEN TokenIO.WriteInt[h, 1] ELSE TokenIO.WriteInt[h, 0]
};
Read: CD.InternalReadProc = {
ob: CD.Object; r: CD.Rect← [0,0,-1,-1];
t: Rope.ROPE; i: INT;
cdFont: REF CDTexts.FontRec; layer: CD.Layer;
IF CDIO.VersionKey[h]>15 THEN r ← CDIO.ReadRect[h]
ELSE {
[] ← CDIO.ReadPos[h];
};
t ← TokenIO.ReadRope[h];
cdFont ← ReadFont[h];
layer ← CDIO.ReadLayer[h];
i ← TokenIO.ReadInt[h];
ob ← Create[text: t, font: cdFont, layer: layer, flip: i=1];
IF r#ob.bbox AND CDBasics.NonEmpty[r] THEN FixSize[ob, r];
RETURN [ob]
};
changeTextSizeIfDifferent: BOOLFALSE;
changeMsg: BOOLFALSE;
FixSize: PROC [ob: CD.Object, r: CD.Rect] = {
IF r#ob.bbox THEN {
TerminalIO.PutRope["** size of text wrong; probably use of different font\n"];
IF ~changeMsg THEN {
TerminalIO.PutRope["** to change object sizes to the current font requirements type "" ← CDTextsImpl.changeTextSizeIfDifferent ← TRUE"" into an interpreter and read in the file again. Then set it again to FALSE\n"];
changeMsg ← TRUE;
};
IF ~changeTextSizeIfDifferent THEN ob.bbox ← r;
};
};
ReadFont: PROC [h: TokenIO.Handle] RETURNS [cdFont: REF CDTexts.FontRec] = {
format: INT ← TokenIO.ReadInt[h];
SELECT format FROM
1 => {
name: Rope.ROPE;
scale: INT;
name ← TokenIO.ReadRope[h];
scale ← TokenIO.ReadInt[h];
cdFont ← InternalMakeFont[name, scale, $IO];
};
ENDCASE => ERROR
};
WriteFont: PROC [h: TokenIO.Handle, cdFont: CDFont] = {
TokenIO.WriteInt[h, cdFont.format];
IF cdFont.format#1 THEN ERROR
ELSE {
TokenIO.WriteRope[h, cdFont.supposedName];
TokenIO.WriteInt[h, cdFont.scaleI];
};
};
-- Fonts ========================================
fontCache: SymTab.Ref ← SymTab.Create[mod: 31, case: FALSE];
MakeKey: PROC [name: Rope.ROPE, scale: INT] RETURNS [Rope.ROPE] = {
RETURN [IO.PutFR["!%0g*%0g", IO.rope[name], IO.int[scale]]];
};
GetCachedFont: PROC [name: Rope.ROPE, scale: CD.Number] RETURNS [REF CDTexts.FontRec] = {
WITH fontCache.Fetch[MakeKey[name, scale]].val SELECT FROM
f: REF CDTexts.FontRec => RETURN [f];
ENDCASE => RETURN [NIL];
};
CreateFont: PROC [name: Rope.ROPE, scale: CD.Number, approx: ATOMNIL] RETURNS [cdFont: REF CDTexts.FontRec←NIL] = {
FindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font←NIL] = {
font ← ImagerFont.Find[name !
Imager.Error => {
font ← NIL;
TerminalIO.PutRopes["**error while loading font ", name, ": "];
TerminalIO.PutRopes[error.explanation, "\n"];
CONTINUE;
};
RuntimeError.UNCAUGHT => {
font ← NIL;
TerminalIO.PutRopes["**unknown error while loading font ", name, "\n"];
CONTINUE;
}
];
};
IsIdentity: PROC [t: Imager.Transformation] RETURNS [BOOL] = {
RETURN [t.a=1.0 AND t.b=0.0 AND t.c=0.0 AND t.d=0.0 AND t.e=1.0 AND t.f=0.0]
};
Internalize: PROC [font: Imager.Font, scale: INT] RETURNS [cdf: REF CDTexts.FontRec←NIL] = {
IF font#NIL THEN {
e: ImagerFont.Extents;
scale ← MAX[1, scale];
IF ~IsIdentity[font.charToClient] THEN ERROR;
cdf ← NEW[CDTexts.FontRec ← [properties: CD.InitPropRef[], origin: [0, 0], xy: [0, 0], format: 1]];
cdf.scaleI ← scale;
cdf.scaleR ← scale;
CDProperties.PutProp[cdf.properties, $OriginalFont, font];
cdf.font ← ImagerFont.Modify[font, ImagerTransformation.Scale[scale]];
e ← ImagerFont.FontBoundingBox[cdf.font];
cdf.xy.x ← Up[e.leftExtent];
cdf.xy.y ← Up[e.descent];
cdf.height ← Up[e.ascent]+Up[e.descent];
cdf.origin.x ← Up[cdf.xy.x];
cdf.origin.y ← Up[cdf.xy.y];
}
};
FindPlaceholderFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font←NIL] = {
TerminalIO.PutRopes["**font ", name, " substituted\n"];
RETURN [VFonts.defaultFont];
};
isPlaceHolder: BOOLFALSE;
font: Imager.Font ← FindFont[name];
IF font=NIL THEN {
SELECT approx FROM
NIL => RETURN [NIL];
$old => {
font ← OldFindFont[name];
IF font#NIL THEN name ← font.name; --to prevent bad cache entries!!
};
$IO => NULL;
ENDCASE => TerminalIO.PutRope["** bad font mode key\n"];
IF font=NIL THEN {
isPlaceHolder ← TRUE;
font ← FindPlaceholderFont[name];
};
};
IF font#NIL THEN { --exact font
cdFont ← Internalize[font, scale];
cdFont.isPlaceHolder ← isPlaceHolder;
cdFont.supposedKey ← MakeKey[name, scale];
cdFont.supposedName ← name;
[] ← fontCache.Store[cdFont.supposedKey, cdFont];
RETURN
};
};
InternalMakeFont: PROC [name: Rope.ROPE, scale: CD.Number, approx: ATOM] RETURNS [cdFont: REF FontRec] = {
cdFont ← GetCachedFont[name, scale];
IF cdFont=NIL THEN cdFont ← CreateFont[name, scale, approx];
};
MakeFont: PUBLIC PROC [name: Rope.ROPE, scale: CD.Number] RETURNS [CDFont] = {
RETURN [InternalMakeFont[name, scale, NIL]]
};
-- Old ========================================
ConvertCreateText: PROC [text: Rope.ROPE, font: REF ANY, layer: CD.Layer, key: ATOM] RETURNS [ob: CD.Object←NIL] = {
WITH font SELECT FROM
cdFont: CDFont => {
flip: BOOL ← layer=CD.commentLayer;
IF Rope.Match["*symbol*", cdFont.supposedName, FALSE] THEN flip ← FALSE;
IF Rope.Match["*gate*", cdFont.supposedName, FALSE] THEN flip ← FALSE;
IF key=$chipnsil OR key=$never THEN flip ← FALSE;
ob ← Create[text, cdFont, layer, flip]
};
ENDCASE => NULL
};
neverFlip: BOOLFALSE;
flipMsg: BOOLFALSE;
ReadEvent: CDEvents.EventProc = {
changeMsg ← flipMsg ← FALSE;
};
ConvertRead: CD.InternalReadProc = {
ob: CD.Object; sz: CD.Position; t: Rope.ROPE;
cdFont: REF CDTexts.FontRec; layer: CD.Layer;
IF CDIO.VersionKey[h]<=8 THEN RETURN [VeryOldReadText[h, NIL]];
t ← TokenIO.ReadRope[h];
layer ← CDIO.ReadLayer[h];
IF layer=CD.undefLayer AND CDIO.VersionKey[h]<=14 THEN {
layer ← CD.commentLayer;
TerminalIO.PutRope["** layer of text converted to comment\n"];
};
sz ← CDIO.ReadPos[h];
cdFont ← ReadFont[h];
ob ← ConvertCreateText[text: t, font: cdFont, layer: layer,
key: IF neverFlip THEN $never ELSE CDIO.DesignInReadOperation[h].technology.key
];
IF ~flipMsg THEN {
flipMsg ← TRUE;
TerminalIO.PutRope["**did convert text to either rigid or flip text; you can guide the conversion with either\n ← CDTextsImpl.neverFlip ← TRUE\n ← CDTextsImpl.neverFlip ← FALSE\nand repeating the input\n"];
};
--originally did compare size of text with sz
RETURN [ob]
};
OldFindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font←NIL] = {
FindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font←NIL] = {
font ← ImagerFont.Find[name !
Imager.Error => {font ← NIL; CONTINUE};
RuntimeError.UNCAUGHT => {font ← NIL; CONTINUE}
];
};
BasePart: PROC [name: Rope.ROPE] RETURNS [Rope.ROPE] = {
fName: Rope.ROPE;
cp: FS.ComponentPositions;
[fullFName: fName, cp: cp] ← FS.ExpandName[name: name];
RETURN [ Rope.Substr[fName, cp.base.start, cp.base.length] ]
};
FindFontOrXFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font←NIL] = {
font ← FindFont[name];
IF font=NIL THEN font ← FindFont[Rope.Concat["Xerox/TiogaFonts/", name]];
};
TryAlso: PROC [name: Rope.ROPE] RETURNS [next: Rope.ROPENIL] = {
--get rid of a B or I (for Bold or Italic)
--we don't handle ropes of length 0 and 1
IF name.Length[]>1 THEN {
ch: CHAR ← name.Fetch[name.Length[]-1];
IF ch='B OR ch='I OR ch='N THEN next ← name.Substr[0, name.Length[]-1]
}
};
ok: BOOLTRUE;
copy: Rope.ROPE ← BasePart[name];
name ← copy;
DO
font ← FindFontOrXFont[copy];
IF font#NIL THEN {
IF copy#name THEN TerminalIO.PutRope[
Rope.Cat["Font ", name, " not found; use ", copy, " instead\n"]
];
RETURN;
};
copy ← TryAlso[copy];
IF copy.IsEmpty[] THEN RETURN;
ENDLOOP;
};
VeryOldReadText: CD.InternalReadProc = {
OldReadFont: PROC [h: TokenIO.Handle] RETURNS [font: REF CDTexts.FontRec] = {
--for version<=8
name: Rope.ROPE = TokenIO.ReadRope[h];
scale: INT = MAX[TokenIO.ReadInt[h]/8, 1]; --originally used a real
ignoreHeight: CD.Number = TokenIO.ReadInt[h];
ignoreWhiteBorder: CD.Number = TokenIO.ReadInt[h];
ignoreLayerSubstitute: CD.Layer = CDIO.ReadLayer[h];
ignoreBaseOffsetX: REAL = TokenIO.ReadInt[h]/8.0;
ignoreBaseOffsetY: REAL = TokenIO.ReadInt[h]/8.0;
ignoreScaleByReplacingFontAllowed: BOOL = (1=TokenIO.ReadInt[h]);
font ← InternalMakeFont[name: name, scale: scale, approx: $old];
};
ob: CD.Object;
x: INT ← -1;
y: INT ← -1;
r: Rope.ROPE;
f: ATOM;
layer: CD.Layer ← CD.undefLayer;
font: REF FontRec;
token: TokenIO.Token ← TokenIO.Read[h];
WITH token SELECT FROM
rope: TokenIO.Token.rope => r ← rope.value; -- very old
int: TokenIO.Token.int => {-- less old
x ← int.value;
y ← TokenIO.ReadInt[h];
layer ← CDIO.ReadLayer[h];
r ← TokenIO.ReadRope[h]
};
ENDCASE => ERROR TokenIO.EncodingError;
f ← TokenIO.ReadAtom[h];
IF f#NIL THEN ERROR;
font ← OldReadFont[h];
ob ← ConvertCreateText[text: r, font: font, layer: layer, key: NIL];
--originally did check size of text with x and y
RETURN [ob]
};
ChangeLayer: CD.ChangeLayerProc = {
newOb: CD.Object;
ts: CDTexts.TextSpecific ← NARROW[inst.ob.specific];
newLayer: CD.Layer ← CDLayers.AbstractToPaint[layer];
IF newLayer=CD.undefLayer AND newLayer#layer THEN RETURN [FALSE];
newOb ← Create[text: ts.text, font: ts.cdFont, layer: layer, flip: CDTexts.IsFlipText[inst.ob]];
IF newOb#NIL THEN inst.ob ← newOb;
RETURN [newOb#NIL];
};
SubstituteTiogaFonts: PUBLIC PROC [imagerFont: Imager.Font] RETURNS [printFont: Imager.Font] = {
--Translates from strike to spline fonts.
--Procedure copied from Giordano's original version in Nectarine.
shortFName, subDir, fullFName, family, attributes: Rope.ROPE;
cp: FS.ComponentPositions;
sizePos, facePos, attributesLeng: INT; size: REAL;
face: NodeStyle.FontFace ← Regular;
[fullFName, cp] ← FS.ExpandName[imagerFont.name];
printFont ← imagerFont;
subDir ← Rope.Substr[fullFName, cp.subDirs.start, cp.subDirs.length];
IF Rope.Equal[subDir, "Xerox>TiogaFonts", FALSE] THEN {
--Construct the old style name:
shortFName ← Rope.Substr[fullFName, cp.base.start, cp.base.length];
--Find the size and face from the old style name:
sizePos ← Rope.SkipTo[shortFName, 0, "0123456789"];
attributesLeng ← Rope.Length[shortFName]-sizePos;
attributes ← Rope.Substr[shortFName, sizePos, attributesLeng];
facePos ← Rope.SkipTo[attributes, 0, "bBiI"];
--Compute the size (assume: there always is a size):
size ← (ORD[Rope.Fetch[attributes, 0]] - ORD ['0]);
FOR i: INT IN [1..facePos) DO
size ← size * 10.0 + (ORD[Rope.Fetch[attributes, i]] - ORD['0])
ENDLOOP;
--Determine the face:
IF facePos#attributesLeng THEN {
it: BOOL ~ Rope.SkipTo[attributes, 0, "iI"]#attributesLeng;
b: BOOL ~ Rope.SkipTo[attributes, 0, "bB"]#attributesLeng;
SELECT TRUE FROM
it AND b => face ← BoldItalic;
it AND NOT b => face ← Italic;
NOT it AND b => face ← Bold;
ENDCASE => ERROR
};
family ← Rope.Substr[shortFName, 0, sizePos];
printFont ← NodeStyleFont.FontFromStyleParams[prefix: Atom.MakeAtom["Xerox/PressFonts/"], family: Atom.MakeAtom[family], face: face, size: size, alphabets: CapsAndLower];
IF printFont=NIL THEN RETURN [imagerFont];
printFont ← ImagerFont.Modify[printFont, imagerFont.charToClient]
};
}; 
[] ← CDProperties.RegisterProperty[$OriginalFont, $CDTextsImpl];
CDEvents.RegisterEventProc[$ReadTechnologyPrivate, ReadEvent];
END.