DIRECTORY
ControllerMenuDefs USING [SetStyleMenus],
Convert USING [RopeFromInt],
GriffinDefs USING [ShowUserMessage],
GriffinStyle,
GriffinColor USING [StringToColor],
GriffinFontDefs,
Imager USING [Error],
ImagerFont USING [Find, Modify],
ImagerTransformation USING [Rotate, Scale, Transformation, FactoredTransformation, Factor, Concat],
ObjectDefs USING [ObjectProc, ForAllPictureObjects],
Real USING [RoundC],
Rope USING [ROPE, Cat, SkipOver, Find, Substr, Equal],
StyleDefs;
~
BEGIN OPEN GriffinStyle, StyleDefs;
ROPE: TYPE = Rope.ROPE;
currentStyle: StyleHandle;
currentNumber: INT ← 0;
CurrentStyle:
PUBLIC
PROCEDURE
RETURNS [StyleHandle] = {
RETURN[currentStyle];
};
CopyCurrentStyle:
PUBLIC
PROCEDURE
RETURNS [StyleHandle] = {
new: StyleHandle ← NEW[Style];
new^ ← currentStyle^;
IF new.font=NIL THEN ERROR;
new.name ← NextName[];
RETURN[new];
};
SetCurrentStyle:
PUBLIC
PROC[style: StyleHandle] = {
currentStyle^ ← style^;
ControllerMenuDefs.SetStyleMenus[style];
};
NextName:
PUBLIC
PROCEDURE
RETURNS [
ROPE] = {
name: ROPE ← Rope.Cat["Style", Convert.RopeFromInt[currentNumber]];
currentNumber ← currentNumber+1;
RETURN[name];
};
Initialize:
PUBLIC
PROC = {
currentStyle ← NEW[Style];
currentStyle.color ← GriffinColor.StringToColor["black"];
currentStyle.dashed ← undashed;
currentStyle.firstend ← LineEnd [round, 0, 0, 0, 0, 0];
currentStyle.lastend ← LineEnd [round, 0, 0, 0, 0, 0];
currentStyle.junctiontype ← round;
currentStyle.width ← 64;
currentStyle.fillcolor ← GriffinColor.StringToColor["grey"];
currentStyle.filled ← TRUE;
currentStyle.outlined ← TRUE;
currentStyle.anchor ← left;
currentStyle.stringRotation ← or0;
currentStyle.stringType ← normal;
currentStyle.font ← NIL; --will be initialized by ControllerMenus
currentStyle.fillbackgnd ← FALSE;
currentStyle.backgndcolor ← GriffinColor.StringToColor["white"];
currentStyle.name ← NextName[];
};
Font: TYPE = StyleDefs.Font;
InternalFont: TYPE = GriffinFontDefs.FontDescriptorHandle;
FontSequence: TYPE = REF FontSequenceRec;
FontSequenceRec: TYPE = RECORD[element: SEQUENCE length:NAT OF Font];
StyleSequence: TYPE = REF StyleSequenceRec;
StyleSequenceRec: TYPE = RECORD[element: SEQUENCE length: NAT OF StyleHandle];
CreateStyleList:
PUBLIC PROC
RETURNS[styles: StyleSequence] = {
next: NAT ← 0;
allStyles: StyleSequence ← NEW[StyleSequenceRec[currentNumber-1]];
proc: ObjectDefs.ObjectProc = {
IF obj.deleted THEN RETURN;
IF FindEquivalentStyle[obj.style, allStyles] =
NIL
THEN {
allStyles[next] ← obj.style;
next ← next+1;
};
};
IF currentNumber > 1
THEN {
--one style for the menus
ObjectDefs.ForAllPictureObjects[proc];
styles ← NEW[StyleSequenceRec[next]];
FOR i:
NAT
IN [0..styles.length)
DO
styles[i] ← allStyles[i];
ENDLOOP;
};
};
CreateFontList:
PUBLIC PROC[styles: StyleSequence]
RETURNS[fonts: FontSequence] = {
allFonts: FontSequence ← NEW[FontSequenceRec[styles.length]];
next: NAT ← 0;
IF styles=NIL THEN RETURN[NIL];
FOR i:
NAT
IN [0..allFonts.length)
DO
dup: BOOL ← FALSE;
FOR j:
NAT
IN [0..next)
DO
IF styles[i].font=allFonts[j] THEN {dup ← TRUE; EXIT};
ENDLOOP;
IF NOT dup THEN {allFonts[next] ← styles[i].font; next ← next+1};
ENDLOOP;
fonts ← NEW[FontSequenceRec[next]];
FOR i:
NAT
IN [0..fonts.length)
DO
fonts[i] ← allFonts[i];
ENDLOOP;
RETURN[fonts]
};
NumberOfStyle:
PUBLIC PROC[style: StyleHandle, styles: StyleSequence]
RETURNS [
CARDINAL] = {
found: BOOLEAN ← FALSE;
styleNum: NAT;
FOR styleNum
IN [0..styles.length)
DO
IF style=styles[styleNum] THEN {found ← TRUE; EXIT};
ENDLOOP;
RETURN[styleNum+1];
};
NumberOfFont:
PUBLIC PROC[font: Font, fonts: FontSequence]
RETURNS[
CARDINAL] = {
found: BOOLEAN ← FALSE;
fontNum: NAT;
FOR fontNum
IN [0..fonts.length)
DO
IF font=fonts[fontNum] THEN {found ← TRUE; EXIT};
ENDLOOP;
RETURN[fontNum+1];
};
FindEquivalentStyle:
PUBLIC
PROC[style: StyleHandle, styles: StyleSequence]
RETURNS [StyleHandle] = {
IF style=NIL OR styles=NIL THEN RETURN[NIL];
FOR i:
NAT
IN [0..styles.length)
DO
IF styles[i]=NIL THEN EXIT;
IF EquivalentStyles[style, styles[i]] THEN RETURN[styles[i]];
ENDLOOP;
RETURN[NIL];
};
EquivalentStyles:
PROC[style1, style2: StyleHandle]
RETURNS[
BOOLEAN] = {
equal: BOOL ← FALSE;
IF style1#
NIL
AND style2#
NIL
THEN {
name1: ROPE ← style1.name;
name2: ROPE ← style2.name;
style1.name ← style2.name ← NIL;
equal ← style1^=style2^;
style1.name ← name1;
style2.name ← name2;
};
RETURN[equal];
};
InternalFontFromFont:
PUBLIC PROC[font: Font]
RETURNS[InternalFont] = {
factors: ImagerTransformation.FactoredTransformation ←
ImagerTransformation.Factor[font.charToClient];
ifont: InternalFont ← NEW[GriffinFontDefs.FontDescriptor];
startName: INT ← Rope.SkipOver[s: font.name, skip: "Xerox/PressFonts/"];
startFace: INT ← Rope.Find[s1: font.name, s2: "-"]+1;
faceCode: ROPE ← Rope.Substr[base: font.name, start: startFace, len: 3];
ifont.name ← Rope.Substr[base: font.name, start: startName, len: startFace-startName-1];
ifont.face ←
SELECT
TRUE
FROM
Rope.Equal[faceCode, "MRR", FALSE] => GriffinFontDefs.Regular,
Rope.Equal[faceCode, "MIR", FALSE] => GriffinFontDefs.Italic,
Rope.Equal[faceCode, "BRR", FALSE] => GriffinFontDefs.Bold,
Rope.Equal[faceCode, "BIR", FALSE] => GriffinFontDefs.BoldItalic,
ENDCASE => ERROR;
ifont.rotation ←
SELECT Real.RoundC[factors.r1+factors.r2]
FROM
0 => GriffinFontDefs.Rot0Degrees,
90 => GriffinFontDefs.Rot90Degrees,
180 => GriffinFontDefs.Rot180Degrees,
270 => GriffinFontDefs.Rot270Degrees,
ENDCASE => ERROR;
ifont.points ← Real.RoundC[factors.s.x];
RETURN[ifont];
};
FontFromInternalFont:
PUBLIC PROC[ifont: InternalFont]
RETURNS[Font] = {
Griffin internal fonts use a short name like TimesRoman or Helvetica.
Assume here Xerox/PressFonts/ for all names
transformation: ImagerTransformation.Transformation;
face:
ROPE ←
SELECT ifont.face
FROM
GriffinFontDefs.Regular => "-MRR",
GriffinFontDefs.Italic => "-MIR",
GriffinFontDefs.Bold => "-BRR",
GriffinFontDefs.BoldItalic => "-BIR",
ENDCASE => ERROR;
name: ROPE ← Rope.Cat["Xerox/PressFonts/",ifont.name, face];
font: StyleDefs.Font ← ImagerFont.Find[name ! Imager.Error => {
GriffinDefs.ShowUserMessage[error.explanation];
GOTO error;
}];
transformation ←
SELECT ifont.rotation
FROM
GriffinFontDefs.Rot0Degrees => ImagerTransformation.Rotate[0],
GriffinFontDefs.Rot90Degrees => ImagerTransformation.Rotate[90],
GriffinFontDefs.Rot180Degrees => ImagerTransformation.Rotate[180],
GriffinFontDefs.Rot270Degrees => ImagerTransformation.Rotate[270],
ENDCASE => ERROR;
transformation ←
ImagerTransformation.Concat[transformation, ImagerTransformation.Scale[ifont.points]];
font ← ImagerFont.Modify[font, transformation];
RETURN[font];
EXITS error => RETURN[NIL];
};
ComputeStringType:
PUBLIC
PROC[stringRotation: StyleDefs.StringRotation,font: StyleDefs.Font]
RETURNS[StyleDefs.StringType] = {
ifont: InternalFont ← InternalFontFromFont[font];
stringR:
INT ←
SELECT stringRotation
FROM
or0 =>0, or90 => 90, or180 => 180, or270 => 270, ENDCASE => ERROR;
fontR:
INT ←
SELECT ifont.rotation
FROM
GriffinFontDefs.Rot0Degrees => 0,
GriffinFontDefs.Rot90Degrees => 90,
GriffinFontDefs.Rot180Degrees => 180,
GriffinFontDefs.Rot270Degrees => 270,
ENDCASE => ERROR;
IF stringR=fontR THEN RETURN[normal] ELSE RETURN[stack];
};