DIRECTORY
Convert USING [RopeFromInt],
GriffinColor USING [StringToColor],
GriffinControllerMenu USING [SetStyleMenus],
GriffinData USING [DataRec],
GriffinKernel USING [DataRec],
GriffinObject USING [ForAllPictureObjects, ObjectProc],
GriffinStyle USING [Bold, BoldItalic, Font, FontDescriptor, FontSequence, FontSequenceRec, InternalFont, Italic, LineEnd, Regular, Rot0Degrees, Rot180Degrees, Rot270Degrees, Rot90Degrees, StringRotation, StringType, Style, StyleHandle, StyleSequence, StyleSequenceRec],
Imager USING [Error],
ImagerFont USING [Find, Font, Modify, Scale],
ImagerTransformation USING [Concat, Factor, FactoredTransformation, Rotate, Scale, Transformation],
MessageWindow USING [Append, Blink],
Real USING [RoundC, RoundI],
Rope USING [Cat, Concat, Equal, Find, ROPE, SkipOver, Substr];
GriffinStyleImpl:
CEDAR
PROGRAM
IMPORTS Convert, GriffinColor, GriffinControllerMenu, GriffinObject, Imager, ImagerFont, ImagerTransformation, MessageWindow, Real, Rope
EXPORTS GriffinStyle, GriffinKernel = BEGIN OPEN GriffinStyle;
ROPE: TYPE = Rope.ROPE;
Data: TYPE = REF DataRec;
DataRec: PUBLIC TYPE = GriffinData.DataRec; -- exported to GriffinKernel
defaultFont: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find["Xerox/PressFonts/Helvetica-MRR"], 10.0];
CopyCurrentStyle:
PUBLIC
PROC [data: Data]
RETURNS [GriffinStyle.StyleHandle] = {
new: GriffinStyle.StyleHandle ← NEW[GriffinStyle.Style];
new^ ← data.currentStyle^;
IF new.font=NIL THEN ERROR;
new.name ← NextName[data];
RETURN[new];
};
CopyStyle:
PROC [data: Data, style: GriffinStyle.StyleHandle]
RETURNS [GriffinStyle.StyleHandle] = {
new: GriffinStyle.StyleHandle ← NEW[GriffinStyle.Style];
new^ ← style^;
new.name ← NextName[data];
RETURN[new];
};
SetCurrentStyle:
PUBLIC
PROC [data: Data, style: GriffinStyle.StyleHandle] = {
data.currentStyle ← CopyStyle[data, style];
GriffinControllerMenu.SetStyleMenus[data, style];
};
NextName:
PUBLIC
PROC [data: Data]
RETURNS [
ROPE] = {
name: ROPE ← Rope.Concat["Style", Convert.RopeFromInt[data.styleNumber]];
data.styleNumber ← data.styleNumber+1;
RETURN[name];
};
Initialize:
PUBLIC
PROC [data: Data] = {
data.currentStyle ← NEW[GriffinStyle.Style];
data.currentStyle.color ← GriffinColor.StringToColor["black"];
data.currentStyle.dashed ← undashed;
data.currentStyle.firstend ← GriffinStyle.LineEnd [round, 0, 0, 0, 0, 0];
data.currentStyle.lastend ← GriffinStyle.LineEnd [round, 0, 0, 0, 0, 0];
data.currentStyle.junctiontype ← round;
data.currentStyle.width ← 64;
data.currentStyle.fillcolor ← GriffinColor.StringToColor["grey"];
data.currentStyle.filled ← TRUE;
data.currentStyle.outlined ← TRUE;
data.currentStyle.anchor ← left;
data.currentStyle.stringRotation ← or0;
data.currentStyle.stringType ← normal;
data.currentStyle.font ← NIL; --will be initialized by ControllerMenus
data.currentStyle.fillbackgnd ← FALSE;
data.currentStyle.backgndcolor ← GriffinColor.StringToColor["white"];
data.currentStyle.name ← NextName[data];
};
Font: TYPE = GriffinStyle.Font;
InternalFont: TYPE = GriffinStyle.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 [data: Data]
RETURNS [styles: StyleSequence] = {
next: NAT ← 0;
allStyles: StyleSequence ← NEW[StyleSequenceRec[data.styleNumber-1]];
Proc: GriffinObject.ObjectProc = {
IF object.deleted THEN RETURN;
IF FindEquivalentStyle[object.style, allStyles] =
NIL
THEN {
allStyles[next] ← object.style;
next ← next+1;
};
};
IF data.styleNumber > 1
THEN {
--one style for the menus
GriffinObject.ForAllPictureObjects[data, 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: GriffinStyle.StyleHandle, styles: StyleSequence]
RETURNS [
CARDINAL] = {
styleNum: NAT;
FOR styleNum
IN [0..styles.length)
DO
IF EquivalentStyles[style, styles[styleNum]] THEN RETURN[styleNum+1];
ENDLOOP;
ERROR; -- can't happen, it says here
};
NumberOfFont:
PUBLIC
PROC [font: GriffinStyle.Font, fonts: FontSequence]
RETURNS [
CARDINAL] = {
fontNum: NAT;
FOR fontNum
IN [0..fonts.length)
DO
IF font=fonts[fontNum] THEN RETURN[fontNum+1];
ENDLOOP;
ERROR; -- can't happen, it says here
};
FindEquivalentStyle:
PUBLIC
PROC [style: GriffinStyle.StyleHandle, styles: StyleSequence]
RETURNS [GriffinStyle.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: GriffinStyle.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: GriffinStyle.Font]
RETURNS [InternalFont] = {
xi: INTEGER ← 0;
factors: ImagerTransformation.FactoredTransformation ←
ImagerTransformation.Factor[font.charToClient];
ifont: InternalFont ← NEW[GriffinStyle.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] => GriffinStyle.Regular,
Rope.Equal[faceCode, "MIR", FALSE] => GriffinStyle.Italic,
Rope.Equal[faceCode, "BRR", FALSE] => GriffinStyle.Bold,
Rope.Equal[faceCode, "BIR", FALSE] => GriffinStyle.BoldItalic,
ENDCASE => ERROR;
xi ← Real.RoundI[factors.r1+factors.r2];
ifont.rotation ←
SELECT xi
FROM
0 => GriffinStyle.Rot0Degrees,
90 => GriffinStyle.Rot90Degrees,
180, -180 => GriffinStyle.Rot180Degrees,
270, -90 => GriffinStyle.Rot270Degrees,
ENDCASE => ERROR;
ifont.points ← Real.RoundC[factors.s.x];
RETURN[ifont];
};
FontFromInternalFont:
PUBLIC
PROC [ifont: InternalFont]
RETURNS [GriffinStyle.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
GriffinStyle.Regular => "-MRR",
GriffinStyle.Italic => "-MIR",
GriffinStyle.Bold => "-BRR",
GriffinStyle.BoldItalic => "-BIR",
ENDCASE => ERROR;
name: ROPE ← Rope.Cat["Xerox/PressFonts/",ifont.name, face];
font: GriffinStyle.Font ← defaultFont; -- in case it bombs out
font ← ImagerFont.Find[name ! Imager.Error => {
MessageWindow.Append[error.explanation, TRUE];
MessageWindow.Blink[];
CONTINUE;
}];
transformation ←
SELECT ifont.rotation
FROM
GriffinStyle.Rot0Degrees => ImagerTransformation.Rotate[0],
GriffinStyle.Rot90Degrees => ImagerTransformation.Rotate[90],
GriffinStyle.Rot180Degrees => ImagerTransformation.Rotate[180],
GriffinStyle.Rot270Degrees => ImagerTransformation.Rotate[270],
ENDCASE => ERROR;
transformation ←
ImagerTransformation.Concat[transformation, ImagerTransformation.Scale[ifont.points]];
font ← ImagerFont.Modify[font, transformation];
RETURN[font];
};
ComputeStringType:
PUBLIC
PROC [stringRotation: GriffinStyle.StringRotation,font: GriffinStyle.Font]
RETURNS [GriffinStyle.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
GriffinStyle.Rot0Degrees => 0,
GriffinStyle.Rot90Degrees => 90,
GriffinStyle.Rot180Degrees => 180,
GriffinStyle.Rot270Degrees => 270,
ENDCASE => ERROR;
IF stringR=fontR THEN RETURN[normal] ELSE RETURN[stack];
};