--GriffinToTANodesImpl.mesa
-- Beach, July 3, 1982 3:53 pm
-- Stone November 26, 1982 7:08 pm
DIRECTORY
GFileFormatDefs,
GriffinToTA,
GriffinToTANodes,
GriffinToTAPrivate,
IO,
NameSymbolTable USING [Name, RopeFromName],
PairList,
PutGet USING [ToFile],
Rope,
SplineDefs,
StyleDefs,
TAProperties USING [SetArtworkProp, SetArtworkPathProp, SetBoundingBoxProp, SetOriginProp],
TextEdit USING [AppendRope, ChangeStyle, ChangeType, DocFromNode, FromRope],
TextNode USING [Ref, RefTextNode],
UserExec USING [GetNameAndPassword],
GraphicsBasic USING [Vec],
CGPath USING [Generate];
GriffinToTANodesImpl: PROGRAM
IMPORTS GriffinToTA, GriffinToTAPrivate, IO, NameSymbolTable, PairList, PutGet, Rope, TAProperties, TextEdit, UserExec, CGPath
EXPORTS GriffinToTANodes = {
OPEN GriffinToTA, GriffinToTAPrivate;
ROPE: TYPE = Rope.ROPE;
topScreenCoord: INTEGER = 808;
-- Griffin Font definitions taken from GriffinFontDefs
Regular: CARDINAL = 0;
Italic: CARDINAL = 1;
Bold: CARDINAL = 2;
BoldItalic: CARDINAL = Bold + Italic;
Rot0Degrees: CARDINAL = 0;
Rot90Degrees: CARDINAL = 5400;
Rot180Degrees: CARDINAL = 10800;
Rot270Degrees: CARDINAL = 16200;
PutClusters: PUBLIC PROCEDURE[fileName: ROPE] = {
thisCluster: CARDINAL;
clusterNumber: CARDINAL ← 0;
figureName: ROPE ← Rope.Substr[fileName, 0, Rope.Find[fileName, "."]];
figureRoot: TextNode.Ref;
figureNode, clusterNode: TextNode.RefTextNode;
clusterX, clusterY: INTEGER ← LAST[INTEGER];
objectBBox: PROC[leftPart, rightPart: REF ANY] = {
IF NARROW[leftPart, REF CARDINAL]^=thisCluster THEN {
refObjectId: REF CARDINAL ← NARROW[rightPart];
griffinObject: ObjectRef ← NARROW[PairList.Right[objectMap, EqualCardinals, refObjectId]];
clusterX ← MIN[clusterX, griffinObject^.bleft];
clusterY ← MIN[clusterY, topScreenCoord-griffinObject^.bbottom];
};
};
doObject: PROC[leftPart, rightPart: REF ANY] = {
IF NARROW[leftPart, REF CARDINAL]^=thisCluster THEN {
IF clusterNode=NIL THEN {
clusterNumber ← clusterNumber+1;
clusterNode ← PutClusterNode[figureRoot, figureNode, clusterNumber, clusterX, clusterY]};
PutObjectNode[figureRoot, clusterNode, NARROW[rightPart, REF CARDINAL], clusterX, clusterY]};
};
figureNode ← PutFigureNode[figureName];
figureRoot ← TextEdit.DocFromNode[figureNode];
TextEdit.ChangeStyle[figureRoot, figureName];
TAProperties.SetArtworkProp[figureRoot];
FOR thisCluster IN [firstCluster .. lastCluster] DO
clusterNode ← NIL;
clusterX ← clusterY ← LAST[INTEGER];
PairList.ForAllPairs[clusterMap, objectBBox];
PairList.ForAllPairs[clusterMap, doObject];
ENDLOOP;
[] ← PutGet.ToFile[fileName, figureRoot];
};
PutFigureNode: PROCEDURE[figureName: ROPE] RETURNS[node: TextNode.RefTextNode] = {
rope: ROPE ← Rope.Cat["% Tioga Artwork figure for ", figureName];
node ← TextEdit.FromRope[rope];
TAProperties.SetArtworkProp[node];
RETURN[node];
};
PutClusterNode: PROCEDURE[figureRoot: TextNode.Ref, figureNode: TextNode.RefTextNode, cluster: CARDINAL, clusterX, clusterY: INTEGER] RETURNS[node: TextNode.RefTextNode] = {
node ← InsertNodeAfterChildrenOf[figureNode];
[] ← TextEdit.AppendRope[figureRoot, node,
IO.PutFToRope["%% Cluster %d*n%d %d .translate",
IO.card[cluster], IO.int[clusterX], IO.int[clusterY]]];
TAProperties.SetArtworkProp[node];
RETURN[node];
};
PutObjectNode: PROCEDURE[figureRoot: TextNode.Ref, clusterNode: TextNode.RefTextNode, refObjectId: REF CARDINAL, clusterX, clusterY: INTEGER] = {
griffinObject: ObjectRef ← NARROW[PairList.Right[objectMap, EqualCardinals, refObjectId]];
objectNode: TextNode.RefTextNode ← InsertNodeAfterChildrenOf[clusterNode];
[] ← TextEdit.AppendRope[figureRoot, objectNode,
IO.PutFToRope["%% Object %d", IO.card[refObjectId^]]];
SELECT griffinObject^.objtype FROM
GFileFormatDefs.typeCurveObject,
GFileFormatDefs.typeAreaObject =>
PutPathNode[figureRoot, objectNode, griffinObject, refObjectId, clusterX, clusterY];
GFileFormatDefs.typeCaptionObject =>
PutCaptionNode[figureRoot, objectNode, griffinObject, refObjectId, clusterX, clusterY];
ENDCASE;
TAProperties.SetArtworkProp[objectNode];
};
PutPathNode: PROCEDURE[figureRoot: TextNode.Ref, objectNode: TextNode.RefTextNode, griffinObject: ObjectRef, refObjectId: REF CARDINAL, clusterX, clusterY: INTEGER] = {
pathNode: TextNode.RefTextNode ← InsertNodeAfterChildrenOf[objectNode];
refStyleId: REF CARDINAL ← NEW[CARDINAL ← griffinObject^.style];
griffinStyle: StyleRef ← NARROW[PairList.Right[styleMap, EqualCardinals, refStyleId]];
areaColor, outlineColor: ColorRef ← NIL;
pathType: ROPE ← NIL;
lineWeight: REAL ← 0;
pathStyle: PathStyleRef;
pathRef: PathRef;
SELECT griffinObject^.objtype FROM
GFileFormatDefs.typeAreaObject => {
IF griffinStyle^.afilled THEN {
areaColor ← FindColor[griffinStyle^.ahue, griffinStyle^.asaturation, griffinStyle^.abrightness];
pathType ← "filled"};
IF griffinStyle^.aoutlined THEN {
outlineColor ← FindColor[griffinStyle^.hue, griffinStyle^.saturation, griffinStyle^.brightness];
pathType ← IF griffinStyle^.afilled THEN "filled+outlined" ELSE "outlined";
lineWeight ← GriffinToTAPrivate.ScalePressToScreenCoord[griffinStyle^.thickness]}};
GFileFormatDefs.typeCurveObject => {
outlineColor ← FindColor[griffinStyle^.hue, griffinStyle^.saturation, griffinStyle^.brightness];
pathType ← "outlined";
lineWeight ← GriffinToTAPrivate.ScalePressToScreenCoord[griffinStyle^.thickness]};
ENDCASE;
pathStyle ← FindPathStyle[areaColor, outlineColor, pathType, lineWeight];
[] ← TextEdit.AppendRope[figureRoot, objectNode,
IO.PutFToRope["\n%d %d .translate",
IO.int[griffinObject^.bleft-clusterX],
IO.int[topScreenCoord-griffinObject^.bbottom-clusterY]]];
--can't use a NARROW as pathRef is opaque, and that construct is not implemented
--this should be pretty safe
pathRef ← LOOPHOLE[PairList.Right[pathMap, EqualCardinals, refObjectId]];
[] ← TextEdit.AppendRope[figureRoot, pathNode,PathToRope[pathRef]];
TextEdit.ChangeType[pathNode, pathStyle^.name];
TAProperties.SetArtworkProp[pathNode];
TAProperties.SetArtworkPathProp[pathNode];
TAProperties.SetBoundingBoxProp[pathNode, griffinObject^.bright-griffinObject^.bleft, griffinObject^.bbottom-griffinObject^.btop];
TAProperties.SetOriginProp[pathNode, 0, 0];
};
PutCaptionNode: PROCEDURE[figureRoot: TextNode.Ref, objectNode: TextNode.RefTextNode, griffinObject: ObjectRef, refObjectId: REF CARDINAL, clusterX, clusterY: INTEGER] = {
captionNode: TextNode.RefTextNode ← InsertNodeAfterChildrenOf[objectNode];
captionStyle: CaptionStyleRef;
caption: CaptionRef ← NARROW[PairList.Right[captionMap, EqualCardinals, refObjectId]];
refStyleId: REF CARDINAL ← NEW[CARDINAL ← griffinObject^.style];
griffinStyle: StyleRef ← NARROW[PairList.Right[styleMap, EqualCardinals, refStyleId]];
refFontId: REF CARDINAL ← NEW[CARDINAL ← griffinStyle^.fontid];
griffinFont: FontRef ← NARROW[PairList.Right[fontMap, EqualCardinals, refFontId]];
family, face, charRotation, lineFormatting: ROPE;
size: REAL;
textRotation: INTEGER;
textColor: ColorRef;
i: CARDINAL;
bold, italic: BOOLEAN ← FALSE;
FOR i IN [1 .. LOOPHOLE[griffinFont^.char[0],CARDINAL]] DO
family ← Rope.Cat[family, Rope.FromChar[griffinFont^.char[i]]];
ENDLOOP;
size ← griffinFont^.points;
SELECT griffinFont^.face FROM
Regular => face ← "regular";
Italic => {face ← "italic"; italic ← TRUE};
Bold => {face ← "bold"; bold ← TRUE};
BoldItalic => {face ← "bold+italic"; bold ← TRUE; italic ← TRUE};
ENDCASE=> face ← "regular";
charRotation ← SELECT griffinFont^.rotation FROM
Rot0Degrees => "0",
Rot90Degrees => "90",
Rot180Degrees => "180",
Rot270Degrees => "270",
ENDCASE => "0";
lineFormatting ← SELECT griffinStyle^.anchor FROM
GFileFormatDefs.typeLeftAnchor => "flushLeft",
GFileFormatDefs.typeCenterAnchor => "centered",
GFileFormatDefs.typeRightAnchor => "flushRight",
ENDCASE => "flushLeft";
captionStyle ← FindCaptionStyle[family, size, face, charRotation, lineFormatting];
textRotation ← SELECT griffinStyle^.torient FROM
GFileFormatDefs.typeRot0 => 0,
GFileFormatDefs.typeRot90 => 90,
GFileFormatDefs.typeRot180 => 180,
GFileFormatDefs.typeRot270 => 270,
ENDCASE => 0;
textColor ← FindColor[griffinStyle^.hue, griffinStyle^.saturation, griffinStyle^.brightness];
[] ← TextEdit.AppendRope[figureRoot, objectNode,
IO.PutFToRope["\n%d %d .translate %d .rotate",
IO.real[caption^.position.x-clusterX],
IO.real[caption^.position.y-clusterY],
IO.int[textRotation]]];
[] ← TextEdit.AppendRope[figureRoot, captionNode, caption^.text];
TextEdit.ChangeType[captionNode, captionStyle^.name];
};
PutStyles: PUBLIC PROCEDURE[fileName: ROPE] = {
OPEN IO;
userName, password: ROPE;
styleRope: ROPE;
p, pp, pTemp: PathStyleRef;
c, cc, cTemp: CaptionStyleRef;
node: TextNode.RefTextNode;
root: TextNode.Ref;
[userName, password] ← UserExec.GetNameAndPassword[];
userName← Rope.Substr[userName, 0, Rope.Find[userName, "."]];
styleRope ← PutFToRope["%% %s\n%% %s, %g\n\n", rope[fileName], rope[userName], time[]];
styleRope ← Rope.Cat[styleRope, "BeginStyle\n\n(BasicGraphics) AttachStyle\n\n(Cedar) AttachStyle\n\n"];
p ← pathStyles;
pp ← NIL;
WHILE p#NIL DO -- reverse the styles list
pTemp ← p.next; p.next ← pp; pp ← p; p ← pTemp;
ENDLOOP;
p ← pathStyles ← pp;
WHILE p#NIL DO
styleRope ← Rope.Cat[styleRope, PathStyleToRope[p]];
p ← p.next;
ENDLOOP;
c ← captionStyles;
cc ← NIL;
WHILE c#NIL DO -- reverse the styles list
cTemp ← c.next; c.next ← cc; cc ← c; c ← cTemp;
ENDLOOP;
c ← captionStyles ← cc;
WHILE c#NIL DO
styleRope ← Rope.Cat[styleRope, CaptionStyleToRope[c]];
c ← c.next;
ENDLOOP;
styleRope ← Rope.Cat[styleRope, "EndStyle\n"];
node ← TextEdit.FromRope[styleRope];
root ← TextEdit.DocFromNode[node];
[] ← PutGet.ToFile[fileName, root];
};
PathStyleToRope: PUBLIC PROCEDURE[p: PathStyleRef] RETURNS[styleRope: ROPE] = {
OPEN IO;
styleRope ← PutFToRope["(%s) \". . .\" {\n", rope[NameSymbolTable.RopeFromName[p.name]]];
IF p.areaColor#NIL THEN
styleRope ← Rope.Cat[styleRope, PutFToRope["\t%s areaColor\n", rope[p.areaColor.name]]];
IF p.outlineColor#NIL THEN
styleRope ← Rope.Cat[styleRope, PutFToRope["\t%s outlineColor\n", rope[p.outlineColor.name]]];
styleRope ← Rope.Cat[styleRope, PutFToRope["\t%s pathType\n", rope[p.pathType]]];
IF p.lineWeight#0 THEN
styleRope ← Rope.Cat[styleRope, PutFToRope["\t%g pt lineWeight\n", real[p.lineWeight]]];
styleRope ← Rope.Cat[styleRope, "\t} StyleRule\n\n"];
};
CaptionStyleToRope: PUBLIC PROCEDURE[p: CaptionStyleRef] RETURNS[styleRope: ROPE] = {
OPEN IO;
styleRope ← Rope.Cat[
PutFToRope["(%s) \". . .\" {\n", rope[NameSymbolTable.RopeFromName[p.name]]],
PutFToRope["\t\"%s\" family\n", rope[p.family]],
PutFToRope["\t%g bp size\n", real[p.size]],
PutFToRope["\t%s face\n", rope[p.face]],
PutFToRope["\t%% %s charRotation\n", rope[p.charRotation]],
PutFToRope["\t%s captionFormatting\n\tflushTop captionAlignment\n\t0 left.indent\n\t} StyleRule\n\n", rope[p.lineFormatting]]];
};
PathToRope: PROC [path: PathRef] RETURNS [ROPE] = {
rope: ROPE;
move: SAFE PROC[p: GraphicsBasic.Vec] = CHECKED {
rope ← Rope.Cat[rope,IO.PutFToRope["%f %f %s ",
IO.real[p.x], IO.real[p.y], IO.rope[" .moveto "]]];
};
line: SAFE PROC[p: GraphicsBasic.Vec] = CHECKED {
rope ← Rope.Cat[rope,IO.PutFToRope["%f %f %s ",
IO.real[p.x], IO.real[p.y], IO.rope[" .lineto "]]];
};
curve: SAFE PROC[b1,b2,b3: GraphicsBasic.Vec] = CHECKED {
rope ← Rope.Cat[rope, IO.PutFToRope["%f %f %f %f ",
IO.real[b1.x], IO.real[b1.y], IO.real[b2.x], IO.real[b2.y]]];
rope ← Rope.Cat[rope, IO.PutFToRope["%f %f %s",
IO.real[b3.x], IO.real[b3.y], IO.rope[" .curveto "]]];
};
CGPath.Generate[path,move,line,curve];
RETURN[rope];
};
}.