DIRECTORY Atom, CardTab, CodeTimer, Convert, Feedback, FeedbackTypes, GGBasicTypes, GGCoreOps, GGEvent, GGFileIn, GGFileOut, GGFont, GGInterfaceTypes, GGModelTypes, GGParseIn, GGParseOut, GGScene, GGSegmentTypes, GGSelect, GGSlice, GGSliceOps, GGState, GGUIUtility, GGUtility, Imager, ImagerColor, ImagerColorPrivate, ImagerTransformation, IO, Real, RefTab, Rope, ViewerClasses; GGFileImpl: CEDAR PROGRAM IMPORTS Atom, CardTab, CodeTimer, Convert, Feedback, GGCoreOps, GGEvent, GGFont, GGParseIn, GGParseOut, GGScene, GGSelect, GGSlice, GGSliceOps, GGState, GGUIUtility, GGUtility, Imager, ImagerColor, ImagerColorPrivate, IO, Real, RefTab, Rope EXPORTS GGFileIn, GGFileOut = BEGIN Camera: TYPE = GGModelTypes.Camera; Caret: TYPE = GGInterfaceTypes.Caret; Color: TYPE = Imager.Color; DefaultData: TYPE = GGModelTypes.DefaultData; MsgRouter: TYPE = FeedbackTypes.MsgRouter; FontData: TYPE = GGModelTypes.FontData; GGData: TYPE = GGInterfaceTypes.GGData; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegmentClass: TYPE = GGSegmentTypes.SegmentClass; Slice: TYPE = GGModelTypes.Slice; SliceClass: TYPE = GGModelTypes.SliceClass; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; StrokeEnd: TYPE = Imager.StrokeEnd; StrokeJoint: TYPE = Imager.StrokeJoint; Traj: TYPE = GGModelTypes.Traj; Viewer: TYPE = ViewerClasses.Viewer; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = Feedback.Problem; OutputPixelArrayTable: TYPE = REF OutputPixelArrayTableObj; OutputPixelArrayTableObj: TYPE = RECORD [ nextIndex: NAT _ 0, table: RefTab.Ref _ NIL -- a mapping from pixel arrays to small integers ]; OutputColorTable: TYPE = REF OutputColorTableObj; OutputColorTableObj: TYPE = RECORD [ pixelArrayTable: OutputPixelArrayTable, nextColorIndex: NAT _ 0, constantOp: CardTab.Ref, -- keys off the intensity constantSpecial: RefTab.Ref, -- keys off the REF sampled: RefTab.Ref -- keys off the REF, used for sampled colors and sampled blacks ]; InputPixelArrayTable: TYPE = REF InputPixelArrayTableObj; InputPixelArrayTableObj: TYPE = RECORD [ table: CardTab.Ref _ NIL -- a mapping from small integers to pixel arrays ]; InputColorTable: TYPE = REF InputColorTableObj; InputColorTableObj: TYPE = RECORD [ pixelArrayTable: InputPixelArrayTable, colors: CardTab.Ref _ NIL -- a mapping from small integers to colors ]; CreateOutputColorTable: PROC [] RETURNS [ct: OutputColorTable] = { ct _ NEW[OutputColorTableObj]; ct.pixelArrayTable _ NEW[OutputPixelArrayTableObj]; ct.pixelArrayTable.table _ RefTab.Create[mod: 17]; ct.constantOp _ CardTab.Create[mod: 17]; ct.constantSpecial _ RefTab.Create[mod: 11]; ct.sampled _ RefTab.Create[mod: 5]; }; NatRef: TYPE = REF NAT; PickANumber: PROC [ct: OutputColorTable] RETURNS [natRef: NatRef] = { natRef _ NEW[NAT _ ct.nextColorIndex]; ct.nextColorIndex _ ct.nextColorIndex + 1; }; FindColorInIntensityTable: PROC [op: ImagerColor.OpConstantColor, table: CardTab.Ref] RETURNS [found: BOOL _ FALSE, nat: NAT _ 0] = { intensity: REAL _ ImagerColorPrivate.IntensityFromColor[op]; key: CARD _ Real.Floor[intensity*32767]; }; AddColorToOutputTable: PROC [color: Imager.Color, ct: OutputColorTable] = { gray: ImagerColor.OpConstantColor _ ImagerColor.ColorFromGray[1]; IF color=NIL THEN { } ELSE { WITH color SELECT FROM op: ImagerColor.OpConstantColor => { IF gray.colorOperator=op.colorOperator THEN { -- "MakeGray" } ELSE { --put out an RGB r, g, b: REAL; [r,g,b] _ GGCoreOps.ExtractRGB[op]; }; }; special: ImagerColor.SpecialColor => { }; sampledBlack: ImagerColor.SampledBlack => { }; sampledColor: ImagerColor.SampledColor => { }; ENDCASE => ERROR; -- Gargoyle doesn't know about this type of color }; }; FileinSceneAndOptions: PUBLIC PROC [f: IO.STREAM, ggData: GGData, alignmentsOnly: BOOL, selectSlices: BOOL] RETURNS [success: BOOL _ FALSE, sceneName: Rope.ROPE] = { ENABLE GGParseIn.SyntaxError => { Feedback.PutF[ggData.router, oneLiner, $Error, "position: %g, wasThere: %g, notThere: %g", [integer[position]], [rope[wasThere]], [rope[notThere]] ]; GOTO Abort; }; scene: Scene _ ggData.scene; version: REAL; count: NAT; entity: Slice; finger, newEntities: LIST OF Slice; [sceneName, version] _ ReadHeaderAndOptions[f, ggData, alignmentsOnly]; GGParseIn.ReadWRope[f, "Entities:"]; GGParseIn.ReadWRope[f, "["]; count _ GGParseIn.ReadWNAT[f]; GGParseIn.ReadWRope[f, "]:"]; GGParseIn.ReadWhiteSpace[f]; [newEntities, finger] _ GGUtility.StartSliceList[]; FOR i: NAT IN[1..count] DO entity _ FileinEntity[f, version, ggData.router, ggData.camera]; IF entity#NIL THEN [newEntities, finger] _ GGUtility.AddSlice[entity, newEntities, finger]; IF ggData.aborted[filein] THEN { ggData.aborted[filein] _ FALSE; GGUIUtility.SafeClose[f, ggData.router]; RETURN[FALSE, NIL]; -- signals a failed read }; ENDLOOP; GGUIUtility.SafeClose[f, ggData.router]; GGSelect.DeselectAll[scene, normal]; GGScene.AddSlices[scene, newEntities]; IF selectSlices THEN FOR sliceList: LIST OF Slice _ newEntities, sliceList.rest UNTIL sliceList=NIL DO GGSelect.SelectEntireSlice[sliceList.first, scene, normal]; ENDLOOP; RETURN[TRUE, sceneName]; EXITS Abort => {}; -- RETURN[FALSE, NIL]; }; FileinSceneOnly: PUBLIC PROC [f: IO.STREAM, scene: Scene, selectSlices: BOOL, camera: Camera] RETURNS [success: BOOL _ FALSE, sceneName: Rope.ROPE] = { ENABLE GGParseIn.SyntaxError => { Feedback.PutFByName[$Gargoyle, oneLiner, $Error, "position: %g, wasThere: %g, notThere: %g", [integer[position]], [rope[wasThere]], [rope[notThere]] ]; GOTO Abort; }; version: REAL; count: NAT; entity: Slice; finger, newEntities: LIST OF Slice; GGParseIn.ReadWRope[f, "Gargoyle file for scene: "]; sceneName _ GGParseIn.ReadLine[f]; GGParseIn.ReadWRope[f, "Produced by version"]; version _ GGParseIn.ReadWReal[f]; version _ Real.Round[version*100.0]/100.0; -- compensate for fuzzy ReadWReal of version IF version >= 8607.17 THEN SkipOptions[f]; GGParseIn.ReadWRope[f, "Entities:"]; GGParseIn.ReadWRope[f, "["]; count _ GGParseIn.ReadWNAT[f]; GGParseIn.ReadWRope[f, "]:"]; GGParseIn.ReadWhiteSpace[f]; [newEntities, finger] _ GGUtility.StartSliceList[]; FOR i: NAT IN[1..count] DO entity _ FileinEntity[f, version, NIL, camera]; IF entity#NIL THEN [newEntities, finger] _ GGUtility.AddSlice[entity, newEntities, finger]; ENDLOOP; GGSelect.DeselectAll[scene, normal]; GGScene.AddSlices[scene, newEntities]; IF selectSlices THEN FOR sliceList: LIST OF Slice _ newEntities, sliceList.rest UNTIL sliceList=NIL DO GGSelect.SelectEntireSlice[sliceList.first, scene, normal]; ENDLOOP; RETURN[TRUE, sceneName]; EXITS Abort => {}; -- RETURN[FALSE, NIL]; }; FileinOptionsOnly: PUBLIC PROC [f: IO.STREAM, ggData: GGData, alignmentsOnly: BOOL] RETURNS [success: BOOL _ FALSE, sceneName: Rope.ROPE] = { ENABLE GGParseIn.SyntaxError => { Feedback.PutF[ggData.router, oneLiner, $Error, "position: %g, wasThere: %g, notThere: %g", [integer[position]], [rope[wasThere]], [rope[notThere]] ]; GOTO Abort; }; version: REAL; [sceneName, version] _ ReadHeaderAndOptions[f, ggData, alignmentsOnly]; GGUIUtility.SafeClose[f, ggData.router]; RETURN[TRUE, sceneName]; EXITS Abort => {}; -- RETURN[FALSE, NIL]; }; ReadHeaderAndOptions: PROC [f: IO.STREAM, ggData: GGData, alignmentsOnly: BOOL] RETURNS [sceneName: Rope.ROPE, version: REAL] = { GGParseIn.ReadWRope[f, "Gargoyle file for scene: "]; sceneName _ GGParseIn.ReadLine[f]; GGParseIn.ReadWRope[f, "Produced by version"]; version _ GGParseIn.ReadWReal[f]; version _ Real.Round[version*100.0]/100.0; -- compensate for fuzzy ReadWReal of version CodeTimer.StartInt[$ReadOptions, $Gargoyle]; IF version >= 8607.17 THEN ReadOptions[f, version, ggData, alignmentsOnly] ELSE GGEvent.StandardAlignments[ggData, LIST[NIL]]; CodeTimer.StopInt[$ReadOptions, $Gargoyle]; }; ReadOptions: PROC [f: IO.STREAM, version: REAL, ggData: GGData, alignmentsOnly: BOOL _ FALSE] = { keyWord, option: Rope.ROPE; good: BOOL; nextChar: CHAR; twoCRsFound: BOOL _ FALSE; GGState.SetPalette[ggData, FALSE]; UNTIL twoCRsFound DO [keyWord, good] _ GGParseIn.ReadKeyWord[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; good _ GGParseIn.ReadHorizontalBlank[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; option _ GGParseIn.ReadLine[f]; ProcessOption[keyWord, option, version, ggData, alignmentsOnly]; nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; ENDLOOP; }; ReadListOfAtom: PUBLIC PROC [f: IO.STREAM] RETURNS [atomList: LIST OF ATOM] = { cr: Rope.ROPE = Rope.FromChar[IO.CR]; lf: Rope.ROPE = Rope.FromChar[IO.LF]; rightParen: Rope.ROPE = Rope.FromChar[')]; rightBracket: Rope.ROPE = Rope.FromChar[']]; AtomsOnOneLineOrParenProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = { SELECT char FROM IO.LF, IO.CR, '), '] =>RETURN [break]; IO.SP, IO.TAB, ', , '; => RETURN [sepr]; ENDCASE => RETURN [other]; }; rope: Rope.ROPE; end: BOOL _ FALSE; [] _ IO.SkipWhitespace[f, TRUE]; atomList _ NIL; WHILE TRUE DO [rope, ----] _ IO.GetTokenRope[f, AtomsOnOneLineOrParenProc !IO.EndOfStream => {end _ TRUE; CONTINUE}]; IF end OR rope = NIL THEN RETURN; IF Rope.Equal[rope, cr] OR Rope.Equal[rope, lf] THEN RETURN; IF Rope.Equal[rope, rightParen] THEN { f.Backup[')]; RETURN; }; IF Rope.Equal[rope, rightBracket] THEN { f.Backup[']]; RETURN; }; atomList _ AppendAtomToAtomList[Atom.MakeAtom[rope], atomList]; ENDLOOP; }; AppendAtomToAtomList: PROC [atom: ATOM, list: LIST OF ATOM] RETURNS [LIST OF ATOM] = { z: LIST OF ATOM _ list; IF z = NIL THEN RETURN[CONS[atom,NIL]]; UNTIL z.rest = NIL DO z _ z.rest; ENDLOOP; z.rest _ CONS[atom,NIL]; RETURN[list]; }; ProcessOption: PROC [keyWord, option: Rope.ROPE, version: REAL, ggData: GGData, alignmentsOnly: BOOL _ FALSE] = { optionStream: IO.STREAM _ IO.RIS[option]; optionList: LIST OF Rope.ROPE; value: REAL; SELECT TRUE FROM Rope.Equal[keyWord, "PaletteForFillColor", FALSE] => { active: BOOL _ GGParseIn.ReadBool[optionStream, version].truth; IF active THEN GGState.SetPalette[ggData, TRUE]; RETURN; }; Rope.Equal[keyWord, "PaletteForStrokeColor", FALSE] => { active: BOOL _ GGParseIn.ReadBool[optionStream, version].truth; IF active THEN GGState.SetPalette[ggData, TRUE]; RETURN; }; Rope.Equal[keyWord, "Palette", FALSE] => { active: BOOL _ GGParseIn.ReadBool[optionStream, version].truth; IF active THEN GGState.SetPalette[ggData, TRUE]; RETURN; }; Rope.Equal[keyWord, "Scripts", FALSE] => { names: LIST OF Rope.ROPE _ GGParseIn.ReadListOfRope[optionStream]; ggData.debug.autoScriptNames _ GGCoreOps.NewRopeListt[]; FOR list: LIST OF Rope.ROPE _ names, list.rest UNTIL list = NIL DO GGCoreOps.AppendRope[list.first, ggData.debug.autoScriptNames]; ENDLOOP; RETURN; }; Rope.Equal[keyWord, "Slope", FALSE] => { IF version>=8706.16 THEN { -- slope values and ON states values: LIST OF REAL; on: LIST OF BOOL; [----, values, on] _ GGParseIn.ReadScalarButtonValues[optionStream, version]; GGState.AddSlopeList[ggData, values, on]; } ELSE { -- slope values only values, ptr: LIST OF REAL; optionList _ GGParseIn.ReadListOfRope[optionStream]; [values, ptr] _ GGCoreOps.StartRealList[]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; [values, ptr] _ GGCoreOps.AddReal[value, values, ptr]; ENDLOOP; GGState.AddSlopeList[ggData, values, NIL]; }; RETURN; }; Rope.Equal[keyWord, "Angle", FALSE] => { IF version>=8706.16 THEN { -- angle values and ON states values: LIST OF REAL; on: LIST OF BOOL; [----, values, on] _ GGParseIn.ReadScalarButtonValues[optionStream, version]; GGState.AddAngleList[ggData, values, on]; } ELSE { -- angle values only values, ptr: LIST OF REAL; optionList _ GGParseIn.ReadListOfRope[optionStream]; [values, ptr] _ GGCoreOps.StartRealList[]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; [values, ptr] _ GGCoreOps.AddReal[value, values, ptr]; ENDLOOP; GGState.AddAngleList[ggData, values, NIL]; }; RETURN; }; Rope.Equal[keyWord, "Radius", FALSE] => { IF version>=8706.16 THEN { -- radius values and ON states values: LIST OF REAL; on: LIST OF BOOL; names: LIST OF Rope.ROPE; [names, values, on] _ GGParseIn.ReadScalarButtonValues[optionStream, version]; GGState.AddRadiusList[ggData, names, values, on]; } ELSE { -- radius values only values, ptr: LIST OF REAL; optionList _ GGParseIn.ReadListOfRope[optionStream]; [values, ptr] _ GGCoreOps.StartRealList[]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; [values, ptr] _ GGCoreOps.AddReal[value, values, ptr]; ENDLOOP; GGState.AddRadiusList[ggData, NIL, values, NIL]; }; RETURN; }; Rope.Equal[keyWord, "LineDistance", FALSE] => { IF version>=8706.16 THEN { -- LineDistance values and ON states values: LIST OF REAL; on: LIST OF BOOL; names: LIST OF Rope.ROPE; [names, values, on] _ GGParseIn.ReadScalarButtonValues[optionStream, version]; GGState.AddLineDistanceList[ggData, names, values, on]; } ELSE { -- LineDistance values only values, ptr: LIST OF REAL; optionList _ GGParseIn.ReadListOfRope[optionStream]; [values, ptr] _ GGCoreOps.StartRealList[]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; [values, ptr] _ GGCoreOps.AddReal[value, values, ptr]; ENDLOOP; GGState.AddLineDistanceList[ggData, NIL, values, NIL]; }; RETURN; }; Rope.Equal[keyWord, "Anchor", FALSE] => { anchored, good: BOOL; [anchored, good] _ GGParseIn.ReadBool[optionStream, version]; IF anchored AND good THEN { point: Point _ GGParseIn.ReadPoint[optionStream]; ggData.anchor^ _ [exists: TRUE, point: point, chair: NIL, attractor: NIL]; } ELSE ggData.anchor.exists _ FALSE; RETURN; }; ENDCASE; IF NOT alignmentsOnly THEN SELECT TRUE FROM Rope.Equal[keyWord, "Midpoints", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBool[optionStream, version]; GGState.SetMidpoints[ggData, on AND good]; }; Rope.Equal[keyWord, "Heuristics", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBool[optionStream, version]; GGState.SetHeuristics[ggData, on AND good]; }; Rope.Equal[keyWord, "ShowAlignments", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBool[optionStream, version]; GGState.SetShowAlignments[ggData, on AND good]; }; Rope.Equal[keyWord, "ShowColors", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBool[optionStream, version]; }; Rope.Equal[keyWord, "Gravity", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBool[optionStream, version]; GGState.SetGravity[ggData, on AND good]; }; Rope.Equal[keyWord, "ScaleUnit", FALSE] => { real: REAL _ GGParseIn.ReadWReal[optionStream]; IF real>0.0 THEN GGState.SetScaleUnit[ggData, real, NIL]; }; Rope.Equal[keyWord, "DisplayStyle", FALSE] => { rope: Rope.ROPE _ GGParseIn.ReadWWord[optionStream]; GGState.SetDisplayStyle[ggData, GGUIUtility.DisplayStyleFromRope[rope]]; }; Rope.Equal[keyWord, "GravityExtent", FALSE] => { real: REAL _ GGParseIn.ReadWReal[optionStream]; GGState.SetGravityExtent[ggData, real]; }; Rope.Equal[keyWord, "GravityType", FALSE] => { rope: Rope.ROPE _ GGParseIn.ReadWWord[optionStream]; GGState.SetGravityType[ggData, GGUIUtility.GravityTypeFromRope[rope]]; }; Rope.Equal[keyWord, "DefaultFont", FALSE] => { fontData: FontData; fontData _ GGFont.ParseFontData[data: NIL, inStream: optionStream, literalP: TRUE, transformP: TRUE, storedSizeP: TRUE, designSizeP: TRUE ! GGFont.ParseError => CONTINUE;]; fontData.substituteOK _ TRUE; -- bad hack here. Avoids a bogus default font GGState.SetDefaultFont[ggData, fontData]; }; Rope.Equal[keyWord, "Defaults", FALSE] => { strokeJoint, strokeEnd: Rope.ROPE; ggData.defaults.fillColor _ GGParseIn.ReadColor[optionStream, version]; ggData.defaults.strokeColor _ GGParseIn.ReadColor[optionStream, version]; ggData.defaults.strokeWidth _ GGParseIn.ReadWReal[optionStream]; strokeJoint _ GGParseIn.ReadWWord[optionStream]; ggData.defaults.strokeJoint _ SELECT TRUE FROM Rope.Equal[strokeJoint, "miter", FALSE] => miter, Rope.Equal[strokeJoint, "bevel", FALSE] => bevel, ENDCASE => round; strokeEnd _ GGParseIn.ReadWWord[optionStream]; ggData.defaults.strokeEnd _ SELECT TRUE FROM Rope.Equal[strokeEnd, "square", FALSE] => square, Rope.Equal[strokeEnd, "butt", FALSE] => butt, ENDCASE => round; }; Rope.Equal[keyWord, "Dashed", FALSE] => { dashed, good: BOOL; [dashed, good] _ GGParseIn.ReadBool[optionStream, version]; ggData.defaults.dashed _ dashed AND good; IF ggData.defaults.dashed THEN { ggData.defaults.pattern _ GGParseIn.ReadArrayOfReal[optionStream]; ggData.defaults.offset _ GGParseIn.ReadWReal[optionStream]; ggData.defaults.length _ GGParseIn.ReadWReal[optionStream]; }; }; Rope.Equal[keyWord, "Shadows", FALSE] => { shadowed, good: BOOL; ggData.defaults.textColor _ GGParseIn.ReadColor[optionStream, version]; IF ggData.defaults.textColor=NIL THEN ggData.defaults.textColor _ Imager.black; [shadowed, good] _ GGParseIn.ReadBool[optionStream, version]; ggData.defaults.dropShadowOn _ shadowed AND good; IF ggData.defaults.dropShadowOn THEN { ggData.defaults.dropShadowOffset _ GGParseIn.ReadPoint[optionStream]; ggData.defaults.dropShadowColor _ GGParseIn.ReadColor[optionStream, version]; }; }; Rope.Equal[keyWord, "Active", FALSE] => { -- Active is not yet stored active, good: BOOL; [active, good] _ GGParseIn.ReadBool[optionStream, version]; GGState.SetActive[ggData, active AND good]; }; ENDCASE => SIGNAL Problem[msg: Rope.Concat["Unknown keyword in gargoyle file: ", keyWord]]; }; -- end ProcessOption SkipOptions: PROC [f: IO.STREAM] = { keyWord, option: Rope.ROPE; good: BOOL; nextChar: CHAR; twoCRsFound: BOOL _ FALSE; UNTIL twoCRsFound DO [keyWord, good] _ GGParseIn.ReadKeyWord[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; good _ GGParseIn.ReadHorizontalBlank[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; option _ GGParseIn.ReadLine[f]; nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; ENDLOOP; }; FileinEntity: PROC [f: IO.STREAM, version: REAL, router: MsgRouter, camera: Camera] RETURNS [entity: Slice] = { nextWord: Rope.ROPE; IF version > 8605.22 THEN { IF version >= 8705.14 THEN { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; } ELSE { nextWord _ GGParseIn.ReadWWord[f]; SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: SliceClass _ GGSlice.FetchSliceClass[$Outline]; entity _ class.filein[f, version, router, camera]; }; Rope.Equal[nextWord, "Slice"] => { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; }; ENDCASE => ERROR } } ELSE { nextWord _ GGParseIn.ReadWWord[f]; SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: SliceClass _ GGSlice.FetchSliceClass[$Outline]; entity _ class.filein[f, version, router, camera]; }; Rope.Equal[nextWord, "Cluster"] => { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; }; ENDCASE => ERROR; }; }; FileoutSceneAndOptions: PUBLIC PROC [f: IO.STREAM, ggData: GGData, fileName: Rope.ROPE, scene: Scene _ NIL] = { sceneOut: Scene _ IF scene#NIL THEN scene ELSE ggData.scene; sliceCount: NAT _ GGScene.CountSlices[sceneOut, first]; DoFileOut: PROC [slice: Slice] RETURNS [done: BOOL _ FALSE] = { f.PutChar[IO.CR]; -- CR before each top-Level slice GGSliceOps.FileoutSlice[f, slice]; }; f.PutF["Gargoyle file for scene: %g\n", [rope[fileName]]]; f.PutF["Produced by version %g\n\n", [rope[GGUtility.versionRope]]]; FileoutOptions[f, ggData]; f.PutF["Entities: [%g]:\n\n", [integer[sliceCount]]]; [] _ GGScene.WalkSlices[sceneOut, first, DoFileOut]; }; FileoutSceneOnly: PUBLIC PROC [f: IO.STREAM, scene: Scene, fileName: Rope.ROPE] = { sliceCount: NAT _ GGScene.CountSlices[scene, first]; DoFileOut: PROC [slice: Slice] RETURNS [done: BOOL _ FALSE] = { f.PutChar[IO.CR]; GGSliceOps.FileoutSlice[f, slice]; }; f.PutF["Gargoyle file for scene: %g\n", [rope[fileName]]]; f.PutF["Produced by version %g\n\n", [rope[GGUtility.versionRope]]]; f.PutChar[IO.CR]; f.PutChar[IO.CR]; f.PutF["Entities: [%g]:\n\n", [integer[sliceCount]]]; [] _ GGScene.WalkSlices[scene, first, DoFileOut]; }; FileoutOptions: PROC [f: IO.STREAM, ggData: GGData] = { values: LIST OF REAL; on: LIST OF BOOL; names: LIST OF Rope.ROPE; defaults: DefaultData; anchor: Caret; f.PutF["Scripts: "]; GGParseOut.WriteListOfRope[f, ggData.debug.autoScriptNames.list]; f.PutChar[IO.CR]; f.PutF["Slope: "]; [values, on] _ GGState.GetSlopeAlignments[ggData]; GGParseOut.WriteScalarButtonValues[f, NIL, values, on]; f.PutChar[IO.CR]; f.PutF["Angle: "]; [values, on] _ GGState.GetAngleAlignments[ggData]; GGParseOut.WriteScalarButtonValues[f, NIL, values, on]; f.PutChar[IO.CR]; f.PutF["Radius: "]; [names, values, on] _ GGState.GetRadiusAlignments[ggData]; GGParseOut.WriteScalarButtonValues[f, names, values, on]; f.PutChar[IO.CR]; f.PutF["LineDistance: "]; [names, values, on] _ GGState.GetLineDistanceAlignments[ggData]; GGParseOut.WriteScalarButtonValues[f, names, values, on]; f.PutF["\nMidpoints: "]; GGParseOut.WriteBool[f, GGState.GetMidpoints[ggData]]; f.PutF["\nHeuristics: "]; GGParseOut.WriteBool[f, GGState.GetHeuristics[ggData]]; f.PutF["\nShowAlignments: "]; GGParseOut.WriteBool[f, GGState.GetShowAlignments[ggData]]; f.PutF["\nScaleUnit: %g", [real[GGState.GetScaleUnit[ggData]]] ]; f.PutF["\nDisplayStyle: %g", [rope[GGUIUtility.DisplayStyleToRope[GGState.GetDisplayStyle[ggData]] ]] ]; f.PutF["\nGravity: "]; GGParseOut.WriteBool[f, GGState.GetGravity[ggData]]; f.PutF["\nGravityExtent: %g", [real[GGState.GetGravityExtent[ggData]]] ]; f.PutF["\nGravityType: %g", [rope[GGUIUtility.GravityTypeToRope[GGState.GetGravityType[ggData]] ]] ]; defaults _ GGState.GetDefaults[ggData]; f.PutF["\nDefaultFont: %g ", [rope[defaults.font.literal]] ]; GGParseOut.WriteFactoredTransformationVEC[f, defaults.font.transform]; f.PutF[" %g %g", [real[defaults.font.storedSize]], [real[defaults.font.designSize]] ]; f.PutF["\nDefaults: "]; GGParseOut.WriteColor[f, defaults.fillColor]; f.PutChar[' ]; -- put a SPACE GGParseOut.WriteColor[f, defaults.strokeColor]; f.PutF[" %g", [real[defaults.strokeWidth]] ]; f.PutF[" %g", [rope[SELECT defaults.strokeJoint FROM bevel => "bevel", miter => "miter", ENDCASE => "round" ]] ]; f.PutF[" %g", [rope[SELECT defaults.strokeEnd FROM square => "square", butt => "butt", ENDCASE => "round" ]] ]; f.PutF["\nDashed: "]; GGParseOut.WriteBool[f, defaults.dashed]; IF defaults.dashed THEN { f.PutChar[' ]; -- put a SPACE GGParseOut.WriteArrayOfReal[f, defaults.pattern]; f.PutF[" %g %g", [real[defaults.offset]], [real[defaults.length]] ]; }; f.PutChar[' ]; -- put a SPACE f.PutF["\nShadows: "]; GGParseOut.WriteColor[f, defaults.textColor]; GGParseOut.WriteBool[f, defaults.dropShadowOn]; IF defaults.dropShadowOn THEN { f.PutChar[' ]; -- put a SPACE GGParseOut.WritePoint[f, defaults.dropShadowOffset]; GGParseOut.WriteColor[f, defaults.dropShadowColor]; }; anchor _ GGState.GetAnchor[ggData]; f.PutF["\nAnchor: "]; GGParseOut.WriteBool[f, IF anchor=NIL THEN FALSE ELSE anchor.exists]; IF anchor.exists THEN { f.PutChar[' ]; -- put a SPACE GGParseOut.WritePoint[f, anchor.point]; }; f.PutF["\nPalette: "]; GGParseOut.WriteBool[f, GGState.GetPalette[ggData]]; f.PutChar[IO.CR]; f.PutChar[IO.CR]; }; IsEndLine: PROC [c: CHAR] RETURNS [BOOL] = { RETURN[c=IO.CR OR c=IO.LF]; }; END. (File: GGFileImpl.mesa Copyright Σ 1987, 1989 by Xerox Corporation. All rights reserved. Pier, April 23, 1992 4:51 pm PDT Kurlander, September 1, 1987 1:47:01 pm PDT Bier, March 18, 1992 6:25 pm PST Doug Wyatt, December 15, 1989 8:35:22 pm PST Contents: Created October 12, 1987 by merging GGFileInImpl and GGFileOutImpl Treat as a special color. f.PutF[" %g]", [rope[special.name]]]; Filing in Loads any objects in f into ggData scene. Merges any alignment line types in f into the viewer represented by ggData. Changes other control panel state variables to options found in f if NOT alignmentsOnly. Read in the scene entities Ignores the control panel state variables options in f. Merges any objects in f into scene. Read in the Header Read in the alignment objects, etc. Read the scene entities GGUIUtility.SafeClose[f]; Merges any alignment line types in f into the viewer represented by ggData. Changes other control panel state variables to options found in f if NOT alignmentsOnly. Read in the Header Read in the options. Initialize Some Options Read in the Options that are Mentioned A copy of List.Nconc1 for LIST OF Rope.ROPE instead of LIST OF REF ANY Rope.Equal[keyWord, "Behaviors", FALSE] => { behaviors: LIST OF ATOM _ ReadListOfAtom[optionStream]; FOR list: LIST OF ATOM _ behaviors, list.rest UNTIL list = NIL DO IF list.first = $PaletteForFillColor THEN GGState.SetPaletteForFillColor[ggData, TRUE] ELSE IF list.first = $PaletteForStrokeColor THEN GGState.SetPaletteForStrokeColor[ggData, TRUE]; ENDLOOP; RETURN; }; GGState.SetShowColors[ggData, on AND good]; fixes NIL text color defaults in many older files. Added by Pier, July 17, 1991 ProcessOption[keyWord, option, ggData]; Filing out f.PutF["\nPaletteForFillColor: "]; GGParseOut.WriteBool[f, GGState.GetPaletteForFillColor[ggData]]; f.PutF["\nPaletteForStrokeColor: "]; GGParseOut.WriteBool[f, GGState.GetPaletteForStrokeColor[ggData]]; InitStats: PROC [] = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$ReadOptions]; CodeTimer.AddInt[interval, $Gargoyle]; }; InitStats[]; Κ– "cedar" style•NewlineDelimiter ˜Iprocšœ™codešœB™BLšœ ™ L™+Lšœ ™ L™,—L™šΟbœD™LL™—šΟk ˜ JšœΚžœ$˜π—K˜šΟn œžœž˜JšžœΣžœ˜πKšžœž˜#—˜Kšœžœ˜#Kšœžœ˜%Kšœžœ˜Kšœ žœ˜-Jšœ žœ˜*Kšœ žœ˜'Kšœžœ˜'Kšœžœ˜!Kšœžœ˜!Kšœ žœ˜'Kšœžœ˜1Kšœžœ˜!Kšœ žœ˜+Kšœžœ˜3Kšœ žœ˜#Kšœ žœ˜'Kšœžœ˜Kšœžœ˜$K˜—KšŸœžœžœ žœ˜;K˜Kšœžœžœ˜;šœ!žœ˜)Lšœ žœ˜LšœžœΟc0˜HL˜L˜—Kšœžœžœ˜1šœžœžœ˜$Lšœ& ˜'Lšœžœ˜Lšœ ˜2Lšœ ˜0Lšœ ?˜SL˜L˜—Kšœžœžœ˜9šœžœžœ˜(Lšœžœ 0˜IL˜L˜—Kšœžœžœ˜/šœžœžœ˜#Lšœ% ˜&Lšœžœ *˜DL˜—L˜L˜šŸœžœžœ˜BKšœžœ˜Kšœžœ˜3K•StartOfExpansionE[mod: NAT _ 17, equal: RefTab.EqualProc, hash: RefTab.HashProc]šœ2˜2Kšœ(˜(Kšœ,˜,Kšœ#˜#K˜K˜—Kšœžœžœžœ˜šŸ œžœžœ˜EKšœ žœžœ˜&Kšœ*˜*Kšœ˜K˜—š Ÿœžœ7žœ žœžœžœ ˜…Kšœ žœ-˜