DIRECTORY ImagerFont USING [XChar], ImagerManhattan USING [Map, Polygon], ImagerMaskCache USING [CharMask, CharMaskRep, Parameters, ParametersRep, Run, SmallCache, smallCacheSize], ImagerSample USING [BoxesFromBitmap, Clear, Clip, Fill, FillBoxes, GetBox, NewSampleMap, ObtainUnsafeDescriptor, ReleaseDescriptor, SampleMap, BasicTransfer], ImagerSys USING [GoodModulus, RawHash], Real USING [Ceiling], RefTab USING [Create, Fetch, Pairs, Ref, Store], SF USING [Add, Box, BoxAction, maxBox, Size, SizeF, SizeS, Vec, zeroVec]; ImagerMaskCacheImpl: CEDAR MONITOR LOCKS x USING x: MaskCache IMPORTS ImagerManhattan, ImagerSample, ImagerSys, Real, RefTab, SF EXPORTS ImagerMaskCache ~ BEGIN CharMask: TYPE ~ ImagerMaskCache.CharMask; CharMaskRep: TYPE ~ ImagerMaskCache.CharMaskRep; Parameters: TYPE ~ ImagerMaskCache.Parameters; ParametersRep: TYPE ~ ImagerMaskCache.ParametersRep; SampleMap: TYPE ~ ImagerSample.SampleMap; SmallCache: TYPE ~ ImagerMaskCache.SmallCache; XChar: TYPE ~ ImagerFont.XChar; bitsPerWord: NAT ~ BITS[WORD]; smallCacheSize: NAT ~ ImagerMaskCache.smallCacheSize; RasterBits: PROC [raster: REF CharMaskRep.raster] RETURNS [LONG POINTER] = INLINE { RETURN [LOOPHOLE[raster, LONG POINTER]+SIZE[CharMaskRep.raster[0]]] }; BitmapFromCharMask: PUBLIC PROC [charMask: CharMask] RETURNS [ImagerSample.SampleMap] ~ { size: SF.Vec ~ SF.Size[charMask.box]; WITH charMask SELECT FROM raster: REF CharMaskRep.raster => TRUSTED { wordsPerLine: CARDINAL ~ (size.f+(bitsPerWord-1))/bitsPerWord; bitmap: ImagerSample.SampleMap ~ ImagerSample.ObtainUnsafeDescriptor[ size: size, bitsPerSample: 1, bitsPerLine: wordsPerLine*bitsPerWord, base: [word: RasterBits[raster], bit: 0], ref: raster, words: wordsPerLine*size.s, delta: charMask.box.min ]; RETURN [bitmap] }; ENDCASE => { bitmap: ImagerSample.SampleMap ~ ImagerSample.NewSampleMap[box: charMask.box, bitsPerSample: 1]; boxGenerator: -- SF.BoxGenerator -- PROC [boxAction: SF.BoxAction] ~ { BoxesFromCharMask[charMask, boxAction, SF.zeroVec, SF.maxBox]; }; ImagerSample.Clear[bitmap]; ImagerSample.FillBoxes[map: bitmap, boxes: boxGenerator, value: 1]; RETURN [bitmap] }; }; BoxesFromCharMask: PUBLIC PROC [charMask: CharMask, boxAction: SF.BoxAction, delta: SF.Vec, clip: SF.Box] ~ { WITH charMask SELECT FROM raster: REF CharMaskRep.raster => TRUSTED { size: SF.Vec ~ SF.Size[charMask.box]; wordsPerLine: CARDINAL ~ (size.f+(bitsPerWord-1))/bitsPerWord; bitmap: ImagerSample.SampleMap ~ ImagerSample.ObtainUnsafeDescriptor[ size: size, bitsPerSample: 1, bitsPerLine: wordsPerLine*bitsPerWord, base: [word: RasterBits[raster], bit: 0], ref: raster, words: wordsPerLine*size.s, delta: SF.Add[charMask.box.min, delta] ]; clipped: ImagerSample.SampleMap ~ ImagerSample.Clip[bitmap, clip]; ImagerSample.BoxesFromBitmap[clipped, boxAction]; ImagerSample.ReleaseDescriptor[bitmap]; ImagerSample.ReleaseDescriptor[clipped]; }; runGroup: REF CharMaskRep.runs => { s0: INTEGER ~ INT[delta.s]+charMask.box.min.s; f0: INTEGER ~ INT[delta.f]+charMask.box.min.f; s: INTEGER ฌ s0; FOR i: NAT IN [0..runGroup.nRuns) WHILE s < clip.max.s DO r: ImagerMaskCache.Run ~ runGroup[i]; IF s >= clip.min.s THEN { fMin: INTEGER ~ MAX[NAT[r.fMin]+f0, clip.min.f]; fMax: INTEGER ~ MIN[NAT[r.fMin+r.fSize]+f0, clip.max.f]; IF fMax > fMin THEN boxAction[[min: [s, fMin], max: [s+1, fMax]]]; }; IF r.lastRun THEN s ฌ s + 1; ENDLOOP; }; ENDCASE => NULL; }; RasterCharMaskFromManhattan: PUBLIC PROC [p: ImagerManhattan.Polygon, bb: SF.Box] RETURNS [REF CharMaskRep.raster] ~ { rast: CARD ~ CARDINAL[SF.SizeF[bb]+(bitsPerWord-1)]/bitsPerWord; bitmapWords: INT ~ SF.SizeS[bb]*rast; IF bitmapWords > 32000 THEN RETURN [NIL] ELSE TRUSTED { mask: REF CharMaskRep.raster ฌ NEW[CharMaskRep.raster[NAT[bitmapWords]]]; bits: SampleMap ~ ImagerSample.ObtainUnsafeDescriptor[size: SF.Size[bb], bitsPerSample: 1, bitsPerLine: rast*bitsPerWord, base: [word: RasterBits[mask], bit: 0], ref: mask, words: bitmapWords, delta: bb.min]; mask.box ฌ bb; WHILE p # NIL DO ImagerSample.Fill[bits, p.first, 1]; p ฌ p.rest; ENDLOOP; ImagerSample.ReleaseDescriptor[bits]; RETURN [mask]; }; }; RasterCharMaskFromSampleMap: PUBLIC PROC [map: ImagerSample.SampleMap] RETURNS [REF CharMaskRep.raster] ~ { bb: SF.Box ~ ImagerSample.GetBox[map]; rast: CARD ~ CARDINAL[SF.SizeF[bb]+(bitsPerWord-1)]/bitsPerWord; bitmapWords: INT ~ SF.SizeS[bb]*CARD[rast]; IF bitmapWords > 32000 THEN RETURN [NIL] ELSE TRUSTED { mask: REF CharMaskRep.raster ฌ NEW[CharMaskRep.raster[NAT[bitmapWords]]]; bits: SampleMap ~ ImagerSample.ObtainUnsafeDescriptor[size: SF.Size[bb], bitsPerSample: 1, bitsPerLine: rast*bitsPerWord, base: [word: RasterBits[mask], bit: 0], ref: mask, words: bitmapWords, delta: bb.min]; mask.box ฌ bb; ImagerSample.BasicTransfer[dst: bits, src: map, dstMin: bb.min, srcMin: bb.min, size: SF.Size[bb]]; ImagerSample.ReleaseDescriptor[bits]; RETURN [mask]; }; }; RunsCharMaskFromManhattan: PUBLIC PROC [p: ImagerManhattan.Polygon, bb: SF.Box, nRuns: INT] RETURNS [mask: REF CharMaskRep.runs] ~ { i: NAT ฌ 0; s: NAT ฌ 0; AppendRun: PROC [box: SF.Box] ~ { check: [1..1] ~ SF.SizeS[box]; smin: NAT ~ box.min.s-bb.min.s; fmin: NAT ~ box.min.f-bb.min.f; IF smin # s THEN { mask[i-1].lastRun ฌ TRUE; s ฌ s + 1; WHILE smin > s DO mask[i] ฌ [fMin: 0, lastRun: TRUE, fSize: 0]; i ฌ i + 1; s ฌ s + 1; ENDLOOP; }; mask[i] ฌ [fMin: fmin, lastRun: FALSE, fSize: SF.SizeF[box]]; i ฌ i + 1; }; IF nRuns = 0 OR nRuns > 4000 THEN RETURN [NIL]; mask ฌ NEW[CharMaskRep.runs[nRuns]]; mask.box ฌ bb; ImagerManhattan.Map[polygon: p, boxAction: AppendRun, runs: TRUE]; IF i#nRuns THEN ERROR; IF CARDINAL[s]+1 # SF.SizeS[mask.box] THEN ERROR; mask[i-1].lastRun ฌ TRUE; }; CountRuns: PUBLIC PROC [p: ImagerManhattan.Polygon] RETURNS [runs: INT ฌ 0] ~ { s: INTEGER ฌ IF p # NIL THEN p.first.min.s ELSE 0; WHILE p # NIL DO sMin: INTEGER ~ p.first.min.s; sSize: NAT ~ SF.SizeS[p.first]; IF sMin > s THEN {runs ฌ runs + (sMin - s)}; s ฌ sMin + sSize; runs ฌ runs + sSize; p ฌ p.rest; ENDLOOP; }; MaskCache: TYPE ~ REF MaskCacheRep; MaskCacheRep: PUBLIC TYPE ~ MONITORED RECORD [ parameters: Parameters, smallCache: SmallCache, smallCacheInUse: BOOL, smallCacheFail: CARDINAL, gen: ARRAY [0..1] OF Generation ]; Generation: TYPE ~ REF GenerationRep; GenerationRep: TYPE ~ RECORD [ size: NAT, seq: SEQUENCE maxSize: CARDINAL OF CharMask ]; nullCharMask: CharMask ~ RasterCharMaskFromManhattan[p: NIL, bb: [[0,0], [0,0]]]; emptyGeneration: Generation ~ NewGeneration[0]; NewGeneration: PROC [sizeLimit: CARDINAL] RETURNS [g: Generation] = { g ฌ NEW[GenerationRep[ImagerSys.GoodModulus[sizeLimit]]]; g.size ฌ 0; }; Create: PUBLIC PROC [param: ParametersRep] RETURNS [new: MaskCache] ~ { maxSize: CARDINAL ฌ 1; lgMaxSize: NAT ฌ 0; parameters: Parameters ฌ NEW[ParametersRep ฌ param]; new ฌ NEW[MaskCacheRep]; new.smallCache ฌ NEW[ARRAY [0..smallCacheSize) OF REF CharMaskRep.raster ฌ ALL[NIL]]; new.smallCacheInUse ฌ FALSE; new.smallCacheFail ฌ 0; new.parameters ฌ parameters; new.gen[0] ฌ NewGeneration[parameters.sizeLimit]; new.gen[1] ฌ emptyGeneration; }; Occupancy: ENTRY PROC [x: MaskCache] RETURNS [lst: LIST OF REF TEXT ฌ NIL] ~ { FOR i: NAT DECREASING IN [0..2) DO gen: Generation ~ x.gen[i]; text: REF TEXT ~ NEW[TEXT[gen.maxSize]]; FOR i: NAT IN [0..gen.maxSize) DO text[i] ฌ SELECT gen[i] FROM nullCharMask => 'X, NIL => '-, ENDCASE => '#; ENDLOOP; text.length ฌ gen.maxSize; lst ฌ CONS[text, lst]; ENDLOOP; }; Size: PUBLIC ENTRY PROC [x: MaskCache] RETURNS [NAT] ~ { RETURN [x.gen[0].size+x.gen[1].size] }; Fetch: PUBLIC ENTRY PROC [x: MaskCache, font: REF, char: XChar] RETURNS [CharMask] ~ TRUSTED { c: CharMask ฌ FetchInternal[gen: x.gen[0], font: font, char: char, remove: FALSE]; IF c = NIL THEN { c ฌ FetchInternal[gen: x.gen[1], font: font, char: char, remove: TRUE]; IF c # NIL THEN { IF NOT StoreInternal[gen: x.gen[0], charMask: c] THEN { Dillon[x]; -- time for a new generation [] ฌ StoreInternal[gen: x.gen[0], charMask: c]; -- Should succeed }; }; }; RETURN [c]; }; CharAndFont: TYPE ~ MACHINE DEPENDENT RECORD [char: XChar, font: REF]; HashCharAndFont: PROC [char: XChar, font: REF, mod: CARDINAL] RETURNS [CARDINAL] ~ { cf: CharAndFont ฌ [char: char, font: font]; TRUSTED { RETURN[ImagerSys.RawHash[[base: LOOPHOLE[@cf], startIndex: 0, count: SIZE[CharAndFont]*BYTES[UNIT]], mod]] }; }; FetchInternal: INTERNAL PROC [gen: Generation, font: REF, char: XChar, remove: BOOL ฌ FALSE] RETURNS [CharMask] ~ TRUSTED { hash: CARDINAL ฌ HashCharAndFont[char, font, gen.maxSize]; last: CARDINAL ฌ gen.maxSize-1; c: CharMask ฌ NIL; UNTIL (c ฌ gen[hash])=NIL OR (c.font=font AND c.char=char) DO IF hash#0 THEN hash ฌ hash-1 ELSE { IF last = CARDINAL.LAST THEN RETURN [NIL]; -- rare because of load factor limit hash ฌ last; last ฌ CARDINAL.LAST; -- stopper }; ENDLOOP; IF remove AND c # NIL THEN { gen[hash] ฌ nullCharMask; gen.size ฌ gen.size - 1; }; RETURN [c]; }; GetParameters: PUBLIC PROC [x: MaskCache] RETURNS [Parameters] ~ { RETURN [x.parameters] }; UpdateParameters: PUBLIC ENTRY PROC [x: MaskCache, action: PROC [Parameters]] ~ { ENABLE UNWIND => NULL; action[x.parameters]; }; Store: PUBLIC ENTRY PROC [x: MaskCache, charMask: CharMask] ~ TRUSTED { IF NOT StoreInternal[gen: x.gen[0], charMask: charMask] THEN { Dillon[x]; -- time for a new generation [] ฌ StoreInternal[gen: x.gen[0], charMask: charMask]; -- Should succeed }; }; StoreInternal: INTERNAL PROC [gen: Generation, charMask: CharMask] RETURNS [BOOL] ~ TRUSTED { hash: CARDINAL ฌ HashCharAndFont[charMask.char, charMask.font, gen.maxSize]; last: CARDINAL ฌ gen.maxSize-1; c: CharMask ฌ NIL; IF gen.size > gen.maxSize - (gen.maxSize)/4 THEN RETURN [FALSE]; -- 75% load factor UNTIL (c ฌ gen[hash]) = NIL OR (c.font=charMask.font AND c.char=charMask.char) DO IF hash#0 THEN hash ฌ hash-1 ELSE { IF last = CARDINAL.LAST THEN RETURN [FALSE]; -- rare because of load factor limit hash ฌ last; last ฌ CARDINAL.LAST; -- stopper }; ENDLOOP; IF c = NIL THEN { gen.size ฌ gen.size + 1 }; gen[hash] ฌ charMask; RETURN [TRUE] }; discardRate: REAL ฌ 0.10; -- When fewer than this fraction of the entries get discarded, growthFactor: REAL ฌ 1.2; -- grow the table by this much. Dillon: INTERNAL PROC [x: MaskCache] ~ { newSize: CARDINAL ~ IF x.gen[1].size < (x.gen[1].maxSize * discardRate) THEN CARDINAL[Real.Ceiling[x.gen[0].maxSize * growthFactor]] ELSE x.parameters.sizeLimit; EraseInternal[x.gen[1]]; x.gen[1] ฌ x.gen[0]; x.gen[0] ฌ NewGeneration[newSize]; }; EraseInternal: INTERNAL PROC [gen: Generation] ~ { FOR i: INT IN [0..gen.maxSize) DO gen[i] ฌ NIL ENDLOOP; gen.size ฌ 0; }; Launder: PUBLIC PROC [x: MaskCache, keep: PROC [CharMask] RETURNS [BOOL]] ~ { list: LIST OF CharMask ฌ GetList[x]; Flush[x]; WHILE list # NIL DO this: CharMask ฌ list.first; next: LIST OF CharMask ฌ list.rest; list.first ฌ NIL; list.rest ฌ NIL; list ฌ next; IF keep[this] THEN Store[x, this]; ENDLOOP; }; Flush: PUBLIC ENTRY PROC [x: MaskCache] ~ { IF x.smallCache # NIL AND NOT x.smallCacheInUse THEN { x.smallCacheญ ฌ ALL[NIL] } ELSE { x.smallCacheInUse ฌ FALSE; x.smallCache ฌ NEW[ARRAY [0..smallCacheSize) OF REF CharMaskRep.raster ฌ ALL[NIL]]; x.smallCacheFail ฌ 0; }; EraseInternal[x.gen[0]]; EraseInternal[x.gen[1]]; x.gen[1] ฌ emptyGeneration; IF NOT x.parameters.sizeLimit IN (x.gen[0].maxSize/2 .. x.gen[0].maxSize] THEN { x.gen[0] ฌ NewGeneration[x.parameters.sizeLimit]; }; }; GetList: PUBLIC ENTRY PROC [x: MaskCache] RETURNS [list: LIST OF CharMask ฌ NIL] ~ { FOR g: [0..1] IN [0..1] DO gen: Generation ~ x.gen[g]; FOR i: INT IN [0..gen.maxSize) DO c: CharMask ฌ gen[i]; IF c # NIL AND c # nullCharMask THEN list ฌ CONS[c, list]; ENDLOOP; ENDLOOP; }; GetNamedCache: PUBLIC PROC [atom: ATOM] RETURNS [r: MaskCache] ~ { r ฌ NARROW[RefTab.Fetch[cacheTab, atom].val]; IF r = NIL THEN { r ฌ Create[[]]; [] ฌ RefTab.Store[cacheTab, atom, r]; }; }; SetNamedCacheParameters: PUBLIC PROC [atom: ATOM, p: ParametersRep] ~ { r: MaskCache ฌ NARROW[RefTab.Fetch[cacheTab, atom].val]; IF r = NIL THEN { r ฌ Create[p]; [] ฌ RefTab.Store[cacheTab, atom, r]; } ELSE { Inner: ENTRY PROC [x: MaskCache] = INLINE { x.parametersญ ฌ p }; IF r.parameters # NIL THEN Inner[r]; }; }; cacheTab: RefTab.Ref ~ RefTab.Create[]; FlushAll: PUBLIC PROC [] ~ { epa: PROC [key, val: REF] RETURNS [quit: BOOL ฌ FALSE] ~ {Flush[NARROW[val]]}; [] ฌ RefTab.Pairs[cacheTab, epa]; }; smallCacheFailLimit: CARDINAL ฌ 500; smallCacheFailureRecoveries: CARD ฌ 0; -- statistics. ObtainSmallCache: PUBLIC ENTRY PROC [x: MaskCache] RETURNS [SmallCache] = { IF x.smallCacheInUse THEN { x.smallCacheFail ฌ x.smallCacheFail + 1; IF x.smallCacheFail > smallCacheFailLimit THEN { x.smallCache ฌ NEW[ARRAY [0..smallCacheSize) OF REF CharMaskRep.raster ฌ ALL[NIL]]; x.smallCacheInUse ฌ FALSE; smallCacheFailureRecoveries ฌ smallCacheFailureRecoveries + 1; }; }; IF x.smallCacheInUse THEN RETURN [NIL]; x.smallCacheInUse ฌ TRUE; x.smallCacheFail ฌ 0; RETURN [x.smallCache]; }; ReleaseSmallCache: PUBLIC ENTRY PROC [x: MaskCache, s: SmallCache] = { IF x.smallCacheInUse AND x.smallCache = s THEN { x.smallCacheInUse ฌ FALSE } ELSE { IF s # NIL THEN sญ ฌ ALL[NIL] }; }; END. า ImagerMaskCacheImpl.mesa Copyright ำ 1985, 1986, 1987, 1988, 1989, 1991 by Xerox Corporation. All rights reserved. Michael Plass, October 10, 1991 1:35 pm PDT Doug Wyatt, June 5, 1990 4:06 pm PDT FOR s: INTEGER IN [bb.min.s..bb.max.s) DO ImagerSample.BasicTransfer[dst: bits, src: map, dstMin: [s, bb.min.f], srcMin: [s, bb.min.f], size: [1, bb.max.f-bb.min.f]]; ENDLOOP; This version includes zero-length runs needed to get the PD run representation to work. Used to overwrite slots in the old generation. Will actually have one slot, but we will not use it, as this is only a placeholder for the old generation. This is for verifying that the hash functions are well-behaved. Call from the debugger. The small cache is busy! Drop it and make a new one. We retain the smallCache pointer so that we check that the same one comes back. The small cache has had many consecutive failures, which probably means a client died while it was checked out. Allocate a new one. สแ–(cedarcode) style•NewlineDelimiter ™code™Kšœ ฯeœO™ZK™+K™$K˜—šฯk ˜ Kšœ žœ ˜Kšœžœ˜%KšœžœU˜jKšœ žœŒ˜žKšœ žœ˜'Kšœžœ ˜Kšœžœ$˜0KšžœžœA˜I—K˜š ะblœžœžœžœžœ ˜=Kšžœ9ž˜BKšžœ˜Kšœž˜K˜Kšœ žœ˜*Kšœ žœ˜0Kšœ žœ˜.Kšœžœ!˜4Kšœ žœ˜)Kšœ žœ˜.Kšœžœ˜Kšœ žœžœžœ˜Kšœžœ"˜5K˜šฯn œžœ žœžœžœžœžœ˜SKš žœžœ žœžœžœ˜CKšœ˜K˜—š œžœžœžœ˜YKšœžœžœ˜%šžœ žœž˜šœžœžœ˜+Kšœžœ(˜>šœE˜EKšœ ˜ Kšœ˜Kšœ&˜&Kšœ)˜)Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšžœ ˜Kšœ˜—šžœ˜ Kšœ`˜`šœฯcœžœ žœ˜FKšœ'žœ žœ ˜>Kšœ˜—Kšœ˜KšœC˜CKšžœ ˜Kšœ˜——Kšœ˜K™—š  œžœžœ!žœžœ žœ ˜mšžœ žœž˜šœžœžœ˜+Kšœžœžœ˜%Kšœžœ(˜>šœE˜EKšœ ˜ Kšœ˜Kšœ&˜&Kšœ)˜)Kšœ ˜ Kšœ˜Kšœžœ˜&Kšœ˜—KšœB˜BKšœ1˜1Kšœ'˜'Kšœ(˜(Kšœ˜—šœ žœ˜#Kšœžœžœ˜.Kšœžœžœ˜.Kšœžœ˜š žœžœžœžœž˜9Kšœ%˜%šžœžœ˜Kšœžœžœžœ˜0Kšœžœžœžœ!˜8Kšžœ žœ/˜BKšœ˜—Kšžœ žœ ˜Kšžœ˜—Kšœ˜—Kšžœžœ˜—Kšœ˜K˜—š  œžœžœ"žœžœžœ˜vKšœžœžœžœ(˜@Kšœ žœžœ˜%šžœ˜Kšžœžœžœ˜šžœžœ˜Kšœžœžœžœ˜IKšœ<žœ’˜ะKšœ˜šžœžœž˜Kšœ$˜$K˜ Kšžœ˜—Kšœ%˜%Kšžœ˜Kšœ˜——Kšœ˜K˜—š  œžœžœžœžœ˜kKšœžœ ˜&Kšœžœžœžœ(˜@Kšœ žœžœ žœ˜+šžœ˜Kšžœžœžœ˜šžœžœ˜Kšœžœžœžœ˜IKšœ<žœ’˜ะKšœ˜•StartOfExpansionช[dst: ImagerSample.SampleMap, src: ImagerSample.SampleMap, delta: SF.Vec _ [s: 0, f: 0], function: ImagerSample.Function _ [dstFunc: null, srcFunc: null]]šžœžœžœž™)Kšœ|™|Kšžœ™—KšœVžœ ˜cKšœ%˜%Kšžœ˜Kšœ˜——Kšœ˜K˜—š œžœžœ"žœ žœžœžœ˜„Kšœžœ˜ Kšœžœ˜ š  œžœžœ ˜!Kšœžœ ˜Kšœžœ˜Kšœžœ˜šžœ žœ˜Kšœžœ˜K˜ šžœ ž˜Kšœžœ ˜-Kšœ ˜ K˜ Kšžœ˜—Kšœ˜—Kšœ žœ˜=Kšœ ˜ Kšœ˜—Kš žœ žœžœžœžœ˜/Kšœžœ˜$Kšœ˜Kšœ<žœ˜BKšžœ žœžœ˜Kš žœžœžœžœžœ˜1Kšœžœ˜Kšœ˜K˜—š   œžœžœžœžœ ˜OK™WKš œžœžœžœžœžœ˜2šžœžœž˜Kšœžœ˜Kšœžœžœ˜Kšžœ žœ˜,Kšœ˜Kšœ˜Kšœ ˜ Kšžœ˜—Kšœ˜K˜—Kšœ žœžœ˜#š œžœžœž œžœ˜.Kšœ˜Kšœ˜Kšœžœ˜Kšœžœ˜Kšœžœžœ ˜Kšœ˜K˜—Kšœ žœžœ˜%šœžœžœ˜Kšœžœ˜ Kšœžœ žœžœ ˜+Kšœ˜K˜—šœ8žœ˜QK™.K™—šœ/˜/K™jK˜—š  œžœ žœžœ˜EKšœžœ2˜9Kšœ ˜ Kšœ˜K˜—š œžœžœžœ˜GKšœ žœ˜Kšœ žœ˜Kšœžœ˜4Kšœžœ˜Kš œžœžœžœžœžœžœ˜UKšœžœ˜Kšœ˜Kšœ˜Kšœ1˜1Kšœ˜Kšœ˜K˜—š  œžœžœžœžœžœžœžœžœ˜NK™?K™š žœžœž œžœž˜"Kšœ˜Kš œžœžœžœžœ˜(šžœžœžœž˜!šœ žœž˜Kšœ˜Kšžœ˜ Kšžœ˜—Kšžœ˜—Kšœ˜Kšœžœ ˜Kšžœ˜—Kšœ˜K˜—š  œžœžœžœžœžœ˜8Kšžœ˜$Kšœ˜K˜—š œžœžœžœžœžœžœ˜^KšœKžœ˜Ršžœžœžœ˜KšœAžœ˜Gšžœžœžœ˜šžœžœ+žœ˜7Kšœ ก˜'Kšœ0ก˜AKšœ˜—Kšœ˜—Kšœ˜—Kšžœ˜ Kšœ˜K˜—š œ žœžœž œžœžœ˜FK˜—š  œžœžœžœžœžœ˜TKšœ+˜+Kš žœžœžœžœžœžœ ˜wK˜K˜—š  œžœžœžœžœžœžœžœ˜{Kšœžœ,˜:Kšœžœ˜Kšœžœ˜š žœžœžœžœž˜=šžœ˜ Kšžœ˜šžœ˜Kš žœžœžœžœžœžœก$˜OKšœ ˜ Kšœžœžœก ˜ Kšœ˜——Kšžœ˜—šžœžœžœžœ˜Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜ Kšœ˜K˜—š  œžœžœžœ˜BKšžœ˜Kšœ˜K˜—š  œžœžœžœžœ˜QKšžœžœžœ˜Kšœ˜Kšœ˜K˜—š  œžœžœžœ&žœ˜Gšžœžœ2žœ˜>Kšœ ก˜'Kšœ7ก˜HKšœ˜—Kšœ˜K˜—š   œžœžœ'žœžœžœ˜]Kšœžœ>˜LKšœžœ˜Kšœžœ˜Kš žœ*žœžœžœก˜Sš žœžœžœžœž˜Qšžœ˜ Kšžœ˜šžœ˜Kš žœžœžœžœžœžœก$˜QKšœ ˜ Kšœžœžœก ˜ Kšœ˜——Kšžœ˜—Kšžœžœžœ˜,Kšœ˜Kšžœžœ˜ Kšœ˜K˜—Kšœ žœ ก>˜Xšœžœก˜9K˜—š œžœžœ˜(Kš œ žœžœ2žœžœ0žœ˜กK˜K˜Kšœ"˜"Kšœ˜K˜—š  œžœžœ˜2Kš žœžœžœžœ žœžœ˜7Kšœ ˜ Kšœ˜K˜—š  œžœžœžœ žœžœ˜MKšœžœžœ˜$Kšœ ˜ šžœžœž˜Kšœ˜Kšœžœžœ˜#Kšœ žœ˜Kšœ žœ˜K˜ Kšžœ žœ˜"Kšžœ˜—Kšœ˜K˜—š œžœžœžœ˜+šžœžœžœ˜/Kšžœžœžœ˜!šžœ˜K™4Kšœžœ˜Kš œžœžœžœžœžœžœ˜SKšœ˜Kšœ˜——K˜K˜Kšœ˜šžœžœžœ*žœ˜PKšœ1˜1Kšœ˜—Kšœ˜K˜—š œžœžœžœžœžœžœ žœ˜Tšžœ žœž˜Kšœ˜šžœžœžœž˜!Kšœ˜Kš žœžœžœžœžœ ˜:Kšžœ˜—Kšžœ˜—Kšœ˜K˜—š   œžœžœžœžœ˜BKšœžœ#˜-šžœžœžœ˜Kšœ˜Kšœ%˜%Kšœ˜—Kšœ˜K˜—š œžœžœžœ˜GKšœžœ#˜8šžœž˜ šžœ˜Kšœ˜Kšœ%˜%Kšœ˜—šžœ˜Kš œžœžœžœ˜@Kšžœžœžœ ˜$Kšœ˜——Kšœ˜K˜—šœ'˜'K˜—š œžœžœ˜Kš œžœ žœžœžœžœ žœ˜NKšœ!˜!Kšœ˜K˜—Kšœžœ˜$Kšœžœก˜6š  œžœžœžœžœ˜KKšœO™Ošžœžœž˜Kšœ(˜(šžœ(žœ˜0K™„Kš œžœžœžœžœžœžœ˜SKšœžœ˜Kšœ>˜>Kšœ˜—Kšœ˜—Kšžœžœžœžœ˜'Kšœžœ˜Kšœ˜Kšžœ˜Kšœ˜K˜—š œžœžœžœ"˜Fšžœžœ˜)Kšžœžœ˜"Kš žœžœžœžœžœžœ˜'—Kšœ˜K˜—Kšžœ˜——…—30Jใ