DIRECTORY Basics USING [LongMult, BITSHIFT, BITAND, logBitsPerWord, bitsPerWord, HighHalf, LongNumber, BITOR, BITNOT, BytePair], ImagerBasic USING [IntPair], PrincOps USING [DstFunc, SrcFunc, BitAddress, BBTableSpace, BBptr], PrincOpsUtils USING [AlignedBBTable, BITBLT], ImagerPixelMaps USING [PixelMap, PixelMapRep, Function, DeviceRectangle, BoundedWindow], ImagerPixelMapsExtras USING [SetBit, Set2Bits, Set4Bits, Set8Bits, Set16Bits, ByteSequence]; ImagerPixelMapsExtrasImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelMaps, PrincOpsUtils, ImagerPixelMapsExtras EXPORTS ImagerPixelMapsExtras ~ BEGIN BytePair: TYPE ~ Basics.BytePair; IntPair: TYPE ~ ImagerBasic.IntPair; DeviceRectangle: TYPE ~ ImagerPixelMaps.DeviceRectangle; Function: TYPE ~ ImagerPixelMaps.Function; ByteSequence: TYPE ~ ImagerPixelMapsExtras.ByteSequence; PixelMap: TYPE ~ ImagerPixelMaps.PixelMap; lgBitsPerWord: NAT ~ Basics.logBitsPerWord; bitsPerWord: NAT ~ Basics.bitsPerWord; BitAddr: UNSAFE PROC [lineStart: LONG POINTER, pixel: CARDINAL, lgBitsPerPixel: INTEGER] RETURNS [PrincOps.BitAddress] ~ UNCHECKED { RETURN [[ word: lineStart + Basics.BITSHIFT[pixel, lgBitsPerPixel-lgBitsPerWord], bit: Basics.BITAND[Basics.BITSHIFT[pixel, lgBitsPerPixel], bitsPerWord-1] ]] }; SGN: PROCEDURE [number: INTEGER] RETURNS [INTEGER] = INLINE { IF number >= 0 THEN RETURN[1] ELSE RETURN[-1]; }; replicator: ARRAY [0..4] OF CARDINAL ~ [0FFFFH, 05555H, 01111H, 00101H, 00001H]; FillConstantTrap: PUBLIC PROC [destination: PixelMap, -- trapezoid, constant color top, bottom, leftTop, leftBot, rightTop, rightBot: NAT, pxlValue: CARDINAL, function: Function _ [null, null]] ~ TRUSTED { lgBitsPerPixel: NAT ~ destination.refRep.lgBitsPerPixel; bitsPerPixel: NAT ~ Basics.BITSHIFT[1, lgBitsPerPixel]; value: CARDINAL ~ MIN[pxlValue, Basics.BITSHIFT[1, bitsPerPixel] - 1]; rastWds: CARDINAL ~ destination.refRep.rast; rastBits: CARDINAL ~ rastWds * bitsPerWord; EdgeBlock: TYPE = RECORD [xPos: LONG CARDINAL, xIncr: LONG INTEGER]; MakeEdge: UNSAFE PROC[xTop, xBot, height: NAT] RETURNS [edge: EdgeBlock] = { LOOPHOLE[edge.xPos, Basics.LongNumber].highbits _ xBot; LOOPHOLE[edge.xPos, Basics.LongNumber].lowbits _ 0; LOOPHOLE[edge.xIncr, Basics.LongNumber].highbits _ xTop - xBot; LOOPHOLE[edge.xIncr, Basics.LongNumber].lowbits _ 0; IF height > 1 THEN edge.xIncr _ edge.xIncr / height; }; DoScanSeg: UNSAFE PROC[] ~ { PrincOpsUtils.BITBLT[bb]; }; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BBptr _ PrincOpsUtils.AlignedBBTable[@bbspace]; replicatedPixel: CARDINAL _ Basics.BITAND[value, Basics.BITSHIFT[1, Basics.BITSHIFT[1, lgBitsPerPixel]]-1] * replicator[lgBitsPerPixel]; -- make brick for BitBlt lEdge: EdgeBlock _ MakeEdge[leftTop, leftBot, top - bottom]; rEdge: EdgeBlock _ MakeEdge[rightTop, rightBot, top - bottom]; bb^ _ [ dst: BitAddr[destination.refRep.pointer + Basics.LongMult[bottom, rastWds], leftBot, lgBitsPerPixel], dstBpl: rastBits, src: [word: @replicatedPixel, bit: 0], srcDesc: [gray[[yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]], height: 1, width: Basics.BITSHIFT[rightTop - leftTop, lgBitsPerPixel], flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: function.srcFunc, dstFunc: function.dstFunc] ]; FOR height: NAT IN [bottom..top] DO bb.dst _ BitAddr[destination.refRep.pointer + Basics.LongMult[height, rastWds], Basics.HighHalf[lEdge.xPos], lgBitsPerPixel]; bb.width _ Basics.BITSHIFT[ Basics.HighHalf[rEdge.xPos] - Basics.HighHalf[lEdge.xPos] + 1, lgBitsPerPixel ]; DoScanSeg[]; lEdge.xPos _ lEdge.xPos + lEdge.xIncr; rEdge.xPos _ rEdge.xPos + rEdge.xIncr; ENDLOOP; }; FillSmoothTrap: PUBLIC PROC [destination: PixelMap, -- bilinear interpolated 8-bit color top, bottom, leftTop, leftBot, rightTop, rightBot: NAT, leftTopVal, leftBotVal, rightTopVal, rightBotVal: NAT] ~ TRUSTED { rastWds: CARDINAL ~ destination.refRep.rast; rastBits: CARDINAL ~ rastWds * bitsPerWord; EdgeBlock: TYPE = RECORD [xPos, value: LONG CARDINAL, xIncr, valIncr: INT]; MakeEdge: UNSAFE PROC[xTop, valTop, xBot, valBot, height: NAT] RETURNS [edge: EdgeBlock] = { valBot _ MIN[valBot, 255]; valTop _ MIN[valTop, 255]; LOOPHOLE[edge.xPos, Basics.LongNumber].highbits _ xBot; LOOPHOLE[edge.xPos, Basics.LongNumber].lowbits _ 0; LOOPHOLE[edge.xIncr, Basics.LongNumber].highbits _ xTop - xBot; LOOPHOLE[edge.xIncr, Basics.LongNumber].lowbits _ 0; LOOPHOLE[edge.value, Basics.LongNumber].highbits _ valBot; LOOPHOLE[edge.value, Basics.LongNumber].lowbits _ 0; LOOPHOLE[edge.valIncr, Basics.LongNumber].highbits _ valTop - valBot; LOOPHOLE[edge.valIncr, Basics.LongNumber].lowbits _ 0; IF height > 1 THEN { edge.xIncr _ edge.xIncr / height; edge.valIncr _ edge.valIncr / height; }; }; DoScanSeg: PROC[lx, lVal, rx, rVal: LONG CARDINAL] = TRUSTED { value, valIncr: INT; xStart: NAT _ Basics.HighHalf[lx]; xFinish: NAT _ Basics.HighHalf[rx]; length: INTEGER _ xFinish - xStart; leftByte: BOOLEAN; valIncr _ INT[rVal] - INT[lVal]; IF ABS[length] >= 1 THEN valIncr _ valIncr / length; IF xFinish >= xStart THEN { value _ lVal; pxlPtr _ scanPtr + LOOPHOLE[Basics.HighHalf[lx] / 2, CARDINAL]; } ELSE { -- twisted or otherwise backwards xTemp: CARDINAL _ xStart; xStart _ xFinish; xFinish _ xTemp; value _ rVal; pxlPtr _ scanPtr + LOOPHOLE[Basics.HighHalf[rx] / 2, CARDINAL]; }; leftByte _ (xStart MOD 2) = 0; FOR i: NAT IN [xStart..xFinish] DO IF leftByte THEN pxlPtr^.high _ Basics.HighHalf[value] ELSE { pxlPtr^.low _ Basics.HighHalf[value]; pxlPtr _ pxlPtr + 1; }; leftByte _ NOT leftByte; value _ value + valIncr; ENDLOOP; }; scanPtr, pxlPtr: LONG POINTER TO Basics.BytePair; wordsPerLine: NAT _ destination.refRep.rast; lEdge: EdgeBlock _ MakeEdge[leftTop, leftTopVal, leftBot, leftBotVal, top - bottom]; rEdge: EdgeBlock _ MakeEdge[rightTop, rightTopVal, rightBot, rightBotVal, top - bottom]; IF destination.refRep.lgBitsPerPixel # 3 THEN ERROR; TRUSTED { scanPtr _ LOOPHOLE[ destination.refRep.pointer + Basics.LongMult[destination.refRep.rast, bottom], LONG POINTER TO Basics.BytePair]; }; FOR height: NAT IN [bottom..top] DO DoScanSeg[lEdge.xPos, lEdge.value, rEdge.xPos, rEdge.value]; lEdge.xPos _ lEdge.xPos + lEdge.xIncr; lEdge.value _ lEdge.value + lEdge.valIncr; rEdge.xPos _ rEdge.xPos + rEdge.xIncr; rEdge.value _ rEdge.value + rEdge.valIncr; scanPtr _ scanPtr + wordsPerLine; ENDLOOP; }; DrawLine: PUBLIC PROC [destination: PixelMap, p1, p2: IntPair, -- fast line, constant color pxlValue: NAT, function: Function _ [null, null]] ~ { increment, bias, error, sBump, t, shiftDist: INTEGER; wrdPtr: LONG POINTER TO WORD; p1s, p1f, p2s, p2f: INTEGER; lgBitsPerPixel: NAT ~ destination.refRep.lgBitsPerPixel; logPxlsPerWd: NAT ~ Basics.logBitsPerWord - lgBitsPerPixel; bitsPerPixel: NAT ~ Basics.BITSHIFT[1, lgBitsPerPixel]; maxShift: NAT ~ Basics.bitsPerWord - bitsPerPixel; maxValue: NAT ~ Basics.BITSHIFT[1, bitsPerPixel] - 1; value: NAT ~ MIN[pxlValue, maxValue]; p1f _ p1.x; p1s _ p1.y; p2f _ p2.x; p2s _ p2.y; IF p1f > p2f THEN { t _ p1f; p1f _ p2f; p2f _ t; t _ p1s; p1s _ p2s; p2s _ t; }; TRUSTED { wrdPtr _ destination.refRep.pointer + Basics.LongMult[destination.refRep.rast, p1s] + Basics.BITSHIFT[p1f, -logPxlsPerWd]; }; shiftDist _ maxShift - Basics.BITSHIFT[ Basics.BITAND[ p1f, Basics.BITSHIFT[1, logPxlsPerWd] - 1], -- p1f MOD pixelsPerWord lgBitsPerPixel ]; IF (p2f - p1f) > ABS[p2s - p1s] THEN { increment _ 2 * (p2s - p1s); bias _ 2 * (p2f - p1f); sBump _ SGN[increment] * destination.refRep.rast; increment _ ABS[increment]; error _ increment - bias/2; IF lgBitsPerPixel = 3 -- speedup for 8 bits per pixel THEN FOR i: NAT IN [0..(p2f-p1f)] DO TRUSTED { IF shiftDist = 0 THEN { LOOPHOLE[wrdPtr^, BytePair].low _ value; wrdPtr _ wrdPtr + 1; shiftDist _ 8; } ELSE { LOOPHOLE[wrdPtr^, BytePair].high _ value; shiftDist _ 0; }; IF error > 0 THEN TRUSTED { wrdPtr _ wrdPtr + sBump; error _ error - bias; }; error _ error + increment; }; ENDLOOP ELSE FOR i: NAT IN [0..(p2f-p1f)] DO TRUSTED { wrdPtr^ _ Basics.BITOR[ -- deposit pixel bits in word Basics.BITAND[wrdPtr^, Basics.BITNOT[Basics.BITSHIFT[maxValue, shiftDist]]], Basics.BITSHIFT[value, shiftDist] ]; }; IF shiftDist = 0 THEN TRUSTED { wrdPtr _ wrdPtr + 1; shiftDist _ maxShift; } ELSE shiftDist _ shiftDist - bitsPerPixel; IF error > 0 THEN TRUSTED { wrdPtr _ wrdPtr + sBump; error _ error - bias; }; error _ error + increment; ENDLOOP; } ELSE { j: NAT _ Basics.BITSHIFT[shiftDist, -lgBitsPerPixel]; pixelsPerWd: NAT ~ Basics.BITSHIFT[1, logPxlsPerWd]; mask, values: ARRAY [0..16) OF CARDINAL; FOR i: NAT IN [0..pixelsPerWd) DO mask[i] _ Basics.BITNOT[Basics.BITSHIFT[maxValue, Basics.BITSHIFT[i, lgBitsPerPixel]]]; values[i] _ Basics.BITSHIFT[value, Basics.BITSHIFT[i, lgBitsPerPixel]]; ENDLOOP; increment _ 2 * (p2f - p1f); bias _ 2 * (p2s - p1s); sBump _ SGN[bias] * destination.refRep.rast; bias _ ABS[bias]; error _ increment - bias/2; IF lgBitsPerPixel = 3 -- speedup for 8 bits per pixel THEN FOR i: NAT IN [0..ABS[p2s - p1s]] DO TRUSTED { IF shiftDist = 0 THEN { LOOPHOLE[wrdPtr^, BytePair].low _ value; IF error > 0 THEN { wrdPtr _ wrdPtr + 1; shiftDist _ 8; error _ error - bias; }; } ELSE { LOOPHOLE[wrdPtr^, BytePair].high _ value; IF error > 0 THEN { shiftDist _ 0; error _ error - bias; }; }; wrdPtr _ wrdPtr + sBump; error _ error + increment; }; ENDLOOP ELSE FOR i: NAT IN [0..ABS[p2s - p1s]] DO TRUSTED { wrdPtr^ _ Basics.BITOR[ Basics.BITAND[wrdPtr^, mask[j]] , values[j]]; }; TRUSTED { wrdPtr _ wrdPtr + sBump; }; IF error > 0 THEN { error _ error - bias; IF j = 0 THEN TRUSTED { wrdPtr _ wrdPtr + 1; j _ pixelsPerWd - 1; } ELSE j _ j - 1; }; error _ error + increment; ENDLOOP; }; }; DrawBltLine: PUBLIC PROC [destination: PixelMap, -- fast line using BitBLT, constant color p1, p2: IntPair, pxlValue: NAT, function: Function _ [null, null]] ~ TRUSTED { increment, bias, error, sBump, t: INTEGER; p1s, p1f, p2s, p2f: INTEGER; wrdPtr: LONG POINTER; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr _ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; lgBitsPerPixel: NAT ~ destination.refRep.lgBitsPerPixel; logBitsPerPixel: NAT ~ lgBitsPerPixel; bitsPerPixel: NAT ~ Basics.BITSHIFT[1, lgBitsPerPixel]; logPxlsPerWd: NAT ~ Basics.logBitsPerWord - logBitsPerPixel; pxlsPerWordLessOne: NAT ~ Basics.BITSHIFT[1, logPxlsPerWd] - 1; replicatedPixel: CARDINAL _ Basics.BITAND[ value, Basics.BITSHIFT[1, Basics.BITSHIFT[1, logBitsPerPixel]] - 1 ] * replicator[logBitsPerPixel]; -- make brick for BitBlt pxlCnt, leftOverPixels: NAT _ 0; --pixels since last jag in line value: NAT ~ MIN[pxlValue, Basics.BITSHIFT[1, bitsPerPixel] - 1]; p1f _ p1.x; p1s _ p1.y; p2f _ p2.x; p2s _ p2.y; IF p1f > p2f THEN { t _ p1f; p1f _ p2f; p2f _ t; t _ p1s; p1s _ p2s; p2s _ t; }; wrdPtr _ destination.refRep.pointer + Basics.LongMult[destination.refRep.rast, p1s] + Basics.BITSHIFT[p1f, -logPxlsPerWd]; leftOverPixels _ Basics.BITAND[p1f, pxlsPerWordLessOne]; bb^ _ [ dst: [word: wrdPtr, bit: Basics.BITSHIFT[leftOverPixels, logBitsPerPixel]], dstBpl: destination.refRep.rast * Basics.bitsPerWord, src: [word: @replicatedPixel, bit: 0], srcDesc: [gray[[yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]], height: 1, width: bitsPerPixel, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: function.srcFunc, dstFunc: function.dstFunc] ]; IF (p2f - p1f) > ABS[p2s - p1s] THEN { increment _ 2 * (p2s - p1s); bias _ 2 * (p2f - p1f); sBump _ SGN[increment] * destination.refRep.rast; increment _ ABS[increment]; error _ increment - bias/2; FOR i: NAT IN [0..(p2f-p1f)] DO pxlCnt _ pxlCnt + 1; IF error > 0 THEN { -- end of straight segment bb.dst _ [word: wrdPtr, bit: Basics.BITSHIFT[leftOverPixels, logBitsPerPixel] ]; bb.width _ Basics.BITSHIFT[pxlCnt, lgBitsPerPixel]; PrincOpsUtils.BITBLT[bb]; pxlCnt _ pxlCnt + leftOverPixels; wrdPtr _ wrdPtr + sBump + Basics.BITSHIFT[pxlCnt, -logPxlsPerWd]; leftOverPixels _ Basics.BITAND[pxlCnt, pxlsPerWordLessOne]; pxlCnt _ 0; error _ error - bias }; error _ error + increment; ENDLOOP; bb.dst _ [word: wrdPtr, -- BLT last segment bit: Basics.BITSHIFT[leftOverPixels, logBitsPerPixel] ]; bb.width _ Basics.BITSHIFT[pxlCnt, logBitsPerPixel]; PrincOpsUtils.BITBLT[bb]; } ELSE { lastWrdPtr: LONG POINTER TO CARDINAL _ wrdPtr; increment _ 2 * (p2f - p1f); bias _ 2 * (p2s - p1s); sBump _ SGN[bias] * destination.refRep.rast; bias _ ABS[bias]; error _ increment - bias/2; FOR i: NAT IN [0..ABS[p2s - p1s]] DO pxlCnt _ pxlCnt + 1; wrdPtr _ wrdPtr + sBump; IF error > 0 THEN { bb.dst _ [ word: IF sBump < 0 THEN wrdPtr ELSE lastWrdPtr, bit: Basics.BITSHIFT[leftOverPixels, logBitsPerPixel] ]; bb.height _ pxlCnt; PrincOpsUtils.BITBLT[bb]; IF leftOverPixels = pxlsPerWordLessOne THEN { wrdPtr _ wrdPtr + 1; leftOverPixels _ 0; } ELSE leftOverPixels _ leftOverPixels + 1; lastWrdPtr _ wrdPtr; pxlCnt _ 0; error _ error - bias; }; error _ error + increment; ENDLOOP; bb.dst _ [word: IF sBump < 0 THEN wrdPtr ELSE lastWrdPtr, -- BLT last segment bit: Basics.BITSHIFT[leftOverPixels, logBitsPerPixel] ]; bb.height _ pxlCnt; PrincOpsUtils.BITBLT[bb]; }; }; LoadScanSeg: PUBLIC PROC[destination: PixelMap, s, f: INTEGER, length: NAT, segment: LONG POINTER, offset: NAT _ 0] = TRUSTED{ bbspace: PrincOps.BBTableSpace; bb: PrincOps.BBptr _ PrincOpsUtils.AlignedBBTable[@bbspace]; pxpWd: NAT ~ Basics.BITSHIFT[1, Basics.logBitsPerWord - destination.refRep.lgBitsPerPixel]; bb^ _ [ dst: [ word: LOOPHOLE[ destination.refRep.pointer + Basics.LongMult[destination.refRep.rast, s] + (f / pxpWd), LONG POINTER], bit: Basics.BITSHIFT[f MOD pxpWd, destination.refRep.lgBitsPerPixel] ], dstBpl: 0, src: [ word: segment + offset/pxpWd, bit: Basics.BITSHIFT[offset MOD pxpWd, destination.refRep.lgBitsPerPixel] ], srcDesc: [srcBpl[0]], width: Basics.BITSHIFT[length , destination.refRep.lgBitsPerPixel], height: 1, flags: [disjoint: TRUE] ]; PrincOpsUtils.BITBLT[bb]; }; StoreScanSeg: PUBLIC PROC [source: PixelMap, s, f: INTEGER, length: NAT, segment: LONG POINTER, offset: NAT _ 0] = TRUSTED{ bbspace: PrincOps.BBTableSpace; bb: PrincOps.BBptr _ PrincOpsUtils.AlignedBBTable[@bbspace]; pxpWd: NAT ~ Basics.BITSHIFT[1, Basics.logBitsPerWord - source.refRep.lgBitsPerPixel]; bb^ _ [ dst: [ word: segment + offset/pxpWd, bit: Basics.BITSHIFT[offset MOD pxpWd, source.refRep.lgBitsPerPixel] ], dstBpl: 0, src: [ word: LOOPHOLE[ source.refRep.pointer + Basics.LongMult[source.refRep.rast, s] + (f / pxpWd), LONG POINTER], bit: Basics.BITSHIFT[f MOD pxpWd, source.refRep.lgBitsPerPixel] ], srcDesc: [srcBpl[0]], width: Basics.BITSHIFT[length , source.refRep.lgBitsPerPixel], height: 1, flags: [disjoint: TRUE] ]; PrincOpsUtils.BITBLT[bb]; }; SetPixel: PUBLIC PROC [destination: PixelMap, s, f: INTEGER, value: NAT] ~ { bounds: DeviceRectangle _ ImagerPixelMaps.BoundedWindow[destination]; sCheck: NAT _ bounds.sSize-1-NAT[s-bounds.sMin]; fCheck: NAT _ bounds.fSize-1-NAT[f-bounds.fMin]; SELECT destination.refRep.lgBitsPerPixel FROM 0 => ImagerPixelMapsExtras.SetBit[destination, s, f, value]; 1 => ImagerPixelMapsExtras.Set2Bits[destination, s, f, value]; 2 => ImagerPixelMapsExtras.Set4Bits[destination, s, f, value]; 3 => ImagerPixelMapsExtras.Set8Bits[destination, s, f, value]; 4 => ImagerPixelMapsExtras.Set16Bits[destination, s, f, value]; ENDCASE => ERROR; }; END. ImagerPixelMapsExtrasImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Frank Crow, August 16, 1984 9:16:11 am PDT Fancy operations on two-dimensional arrays of pixels. Last Edited by: Stone, August 15, 1984 7:05:30 pm PDT Type Definitions RECORD [ These parameters define a window within the buffer, as well as where the buffer is positioned in device space; they are fair game for clients to modify. sOrigin, fOrigin: INTEGER, sMin, fMin: INTEGER, sSize, fSize: NAT, refRep: REF PixelMapRep ]; PixelMapRep: TYPE ~ RECORD [ ref: REF, pointer: LONG POINTER, words: LONG CARDINAL, lgBitsPerPixel: [0..4], -- logarithm base two of bitsPerPixel rast: CARDINAL, lines: CARDINAL Stored contiguously, with each line padded to a word boundary, rast words per line. The ref is for garbage collection hacks; the long pointer points to the actual bits. Must have rast*lines <= words. Clients should try to avoid dealing directly with this record. ]; Utility Procedures Pixel operations Get necessary constants based on bits per pixel Make sure of positive-going fast coordinate Get pointer to initial word and bit offset More horizontal line (moves faster along fast axis) More vertical line (moves faster along slow axis) Get necessary constants based on bits per pixel Make sure of positive-going fast coordinate Get pointer to initial word and bit offset Set up BITBLT table More horizontal line (moves faster along fast axis) More vertical line (moves faster along slow axis) Raises bounds fault if the point is not in the window. Κέ˜Jšœ™šœ Οmœ1™˜EJšžœ˜—Jšœž˜head2šœ™Iunitšœ žœ˜!Iašœ žœ˜$Jšœžœ#˜8Mšœ žœ˜*Mšœžœ&˜8šœ žœ˜*šžœ™J™™Jšœžœ™Jšœ žœ™Jšœžœ™Jšœžœ ™Jšœ™—šœ žœžœ™Jš œžœ žœžœ žœžœ™6JšœΟc%™=Jšœžœ ž™Jšœ‰™‰Jšœ™———™Jšœžœ˜+Jšœ žœ˜&M˜šΟnœžœžœ žœžœ žœžœžœž œ˜„šžœ˜ Jšœžœ&˜GJšœ žœžœ'˜IJšœ˜—Jšœ˜J˜—š  œž œ žœžœžœžœ˜?Jš žœ žœžœžœžœ˜0Jšœ˜——™Jš œ žœžœžœΟf&œ˜PLš œž œŸ˜SMšœ8žœ˜<šœžœ'žœ˜GLšœžœ%˜8Mšœžœ žœ˜7Mšœžœžœžœ˜FJšœ žœ˜,Jšœ žœ˜+Mš œ žœžœžœžœ žœžœ˜Dš  œžœžœžœžœ˜LJšžœ/˜7Jšžœ+˜3Jšžœ7˜?Jšžœ-˜5Jšžœ žœ#˜5Jšœ˜—Mš  œžœžœžœ ˜;Lšœ˜Jšœ<˜˜>šœ˜JšœL˜LJšœ˜Jšœ˜Jšœ&˜&JšœC˜CJšœ ˜ Jšœžœ%˜;Jšœ&žœžœžœ7˜‚Jšœ˜—J˜šžœ žœžœž˜#JšœP˜PJšœ4˜4Jšœžœ@˜ZJšœ˜Jšœ ˜ J˜'J˜&—Jšžœ˜Jšœ˜—Lš œž œŸ$˜YMšœ<žœ˜@šœ;žœžœ˜LJšœ žœ˜,Jšœ žœ˜+Mš œ žœžœžœžœžœ˜KJš œžœžœ%žœ˜?šœžœ˜$Jšœžœžœ˜8Jšžœ/˜7Jšžœ+˜3Jšžœ7˜?Jšžœ-˜5Jšžœ2˜:Jšžœ,˜4Jšžœ=˜EJšžœ/˜7šžœ ˜JšžœQ˜U—Jšœ˜—š   œžœžœžœžœ˜>Jšœžœ˜Jšœžœ˜"Jšœ žœ˜#Jšœžœ˜#Jšœ žœ˜Lšœ žœ žœ˜ Jšžœžœžœ˜6Jšžœ˜šžœ˜ Jšœ#ž œžœ˜RJšœ˜—šžœŸ!˜4Jšœžœ3˜BJšœ$žœžœ˜QJšœ˜—Jšœžœ˜šžœžœžœž˜"šžœ ˜ Jšžœ&˜*JšžœE˜I—Jšœ žœ ˜Jšœ˜Jšžœ˜ —J˜—Lšœžœžœžœ˜2Jšœžœ˜,MšœT˜TJšœX˜XJšžœ'žœžœ˜4Jšžœžœ˜šœU˜UJšžœžœžœ˜+—šžœ žœžœž˜#Jšœ<˜—Mšœžœ Ÿ#˜GJšœžœžœžœ˜AM˜šœ8˜8LšŸ+™+—šžœ žœY˜jL™*—MšœT˜TMšœžœ˜1šœžœ˜8M™—šœ ˜ Jšœ žœ#˜KJšœ5˜5Jšœ&˜&JšœC˜CJšœ ˜ Jšœ˜Jšœ&žœžœžœ˜MJšœ7˜7Jšœ˜—šžœžœ ˜LšŸ3™3—šžœŸ˜Jšœ ˜ Jšœ˜Jšœžœ&˜1Jšœ žœ ˜J˜šžœžœžœž˜Jšœ˜šžœ žœŸ˜Fšœ˜Jšœžœ"˜8Jšœ˜—Jšœžœ˜3Jšœžœ˜Jšœ!˜!Jšœ!žœ˜AJšœžœ˜;Jšœ ˜ Jšœ˜Jšœ˜—Jšœ˜Jšžœ˜šœ2Ÿ˜EJšœžœ"˜8Jšœ˜—Jšœžœ˜4Jšœžœ˜—J˜LšŸœŸ™1—šžœ˜Jš œ žœžœžœž œž˜.Jšœ ˜ Jšœ˜Jšœžœ!˜,Jšœžœ˜J˜š žœžœžœžœ žœ˜%Jšœ˜Jšœ˜šžœ žœ˜šœžœ žœ žœ ˜=Jšœžœ"˜9Jšœ˜—Jšœ˜Jšœžœ˜šžœ%˜'Jšžœ4˜8Jšžœ&˜*—Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜—Jšœ˜Jšžœ˜šœžœ žœ žœŸ˜SJšœžœ"˜8Jšœ˜—Jšœ˜Jšœžœ˜—Jšœ˜—Mšœ˜M˜—Lš  œžœžœ˜0Mšœžœ žœ˜%š œžœžœ žœžœ˜Jšœ ˜ Jšœžœ˜J˜—Jšœžœ˜Jšœ˜—L˜š œž œž œžœ˜LJ™6JšœE˜EJšœžœžœ˜0Jšœžœžœ˜0šžœ#ž˜-Jšœ<˜˜>Jšœ>˜>Jšœ>˜>Jšœ?˜?Jšžœžœ˜—Jšœ˜——Jšžœ˜—…—>JV;