DIRECTORY Basics USING [bitsPerWord, RawWords, UnsafeBlock], RasterBasics USING [BitAddress, DstFunc, SrcFunc], Scaled USING [Value], SF USING [Box, BoxAction, BoxGenerator, maxVec, minVec, Vec, zeroVec]; ImagerSample: CEDAR DEFINITIONS ~ BEGIN Vec: TYPE ~ SF.Vec; minVec: Vec ~ SF.minVec; zeroVec: Vec ~ SF.zeroVec; maxVec: Vec ~ SF.maxVec; Box: TYPE ~ SF.Box; maxBox: Box ~ [min: minVec, max: maxVec]; BoxAction: TYPE ~ SF.BoxAction; BoxGenerator: TYPE ~ SF.BoxGenerator; maxCount: NAT ~ NAT.LAST; MultipleReleaseOfScratch: ERROR; Sample: TYPE ~ WORD; maxSample: Sample ~ Sample.LAST; RawSamples: TYPE ~ Basics.RawWords; maxBitsPerSample: NAT ~ Basics.bitsPerWord; BitsPerSample: TYPE ~ NAT[0..maxBitsPerSample]; SampleBuffer: TYPE ~ REF SampleBufferRep; SampleBufferRep: TYPE ~ RECORD [ length: NAT, samples: SEQUENCE maxLength: NAT OF Sample ]; BitAddress: TYPE ~ RasterBasics.BitAddress; NewSamples: PROC [length: NAT, scratch: SampleBuffer ฌ NIL] RETURNS [SampleBuffer]; ObtainScratchSamples: PROC [length: NAT] RETURNS [SampleBuffer]; ReleaseScratchSamples: PROC [buffer: SampleBuffer]; DoWithScratchSamples: PROC [length: NAT, action: PROC [SampleBuffer]]; PointerToSamples: PROC [buffer: SampleBuffer, start, count: NAT] RETURNS [LONG POINTER TO RawSamples]; FlipSamples: PROC [buffer: SampleBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount]; FillSamples: PROC [buffer: SampleBuffer, value: Sample, start: NAT ฌ 0, count: NAT ฌ maxCount]; CopySamples: PROC [dst, src: SampleBuffer, dstStart, srcStart: NAT ฌ 0, count: NAT ฌ maxCount]; ClearSamples: PROC [buffer: SampleBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount]; SampleMap: TYPE ~ REF SampleMapRep; SampleMapRep: TYPE ~ PRIVATE RECORD [ box: Box, -- lower and upper bounds in each direction immutable: BOOL, bitsPerSample: [0..BITS[Sample]], -- number of bits per sample v: SELECT tag: * FROM raster => [ bitsPerLine: CARD, -- bits per scan line base: BitAddress, -- starting bit address ref: REF -- for retaining the underlying storage ], object => [class: SampleMapClass, data: REF], ENDCASE ]; SampleMapClass: TYPE ~ REF SampleMapClassRep; SampleMapClassRep: TYPE; -- Opaque to allow more flexibility ObjectGetProc: TYPE ~ PROC [self: ObjectSampleMap, initIndex: SF.Vec, buffer: SampleBuffer, start, count: NAT]; ObjectPutProc: TYPE ~ PROC [self: ObjectSampleMap, initIndex: SF.Vec, buffer: SampleBuffer, start, count: NAT, function: Function]; RasterSampleMap: TYPE ~ REF SampleMapRep.raster; ObjectSampleMap: TYPE ~ REF SampleMapRep.object; UnsafeNewSampleMap: UNSAFE PROC [box: Box, bitsPerSample: BitsPerSample, bitsPerLine: INT, base: BitAddress, ref: REF, words: INT, scratchDescriptor: SampleMap ฌ NIL] RETURNS [RasterSampleMap]; BitsForSamples: PROC [fSize: NAT, bitsPerSample: NAT] RETURNS [INT]; WordsForLines: PROC [sSize: NAT, bitsPerLine: INT] RETURNS [INT]; WordsForMap: PROC [size: Vec, bitsPerSample: BitsPerSample ฌ 1, bitsPerLine: INT ฌ 0] RETURNS [INT]; NewSampleMap: PROC [box: Box, bitsPerSample: BitsPerSample ฌ 1, bitsPerLine: INT ฌ 0] RETURNS [RasterSampleMap]; NewObjectSampleMap: PROC [box: Box, bitsPerSample: BitsPerSample, getSamples: ObjectGetProc, putSamples: ObjectPutProc, data: REF] RETURNS [ObjectSampleMap]; Copy: PROC [map: SampleMap, delta: Vec ฌ zeroVec, box: Box ฌ maxBox] RETURNS [RasterSampleMap]; ObtainScratchMap: PROC [box: Box, bitsPerSample: BitsPerSample ฌ 1, bitsPerLine: INT ฌ 0] RETURNS [RasterSampleMap]; ReleaseScratchMap: PROC [map: SampleMap]; DoWithScratchMap: PROC [box: Box, bitsPerSample: BitsPerSample ฌ 1, action: PROC [RasterSampleMap]]; ObtainUnsafeDescriptor: UNSAFE PROC [size: Vec, bitsPerSample: BitsPerSample, bitsPerLine: INT, base: BitAddress, ref: REF, words: INT, rawMin, delta: Vec ฌ zeroVec] RETURNS [RasterSampleMap]; ReIndex: PROC [map: SampleMap, delta: Vec ฌ zeroVec, box: Box ฌ maxBox] RETURNS [SampleMap]; Clip: PROC [map: SampleMap, box: Box ฌ maxBox] RETURNS [SampleMap]; Shift: PROC [map: SampleMap, delta: Vec ฌ zeroVec] RETURNS [SampleMap]; ZeroOrigin: PROC [map: SampleMap] RETURNS [SampleMap]; ReleaseDescriptor: UNSAFE PROC [map: SampleMap]; GetBox: PROC [map: SampleMap] RETURNS [Box] ~ INLINE {RETURN [map.box]}; GetSize: PROC [map: SampleMap] RETURNS [Vec] ~ INLINE {b: Box ~ map.box; RETURN [[s: b.max.s-b.min.s, f: b.max.f-b.min.f]]}; GetImmutable: PROC [map: SampleMap] RETURNS [BOOL] ~ INLINE {RETURN [map.immutable]}; MakeImmutable: PROC [map: SampleMap] ~ INLINE {map.immutable ฌ TRUE}; GetBitsPerSample: PROC [map: SampleMap] RETURNS [BitsPerSample] ~ INLINE {RETURN [map.bitsPerSample]}; GetBitsPerLine: PROC [map: RasterSampleMap] RETURNS [INT] ~ INLINE {RETURN [map.bitsPerLine]}; GetBase: PROC [map: RasterSampleMap] RETURNS [BitAddress] ~ INLINE {RETURN [map.base]}; GetUnsafeBlock: PROC [map: RasterSampleMap] RETURNS [Basics.UnsafeBlock]; GetRef: PROC [map: RasterSampleMap] RETURNS [REF] ~ INLINE {RETURN [map.ref]}; GetData: PROC [map: ObjectSampleMap] RETURNS [REF] ~ INLINE {RETURN [map.data]}; SrcFunc: TYPE ~ RasterBasics.SrcFunc; DstFunc: TYPE ~ RasterBasics.DstFunc; Function: TYPE ~ MACHINE DEPENDENT RECORD [dstFunc: DstFunc, srcFunc: SrcFunc]; nullFunction: Function ~ [dstFunc: null, srcFunc: null]; ApplyFunction: PROC [function: Function, dstVal, srcVal: Sample] RETURNS [Sample]; Get: PROC [map: SampleMap, index: Vec] RETURNS [Sample]; Put: PROC [map: SampleMap, index: Vec, value: Sample, function: Function ฌ nullFunction]; GetSamples: PROC [map: SampleMap, initIndex: Vec ฌ zeroVec, delta: Vec ฌ [s: 0, f: 1], buffer: SampleBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount]; GetTileSamples: PROC [tile: SampleMap, phase: NAT ฌ 0, initIndex: SF.Vec ฌ zeroVec, buffer: SampleBuffer]; Halftone: PROC [map: SampleMap, min: SF.Vec, sampleBuffer, thresholdBuffer: SampleBuffer, function: Function]; PutSamples: PROC [map: SampleMap, initIndex: Vec ฌ zeroVec, delta: Vec ฌ [s: 0, f: 1], buffer: SampleBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount, function: Function ฌ nullFunction]; Clear: PROC [map: SampleMap]; BasicTransfer: PROC [dst: SampleMap, src: SampleMap, dstMin: Vec ฌ zeroVec, srcMin: Vec ฌ zeroVec, size: Vec, function: Function ฌ nullFunction]; Transfer: PROC [dst: SampleMap, src: SampleMap, delta: Vec ฌ zeroVec, function: Function ฌ nullFunction]; Move: PROC [map: SampleMap, dstMin: Vec ฌ zeroVec, srcMin: Vec ฌ zeroVec, size: Vec ฌ maxVec, function: Function ฌ nullFunction]; Fill: PROC [map: SampleMap, box: Box ฌ maxBox, value: Sample ฌ maxSample, function: Function ฌ nullFunction]; RawDescriptor: TYPE ~ RECORD [box: Box, bitsPerLine: NAT, basePointer: LONG POINTER, ref: REF]; RawListTransfer: PROC [dst: RasterSampleMap, src: LIST OF RawDescriptor, function: Function ฌ nullFunction]; TileFromStipple: PROC [stipple: WORD, bitsPerSample: BitsPerSample ฌ 1, value0: Sample ฌ 0, value1: Sample ฌ maxSample, scratch: SampleMap ฌ NIL] RETURNS [SampleMap]; Tile: PROC [map: SampleMap, box: Box ฌ maxBox, tile: SampleMap, phase: NAT ฌ 0, function: Function ฌ nullFunction]; TileBoxes: PROC [map: SampleMap, boxes: BoxGenerator, tile: SampleMap, phase: NAT ฌ 0, function: Function ฌ nullFunction]; TransferBoxes: PROC [dst: SampleMap, src: SampleMap, delta: Vec ฌ zeroVec, boxes: BoxGenerator, function: Function ฌ nullFunction]; FillBoxes: PROC [map: SampleMap, boxes: BoxGenerator, value: Sample ฌ maxSample, function: Function ฌ nullFunction]; EdgeAction: TYPE ~ PROC [ which: [0..1], -- Which side this specifies sMin: INTEGER, -- First scan line touched sCount: NAT, -- Number of scan lines touched f0: Scaled.Value, -- Initial value of f, offset by 1/2 pixel df: Scaled.Value -- df/ds ]; RegionFill: PROC [dst: RasterSampleMap, edgeGenerator: PROC [EdgeAction], value: Sample ฌ maxSample, function: Function ฌ nullFunction]; BoxesFromBitmap: PROC [map: SampleMap, boxAction: BoxAction]; Trim: PROC [map: SampleMap, box: Box ฌ maxBox, background: Sample ฌ 0] RETURNS [Box]; IsAll: PROC [map: SampleMap, box: Box ฌ maxBox, value: Sample ฌ 0] RETURNS [BOOL]; Equal: PROC [s1, s2: SampleMap] RETURNS [BOOL]; END. p ImagerSample.mesa Copyright ำ 1985, 1986, 1987, 1988, 1989, 1991 by Xerox Corporation. All rights reserved. Michael Plass, August 16, 1991 2:47 pm PDT Doug Wyatt, March 7, 1986 2:41:21 pm PST Samples and SampleBuffers Reverses the order of the samples in the buffer. SampleMap creation -- It is UNSAFE to alter these fields. -- This type defines a two-dimensional array of samples. To avoid confusion no matter how the represented image is oriented, terms like height and width are avoided, and the coordinates are expressed in terms of s and f, for slow and fast. On a display, the s axis is normally vertical, and points down, but on a printer that scans in the long direction, the f axis will point up. The samples are indexed by s in the range [box.min.s..box.max.s) and f in the range [box.min.f..box.max.f). It is the client's responsibility to ensure that an appropriate block of storage is provided; the parameters will be checked for internal consistency; words declares the number of words of storage supplied, starting at base.word; scratchDescriptor may be provided to avoid the need to allocate a new descriptor. Returns number of bits for fSize samples, rounded up to a whole number of words. Returns number of words for sSize scan lines, starting at a word boundary. Returns number of words required for a new sample map of given size. If bitsPerLine=0, bitsPerLine _ BitsForSamples[size.f, bitsPerSample]. Allocates counted storage or counted VM, as needed. If bitsPerLine=0, bitsPerLine _ BitsForSamples[size.f, bitsPerSample]. Allocates a object-oriented sampleMap. Allocates a new map and copies the samples. Get[map, p] = Get[result, SF.Add[p, delta]] result.box = SF.Intersect[box, SF.Displace[map.box, delta]] SampleMap descriptor operations The same caveats apply as for UnsafeNewSampleMap the descriptor is allocated from the scratch pool words declares the number of words of storage supplied, starting at base.word rawMin tells which sample in the raw storage is to be the first actual sample delta will become result.box.min Creates a new descriptor on all or part of the same sample storage the descriptor is allocated from the scratch pool Get[map, p] = Get[result, SF.Add[p, delta]] result.box = SF.Intersect[box, SF.Displace[map.box, delta]] ReIndex[map: map, box: box] ReIndex[map: map, delta: delta] ReIndex[map: temp, delta: SF.Neg[map.box.min]] Releases descriptor to a small pool. Unsafe to use the SampleMap any more after this is called. SampleMap selectors For easier I/O of samplemaps. Error if initial sample is not byte-aligned or if the scanlines are not contiguous. May include up to 7 bits of padding at the end. SampleMap sample access [null, null] dst _ src [or, null] dst _ BITOR[dst, src] [and, null] dst _ BITAND[dst, src] [and, complement] dst _ BITAND[dst, BITNOT[src]] [xor, null] dst _ BITXOR[dst, src] et cetera. Applies a Function to a pair of samples. Gets the indexed sample from the map. BoundsFault if NOT SF.In[index, map.box] Puts modified value into the map at indexed location, dropping extra high-order bits. BoundsFault if NOT SF.In[index, map.box] Gets a run of samples from the map into a buffer. The effect is: FOR j: NAT IN [0..MIN[buffer.length-start, count]) DO p: Vec ~ [s: j*delta.s, f: j*delta.f]; buffer[start+j] _ map.Get[initIndex.Add[p]]; ENDLOOP; except that any BoundsFault may be raised before any samples are moved. tempBox: Box ~ [min: initIndex, max: initIndex.Add[[1, buffer.length]]]; temp: SampleMap ~ NewSampleMap[box: tempBox, bitsPerSample: tile.bitsPerSample]; Tile[map: temp, tile: tile, phase: phase]; GetSamples[map: temp, initIndex: initIndex, buffer: buffer] FOR j: NAT IN [0..MIN[samples.length, thresholds.length]) DO bit: [0..1] ~ IF sampleBuffer[j] > thresholdBuffer[j] THEN 0 ELSE 1; Put[map, min.Add[[0, j]], bit, function]; ENDLOOP; Stores a run of samples from a buffer into the map. The effect is: FOR j: NAT IN [0..MIN[buffer.length-start, count]) DO p: Vec ~ [s: j*delta.s, f: j*delta.f]; map.Put[initIndex.Add[p], buffer[start+j], function]; ENDLOOP; except that any BoundsFault may be raised before any samples are moved. SampleMap block operations A fast way to clear a map to zero. Clears the padding bits on both ends of the scan lines as well as the actual samples. Does not clear words that are entirely unused. Transfers samples to dst from src. The effect is: FOR s: INTEGER IN [0..size.s) DO FOR f: INTEGER IN [0..size.f) DO p: Vec ~ [s: s, f: f]; value: Sample ~ Get[src, p.Add[srcMin]]; Put[dst, p.Add[dstMin], value, function]; ENDLOOP; ENDLOOP; except that if a bounds fault occurs, it occurs before any samples are moved. Transfers samples to dst from src. The effect is: box: Box ~ SF.Intersect[dst.box, SF.Displace[src.box, delta]]; BasicTransfer[dst: dst, src: src, dstMin: box.min, srcMin: SF.Sub[box.min, delta], size: SF.Size[box], function: function]; The effect is: BasicTransfer[dst: map, src: Copy[map], dstMin: dstMin, srcMin: srcMin, size: size, function: function]; (avoids ripple if the source and destination overlap) Fills a box with a constant sample value. The effect is: actualBox: Box ~ Intersect[map.box, box]; FOR s: INTEGER IN [actualBox.min.s..actualBox.max.s) DO FOR f: INTEGER IN [actualBox.min.f..actualBox.max.f) DO Put[map, [s, f], value, function]; ENDLOOP; ENDLOOP; SampleMap raw transfer The ref may be used to prevent premature GC of the memory that basePointer points into; RawListTransfer does not depend on it being provided. Tile operations Makes a tile from a 4-by-4 pattern. Tiles the box with the pattern designated by (tile, phase). The effect is: actualBox: Box ~ Intersect[map.box, box]; tileSize: Vec ~ Size[tile.box]; s0: INT ~ tile.box.min.s; f0: INT ~ tile.box.min.f; FOR s: INTEGER IN [actualBox.min.s..actualBox.max.s) DO FOR f: INTEGER IN [actualBox.min.f..actualBox.max.f) DO sTile: INT ~ s-s0; fTile: INT ~ f-(f0+phase*(sTile div tileSize.s)); value: Sample ~ tile.Get[[s0 + sTile mod tileSize.s, f0 + fTile mod tileSize.f]]; map.Put[[s, f], value, function]; ENDLOOP; ENDLOOP; For div and mod, the sign of the remainder is the sign of the divisor, not the dividend. Tiles each of the boxes. The effect is: tileBox: PROC [box: Box] ~ { true: [TRUE..TRUE] ~ SF.Inside[box, map.box] Tile[map, box, tile, phase, function] }; boxes[tileBox]; SampleMap area operations Transfers several boxes. The effect is: transferBox: PROC [box: Box] ~ { BasicTransfer[dst: dst, src: src, dstMin: box.min, srcMin: SF.Sub[box.min, delta], size: Size[box], function: function]; }; boxes[transferBox]; Note a bounds fault occurs if the BoxGenerator provides a box that is not inside the bounds of both dst and the displaced src, the assumption being that the client has already clipped the boxes. Fills several boxes. The effect is: fillBox: PROC [box: Box] ~ { true: [TRUE..TRUE] ~ SF.Inside[box, map.box]; Fill[map, box, value, function]; }; boxes[fillBox]; Fills a monotone region designated by the edges. The edgeGenerator must specify the edges in nondecreasing sMin order. Clips to the destination bounds. Generates boxes that cover all of the non-zero samples in the SampleMap, and none of the zeros. SampleMap scanning operations For removing a constant border. All of the samples inside Intersect[map.box, box] and outside the resulting box will be equal to background. Tests for a constant. Tests for equality. Equal if s1.box = s2.box and Get[s1, p] = Get[s2, p] for all p in the common box. Note bitsPerSample need not match. ส%•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ฯeœO™ZK™*K™(—K˜šฯk ˜ Kšœžœ&˜2Kšœ žœ ˜2Kšœžœ ˜Kšžœžœ>˜F—K˜Kšะbl œžœž ˜šœž˜K˜Kšœžœžœ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœžœžœ˜Kšœ)˜)Kšœ žœžœ ˜Kšœžœžœ˜%Kšœ žœžœžœ˜K˜šœžœ˜ K˜——head™Kšœžœžœ˜Kšœžœ˜ Kšœ žœ˜#Kšœžœ˜+Kšœžœžœ˜/K˜Kšœžœžœ˜)šœžœžœ˜ Kšœžœ˜ Kšœ žœ žœžœ˜*Kšœ˜K˜—šœ žœ˜+K˜—š ฯn œžœ žœžœžœ˜SK˜—š œžœ žœžœ˜@K™—š œžœ˜3K˜—š œžœ žœ žœ˜FK˜—š œžœ&žœžœžœžœžœ ˜fK˜—š  œžœžœ žœ ˜PK™0K˜—š  œžœ.žœ žœ ˜_K˜—š  œžœ.žœ žœ ˜_K˜—š  œžœžœ žœ ˜QK˜——™Kšœ žœžœ˜#šœžœžœžœ˜%K™)Kšœ ฯc+˜5Kšœ žœ˜Kšœžœ ก˜>šœžœž˜šœ ˜ Kšœ žœก˜(Kšœก˜)Kšœžœก'˜0Kšœ˜—Kšœ(žœ˜-Kšž˜—Kšœ˜Kš œาฯbœขœ(ขœdขœ1ขœ)ขœ%™่K˜—K˜Kšœžœžœ˜-šœžœก#˜=K˜—Kš œžœžœ$žœ*žœ˜oš œžœžœ$žœ*žœ˜ƒK˜—Kšœžœžœ˜0šœžœžœ˜0K˜—K˜š œžœžœ8žœžœ žœ"žœžœ˜รKšœท™ทK˜—K˜š  œžœ žœžœžœžœ˜DK™PK˜—š   œžœ žœžœžœžœ˜AK™JK˜—š   œžœ=žœžœžœ˜eK™DKšœG™GK™—K˜š  œžœ;žœžœ˜pK™3KšœG™GK˜—š œžœfžœžœ˜K™&K˜—š œžœ;žœ˜_Kšœ+™+Kšœ+™+Kšœ žœžœ™;K˜—K˜š œžœ;žœžœ˜uK˜—š œžœ˜)K˜—š œžœ6žœ˜dK˜——šœ™š œžœžœ9žœžœ žœ žœ˜มšœ0™0Kšœ1™1KšœM™MKšœM™MKšœ ™ —K˜—š œžœ;žœ ˜\šœB™BKšœ1™1—Kšœ+™+Kšœ žœžœ™;K˜—š œžœ%žœ ˜CKšœ™K˜—š œžœ(žœ ˜GKšœ™K˜—š  œžœžœ ˜6Kšœžœ™.K˜—š œžœžœ˜0K™$Kšœ:™:K˜——šœ™š  œžœžœ žœžœ ˜HK˜—š  œžœžœ žœžœ-˜|K˜—š   œžœžœžœžœžœ˜UK˜—š  œžœžœžœ˜EK˜—š  œžœžœžœžœ˜fK˜—š  œžœžœžœžœžœ˜^K˜—š  œžœžœžœžœ ˜WK˜—š œžœžœ˜IK™K™„K˜—š  œžœžœžœžœžœ ˜NK˜—š  œžœžœžœžœžœ ˜PK˜——šœ™Kšœ žœ˜%Kšœ žœ˜%Kš œ žœžœž œžœ&˜Ošœ8˜8Kšœ™Kšœžœ ™!Kšœžœ ™#Kšœžœžœ™1Kšœžœ ™#K™ K™—š  œžœ.žœ ˜RK™(K˜—š œžœžœ ˜8K™%Kšœžœžœ™(K˜—š œžœP˜YKšœU™UKšœžœžœ™(K˜—K˜š  œžœdžœ žœ ˜”™Aš žœžœžœžœž™5Kšœ&™&Kšœ,™,Kšžœ™—KšœG™G—K˜—š œžœžœžœ&˜jK•StartOfExpansionT[box: SF.Box, bitsPerSample: IISample.BitsPerSample _ 1, bitsPerLine: NAT _ 0]šœI™IKšœP™PKšœ*™*K–ฒ[self: IISample.SampleMap, initIndex: SF.Vec _ [s: 0, f: 0], delta: SF.Vec _ [s: 0, f: 1], samples: IISample.SampleBuffer, start: NAT _ 0, count: NAT _ 32767]šœ;™;K˜—š œžœžœG˜nš žœžœžœžœ%ž™Kšœ;žœžœ ™{—K˜—š œžœy˜ƒ™Kšœh™h—Kšœ5™5K˜—š œžœd˜n™9Kšœ)™)šžœžœžœ$ž™7šžœžœžœ$ž™7Kšœ"™"Kšžœ™—Kšžœ™——K˜——šœ™š œžœžœžœžœžœžœ˜_Kšœ™K˜—Kš œžœžœžœ3˜l—šœ™š  œžœ žœkžœžœ ˜จKšœ#™#K˜—š œžœ>žœ*˜ušœK™KKšœ)™)Kšœ™Kšœžœ™Kšœžœ™šžœžœžœ$ž™7šžœžœžœ$ž™7Kšœžœ™Kšœžœขœ™1Kšœ%ขœขœ™QKšœ!™!Kšžœ™—Kšžœ™—KšœขœขœI™X—K˜—š  œžœ?žœ*˜{šœ(™(šœ žœ™Kšœžœžœžœ™,Kšœ%™%Kšœ™—Kšœ™—K™——šœ™š  œžœq˜„™(šœ žœ™ Kšœ;žœ;™xKšœ™—Kšœ™—Kšœย™ยK˜—š  œžœf˜u™$šœ žœ™Kšœžœžœžœ™-Kšœ ™ Kšœ™—Kšœ™—K˜—šœ žœžœ˜Kšœก˜+Kšœžœก˜)Kšœžœก˜,Kšœก*˜