DIRECTORY Basics USING [DIVMOD, LongDivMod, LongMult], CGArea USING [Empty, Ref, Remove], CGBitmapDevice USING [], -- exports only CGBitmapDeviceExtras USING [], -- exports only CGColor USING [GetStipple], CGDevice USING [Ref, Rep], CGMatrix USING [Inv, InvRel, IsTrivial, Make, Ref], CGSample USING [Flags, Sample0, Sample8, Table], CGScreen USING [Bits], CGSource USING [Mode, Ref, Type], CGStorage USING [pZone, qZone], GraphicsBasic USING [black, Box, Color, Trap, white], GraphicsColor USING [ColorToIntensity], PrincOps USING [BBTableSpace, BitBltTable, BitBltTablePtr], PrincOpsUtils USING [AlignedBBTable, BITBLT], Real USING [Fix, FixC, RoundC]; CGBitmapDeviceImpl: CEDAR PROGRAM IMPORTS Basics, CGArea, CGColor, CGMatrix, CGSample, CGScreen, CGStorage, GraphicsColor, PrincOpsUtils, Real EXPORTS CGBitmapDevice, CGBitmapDeviceExtras = { OPEN CGDevice, GraphicsBasic; dataZone: ZONE = CGStorage.qZone; repZone: ZONE = CGStorage.qZone; brickZone: ZONE = CGStorage.pZone; Error: SIGNAL = CODE; Data: TYPE = REF DataRep; DataRep: TYPE = RECORD [ baseref: REF, -- ref for bitmap (or NIL if screen) base: LONG POINTER, -- base address of bitmap rast: CARDINAL, -- bitmap words per line lines: CARDINAL, -- bitmap lines matrix: CGMatrix.Ref -- base transformation matrix ]; New: PUBLIC PROC[base: REF, raster, height: CARDINAL] RETURNS[Ref] = { data: Data _ dataZone.NEW[DataRep _ [baseref: NIL, base: NIL, rast: 0, lines: 0, matrix: NIL]]; IF base=NIL THEN [base: data.base, raster: raster, height: height] _ CGScreen.Bits[] ELSE { data.baseref _ base; data.base _ LOOPHOLE[base] }; data.rast _ raster; data.lines _ height; data.matrix _ CGMatrix.Make[[1,0,0,-1,0,height]]; RETURN[repZone.NEW[Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: Show, GetRaster: GetRaster, MoveBlock: MoveBlock, data: data]]]; }; UnsafeNew: PUBLIC UNSAFE PROC[base: LONG POINTER, raster, height: CARDINAL] RETURNS[Ref] = { data: Data _ dataZone.NEW[DataRep _ [baseref: NIL, base: base, rast: raster, lines: height, matrix: NIL]]; data.matrix _ CGMatrix.Make[[1,0,0,-1,0,height]]; RETURN[repZone.NEW[Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: Show, GetRaster: GetRaster, MoveBlock: MoveBlock, data: data]]]; }; GetMatrix: PROC[self: Ref] RETURNS[CGMatrix.Ref] = { data: Data _ NARROW[self.data]; RETURN[data.matrix]; }; GetBounds: PROC[self: Ref] RETURNS[Box] = { data: Data _ NARROW[self.data]; w: CARDINAL _ 16*data.rast; h: CARDINAL _ data.lines; e: REAL = 0.1; -- small fudge factor RETURN[[xmin: e, ymin: e, xmax: w-e, ymax: h-e]]; }; GetRaster: PROC[self: Ref] RETURNS[LONG POINTER,CARDINAL] = { data: Data _ NARROW[self.data]; RETURN[data.base,data.rast]; }; Show: PROC[self: Ref, area: CGArea.Ref, src: CGSource.Ref, map: CGMatrix.Ref] = { data: Data _ NARROW[self.data]; fat: BOOLEAN _ (src.fat AND src.type#array); UNTIL CGArea.Empty[area] DO trap: Trap _ CGArea.Remove[area]; IF trap.xbotL=trap.xtopL AND trap.xbotR=trap.xtopR THEN { rect: Box _ [xmin: trap.xbotL, ymin: trap.ybot, xmax: trap.xbotR, ymax: trap.ytop]; ShowRect[data,rect,src,map] } ELSE ShowTrap[data,trap,src,map]; ENDLOOP; }; Bot: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Top: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]+1] }; Fix: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Rnd: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r+.5]] }; RndI: PROC[r: REAL] RETURNS[INTEGER] = INLINE { RETURN[Real.FixC[r+(LAST[INTEGER]+.5)]-LAST[INTEGER]] }; FixF: PROC[r: REAL] RETURNS[LONG INTEGER] = INLINE { RETURN[Real.Fix[r*200000B]] }; Brick: TYPE = REF BrickRep; BrickRep: TYPE = RECORD[w, h, d: CARDINAL, array: SEQUENCE size: CARDINAL OF CARDINAL]; brick3, brick4: Brick _ NIL; currentBrick, defaultBrick: Brick _ NIL; InitBricks: PROC = { index3: ARRAY[0..9) OF NAT = [8,3,6,5,1,9,2,7,4]; index4: ARRAY[0..16) OF NAT = [09,13,08,04,14,07,03,10,06,02,11,15,01,12,16,05]; brick3 _ brickZone.NEW[BrickRep[9] _ [w: 3, h: 3, d: 0, array: ]]; FOR i: NAT IN[0..9) DO brick3[i] _ (255*index3[i]+5)/10 ENDLOOP; brick4 _ brickZone.NEW[BrickRep[16] _ [w: 4, h: 4, d: 0, array: ]]; FOR i: NAT IN[0..16) DO brick4[i] _ (255*index4[i]+8)/17 ENDLOOP; currentBrick _ defaultBrick _ brick3; }; BadArgs: ERROR = CODE; SetBrick: PUBLIC PROC[w, h, d: CARDINAL, proc: PROC[i: CARDINAL] RETURNS[CARDINAL]] = { IF w>0 AND h>0 AND d TRUE, -- always easy array => (CGMatrix.IsTrivial[map] AND src.bps<2), -- bitmap is easy proc => FALSE, -- never easy ENDCASE => ERROR); fat: BOOLEAN _ (src.fat AND type#array); xmin, xmax, ymin, ymax: CARDINAL _ 0; dbase: LONG POINTER _ data.base; drast: CARDINAL _ data.rast; IF fat THEN { xmin _ Bot[rect.xmin]; xmax _ Top[rect.xmax]; ymin _ Bot[rect.ymin]; ymax _ Top[rect.ymax]; } ELSE { xmin _ Rnd[rect.xmin]; xmax _ Rnd[rect.xmax]; ymin _ Rnd[rect.ymin]; ymax _ Rnd[rect.ymax]; }; IF NOT(xmin or, invert => xor, ENDCASE => null); bb.dst.word _ dbase + Basics.LongMult[ymin, drast] + xmin/16; bb.dst.bit _ xmin MOD 16; bb.dstBpl _ drast*16; SELECT type FROM const => { yOffset: [0..4) _ ymin MOD 4; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 3]; bb.srcDesc.gray.yOffset _ yOffset; bb.src.word _ @gray + yOffset; bb.src.bit _ xmin MOD 16; gray _ MakeGray[color]; }; tile => { yOffset: [0..16) _ ymin MOD 16; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 15]; bb.srcDesc.gray.yOffset _ yOffset; bb.src.word _ src.xbase + yOffset; bb.src.bit _ xmin MOD 16; IF mode=transparent AND color=0 THEN { bb.flags.srcFunc _ complement; bb.flags.dstFunc _ and }; }; array => { sxmin: CARDINAL _ Real.FixC[xmin+0.5-map.m.e]; symin: CARDINAL _ Real.FixC[ymin+0.5-map.m.f]; sbase: LONG POINTER _ src.xbase; srast: CARDINAL _ src.xrast; bb.flags.gray _ FALSE; IF (src.bps>0)=(color>0) THEN bb.flags.srcFunc _ complement; bb.src.word _ sbase + Basics.LongMult[symin,srast] + sxmin/16; bb.src.bit _ sxmin MOD 16; bb.srcDesc.srcBpl _ srast*16; }; ENDCASE => ERROR; bb.width _ xmax - xmin; bb.height _ ymax - ymin; PrincOpsUtils.BITBLT[bb]; } ELSE TRUSTED { table: CGSample.Table _ nullSampleTable; rsx, rsy, rsdx, rsdy: REAL; y: CARDINAL _ ymin; [[rsdx,rsdy]] _ CGMatrix.InvRel[map,[1,0]]; table.sdx _ FixF[rsdx]; table.sdy _ FixF[rsdy]; table.sBase _ src.xbase; table.sRast _ src.xrast; table.dLine _ dbase+Basics.LongMult[drast, ymin]; table.di _ xmin; table.count _ xmax-xmin; IF src.bps=8 THEN { brick: Brick _ currentBrick; bbase: LONG POINTER _ @brick[0]; bw, bh, bd, be, br, bx, by: CARDINAL; bw _ brick.w; bh _ brick.h; bd _ brick.d; be _ (IF bd=0 THEN 0 ELSE bw-bd); [quotient: br, remainder: by] _ Basics.DIVMOD[y, bh]; bx _ Basics.LongDivMod[Basics.LongMult[br, be], bw].remainder; table.bLine _ bbase + by*bw; table.bw _ bw; table.bi _ (xmin+bx) MOD bw; table.map _ LOOPHOLE[defaultMap]; DO [[rsx,rsy]] _ CGMatrix.Inv[map,[xmin+0.5,y+0.5]]; table.sx _ FixF[rsx]; table.sy _ FixF[rsy]; CGSample.Sample8[@table, mode]; IF (y _ y+1)=ymax THEN EXIT; table.dLine _ table.dLine+drast; IF (by _ by+1)=bh THEN { by _ 0; table.bLine _ bbase; IF bxymin THEN { IF ymin>ymax THEN SIGNAL Error; RETURN }; -- nothing to do dy _ trap.ytop-trap.ybot; -- delta y dxL _ (trap.xtopL-trap.xbotL)/dy; -- dx/dy, left dxR _ (trap.xtopR-trap.xbotR)/dy; -- dx/dy, right fy _ (ymin+0.5)-trap.ybot; -- distance to middle of first line xL _ trap.xbotL+fy*dxL; xR _ trap.xbotR+fy*dxR; -- left and right x at middle of current line y _ ymin; drast _ data.rast; dline _ data.base + Basics.LongMult[y, drast]; SELECT type FROM const, tile => { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr _ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: ARRAY [0..4) OF CARDINAL; -- gray pattern, if type=const pbase: LONG POINTER; -- pattern base address ph, py: CARDINAL; -- pattern height and current line bb^ _ nullBitBltTable; bb.dstBpl _ drast*16; bb.height _ 1; bb.flags.gray _ TRUE; bb.flags.dstFunc _ (SELECT mode FROM transparent => or, invert => xor, ENDCASE => null); IF type=const THEN { pbase _ @gray; ph _ 4; gray _ MakeGray[color] } ELSE { pbase _ src.xbase; ph _ 16; IF mode=transparent AND color=0 THEN { bb.flags.srcFunc _ complement; bb.flags.dstFunc _ and }; }; py _ y MOD ph; bb.src.word _ pbase + py; bb.srcDesc.gray _ [yOffset: py, widthMinusOne: 0, heightMinusOne: ph-1]; DO xmin _ Rnd[xL]; xmax _ Rnd[xR]; IF xmin IF CGMatrix.IsTrivial[map] AND src.bps=0 THEN { -- easy array bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr _ PrincOpsUtils.AlignedBBTable[@bbspace]; tx, ty: INTEGER; sline: LONG POINTER; srast: CARDINAL; bb^ _ nullBitBltTable; bb.dstBpl _ drast*16; bb.height _ 1; bb.flags.gray _ FALSE; bb.flags.dstFunc _ (SELECT mode FROM transparent => or, invert => xor, ENDCASE => null); IF color=0 THEN { bb.flags.srcFunc _ complement; IF mode=transparent THEN bb.flags.dstFunc _ and }; tx _ RndI[map.m.e]; ty _ RndI[map.m.f]; srast _ src.xrast; sline _ src.xbase + Basics.LongMult[(ymin-ty), srast]; bb.srcDesc.srcBpl _ srast*16; DO xmin _ Rnd[xL]; xmax _ Rnd[xR]; IF xmin ERROR; -- bad src.type }; ShowFatTrap: PROC[data: Data, trap: Trap, src: CGSource.Ref] = TRUSTED { type: CGSource.Type _ src.type; mode: CGSource.Mode _ src.mode; color: CARDINAL _ ColorToStipple[src.color]; ymin, ymax, ylast, xl, xr, y: CARDINAL; dxL, dxR, xbL, xbR, xtL, xtR, dy, fy: REAL; topL, topR: BOOLEAN; dline: LONG POINTER; -- destination line for current y drast: CARDINAL; -- destination raster width (in words) bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr _ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: ARRAY [0..4) OF CARDINAL; -- gray pattern, if type=const pbase: LONG POINTER; -- pattern base address ph, py: CARDINAL; -- pattern height and current line ymin _ Bot[trap.ybot]; ymax _ Top[trap.ytop]; IF NOT ymax>ymin THEN { SIGNAL Error; RETURN }; ylast _ ymax-1; -- ylast is last line y _ ymin; drast _ data.rast; dline _ data.base + Basics.LongMult[y, drast]; bb^ _ nullBitBltTable; bb.dstBpl _ drast*16; bb.height _ 1; bb.flags.gray _ TRUE; bb.flags.dstFunc _ (SELECT mode FROM transparent => or, invert => xor, ENDCASE => null); IF type=const THEN { pbase _ @gray; ph _ 4; gray _ MakeGray[color] } ELSE { pbase _ src.xbase; ph _ 16 }; py _ y MOD ph; bb.src.word _ pbase + py; bb.srcDesc.gray _ [yOffset: py, widthMinusOne: 0, heightMinusOne: ph-1]; xbL _ trap.xbotL; xbR _ trap.xbotR; -- bottom x IF ylast>ymin THEN { -- more than one line dy _ trap.ytop-trap.ybot; -- height of trapezoid dxL _ (trap.xtopL-trap.xbotL)/dy; -- left dx/dy dxR _ (trap.xtopR-trap.xbotR)/dy; -- right dx/dy fy _ (ymin+1)-trap.ybot; -- distance to top of first line xtL _ xbL+fy*dxL; xtR _ xbR+fy*dxR; -- top x topL _ (dxL<0); -- TRUE means leftmost x is at top of line topR _ (dxR>0); -- TRUE means rightmost x is at top of line } ELSE { -- exactly one line xtL _ trap.xtopL; xtR _ trap.xtopR; -- top x topL _ (xtLxbR); -- TRUE means rightmost x is at top of line }; DO -- for each scan line xl _ Bot[IF topL THEN xtL ELSE xbL]; xr _ Top[IF topR THEN xtR ELSE xbR]; IF xl0 AND height>0 AND fromXdx AND (dx+w)>sx AND (sy+h)>dy AND (dy+h)>sy THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF dy=sy THEN bb.flags.disjointItems _ FALSE; -- so do the items IF dy>sy OR (dy=sy AND dx>sx) THEN { -- reverse direction bb.flags.direction _ backward; bpl _ -bpl; sy _ sy + (h-1); dy _ dy + (h-1); }; }; bb.dst.word _ dbase + Basics.LongMult[dy, drast] + dx/16; bb.dst.bit _ dx MOD 16; bb.src.word _ dbase + Basics.LongMult[sy, drast] + sx/16; bb.src.bit _ sx MOD 16; bb.dstBpl _ bb.srcDesc.srcBpl _ bpl; bb.width _ w; bb.height _ h; PrincOpsUtils.BITBLT[bb]; }; }; InitBricks[]; }. zCGBitmapDeviceImpl.mesa Last changed by Paul Rovner, August 10, 1983 11:29 am Last changed by Doug Wyatt, January 13, 1984 4:54 pm weird "transparent white" semantics for McGregor's grey text hack: map transforms source coordinates to device coordinates Since this is an easy case, we know map is a simple translation; so subtracting map's translation elements will take us from device to source function#0 means "white" (by private agreement with Sample0) weird "transparent white" semantics for McGregor's grey text hack: The matrix 'map' transforms source coordinates to device coordinates. Here we know map is a simple translation, so subtracting its translation elements will take us from device to source coordinates. function#0 means "white" (by private agreement with Sample0) compute ymin (bottom of first scanline) and ymax (top of last scanline) ---- Initialization ------ ÊC˜šœ™Jšœ5™5Jšœ4™4—J˜šÏk ˜ Jšœœœ˜,Jšœœ˜"JšœœÏc˜(Jšœœž˜.Jšœœ˜Jšœ œ ˜Jšœ œ%˜3Jšœ œ"˜0Jšœ œ˜Jšœ œ˜!Jšœ œ˜Jšœœ"˜5Jšœœ˜'Jšœ œ-˜;Jšœœœ˜-Jšœœ˜J˜—Jšœœ˜!šœB˜IJ˜"—Jšœ)˜0Jšœ˜J˜Jšœ œ˜!Jšœ œ˜ Jšœ œ˜"J˜Jšœœœ˜J˜Jšœœœ ˜šœ œœ˜Jšœ œž$˜2Jšœœœž˜-Jšœœž˜(Jšœœž˜ Jšœž˜2J˜J˜—š Ïnœœœœœœ ˜FJš œœœœœ˜_JšœœœD˜TJšœ$œ ˜9J˜(J˜1šœ œ˜J˜7J˜:—J˜J˜—šŸ œœœœœœœœ ˜\šœœœ˜2Jšœ1œ˜7—J˜1šœ œ˜J˜7J˜:—J˜J˜—šŸ œœ œ˜4Jšœ œ ˜Jšœ˜J˜J˜—šŸ œœ œ ˜+Jšœ œ ˜Jšœœ˜Jšœœ˜Jšœœž˜$Jšœ+˜1J˜J˜—š Ÿ œœ œœœœ˜=Jšœ œ ˜Jšœ˜J˜J˜—šŸœœG˜QJšœ œ ˜Jšœœ œ˜,šœ˜J˜!šœœœ˜9J˜SJ˜—Jšœ˜!Jšœ˜—J˜J˜—JšŸœœœœœœœ˜GJšŸœœœœœœœ˜IJšŸœœœœœœœ˜GJšŸœœœœœœœ˜Jš Ÿœœœœœœ˜/Jš œœœœœ˜8—šŸœœœœœœœ˜4Jšœ˜J˜J˜—Jšœœœ ˜Jšœ œœ œ œœœœ˜WJ˜Jšœœ˜Jšœ$œ˜(J˜šŸ œœ˜Jšœœœœ˜1Jšœœœœ5˜PJšœœ,˜BJš œœœœ"œ˜@Jšœœ-˜CJš œœœœ"œ˜AJ˜%J˜J˜—Jšœ œœ˜J˜šŸœœœ œ˜(Jš œœœœœ˜.šœœœœœœœ˜FJšœœ˜Jšœœ/˜KJš œœœ œœ˜5J˜—Jšœœ ˜J˜J˜—JšŸ œœœ#˜:J˜Jšœœ ˜J˜š Ÿœœœœœ ˜7Jšœ œœœ˜7J˜J˜—Jšœœœœ˜!J˜šœ œœœ˜'J˜GJ˜HJ˜—Jš œ œœœœ˜+J˜š Ÿœœœœœ˜=Jš œ œœœ œœ˜JJ˜—šŸ œœœœ˜6Jšœœ˜šœœ œ˜!š œœ œœ˜&Jšœœ˜1Jšœ˜ ——Jšœ˜ J˜J˜—š Ÿœœœœœ˜MJšœœœ ˜1Jšœœœœ˜0Jšœœœœ˜@Jšœœ˜%J˜—šŸœœœœ˜Fšœœ œœ˜$J˜9J˜.—Jšœœœ˜;šœœ)˜?Jšœ(œ ˜;—J˜J˜—šœ5œ˜MJšœ œ5˜DJšœœœ!˜CJ˜—˜/Jš œœ œ œ œ ˜E—˜:Jšœ'œ œœ˜OJšœœœ)˜MJ˜J˜—Jš œ œœ œœ˜+Jšœ œ˜,šŸœœœœ˜.Jšœœœ ˜*Jš œœœ œ œ˜,Jšœ˜J˜—šŸœœA˜OJ˜J˜šœœœ˜!Jšœœž˜#Jšœ"œ ž˜CJšœœž ˜Jšœœ˜—Jšœœ œ ˜(Jšœœ˜%Jšœœœ ˜ Jšœœ ˜šœœ˜ J˜-J˜-J˜—šœ˜J˜-J˜-J˜—Jš œœ œ œœž˜=šœœœ˜J˜J˜EJšœœœœ˜Jšœœ˜,J˜Jšœœœ#œ ˜XJ˜=Jšœœ˜/šœ˜šœ"œ˜(J˜DJ˜"Jšœ1œ˜8J˜J˜—šœ"œ˜)J˜EJ˜"Jšœ5œ˜Jšœœ˜J˜J˜—Jšœœ˜—J˜0Jšœœ˜J˜—šœœ˜J˜(Jšœœ˜Jšœœ˜J˜+J˜/J˜1J˜1J˜)šœ œ˜J˜Jšœœœ ˜ Jšœœ˜%J˜)Jšœœœœ˜!Jšœ'œ˜5J˜>J˜+Jšœœ˜Jšœ œ ˜!š˜J˜1J˜+J˜Jšœœœ˜J˜ šœœ˜5Jšœœ œ ˜)Jšœœ˜—Jšœ˜"Jšœ˜—J˜—šœœ œ˜šœœ˜?Jšœ<™<—š˜J˜1J˜+J˜Jšœœœ˜J˜ Jšœ˜—J˜—Jšœœ˜ J˜—J˜J˜—šŸœœAœ˜XJ˜J˜Jšœœ˜,Jšœœ˜$Jšœœ˜Jšœœœž!˜6Jšœœž&˜7J˜Jšœ œ œ!œ˜HJ˜-Jšœœ œœ œœœž˜RJšœž ˜$Jšœ"ž˜0Jšœ"ž˜1Jšœž#˜>Jšœ0ž-˜]J˜Kšœ˜˜J˜J˜EJšœœœœž˜>Jšœœœž˜,Jšœœž"˜4J˜Jšœ5œ˜:Jšœœœ#œ ˜XJšœ œ2˜Dšœ˜"JšœB™Bšœœ œ˜&J˜8—J˜—Jšœœ˜(J˜Hšœ ˜"šœ œ˜Jšœ1œ˜8J˜.Jšœœ˜—Jšœœœ˜Jšœž˜4Jšœž˜/Jšœœ ˜6Jšœ ž˜8Jšœ˜—J˜—šœ œœ œž ˜FJ˜J˜EJšœœ˜Jšœœœ˜Jšœœ˜J˜Jšœ5œ˜;Jšœœœ#œ ˜Xšœ œ!˜0Jšœœ˜2—JšœE™EJšœH™HJšœ8™8J˜'J˜IJ˜šœ ˜"šœ œ œ ˜.Jšœ1œ˜8Jšœ3œ˜:J˜Jšœœ˜—Jšœœœ˜Jšœž˜4Jšœž˜-Jšœž˜(Jšœ˜—J˜—šœž ˜J˜(Jšœœ˜J˜+J˜-J˜1šœ œ˜J˜Jšœœœ ˜ Jšœœ˜%J˜)Jšœœœœ˜!Jšœ'œ˜5J˜>J˜+Jšœ œ ˜!šœ ˜"šœ œ˜J˜2J˜)Jšœœ˜J˜%J˜J˜J˜—Jšœœœ˜Jšœž˜4Jšœž˜-šœœ˜5Jšœœ œ ˜*—Jšœž˜5Jšœ˜—J˜—šœœ œ˜šœœ˜?Jšœ<™<—šœ ˜"šœ œ˜J˜2J˜)J˜%J˜J˜J˜—Jšœœœ˜Jšœž˜4Jšœž˜-Jšœ˜—J˜—Jšœœ˜ J˜—Jšœœž˜!—J˜J˜—šŸ œœ.œ˜HJ˜J˜Jšœœ˜,Jšœœ˜'Jšœ&œ˜+Jšœ œ˜Jšœœœž!˜6Jšœœž&˜7J˜J˜EJšœœœœž˜>Jšœœœž˜,Jšœœž"˜4J˜JšœG™GJ˜-Jš œœ œœœ˜/Jšœž˜%J˜KJ˜Jšœ5œ˜:Jšœœœ#œ ˜XJšœ œ2˜DJšœ ˜$Jšœœ˜(J˜HJ˜Jšœ$ž ˜/šœ œž˜*Jšœž˜0Jšœ"ž ˜/Jšœ"ž˜0Jšœž ˜9Jšœ$ž˜,Jšœž*˜:Jšœž+˜;J˜—šœž˜Jšœ$ž˜,Jšœž*˜