DIRECTORY BasicTime, CedarProcess, Commander, CommanderOps, Controls, Cursors, FS, FileNames, G2dBasic, G3dBasic, G3dControl, G3dLight, G3dMatrix, G3dRender, G3dTimeTrees, G3dTool, G3dView, Icons, ImagerSample, IO, Process, ProcessProps, RawViewers, Real, Rope, TEditSelection, TiogaMenuOps, UnixSpawnTCP, ViewerClasses, ViewerOps, ViewerSpecs, ViewersWorldInstance; G3dToolViewerImpl: CEDAR PROGRAM IMPORTS BasicTime, CedarProcess, CommanderOps, Controls, Cursors, FileNames, FS, G3dControl, G3dLight, G3dMatrix, G3dRender, G3dTool, G3dView, Icons, ImagerSample, IO, Process, ProcessProps, RawViewers, Rope, TEditSelection, TiogaMenuOps, UnixSpawnTCP, ViewerOps, ViewerSpecs, ViewersWorldInstance EXPORTS G3dTool ~ BEGIN ForkableProc: TYPE ~ CedarProcess.ForkableProc; ButtonList: TYPE ~ Controls.ButtonList; ClickProc: TYPE ~ Controls.ClickProc; ControlList: TYPE ~ Controls.ControlList; ControlProc: TYPE ~ Controls.ControlProc; ControlSizes: TYPE ~ Controls.ControlSizes; DestroyProc: TYPE ~ Controls.DestroyProc; GraphicsData: TYPE ~ Controls.GraphicsData; MouseProc: TYPE ~ Controls.MouseProc; Viewer: TYPE ~ Controls.Viewer; Box2d: TYPE ~ G2dBasic.Box; Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; CameraControl: TYPE ~ G3dControl.CameraControl; Matrix: TYPE ~ G3dMatrix.Matrix; Viewport: TYPE ~ G3dMatrix.Viewport; Context3d: TYPE ~ G3dRender.Context3d; Client: TYPE ~ G3dTool.Client; NamedBuffer: TYPE ~ G3dTool.NamedBuffer; Operations: TYPE ~ G3dTool.Operations; ScreenSequence: TYPE ~ G3dTool.ScreenSequence; Tool: TYPE ~ G3dTool.Tool; ToolRep: TYPE ~ G3dTool.ToolRep; View: TYPE ~ G3dTool.View; ViewProc: TYPE ~ G3dTool.ViewProc; ViewRep: TYPE ~ G3dTool.ViewRep; ViewSequence: TYPE ~ G3dTool.ViewSequence; TTNode: TYPE ~ G3dTimeTrees.Node; Camera: TYPE ~ G3dView.Camera; CameraRep: TYPE ~ G3dView.CameraRep; SampleMap: TYPE ~ ImagerSample.SampleMap; ROPE: TYPE ~ Rope.ROPE; IconFlavor: TYPE ~ ViewerClasses.IconFlavor; defaultIcon: IconFlavor ¬ Icons.NewIconFromFile["G3dUser.icons", 0]; MakeTool: PUBLIC PROC [ name: ROPE, extraButtons: ButtonList ¬ NIL, extraControls: ControlList ¬ NIL, controlSizes: ControlSizes ¬ [], ops: Operations ¬ [], client: Client ¬ [], nViews: NAT ¬ 1, noOpen: BOOL ¬ FALSE, useArcBalls: BOOL ¬ TRUE, arcBallSize: INTEGER ¬ 136, graphicsHeight: INTEGER ¬ 475, icon: IconFlavor ¬ document, useExistingTool: BOOL ¬ FALSE, camera: CameraRep ¬ [[0.0, 2.0, 0.0], [], 1.0, 60.0], background: Triple ¬ [1.0, 1.0, 1.0], typescriptHeight: INT ¬ 36, toolSettings: ToolRep ¬ []] RETURNS [t: Tool] ~ { IF useExistingTool AND activeTool # NIL THEN { t ¬ NEW[ToolRep ¬ activeTool^]; t.outerData ¬ Controls.OuterViewer[name: name, column: left, buttons: extraButtons, controls: extraControls, controlSizes: controlSizes, destroyProc: OuterDestroy, icon: icon]; IF client # [] THEN { activeClients ¬ CONS[client, activeClients]; ViewerOps.AddProp[t.outerData.parent, $ToolClient, NEW[Client ¬ client]]; }; IF NOT noOpen THEN ViewerOps.OpenIcon[t.outerData.parent]; } ELSE { Enumerate: ViewerOps.EnumProc ~ {ViewerOps.PaintViewer[v, caption]}; NewButton: PROC [name: ROPE, proc: ClickProc, guarded: BOOL ¬ FALSE] ~ { t.buttons ¬ CONS[Controls.ClickButton[name, proc, t, 0,,,,,, guarded], t.buttons]; }; RawViewers.SetColorWorld[ViewersWorldInstance.GetWorld[], $dense]; ViewerOps.EnumerateViewers[Enumerate]; -- fix up caption and icon colors SetActiveTool[t ¬ NEW[ToolRep ¬ toolSettings]]; IF t.ipStrokeWidth = 2.0 THEN t.ipStrokeWidth ¬ 1.0; -- better default t.activeViews ¬ LIST[0]; t.ops ¬ ops; t.client ¬ client; IF t.cmd = NIL THEN t.cmd ¬ NARROW[ProcessProps.GetProp[$CommanderHandle], Commander.Handle]; IF NOT Rope.IsEmpty[name] THEN t.name ¬ name; t.camera ¬ G3dControl.InitCameraControl[ proc: G3dTool.Controller, clientData: t, fieldOfView: camera.fieldOfView, proxyMode: eye, scale: camera.scale, move: camera.move, rotate: camera.rotate]; G3dControl.SetArcBallSize[t.camera.arcBall, arcBallSize]; Context3dOk[t]; t.background ¬ background; t.buttons ¬ extraButtons; IF ops.io THEN NewButton["IO", G3dTool.IOOpsButton]; IF ops.lines THEN NewButton["Draw", G3dTool.DrawOpsButton]; IF ops.light THEN NewButton["Light", G3dTool.LightOpsButton]; IF ops.shape THEN NewButton["Shapes", G3dTool.ShapeOpsButton]; IF ops.render THEN NewButton["Render", G3dTool.RenderOpsButton]; IF ops.stop THEN NewButton["STOP", G3dTool.StopButton, TRUE]; t.controls ¬ G3dControl.AddCameraControl[extraControls, t.camera, useArcBalls]; IF nViews > 0 THEN { t.outerData ¬ Controls.OuterViewer[ name: name, column: left, buttons: t.buttons, controls: t.controls, controlSizes: controlSizes, typescriptHeight: typescriptHeight, graphicsHeight: graphicsHeight, mouseProc: G3dTool.Mouse, destroyProc: Destroy, drawProc: DoDraw, noOpen: TRUE, icon: IF icon # document THEN icon ELSE defaultIcon, clientData: t]; t.outer ¬ t.outerData.parent; t.outer.label ¬ name; t.typescript ¬ t.outerData.typescript; t.graphics ¬ t.outerData.graphics; t.views ¬ MakeViews[t, nViews]; IF NOT noOpen THEN [] ¬ CedarProcess.Fork[OpenViewer, t]; }; }; t.directory ¬ FileNames.CurrentWorkingDirectory[]; }; DoDraw: Controls.DrawProc ~ { t: Tool ¬ NARROW[clientData]; v: G3dTool.View ¬ G3dTool.GetView[viewer, t]; G3dTool.Draw[context, viewer, whatChanged, v.camera.matrix, v.viewport, v, t, t]; }; OpenViewer: ForkableProc ~ { Process.PauseMsec[250]; -- should be plenty ViewerOps.OpenIcon[NARROW[data, Tool].outer]; }; OuterDestroy: Controls.DestroyProc ~ { ref: REF ANY ¬ ViewerOps.FetchProp[viewer, $ToolClient]; IF ref # NIL THEN { client: Client ¬ NARROW[ref, REF Client]^; IF activeClients.first = client THEN activeClients ¬ activeClients.rest ELSE FOR c: LIST OF Client ¬ activeClients, c.rest WHILE c.rest # NIL DO IF c.rest.first = client THEN {c.rest ¬ c.rest.rest; EXIT}; ENDLOOP; }; }; Destroy: Controls.DestroyProc ~ { t: Tool ¬ NARROW[clientData]; IF t = NIL THEN RETURN; IF t.unixSpawn # NIL THEN UnixSpawnTCP.Kill[t.unixSpawn]; IF t.client.destroy # NIL THEN t.client.destroy[viewer, $ToolKilled, t.client.data]; IF t = activeTool THEN { FOR c: LIST OF Client ¬ activeClients, c.rest WHILE c # NIL DO IF c.first.destroy # NIL THEN c.first.destroy[viewer, $ToolKilled, c.first.data]; IF c.first.change # NIL THEN c.first.change[activeTool, NIL, c.first.data]; ENDLOOP; activeTool ¬ NIL; }; IF t.views # NIL THEN FOR i: INTEGER IN [0..t.views.length) DO FOR l: LIST OF G3dTool.NamedBuffer ¬ t.views[i].idBuffer, l.rest WHILE l # NIL DO ImagerSample.ReleaseScratchMap[l.first.map]; ENDLOOP; ENDLOOP; }; Context3dOk: PUBLIC PROC [tool: Tool] ~ { IF tool.context3d = NIL THEN { tool.context3d ¬ G3dRender.Create[]; tool.lights ¬ G3dLight.AddLight[tool.lights, "Light1", [-.2, .2, .3], [.2, -.2, -.3]]; G3dTool.SetRenderView[tool.context3d, tool.camera]; }; }; activeTool, previousTool: Tool; activeClients: LIST OF Client ¬ NIL; SetActiveTool: PUBLIC PROC [tool: Tool] ~ { IF tool = activeTool THEN RETURN; previousTool ¬ activeTool; activeTool ¬ tool; FOR c: LIST OF Client ¬ activeClients, c.rest WHILE c # NIL DO IF c.first.change # NIL THEN c.first.change[previousTool, activeTool, c.first.data]; ENDLOOP; }; GetActiveTool: PUBLIC PROC RETURNS [Tool] ~ {RETURN[activeTool]}; GetActiveClients: PUBLIC PROC RETURNS [LIST OF Client] ~ {RETURN[activeClients]}; ToolBusy: PUBLIC PROC [tool: Tool] RETURNS [BOOL] ~ { RETURN[tool.process # NIL AND CedarProcess.GetStatus[tool.process] = busy]; }; ForceFork: PUBLIC PROC [tool: Tool, proc: ForkableProc] ~ { IF ToolBusy[tool] THEN Stop[tool, NIL, TRUE]; tool.process ¬ CedarProcess.Fork[proc, tool, [background, TRUE]] }; MaybeFork: PUBLIC PROC [tool: Tool, proc: ForkableProc, data: REF ANY ¬ NIL] RETURNS [forked: BOOL] ~ { IF (forked ¬ NOT ToolBusy[tool]) THEN tool.process ¬ CedarProcess.Fork[proc, IF data = NIL THEN tool ELSE data, [background, TRUE]] ELSE TSWrite[tool, "Tool is busy!\n"]; }; Stop: PUBLIC PROC [tool: Tool, reason: ROPE ¬ NIL, waitTilAborted: BOOL ¬ FALSE] ~ { IF tool.unixSpawn # NIL THEN { UnixSpawnTCP.Kill[tool.unixSpawn]; tool.unixSpawn ¬ NIL; }; IF tool.process # NIL AND NOT tool.process.abortRequested THEN { CedarProcess.Abort[tool.process]; IF waitTilAborted THEN [] ¬ CedarProcess.Join[tool.process]; IF tool.client.stop # NIL THEN tool.client.stop[tool.client.data, reason]; }; IF reason # NIL THEN TSWrite[tool, reason]; }; MakeViews: PUBLIC PROC [tool: Tool, nViews: NAT] RETURNS [views: ViewSequence] ~ { g: Viewer ¬ tool.graphics; w: NAT ¬ SELECT g.column FROM left => ViewerSpecs.openLeftWidth, right => ViewerSpecs.openRightWidth, ENDCASE => ViewerSpecs.colorScreenWidth; views ¬ NEW[G3dTool.ViewSequenceRep[nViews]]; ViewerOps.AddProp[g, $Width, NEW[INTEGER ¬ w]]; -- redundant over ControlsOuter ViewerOps.AddProp[g, $Height, NEW[INTEGER ¬ g.ch]]; FOR n: NAT IN [0..nViews) DO MakeViewer: PROC [x, y, w, h: NAT] RETURNS [vwr: Viewer] ~ { data: GraphicsData ¬ NEW[Controls.GraphicsDataRep ¬ NARROW[g.data, GraphicsData]^]; vwr ¬ data.viewer ¬ ViewerOps.CreateViewer[flavor: $Graphics, paint: FALSE, info: [wx: x, wy: y, ww: w, wh: h, data: data, scrollable: FALSE, border: nViews > 1, parent: g]]; ViewerOps.AddProp[vwr, $View, v]; -- property not there on initial opening!? ViewerOps.AddProp[vwr, $CreatedInOuterViewer, $True]; -- avoid Controls.AdjustProc }; v: View ¬ views[n] ¬ NEW[ViewRep]; v.screens ¬ NEW[G3dTool.ShapeScreensRep[10]]; v.tool ¬ tool; v.index ¬ n; IF nViews = 1 THEN v.viewer ¬ MakeViewer[0, 0, w, g.ch] ELSE { miniW: NAT ¬ w/MIN[nViews, 3]; v.viewer ¬ MakeViewer[n*miniW, 0, miniW, g.wh] }; G3dControl.SaveState[tool.camera, v.camera ¬ NEW[CameraRep]]; ENDLOOP; }; DoWithViews: PUBLIC PROC [tool: Tool, action: ViewProc, activeOnly: BOOL ¬ TRUE] ~ { IF tool = NIL THEN RETURN; IF activeOnly THEN FOR l: LIST OF NAT ¬ tool.activeViews, l.rest WHILE l # NIL DO IF NOT action[tool.views[l.first]] THEN EXIT; ENDLOOP ELSE FOR i: NAT IN [0..tool.views.length) DO IF NOT action[tool.views[i]] THEN EXIT; ENDLOOP; }; GetFirstActiveView: PUBLIC PROC [tool: Tool] RETURNS [v: View] ~ { IF tool # NIL AND tool.views # NIL AND tool.activeViews # NIL THEN v ¬ tool.views[tool.activeViews.first]; }; GetView: PUBLIC PROC [viewer: Viewer, tool: Tool ¬ NIL] RETURNS [v: View] ~ { IF viewer # NIL THEN { ref: REF ¬ ViewerOps.FetchProp[viewer, $View]; IF ref # NIL THEN v ¬ NARROW[ref]; }; IF v = NIL AND tool # NIL THEN v ¬ tool.views[tool.activeViews.first]; IF viewer = NIL AND v # NIL THEN viewer ¬ v.viewer; IF v # NIL THEN v.viewport ¬ G3dView.GetViewport[viewer]; }; GetViewTransform: PUBLIC PROC [ viewer: Viewer ¬ NIL, tool: Tool ¬ NIL, out: Matrix ¬ NIL] RETURNS [m: Matrix] ~ { v: View ¬ GetView[viewer, tool]; IF v # NIL THEN m ¬ G3dMatrix.CopyMatrix[v.camera.matrix, out]; }; GetBufferedSampleMap: PUBLIC PROC [view: View, id: ATOM ¬ $Frame] RETURNS [map: SampleMap] ~ { IF view # NIL THEN FOR l: LIST OF NamedBuffer ¬ view.idBuffer, l.rest WHILE l # NIL DO IF l.first.id = id THEN RETURN[l.first.map]; ENDLOOP; }; SetBufferedSampleMap: PUBLIC PROC [map: SampleMap, view: View, id: ATOM ¬ $Frame]~ { nb: NamedBuffer ¬ [id, map]; IF view = NIL THEN RETURN; FOR l: LIST OF NamedBuffer ¬ view.idBuffer, l.rest WHILE l # NIL DO IF l.first.id = id THEN {l.first ¬ nb; RETURN}; ENDLOOP; view.idBuffer ¬ CONS[nb, view.idBuffer]; }; InvalidateViewScreens: PUBLIC PROC [view: View] ~ { IF view # NIL AND view.screens # NIL THEN FOR i: INTEGER IN [0..view.screens.length) DO view.screens[i].screensValid ¬ FALSE; ENDLOOP; }; FinishButton: PUBLIC ClickProc ~ { t: Tool ¬ NARROW[clientData]; IF t.cmd = NIL THEN G3dTool.TSWrite[t, "No command handle!\n"] ELSE { prompt: ROPE ¬ "When done with a forked process, do: "; IF t.command # NIL THEN prompt ¬ Rope.Cat[prompt, "(presently ", t.command, ") "]; t.command ¬ Controls.TypescriptRead[t.typescript, prompt]; }; }; Finish: PUBLIC PROC [tool: Tool, reason: ROPE] ~ { IF tool.client.stop # NIL THEN tool.client.stop[tool.client.data, reason]; IF tool.command # NIL AND tool.cmd # NIL THEN [] ¬ CommanderOps.DoCommand[tool.command, tool.cmd]; }; HelpButton: PUBLIC ClickProc ~ {OpenHelp["A tool for line drawings or shaded images"]}; StopButton: PUBLIC ClickProc ~ {Stop[NARROW[clientData], " . . . aborted\n"]}; doc: ROPE ¬ "Graphics3dDoc.tioga"; docProp: REF ROPE ¬ NEW[ROPE ¬ "Yo!"]; OpenHelp: PUBLIC PROC [key: ROPE] ~ { name: ROPE ¬ doc; vHelp: Viewer; PropProc: ViewerOps.EnumProc ~ { WITH ViewerOps.FetchProp[v, $G3dHelp] SELECT FROM r: REF ROPE => IF r = docProp THEN {vHelp ¬ v; RETURN[FALSE]}; ENDCASE => RETURN[TRUE]; }; name ¬ FileNames.StripVersionNumber[FS.FileInfo[doc ! FS.Error => CONTINUE].fullFName]; vHelp ¬ ViewerOps.FindViewer[name]; IF vHelp = NIL THEN ViewerOps.EnumerateViewers[PropProc]; IF vHelp # NIL THEN {IF vHelp.column # right THEN ViewerOps.ChangeColumn[vHelp, right]} ELSE { vHelp ¬ ViewerOps.CreateViewer[ flavor: $Text, paint: FALSE, info: [iconic: TRUE, column: right, openHeight: 140]]; TiogaMenuOps.Load[viewer: vHelp, fileName: doc]; ViewerOps.AddProp[viewer: vHelp, prop: $G3dHelp, val: docProp]; }; ViewerOps.SetOpenHeight[viewer: vHelp, clientHeight: 140]; ViewerOps.OpenIcon[icon: vHelp, bottom: FALSE, paint: FALSE]; -- must do Open before Top ViewerOps.TopViewer[viewer: vHelp, paint: FALSE]; ViewerOps.ComputeColumn[right]; TEditSelection.FindRope[vHelp, key]; }; SetCursor: PUBLIC PROC [tool: Tool, waiting: BOOL] ~ { IF waiting THEN Cursors.SetCursor[tool.outer.class.cursor ¬ tool.graphics.class.cursor ¬ hourGlass] ELSE Cursors.SetCursor[tool.outer.class.cursor ¬ tool.graphics.class.cursor ¬ textPointer]; }; StartTimer: PUBLIC PROC [tool: Tool] ~ { tool.clock ¬ BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]]; }; ElapsedTime: PUBLIC PROC [tool: Tool] RETURNS [seconds: REAL] ~ { RETURN[BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]]-tool.clock]; }; PrintElapsedTime: PUBLIC PROC [tool: Tool, elapsedTime: REAL ¬ 0.0, action: ROPE ¬ NIL] ~ { IF action = NIL THEN action ¬ "elapsed"; IF elapsedTime = 0.0 THEN elapsedTime ¬ ElapsedTime[tool]; TSWrite[tool, IO.PutFR["%g time: %6.3f seconds.", IO.rope[action], IO.real[elapsedTime]]] }; TSWrite: PUBLIC PROC [tool: Tool, message: ROPE] ~ { IF tool.outer # NIL THEN Controls.TypescriptWrite[tool.typescript, Rope.Concat[message, "\n"]] ELSE IO.PutRope[tool.cmd.out, message]; }; END. ζ G3dToolViewerImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, April 8, 1993 0:04 am PDT Heckbert, August 9, 1988 5:51:51 pm PDT Glassner, July 18, 1990 2:25:48 pm PDT Shoemake, November 6, 1989 11:57:54 pm PST 3d Tool: Creation and Miscellany Types Tool Creation and Control (actually, add another field: strokeWidth, for use with screen display) IF ops.render THEN NewButton["Render", G3dTool.RenderButton]; IF ops.animation THEN NewButton["Animate", G3dTool.AnimateOpsButton]; IF ops.scene THEN NewButton["Scene", G3dTool.SceneOpsButton]; IF ops.texture THEN NewButton["Texture", G3dTool.TextureOpsButton]; IF ops.render THEN NewButton["Abort Render", G3dTool.AbortButton, TRUE]; IF ops.help THEN NewButton["Help", G3dTool.HelpButton]; Only upon return does the application have a Tool, which it needs if it is to draw. Thus, we give the client some time with a Tool before drawing the viewer: View Operations Stop, Finish, and Help Miscellany Κ™•NewlineDelimiter ™™Jšœ Οmœ1™JšŸœ Ÿœ.˜@JšŸœ Ÿœ.˜@JšŸœ Ÿœ/˜BJšŸœ Ÿœ,™?JšŸœŸœ1™FJšŸœ Ÿœ.™@JšŸœ Ÿœ1™DJšŸœ Ÿœ€œŸœ™HJšŸœ Ÿœ)™:JšŸœ Ÿœ)Ÿœ˜@J˜OšŸœ Ÿœ˜˜#J˜ J˜ J˜J˜J˜J˜#J˜J˜J˜J˜JšœŸœ˜ JšœŸœŸœŸœ ˜4J˜—J˜J˜J˜&J˜"J˜šŸœŸœŸœ'˜9JšœS™SJšœI™I—J˜—J˜——J˜2J˜J˜—–(Postfix0.320 0.931 0.362 textColorš£œ˜Jšœ Ÿœ ˜J˜-J˜RJ˜J˜—–( Postfix0.320 0.931 0.362 textColorš£ œ˜Jšœ₯˜+JšœŸœ˜-J˜J˜—–( Postfix0.320 0.931 0.362 textColorš£ œ˜&JšœŸœŸœ,˜8šŸœŸœŸœ˜JšœŸœŸœ ˜*šŸœ˜JšŸœ#˜'š ŸœŸœŸœŸœ Ÿœ ŸœŸ˜HJšŸœŸœŸœ˜;JšŸœ˜——J˜—J˜J˜—–(Postfix0.320 0.931 0.362 textColorš£œ˜!Jšœ Ÿœ ˜JšŸœŸœŸœŸœ˜JšŸœŸœŸœ ˜9JšŸœŸœŸœ6˜TšŸœŸœ˜š ŸœŸœŸœ ŸœŸœŸ˜>JšŸœŸœŸœ4˜QJšŸœŸœŸœŸœ˜KJšŸœ˜—Jšœ Ÿœ˜J˜—šŸœ ŸœŸ˜šŸœŸœŸœŸ˜(š ŸœŸœŸœ3ŸœŸœŸ˜QJ˜,JšŸœ˜—JšŸœ˜——J˜J˜—–( Postfix0.320 0.931 0.362 textColorš£ œŸ œ˜)šŸœŸœŸœ˜J˜$J˜VJšœ3˜3J˜—Jšœ˜J˜—J˜šœŸœŸœ Ÿœ˜$J˜—–( Postfix0.320 0.931 0.362 textColorš£ œŸ œ˜+JšŸœŸœŸœ˜!J˜J˜š ŸœŸœŸœ ŸœŸœŸ˜>JšŸœŸœŸœ8˜TJšŸœ˜—J˜J˜—J–( Postfix0.320 0.931 0.362 textColor4š £ œŸœŸœŸœ Ÿœ˜A–(Postfix0.320 0.931 0.362 textColorAš£œŸœŸœŸœŸœŸœ Ÿœ˜QJ˜—–(Postfix0.320 0.931 0.362 textColor-š £œŸœŸœŸœŸœ˜5JšŸœŸœŸœ.˜KJšœ˜J˜—–( Postfix0.320 0.931 0.362 textColor2š£ œŸœŸœ%˜;JšŸœŸœ ŸœŸœ˜-Jšœ:Ÿœ˜@J˜J˜—–( Postfix0.320 0.931 0.362 textColorCš £ œŸœŸœ(ŸœŸœŸœ˜LJšŸœ Ÿœ˜Jšœ˜šŸœ Ÿœ˜ šŸœ˜Jš œŸœŸœŸœŸœŸœ˜N—JšŸœ"˜&—J˜J˜—–(Postfix0.320 0.931 0.362 textColorPš£œŸœŸœŸœŸœŸœŸœ˜TšŸœŸœŸœ˜J˜"JšœŸœ˜J˜—š ŸœŸœŸœŸœŸœ˜@Jšœ!˜!JšŸœŸœ&˜JšŸœŸœŸœ˜—J˜—Jšœ$ŸœŸœ Ÿœ ˜WJ˜#JšŸœ Ÿœ&˜9šŸœ Ÿ˜JšŸœŸœŸœ&˜HšŸœ˜˜JšœŸœŸœ#˜S—J˜0J˜?J˜——J˜:Jšœ(Ÿœ Ÿœ₯˜XJšœ*Ÿœ˜1J˜J˜$J˜J˜—–( Postfix0.320 0.931 0.362 textColor-š£ œŸ œŸœ˜6šŸœ˜ JšŸœT˜XJšŸœW˜[—J˜J˜—–( Postfix0.320 0.931 0.362 textColorš£ œŸ œ˜(J˜CJ˜J˜—–( Postfix0.320 0.931 0.362 textColor6š£ œŸ œŸœ Ÿœ˜AJšŸœC˜IJ˜J˜—–(Postfix0.320 0.931 0.362 textColorKš £œŸœŸœŸœŸœŸœ˜[JšŸœ ŸœŸœ˜(JšŸœŸœ!˜:JšœŸœ"ŸœŸœ˜YJ˜J˜—–(Postfix0.320 0.931 0.362 textColor-š£œŸ œŸœ˜4šŸœŸ˜JšŸœF˜JJšŸœŸœ ˜'—J˜——J˜JšŸœ˜—…—8dYγ