DIRECTORY Basics USING [bitsPerWord, LongMult], ImagerColor, ImagerDevice USING [Class, ClassRep, Device, DeviceRep, HalftoneParameters, RunProc], ImagerPixelArray, ImagerPixelMap USING [Create, DeviceRectangle, Function, PixelMap], ImagerPixelRow USING [ClearPixelRow, CreatePixelRow, PixelRow, StorePixelRow], ImagerSampler USING [CreateSampler, DotScreen, HalftoneLine, ObtainPointSamples, Sampler], ImagerTransformation USING [Cat, Copy, PreRotate, PreScale, Transformation, Translate], PrincOps USING [BBTableSpace, BitBltTable, BitBltTablePtr, zBNDCK, zINC], PrincOpsUtils USING [AlignedBBTable, BITBLT], Real USING [FixC], Vector2 USING [VEC]; ImagerLFDeviceImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelArray, ImagerPixelMap, ImagerPixelRow, ImagerSampler, ImagerTransformation, PrincOpsUtils, Real ~ BEGIN Device: TYPE ~ ImagerDevice.Device; RunProc: TYPE ~ ImagerDevice.RunProc; HalftoneParameters: TYPE ~ ImagerDevice.HalftoneParameters; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; VEC: TYPE ~ Vector2.VEC; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColor.Color; ConstantColor: TYPE ~ ImagerColor.ConstantColor; SampledColor: TYPE ~ ImagerColor.SampledColor; SpecialColor: TYPE ~ ImagerColor.SpecialColor; ColorOperator: TYPE ~ ImagerColor.ColorOperator; ColorOperatorRep: TYPE ~ ImagerColor.ColorOperatorRep; GrayArray: TYPE ~ ARRAY [0..16) OF CARDINAL; grayHeight: NAT ~ 16; -- must not exceed 16, should be a power of 2 checkeredGray: GrayArray ~ [ 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH -- @ . @ . @ . @ . @ . @ . @ . @ . ]; desktopGray: GrayArray ~ [ 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H -- . @ . . . @ . . . @ . . . @ . . ]; Case: TYPE ~ {nil, constant, gray, sampled}; defaultHalftone: HalftoneParameters _ [dotsPerInch: 18, angle: 30, shape: 0.5]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ frame: ImagerPixelMap.PixelMap, -- the bitmap pixelsPerInch: REAL, -- declared resolution dot: ImagerPixelMap.PixelMap, -- a halftone dot case: Case _ nil, -- what type of color function: ImagerPixelMap.Function _ [null, null], -- bitblt function gray: GrayArray _ ALL[0], -- bitblt gray block halftone: HalftoneParameters _ defaultHalftone, -- halftone screen parameters pa: ImagerPixelArray.PixelArray _ NIL, -- pixel array from sampled color multiplier: CARDINAL _ 1, lgScale: INTEGER _ 0, -- scale pa samples to match dot samples transparent: BOOL _ FALSE, paToDevice: Transformation _ NIL, -- transformation from pa coords to display dotToDevice: Transformation _ NIL, -- transformation from dot coords to display source: ImagerPixelMap.PixelMap _ [0, 0, 0, 0, 0, 0, NIL], -- source values from pixel array paSampler: ImagerSampler.Sampler _ NIL, -- for sampling pixel array dotSampler: ImagerSampler.Sampler _ NIL, -- for sampling halftone dot paRow: ImagerPixelRow.PixelRow _ NIL, -- buffer for pixels sampled from pa dotRow: ImagerPixelRow.PixelRow _ NIL -- buffer for pixels sampled from dot ]; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $LFDisplay, SetColor: SetColor, SetPriority: SetPriority, SetHalftone: SetHalftone, MaskRuns: MaskRuns ]]; defaultDot: ImagerPixelMap.PixelMap ~ ImagerSampler.DotScreen[ r: 0.5, sSize: 16, fSize: 16, maxPixelValue: 255]; defaultPixelsPerInch: REAL ~ 72; Create: PUBLIC PROC[frame: ImagerPixelMap.PixelMap, pixelsPerInch: REAL _ defaultPixelsPerInch] RETURNS[Device] ~ { data: Data ~ NEW[DataRep _ [frame: frame, pixelsPerInch: pixelsPerInch, dot: defaultDot]]; surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frame.sSize, 0]]; surfaceToDevice.PreRotate[90]; data.paRow _ ImagerPixelRow.CreatePixelRow[sMin: 0, fMin: 0, fSize: frame.fSize]; data.dotRow _ ImagerPixelRow.CreatePixelRow[sMin: 0, fMin: 0, fSize: frame.fSize]; RETURN[NEW[ImagerDevice.DeviceRep _ [class: class, clipBox: [sMin: 0, fMin: 0, sSize: frame.sSize, fSize: frame.fSize], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch], surfaceUnitsPerPixel: 1, data: data]]]; }; Val: TYPE ~ ImagerPixelArray.Val; Table: TYPE ~ REF TableRep; TableRep: TYPE ~ RECORD[SEQUENCE size: NAT OF CARDINAL]; BuildTable: PROC[max: Val, scale: REAL, sWhite, sBlack: REAL, map: ImagerColor.SampleMap _ NIL] RETURNS[Table] ~ { table: Table ~ NEW[TableRep[max+1]]; FOR s0: Val IN[0..max] DO s: REAL ~ IF map=NIL THEN s0 ELSE map[s0]; v: REAL ~ MIN[MAX[(s-sBlack)/(sWhite-sBlack), 0], 1]; table[s0] _ Real.FixC[scale*v]; ENDLOOP; RETURN[table]; }; SetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; WITH color SELECT FROM color: ConstantColor => { data.function _ [null, null]; SELECT color.cie.Y FROM 0 => { data.gray _ ALL[177777B]; data.case _ constant }; 1 => { data.gray _ ALL[0]; data.case _ constant }; ENDCASE => { data.gray _ checkeredGray; data.case _ gray }; }; color: SampledColor => { pa: ImagerPixelArray.PixelArray ~ color.pa; samples: ImagerPixelArray.Row ~ NEW[ImagerPixelArray.RowRep[pa.fSize]]; row: ImagerPixelRow.PixelRow ~ ImagerPixelRow.CreatePixelRow[ sMin: 0, fMin: 0, fSize: pa.fSize]; data.pa _ pa; data.paToDevice _ ImagerTransformation.Cat[pa.m, color.um, viewToDevice]; data.dotToDevice _ viewToDevice.Copy[]; data.dotToDevice.PreScale[data.pixelsPerInch/(data.halftone.dotsPerInch*16)]; data.dotToDevice.PreRotate[data.halftone.angle]; data.source _ ImagerPixelMap.Create[lgBitsPerPixel: 3, bounds: [sMin: 0, fMin: 0, sSize: pa.sSize, fSize: pa.fSize]]; WITH color.colorOperator SELECT FROM op: REF ColorOperatorRep.grayLinear => { table: Table _ NIL; IF pa.samplesPerPixel#1 THEN ERROR; -- samplesPerPixel must be 1 table _ BuildTable[max: pa.MaxSampleValue[0], scale: 255, sWhite: op.sWhite, sBlack: op.sBlack, map: op.map]; FOR s: NAT IN[0..pa.sSize) DO ImagerPixelArray.GetRow[pa, samples, s, 0, 0]; FOR f: NAT IN[0..pa.fSize) DO row[f] _ table[samples[f]] ENDLOOP; row.sOrigin _ s; ImagerPixelRow.StorePixelRow[row, data.source]; ENDLOOP; }; op: REF ColorOperatorRep.separations => { tables: ARRAY[0..4) OF Table _ ALL[NIL]; IF pa.samplesPerPixel#op.samplesPerPixel THEN ERROR; -- samplesPerPixel must match FOR i: NAT IN[0..pa.samplesPerPixel) DO sep: ImagerColor.Separation ~ op[i]; tables[i] _ BuildTable[max: pa.MaxSampleValue[i], scale: 255*sep.cie.Y, sWhite: sep.sMax, sBlack: sep.sMin, map: sep.map]; ENDLOOP; FOR s: NAT IN[0..pa.sSize) DO row.sOrigin _ s; ImagerPixelRow.ClearPixelRow[row]; FOR i: NAT IN[0..pa.samplesPerPixel) DO table: Table ~ tables[i]; ImagerPixelArray.GetRow[pa, samples, s, 0, i]; FOR f: NAT IN[0..pa.fSize) DO row[f] _ row[f]+table[samples[f]] ENDLOOP; ENDLOOP; ImagerPixelRow.StorePixelRow[row, data.source]; ENDLOOP; }; ENDCASE => ERROR; -- unknown ColorOperator data.paSampler _ ImagerSampler.CreateSampler[ m: data.paToDevice, x: 0, y: 0, sPixels: pa.sSize, fPixels: pa.fSize]; data.dotSampler _ ImagerSampler.CreateSampler[ m: data.dotToDevice, x: 0, y: 0, sPixels: data.dot.sSize, fPixels: data.dot.fSize]; data.case _ sampled; }; color: SpecialColor => SELECT color.ref FROM $XOR => { data.function _ [xor, null]; data.gray _ ALL[177777B]; data.case _ constant; }; ENDCASE => ERROR; -- unknown special color ENDCASE => ERROR; -- unknown color variant }; SetPriority: PROC[device: Device, priorityImportant: BOOL] ~ { }; SetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ { data: Data ~ NARROW[device.data]; data.halftone _ halftone; }; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: []]; Check: PROC[x: INTEGER, max: NAT] RETURNS[NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; MaskRuns: PROC[device: Device, runs: PROC[RunProc]] ~ { data: Data ~ NARROW[device.data]; frame: ImagerPixelMap.PixelMap ~ data.frame; SELECT data.case FROM nil => ERROR; -- color not initialized constant, gray => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: LONG POINTER ~ @data.gray; base: LONG POINTER ~ frame.refRep.pointer; rast: CARDINAL ~ frame.refRep.rast; runConstant: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, frame.fSize]; s: NAT ~ Check[sMin, frame.sSize]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ f MOD Basics.bitsPerWord; bb.width _ Check[fSize, frame.fSize-f]; bb.height _ Check[1, frame.sSize-s]; PrincOpsUtils.BITBLT[bb]; }; runGray: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, frame.fSize]; s: NAT ~ Check[sMin, frame.sSize]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ bb.src.bit _ f MOD Basics.bitsPerWord; bb.src.word _ gray+(bb.srcDesc.gray.yOffset _ s MOD grayHeight); bb.width _ Check[fSize, frame.fSize-f]; bb.height _ Check[1, frame.sSize-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ rast*Basics.bitsPerWord; bb.src.word _ gray; bb.src.bit _ 0; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: grayHeight-1]; bb.flags _ [direction: forward, disjoint: TRUE, gray: TRUE, srcFunc: data.function.srcFunc, dstFunc: data.function.dstFunc]; runs[IF data.case=constant THEN runConstant ELSE runGray]; }; sampled => { paRow: ImagerPixelRow.PixelRow ~ data.paRow; dotRow: ImagerPixelRow.PixelRow ~ data.dotRow; pa: ImagerPixelArray.PixelArray ~ data.pa; -- pixel array from sampled color source: ImagerPixelMap.PixelMap ~ data.source; run: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ { paRow.sOrigin _ dotRow.sOrigin _ Check[sMin, frame.sSize]; paRow.fOrigin _ dotRow.fOrigin _ Check[fMin, frame.fSize]; paRow.fSize _ dotRow.fSize _ Check[fSize, frame.fSize-fMin]; ImagerSampler.ObtainPointSamples[sampler: data.paSampler, pixelRow: paRow, source: source, multiplier: data.multiplier, lgScale: data.lgScale]; ImagerSampler.ObtainPointSamples[sampler: data.dotSampler, pixelRow: dotRow, source: data.dot]; ImagerSampler.HalftoneLine[dest: frame, pixels: paRow, thresholds: dotRow, invertOutput: FALSE, transparent: data.transparent]; }; runs[run]; }; ENDCASE => ERROR; -- illegal case }; END.  ImagerLFDeviceImpl.mesa Copyright c 1984 Xerox Corporation. All rights reserved. Michael Plass, June 19, 1984 1:19:53 pm PDT Doug Wyatt, November 5, 1984 3:18:31 pm PST IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault Might want to interpolate or average here. How do we decide? MaskRectanglesGray: PROC[device: Device, rectangles: PROC[RectangleProc]] ~ TRUSTED { data: Data ~ NARROW[device.data]; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: LONG POINTER ~ @data.gray; base: LONG POINTER ~ data.frame.refRep.pointer; rast: CARDINAL ~ data.frame.refRep.rast; fSizeDevice: NAT ~ data.frame.fSize; sSizeDevice: NAT ~ data.frame.sSize; rectangle: PROC[r: DeviceRectangle] ~ TRUSTED { f: NAT ~ Check[r.fMin, fSizeDevice]; s: NAT ~ Check[r.sMin, sSizeDevice]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ bb.src.bit _ f MOD Basics.bitsPerWord; bb.src.word _ gray+(bb.srcDesc.gray.yOffset _ s MOD grayHeight); bb.width _ Check[r.fSize, fSizeDevice-f]; bb.height _ Check[r.sSize, sSizeDevice-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ rast*Basics.bitsPerWord; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: grayHeight-1]; bb.flags _ [direction: forward, disjoint: TRUE, gray: TRUE, srcFunc: data.function.srcFunc, dstFunc: data.function.dstFunc]; rectangles[rectangle]; }; MaskRectanglesConst: PROC[device: Device, rectangles: PROC[RectangleProc]] ~ TRUSTED { data: Data ~ NARROW[device.data]; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: LONG POINTER ~ @data.gray; base: LONG POINTER ~ data.frame.refRep.pointer; rast: CARDINAL ~ data.frame.refRep.rast; fSizeDevice: NAT ~ data.frame.fSize; sSizeDevice: NAT ~ data.frame.sSize; rectangle: PROC[r: DeviceRectangle] ~ TRUSTED { f: NAT ~ Check[r.fMin, fSizeDevice]; s: NAT ~ Check[r.sMin, sSizeDevice]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ f MOD Basics.bitsPerWord; bb.width _ Check[r.fSize, fSizeDevice-f]; bb.height _ Check[r.sSize, sSizeDevice-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ rast*Basics.bitsPerWord; bb.src.word _ gray; bb.src.bit _ 0; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: grayHeight-1]; bb.flags _ [direction: forward, disjoint: TRUE, gray: TRUE, srcFunc: data.function.srcFunc, dstFunc: data.function.dstFunc]; rectangles[rectangle]; }; MaskRunsGray: PROC[device: Device, runs: PROC[RunProc]] ~ TRUSTED { data: Data ~ NARROW[device.data]; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: LONG POINTER ~ @data.gray; base: LONG POINTER ~ data.frame.refRep.pointer; rast: CARDINAL ~ data.frame.refRep.rast; fSizeDevice: NAT ~ data.frame.fSize; sSizeDevice: NAT ~ data.frame.sSize; run: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, fSizeDevice]; s: NAT ~ Check[sMin, sSizeDevice]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ bb.src.bit _ f MOD Basics.bitsPerWord; bb.src.word _ gray+(bb.srcDesc.gray.yOffset _ s MOD grayHeight); bb.width _ Check[fSize, fSizeDevice-f]; bb.height _ Check[1, sSizeDevice-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ rast*Basics.bitsPerWord; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: grayHeight-1]; bb.flags _ [direction: forward, disjoint: TRUE, gray: TRUE, srcFunc: data.function.srcFunc, dstFunc: data.function.dstFunc]; runs[run]; }; Ê É˜šœ™Jšœ Ïmœ.™9J™+J™+—J˜šÏk ˜ Jšœžœ˜%Jšœ ˜ Jšœ žœC˜UJšœ˜Jšœžœ/˜CJšœžœ:˜NJšœžœG˜ZJšœžœ=˜WJšœ žœ;˜IJšœžœžœ˜-Jšœžœ˜Jšœžœžœ˜J˜—Jšœžœž˜!Jšžœs˜zJšœž˜J˜Jšœžœ˜#Jšœ žœ˜%Jšœžœ#˜;Jšœžœ"˜7J˜Jšžœžœ žœ˜Jšœžœ'˜;Jšœžœ˜ Jšœžœ˜0Jšœžœ˜.Jšœžœ˜.Jšœžœ˜0Jšœžœ ˜6J˜Jš œ žœžœ žœžœ˜,Jšœ žœÏc-˜CJ˜˜JšÏf*˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*J˜J˜—˜Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*Jš *˜*J˜J˜—Jšœžœ"˜,J˜JšœO˜OJ˜Jšœžœžœ ˜šœ žœžœ˜Jšœ Ÿ ˜-JšœžœŸ˜+JšœŸ˜/JšœŸ˜'Jšœ2Ÿ˜DJšœžœŸ˜.Jšœ0Ÿ˜MJšœ"žœŸ!˜HJšœ žœžœŸ(˜XJšœ žœžœ˜JšœžœŸ+˜MJšœžœŸ,˜OJšœ5žœŸ!˜\Jšœ#žœŸ˜CJšœ$žœŸ˜EJšœ!žœŸ$˜JJšœ"žœŸ%˜KJ˜J˜—šœžœ˜9Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—šœ>˜>Jšœ2˜2J˜—šœžœ˜ J˜—šÏnœžœžœ ˜3Jšœžœžœ ˜?Jšœ žœJ˜ZJšœS˜SJšœ˜J˜QJ˜Ršžœžœ(˜2JšœD˜DJšœ!˜!Jšœ4˜4Jšœ˜Jšœ˜—J˜J˜—Jšœžœ˜!Jšœžœžœ ˜Jš œ žœžœžœžœžœžœ˜8J˜š¡ œžœžœžœ˜=Jšœžœžœ ˜4Jšœžœ˜$šžœ žœ ž˜Jš œžœžœžœžœžœ ˜*Jšœžœžœžœ$˜5Jšœ˜Jšžœ˜—Jšžœ˜J˜J˜—š¡œžœ@˜NJšœ žœ˜!šžœžœž˜˜Jšœ˜šžœ žœž˜Jšœžœ"˜8Jšœžœ˜2Jšžœ4˜;—J˜—˜Jšœ+˜+Jšœ žœ$˜G˜=J˜#—J˜ JšœI˜IJšœ'˜'JšœM˜MJšœ0˜0šœ6˜6Jšœ>˜>—šžœžœž˜$šœžœ!˜(Jšœžœ˜JšžœžœžœŸ˜@šœ9˜9Jšœ3˜3—šžœžœžœž˜Jšœ.˜.Jš žœžœžœžœžœ˜AJ˜J˜/Jšžœ˜—J˜—šœžœ"˜)Jš œžœžœ žœžœ˜(Jšžœ'žœžœŸ˜Ršžœžœžœž˜'J˜$šœEžœ˜GJšœ2˜2—Jšžœ˜—šžœžœžœž˜J˜Jšœ"˜"šžœžœžœž˜'J˜J˜.Jš žœžœžœžœ#žœ˜HJšžœ˜—J˜/Jšžœ˜—J˜—JšžœžœŸ˜*—šœ-˜-JšœF˜F—šœ.˜.JšœS˜S—J˜J˜—šœžœ ž˜,šœ ˜ Jšœ˜Jšœ žœ ˜J˜J˜—JšžœžœŸ˜*—JšžœžœŸ˜*—Jšœ˜J˜—š¡ œžœ$žœ˜>Jšœ˜J˜—š¡ œžœ2˜CJšœ žœ˜!J˜J˜J˜—šœ)˜)Jšœ žœ˜$Jšœ žœ ˜/Jšœ ˜ J˜—š ¡œžœžœžœžœžœ˜0Jšžœžœžœ$˜8Jš žœžœ žœžœžœžœ™BJ˜—š¡œžœžœ˜7Jšœ žœ˜!Jšœ,˜,šžœ ž˜JšœžœŸ˜&šœžœ˜J˜JšœE˜EJšœžœžœ˜ Jšœžœžœ˜*Jšœžœ˜#š œ žœ žœ žœžœ˜>Jšœžœ˜"Jšœžœ˜"JšœA˜AJšœžœ˜&Jšœ'˜'Jšœ$˜$Jšœžœ˜J˜—š œ žœ žœ žœžœ˜:Jšœžœ˜"Jšœžœ˜"JšœA˜AJšœžœ˜3Jšœ0žœ ˜@Jšœ'˜'Jšœ$˜$Jšœžœ˜J˜—Jšœ˜Jšœ$˜$Jšœ˜Jšœ˜JšœO˜Ošœ*žœžœ˜;Jšœ@˜@—Jšœžœžœ žœ ˜:J˜—˜ J˜,Jšœ.˜.Jšœ+Ÿ!˜LJšœ.˜.šœžœ žœ žœ˜.Jšœ:˜:Jšœ:˜:Jšœ<˜