DIRECTORY BiScrollers, Geom2D, Imager, ImagerBox, ImagerTransformation, IO, Menus, MessageWindow, Real, RealFns, Rope, ViewerOps, ViewerTools; BiScrollersImpl: CEDAR MONITOR IMPORTS Geom2D, ImagerBox, ImagerTransformation, IO, Menus, MessageWindow, Real, RealFns, Rope, ViewerOps, ViewerTools EXPORTS BiScrollers SHARES Menus = BEGIN OPEN BiScrollers; StyleList: TYPE = LIST OF RECORD [name: ROPE, style: BiScrollerStyle]; bsMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; styles: StyleList _ NIL; defaultStyleName: ROPE _ NIL; GetStyle: PUBLIC PROC [name: ROPE _ NIL] RETURNS [style: BiScrollerStyle] = { IF name = NIL THEN name _ defaultStyleName; FOR sl: StyleList _ styles, sl.rest WHILE sl # NIL DO IF sl.first.name.Equal[name] THEN RETURN [sl.first.style] ENDLOOP; style _ NIL; }; RegisterStyle: PUBLIC ENTRY PROC [name: ROPE, style: BiScrollerStyle] = { ENABLE UNWIND => {}; styles _ CONS[[name, style], styles]; }; SetDefaultStyle: PUBLIC ENTRY PROC [name: ROPE] RETURNS [old: ROPE] = {old _ defaultStyleName; defaultStyleName _ name}; IsBiScroller: PUBLIC PROC [ra: REF ANY] RETURNS [BOOLEAN] = {RETURN [ISTYPE[ra, BiScroller]]}; NarrowToBiScroller: PUBLIC PROC [ra: REF ANY] RETURNS [BiScroller] = {bs: BiScroller _ NARROW[ra]; RETURN [bs]}; QuaViewer: PUBLIC PROC [bs: BiScroller, inner: BOOL _ FALSE] RETURNS [Viewer] = {RETURN [bs.style.QuaViewer[bs, inner]]}; QuaBiScroller: PUBLIC PROC [v: Viewer] RETURNS [BiScroller] = {bs: BiScroller _ NARROW[v.data]; RETURN [bs]}; ViewerIsABiScroller: PUBLIC PROC [v: Viewer] RETURNS [BOOLEAN] = {RETURN [ISTYPE[v.data, BiScroller]]}; ClientDataOf: PUBLIC PROC [bs: BiScroller] RETURNS [REF ANY] = {RETURN [bs.style.ClientDataOf[bs]]}; ClientDataOfViewer: PUBLIC PROC [v: Viewer] RETURNS [REF ANY] = {bs: BiScroller _ NARROW[v.data]; RETURN [bs.style.ClientDataOf[bs]]}; ViewportExtrema: PUBLIC PROC [bs: BiScroller, direction: Vec] RETURNS [min, max: Vec] = BEGIN vl: VecList _ bs.style.ViewportOf[bs]; e: Geom2D.ExtremaRec _ Geom2D.Extreme[direction, vl.first, Geom2D.Extreme[direction, vl.rest.first, Geom2D.Extreme[direction, vl.rest.rest.first, Geom2D.StartExtreme[direction, vl.rest.rest.rest.first]]]]; RETURN [e.minV, e.maxV]; END; ViewportBox: PUBLIC PROC [bs: BiScroller] RETURNS [bb: Rect] = { Pt: PROC [v: Vec] RETURNS [a: Rect] = INLINE {a _ [v.x, v.y, 0, 0]}; vl: VecList _ bs.style.ViewportOf[bs]; bb _ Geom2D.UpdateRects[ Geom2D.UpdateRects[ Geom2D.UpdateRects[ Pt[vl.first], Pt[vl.rest.first]], Pt[vl.rest.rest.first]], Pt[vl.rest.rest.rest.first]]; }; GenID: PUBLIC PROC [BiScroller] RETURNS [Transform] --TransformGenerator-- = {RETURN [Geom2D.id]}; ConstantVector: PROC [bs: BiScroller] RETURNS [cv: Vec] = { v: Viewer _ bs.style.QuaViewer[bs, TRUE]; cv _ [v.cw/2, v.ch/2]; }; ViewLimitsOfImage: PUBLIC PROC [bs: BiScroller, axis: Axis] RETURNS [vmin, vmax: REAL] = BEGIN t: Transform _ bs.style.GetTransforms[bs].clientToViewer; tn: Geom2D.Trans _ Geom2D.ToTrans[t]; norm, min, max: Vec; SELECT axis FROM X => norm _ [tn.dxdx, tn.dxdy]; Y => norm _ [tn.dydx, tn.dydy]; ENDCASE => ERROR; [min, max] _ bs.class.common.extrema[bs.style.ClientDataOf[bs], norm]; min _ t.Transform[min]; max _ t.Transform[max]; SELECT axis FROM X => {vmin _ min.x; vmax _ max.x}; Y => {vmin _ min.y; vmax _ max.y}; ENDCASE => ERROR; END; Scale: PUBLIC ENTRY PROC [bs: BiScroller, op: ScaleOp, paint: BOOL _ TRUE] = {ENABLE ABORTED => {}; IntScale[bs, op, paint]}; IntScale: INTERNAL PROC [bs: BiScroller, op: ScaleOp, paint: BOOL _ TRUE] = { cv: Vec _ ConstantVector[bs]; old: Transform _ bs.style.GetTransforms[bs].clientToViewer; new: Transform _ old.PostTranslate[cv.Neg[]]; WITH op SELECT FROM reset => { v: Geom2D.Trans _ Geom2D.ToTrans[bs.class.common.vanilla[bs]]; vd: REAL _ v.dxdx*v.dydy - v.dydx*v.dxdy; od: REAL _ old.a*old.e - old.d*old.b; new _ new.PostScale[ RealFns.SqRt[ABS[vd/ZeroProtect[od]]]*SGN[vd]*SGN[od] ]; }; byArg => new _ new.PostScale[arg]; ENDCASE => ERROR; new _ new.PostTranslate[cv]; bs.style.ChangeTransform[bs, new, paint]; }; SGN: PROC [r: REAL] RETURNS [sgn: [-1 .. 1]] = { sgn _ SELECT r FROM <0 => -1, =0 => 0, >0 => 1, ENDCASE => ERROR}; ZeroProtect: PROC [r: REAL] RETURNS [r0: REAL] = {r0 _ IF r = 0.0 THEN 1.0 ELSE r}; Rotate: PUBLIC ENTRY PROC [bs: BiScroller, op: RotateOp, paint: BOOL _ TRUE] = {ENABLE ABORTED => {}; IntRotate[bs, op, paint]}; IntRotate: INTERNAL PROC [bs: BiScroller, op: RotateOp, paint: BOOL _ TRUE] = { cv: Vec _ ConstantVector[bs]; old: Transform _ bs.style.GetTransforms[bs].clientToViewer; new: Transform _ old.PostTranslate[cv.Neg[]]; WITH op SELECT FROM reset => { v: Geom2D.Trans _ Geom2D.ToTrans[bs.class.common.vanilla[bs]]; new _ new.PostRotate[ RealFns.ArcTanDeg[y: v.dydx, x: v.dxdx] - RealFns.ArcTanDeg[y: old.d, x: old.a] ]; }; byArg => new _ new.PostRotate[arg]; ENDCASE => ERROR; new _ new.PostTranslate[cv]; bs.style.ChangeTransform[bs, new, paint]; }; Shift: PUBLIC ENTRY PROC [bs: BiScroller, dx, dy: REAL, paint: BOOL _ TRUE] = {ENABLE ABORTED => {}; IntShift[bs, dx, dy, paint]}; IntShift: INTERNAL PROC [bs: BiScroller, dx, dy: REAL, paint: BOOL _ TRUE] = { old: Transform _ bs.style.GetTransforms[bs].clientToViewer; new: Transform _ old.PostTranslate[[dx, dy]]; bs.style.ChangeTransform[bs, new, paint]; }; Align: PUBLIC ENTRY PROC [bs: BiScroller, client, viewer: Location, doX, doY, paint: BOOL _ TRUE] = {ENABLE ABORTED => {}; IntAlign[bs, client, viewer, doX, doY, paint]}; IntAlign: INTERNAL PROC [bs: BiScroller, client, viewer: Location, doX, doY, paint: BOOL _ TRUE] = { old: Transform _ bs.style.GetTransforms[bs].clientToViewer; new: Transform; from, to: Vec; Blend: PROC [a: REAL, b0, b1: REAL] RETURNS [c: REAL] = {c _ (1-a)*b0 + a*b1}; WITH client SELECT FROM coord => from _ old.Transform[[x, y]]; fraction => { min, max: REAL; IF doX THEN { [min, max] _ ViewLimitsOfImage[bs, X]; from.x _ Blend[fx, min, max]; }; IF doY THEN { [min, max] _ ViewLimitsOfImage[bs, Y]; from.y _ Blend[fy, min, max]; }; }; ENDCASE => ERROR; WITH viewer SELECT FROM coord => to _ [x, y]; fraction => { v: Viewer _ bs.style.QuaViewer[bs, TRUE]; to _ [fx*v.cw, fy*v.ch]; }; ENDCASE => ERROR; IF NOT doX THEN to.x _ from.x; IF NOT doY THEN to.y _ from.y; new _ old.PostTranslate[from.Neg[]].PostTranslate[to]; bs.style.ChangeTransform[bs, new, paint]; }; BoxScale: PUBLIC ENTRY PROC [bs: BiScroller, from, to: Rect --both in viewer coords--, paint: BOOL _ TRUE] = {ENABLE ABORTED => {}; IntBoxScale[bs, from, to, paint]}; IntBoxScale: INTERNAL PROC [bs: BiScroller, from, to: Rect --both in viewer coords--, paint: BOOL _ TRUE] = { cv: Vec _ ConstantVector[bs]; old: Transform _ bs.style.GetTransforms[bs].clientToViewer; new: Transform _ old.PostTranslate[[ -(from.x + from.w/2), -(from.y + from.h/2)]]; ndx, ndy, odx, ody, sx, sy: REAL; ndx _ to.w; ndy _ to.h; odx _ from.w; ody _ from.h; sx _ IF ndx=0 OR odx=0 THEN 1 ELSE ndx/odx; sy _ IF ndy=0 OR ody=0 THEN 1 ELSE ndy/ody; IF NOT bs.class.common.mayStretch THEN sx _ sy _ MIN[sx, sy]; IF bs.class.common.preferIntegerCoefficients THEN {sx _ Round[sx]; sy _ Round[sy]}; new _ new.PostScale2[[sx, sy]]; new _ new.PostTranslate[[ (to.x + to.w/2), (to.y + to.h/2)]]; bs.style.ChangeTransform[bs, new, paint]; }; Round: PROC [r: REAL] RETURNS [rr: REAL] = { i: INT _ Real.RoundLI[r]; rr _ IF (i=0) # (r=0) THEN r ELSE REAL[i]; }; GetArg: PROC RETURNS [valid: BOOL, arg: REAL] = { sel: ROPE _ ViewerTools.GetSelectionContents[]; s: IO.STREAM; valid _ SELECT sel.Length[] FROM > 1 => TRUE, > 0 => sel.Fetch[0] IN ['0 .. '9], ENDCASE => FALSE; IF NOT valid THEN RETURN; s _ IO.RIS[sel]; arg _ s.GetReal[! IO.Error, IO.EndOfStream => { valid _ FALSE; MessageWindow.Append[ message: IO.PutFR["Select a number, not %g", IO.refAny[sel]], clearFirst: TRUE]; MessageWindow.Blink[]; CONTINUE} ]; s.Close[]; }; GetBS: PROC [v: Viewer] RETURNS [bs: BiScroller] = { FOR v _ v, v.parent WHILE (bs _ NARROW[ViewerOps.FetchProp[v, $SubBiScroller]]) = NIL DO NULL ENDLOOP; }; SetBS: PUBLIC PROC [v: Viewer, bs: BiScroller] = { FOR v _ v, v.parent WHILE v # NIL DO ViewerOps.AddProp[v, $SubBiScroller, bs] ENDLOOP; }; ScaleButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; valid: BOOL; arg: REAL; [valid, arg] _ GetArg[]; IF NOT valid THEN arg _ 2.0; IntScale[ bs, SELECT mouseButton FROM red => [byArg[arg]], yellow => [reset[]], blue => [byArg[1.0/arg]], ENDCASE => ERROR ]; }; RotateButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; valid: BOOL; arg: REAL; [valid, arg] _ GetArg[]; IF NOT valid THEN arg _ 90; IntRotate[ bs, SELECT mouseButton FROM red => [byArg[arg]], yellow => [reset[]], blue => [byArg[-arg]], ENDCASE => ERROR ]; }; FitButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; iv: Viewer _ bs.style.QuaViewer[bs, TRUE]; limits: Imager.Box; [limits.xmin, limits.xmax] _ ViewLimitsOfImage[bs, X]; [limits.ymin, limits.ymax] _ ViewLimitsOfImage[bs, Y]; IntBoxScale[bs, ImagerBox.RectFromBox[limits], [0, 0, iv.cw, iv.ch]]; }; ResetAndCenterButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; bs.style.ChangeTransform[bs, bs.class.common.vanilla[bs], FALSE]; IntAlign[bs, [fraction[0.5, 0.5]], [fraction[0.5, 0.5]]]; }; CenterButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; IntAlign[bs, [fraction[0.5, 0.5]], [fraction[0.5, 0.5]]]; }; VanillaButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; bs.style.ChangeTransform[bs, bs.class.common.vanilla[bs], TRUE]; }; LeftButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; IntAlign[bs: bs, client: [fraction[0.0, 0.0]], viewer: [fraction[0.0, 0.0]], doY: FALSE]; }; RightButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; IntAlign[bs: bs, client: [fraction[1.0, 0.0]], viewer: [fraction[1.0, 0.0]], doY: FALSE]; }; BottomButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; IntAlign[bs: bs, client: [fraction[0.0, 0.0]], viewer: [fraction[0.0, 0.0]], doX: FALSE]; }; TopButt: ENTRY PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE] --Menus.MenuProc-- = {ENABLE ABORTED => NULL; v: Viewer _ NARROW[parent]; bs: BiScroller _ GetBS[v]; IntAlign[bs: bs, client: [fraction[0.0, 1.0]], viewer: [fraction[0.0, 1.0]], doX: FALSE]; }; CatenateMenus: PUBLIC PROC [pre, post: Menus.Menu] RETURNS [menu: Menus.Menu] = { preLines, postLines: INT; menu _ IF pre = NIL THEN Menus.CreateMenu[0] ELSE pre.CopyMenu[]; preLines _ menu.GetNumberOfLines[]; postLines _ post.GetNumberOfLines[]; menu.ChangeNumberOfLines[preLines + postLines]; FOR i: INT IN [0 .. postLines) DO menu.SetLine[preLines+i, post.GetLine[i]] ENDLOOP; }; SetViewerPosition: PUBLIC PROC [v: Viewer, x, y, w, h: INTEGER] = { ViewerOps.MoveViewer[v, x, y, w, h, FALSE]; }; Start: PROC = { bsMenu.AppendMenuEntry[Menus.CreateEntry["Scale", ScaleButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Rotate", RotateButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Fit", FitButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["ResetAndCenter", ResetAndCenterButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Center", CenterButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Vanilla", VanillaButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Left", LeftButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Right", RightButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Top", TopButt], 0]; bsMenu.AppendMenuEntry[Menus.CreateEntry["Bottom", BottomButt], 0]; }; Start[]; END. όFILE: BiScrollersImpl.Mesa Last Edited by: Spreitzer, November 10, 1985 5:16:51 pm PST vbs: INTEGER = IF v.border THEN ViewerSpecs.windowBorderSize ELSE 0; v.wx _ x; v.wy _ y; v.ww _ w; v.wh _ h; v.ch _ v.wh - (vbs+vbs) - (IF v.column=static OR v.parent#NIL THEN 0 ELSE ViewerSpecs.captionHeight); IF v.menu#NIL THEN v.ch _ v.ch - (v.menu.linesUsed*ViewerSpecs.menuHeight); v.cx _ v.wx + vbs + (IF v.scrollable THEN ViewerSpecs.scrollBarW ELSE 0); v.cy _ v.wy + vbs; v.cw _ v.ww - (v.cx-v.wx) - vbs; Κ˜J™J™;J™codešΟk œ?œD˜ŽK˜—šΠbxœœ˜Kšœ*œC˜vKšœ ˜Kšœ˜K˜—Kšœœ ˜K˜Kš œ œœœœœ˜FK˜Kšœœ!˜/K˜Kšœœ˜K˜Kšœœœ˜K˜š Οnœœœœœœ˜MKšœœœ˜+šœ!œœ˜5Kšœœœ˜9Kšœ˜—Kšœœ˜ K˜—K˜š Ÿ œœœœœ˜IKšœœ˜Kšœ œ˜%Kšœ˜—K˜šŸœœœœœœœ˜EKšœ2˜2—K˜šŸ œœœœœœœ˜;Kšœœœ˜"—K˜š Ÿœœœœœœ˜DKšœœœ˜+—K˜š Ÿ œœœœœœ ˜OKšœœ"˜)—K˜šŸ œœœ œ˜=Kšœœ œ˜/—K˜š Ÿœœœ œœ˜@Kšœœœ˜&—K˜š Ÿ œœœœœœ˜>Kšœœ˜%—K˜š Ÿœœœ œœœ˜?Kšœœ œ˜F—K˜šŸœœœ"œ˜WKš˜Kšœ&˜&˜K˜#K˜(K˜-K˜;—Kšœ˜Kšœ˜—K˜šŸ œœœœ˜@šŸœœ œ ˜,K˜—Kšœ&˜&šœ@˜@Kšœ ˜ Kšœ˜K˜K˜—K˜—K˜š Ÿœœœœ Οcœ˜LKšœœ˜—K˜šŸœœœ˜;Kšœ#œ˜)K˜K˜—K˜š Ÿœœœœœ˜XKš˜K˜9K˜%K˜šœ˜Kšœ˜Kšœ˜Kšœœ˜—K˜FKšœ˜Kšœ˜šœ˜Kšœ!˜"Kšœ!˜"Kšœœ˜—Kšœ˜—K˜š Ÿœœœœ&œœ˜LKšœœœ!˜0—K˜š Ÿœœœ&œœ˜MK˜Kšœ;˜;Kšœ-˜-šœœ˜šœ ˜ K˜>Kšœœ!˜)Kšœœ˜%šœ˜Kšœ œœœ˜5Kšœ˜—Kšœ˜—Kšœ"˜"Kšœœ˜—Kšœ˜Kšœ)˜)K˜—K˜šœœœœ˜0šœœ˜K˜ K˜K˜Kšœœ˜——K˜š Ÿ œœœœœ˜0Kšœœ œœ˜"—K˜š Ÿœœœœ'œœ˜NKšœœœ"˜1—K˜š Ÿ œœœ'œœ˜OK˜Kšœ;˜;Kšœ-˜-šœœ˜šœ ˜ K˜>šœ˜Kšœ)˜)Kšœ%˜%Kšœ˜—Kšœ˜—Kšœ#˜#Kšœœ˜—Kšœ˜Kšœ)˜)K˜—K˜šŸœœœœœ œœ˜MKšœœœ%˜4—K˜š Ÿœœœœ œœ˜NKšœ;˜;Kšœ-˜-Kšœ)˜)K˜—K˜š Ÿœœœœ=œœ˜cKšœœœ7˜F—K˜š Ÿœœœ=œœ˜dKšœ;˜;K˜Kšœ˜šŸœœΟgœœ œœœ˜7Kšœ‘œ‘œ˜—šœœ˜K˜&˜ Kšœ œ˜šœœ˜ Kšœ#œ˜&K˜K˜—šœœ˜ Kšœ#œ˜&K˜K˜—K˜—Kšœœ˜—šœœ˜K˜šœ ˜ Kšœ#œ˜)K˜K˜—Kšœœ˜—Kšœœœ˜Kšœœœ˜Kšœ6˜6Kšœ)˜)K˜—K˜šŸœœœœ! œ œœ˜lKšœœœ*˜9—K˜š Ÿ œœœ! œ œœ˜mK˜Kšœ;˜;šœ$˜$K˜K˜—Kšœœ˜!K˜ K˜ K˜ K˜ Kš œœœœœ ˜+Kš œœœœœ ˜+Kšœœœ œ ˜=šœ*˜,Kšœ"˜&—Kšœ˜šœ˜Kšœ˜Kšœ˜—Kšœ)˜)K˜—K˜š Ÿœœœœœ˜,Kšœœ˜Kš œœœœœ˜*K˜—K˜š Ÿœœœ œœ˜1Kšœœ&˜/Kšœœœ˜ šœœ˜ Kšœœ˜ Kšœœ ˜"Kšœœ˜—Kšœœœœ˜Kšœœœ˜šœ˜šœœ˜Kšœœ˜šœ˜Kšœ œ"œ˜=Kšœ œ˜—K˜Kšœ˜ —Kšœ˜—K˜ K˜—K˜šŸœœ œ˜4Kšœœœ,œœœœ˜fK˜—K˜šŸœœœ ˜2šœœœ˜$Kšœ(˜(Kšœ˜—K˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜΄Kšœ œ ˜Kšœ˜Kšœœ˜ Kšœœ˜ K˜Kšœœœ ˜šœ ˜ Kšœ˜šœ ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—K˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜΅Kšœ œ ˜Kšœ˜Kšœœ˜ Kšœœ˜ K˜Kšœœœ ˜šœ ˜ Kšœ˜šœ ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—K˜—K˜šŸœœœ œœœœœ8œœ œœœœ˜²Kšœ œ ˜Kšœ˜Kšœ$œ˜*K˜Kšœ3œ˜6Kšœ3œ˜6KšœE˜EK˜—K˜šŸœœœ œœœœœ8œœ œœœœ˜½Kšœ œ ˜Kšœ˜Kšœ:œ˜AKšœ9˜9K˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜΅Kšœ œ ˜Kšœ˜Kšœ9˜9K˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜ΆKšœ œ ˜Kšœ˜Kšœ:œ˜@K˜—K˜šŸœœœ œœœœœ8œœ œœœœ˜³Kšœ œ ˜Kšœ˜KšœRœ˜YK˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜΄Kšœ œ ˜Kšœ˜KšœRœ˜YK˜—K˜šŸ œœœ œœœœœ8œœ œœœœ˜΅Kšœ œ ˜Kšœ˜KšœRœ˜YK˜—K˜šŸœœœ œœœœœ8œœ œœœœ˜²Kšœ œ ˜Kšœ˜KšœRœ˜YK˜—K˜šŸ œœœœ˜QKšœœ˜Kš œœœœœ˜AKšœ#˜#Kšœ$˜$Kšœ/˜/Kš œœœœ+œ˜TK˜—K˜šŸœœœœ˜CKšœ$œ˜+Kš œœœ œœ™DK™'Kš œœœ œœœ™eKšœœœ9™KKšœœœœ™IK™K™ K˜—K˜šŸœœ˜KšœA˜AKšœC˜CKšœ=˜=KšœS˜SKšœC˜CKšœE˜EKšœ?˜?KšœA˜AKšœ=˜=KšœC˜CK˜—K˜K˜K˜Kšœ˜K˜—…—2ΖEΚ