DIRECTORY
Basics USING [BITSHIFT, bitsPerWord, BYTE, LongMult],
ImagerColorDefs USING [Color, ColorOperator, ConstantColor, ConstantColorImplRep, SampledColor],
ImagerColorOperator USING [GetColorOperatorClass, Mapper, MapPixels, NewMapper],
ImagerColorPrivate USING [ConstantColorImpl, ConstantColorImplRep],
ImagerDevice USING [BoxProc, Class, ClassRep, Device, DeviceBox, DeviceRep, HalftoneParameters, RunProc],
ImagerMask USING [RunsFromBits, RunsFromBox],
ImagerPixelArray USING [GetPixels, MaxSampleValue],
ImagerPixelArrayDefs USING [PixelArray],
ImagerPixelMap USING [PixelMap, Reshape],
ImagerRaster USING [],
ImagerSample USING [BitsPerSample, GetPointer, GetPointSamples, NewBuffer, Sample, SampleBuffer, Sampler, SamplerRep, SetSamplerIncrements, SetSamplerPosition, UnsafePutF, UnsafeSamples],
ImagerTransformation USING [ApplyPreRotate, Cat, Transformation, Translate],
PrincOps USING [BBTableSpace, BitAddress, BitBltFlags, BitBltTable, BitBltTablePtr, GrayParm, op, zBNDCK, zINC],
PrincOpsUtils USING [AlignedBBTable, BITBLT],
Real USING [RoundC],
Terminal USING [FrameBuffer, GetColorFrameBufferA, ModifyColorFrame, Virtual],
Vector2 USING [VEC];

ImagerGrayDeviceImpl: CEDAR PROGRAM
IMPORTS Basics, ImagerColorOperator, ImagerMask, ImagerPixelArray, ImagerPixelMap, ImagerSample, ImagerTransformation, PrincOpsUtils, Real, Terminal
EXPORTS ImagerColorDefs, ImagerRaster
~ BEGIN OPEN ImagerDevice;

BYTE: TYPE ~ Basics.BYTE;
VEC: TYPE ~ Vector2.VEC;
Transformation: TYPE ~ ImagerTransformation.Transformation;
Color: TYPE ~ ImagerColorDefs.Color;
ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor;
SampledColor: TYPE ~ ImagerColorDefs.SampledColor;
ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator;
PixelArray: TYPE ~ ImagerPixelArrayDefs.PixelArray;
Sample: TYPE ~ ImagerSample.Sample;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
UnsafeSamples: TYPE ~ ImagerSample.UnsafeSamples;

ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl;
ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep;

Case: TYPE ~ {nil, constant, stipple, sampled};

StippleArray: TYPE ~ PACKED ARRAY [0..16) OF BYTE;

Data: TYPE ~ REF DataRep;
DataRep: TYPE ~ RECORD[
terminal: Terminal.Virtual,
frame: Terminal.FrameBuffer, -- the frame buffer
case: Case _ nil, -- what type of color
sampledBlack: BOOL _ FALSE,
sampledBlackClear: BOOL _ FALSE,
bitsPerPixel: ImagerSample.BitsPerSample _ 0,
flags: PrincOps.BitBltFlags _ [], -- bitblt flags
grayWord: WORD _ 0, -- constant gray word (two pixels)
stipple: StippleArray _ ALL[0], -- stipple pattern
sampledColor: SampledColor _ NIL, -- sampled color
paToDevice: Transformation _ NIL, -- transformation from pa coords to display
source: ImagerPixelMap.PixelMap _ [0, 0, 0, 0, 0, 0, NIL], -- source values from pixel array
sampler: ImagerSample.Sampler _ NIL, -- sampler information
buffer: ImagerSample.SampleBuffer _ NIL -- scan line buffer for samples
];

class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [
type: $GrayDisplay,
SetColor: GraySetColor,
SetPriority: GraySetPriority,
SetHalftone: GraySetHalftone,
MaskRuns: GrayMaskRuns,
MaskBoxes: GrayMaskBoxes,
MaskBits: GrayMaskBits,
MoveBoxes: GrayMoveBoxes
]];

NewGrayDevice: PUBLIC PROC[terminal: Terminal.Virtual] RETURNS[Device] ~ {
frame: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[terminal];
IF frame=NIL OR frame.bitsPerPixel#8 THEN RETURN[NIL]
ELSE {
data: Data ~ NEW[DataRep _ [terminal: terminal, frame: frame]];
pixelsPerInch: REAL ~ terminal.colorPixelsPerInch;
surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frame.height, 0]];
surfaceToDevice.ApplyPreRotate[90];
RETURN[NEW[ImagerDevice.DeviceRep _ [class: class,
box: [smin: 0, fmin: 0, smax: frame.height, fmax: frame.width],
surfaceToDevice: surfaceToDevice,
surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch],
surfaceUnitsPerPixel: 1,
data: data]]];
};
};


nullBitBltTable: PrincOps.BitBltTable ~ [
dst: [word: NIL, bit: 0], dstBpl: 0,
src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]],
width: 0, height: 0, flags: []
];

bitsPerPixel: NAT ~ 8;
bitsPerWord: NAT ~ Basics.bitsPerWord;

StippleArrayFromWord: PROC[t: WORD] RETURNS[array: StippleArray _ ALL[0]] ~ {
bits: PACKED ARRAY [0..16) OF BOOL ~ LOOPHOLE[t];
FOR i: [0..16) IN [0..16) DO IF bits[i] THEN array[i] _ BYTE.LAST ENDLOOP;
};

PixelFromIntensity: PROC[Y: REAL] RETURNS[BYTE] ~ {
IF Y<=0 THEN RETURN[0]; -- black
IF Y>=1 THEN RETURN[BYTE.LAST]; -- white
RETURN[Real.RoundC[Y*BYTE.LAST]]; -- gray
};

sourceLgBitsPerSample: NAT ~ 3; -- for array of samples from sampled color
sourceBitsPerSample: NAT ~ Basics.BITSHIFT[1, sourceLgBitsPerSample];
maxSourceSample: Sample ~ Basics.BITSHIFT[1, sourceBitsPerSample]-1;

GraySetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ {
data: Data ~ NARROW[device.data];
WITH color SELECT FROM
color: ConstantColor => {
impl: ConstantColorImpl ~ color.impl;
data.case _ constant;
data.source.refRep _ NIL;
data.flags _ [disjoint: TRUE, gray: TRUE, srcFunc: null, dstFunc: null];
WITH impl: impl SELECT FROM
stipple => {
word: WORD ~ impl.word;
SELECT impl.function FROM
replace => { data.flags.srcFunc _ complement };
paint => { data.flags.srcFunc _ complement; data.flags.dstFunc _ and };
invert => { data.flags.dstFunc _ xor };
erase => { data.flags.dstFunc _ or };
ENDCASE => ERROR;
IF word=WORD.LAST THEN data.grayWord _ word
ELSE { data.stipple _ StippleArrayFromWord[word]; data.case _ stipple };
};
ENDCASE => {
pixel: BYTE ~ PixelFromIntensity[impl.Y];
data.grayWord _ pixel*400B+pixel;
};
};
color: SampledColor => {
pa: PixelArray ~ color.pa;
um: Transformation ~ color.um;
colorOperator: ColorOperator ~ color.colorOperator;
samplesPerPixel: NAT ~ pa.samplesPerPixel;
sSize: NAT ~ pa.sSize;
fSize: NAT ~ pa.fSize;
maxIn: Sample ~ ImagerPixelArray.MaxSampleValue[pa, 0];
source: ImagerPixelMap.PixelMap ~ data.source.refRep.Reshape[
lgBitsPerPixel: sourceLgBitsPerSample, 
bounds: [sMin: 0, fMin: 0, sSize: sSize, fSize: fSize]];
sourceBase: LONG POINTER ~ source.refRep.pointer;
sourceWordsPerLine: NAT ~ source.refRep.rast;
pixels: SampleBuffer ~ ImagerSample.NewBuffer[samplesPerPixel, fSize];
buffer: SampleBuffer ~ ImagerSample.NewBuffer[1, fSize];
mapper: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[
op: colorOperator, component: $Intensity, maxIn: maxIn, maxOut: maxSourceSample];
samples: UnsafeSamples ~ buffer.GetPointer[0, 0, fSize];
FOR s: NAT IN[0..sSize) DO
ImagerPixelArray.GetPixels[pa: pa, s: s, f: 0, buffer: pixels, count: fSize];
ImagerColorOperator.MapPixels[mapper: mapper, pixels: pixels, 
buffer: buffer, count: fSize];
TRUSTED { ImagerSample.UnsafePutF[samples: samples, count: fSize, 
base: sourceBase, wordsPerLine: sourceWordsPerLine, 
bitsPerSample: sourceBitsPerSample, s: s, f: 0] };
ENDLOOP;
data.sampledColor _ color;
data.paToDevice _ ImagerTransformation.Cat[pa.m, color.um, viewToDevice];
data.source _ source;
IF data.sampler=NIL THEN data.sampler _ NEW[ImagerSample.SamplerRep _ []];
data.sampler.base _ sourceBase;
data.sampler.wordsPerLine _ sourceWordsPerLine;
data.sampler.bitsPerSample _ sourceBitsPerSample;
data.sampler.sMin _ source.sMin;
data.sampler.fMin _ source.fMin;
data.sampler.sSize _ source.sSize;
data.sampler.fSize _ source.fSize;
ImagerSample.SetSamplerIncrements[data.sampler, data.paToDevice];
IF data.buffer=NIL THEN data.buffer _ ImagerSample.NewBuffer[1, data.frame.width];
SELECT ImagerColorOperator.GetColorOperatorClass[colorOperator] FROM
$SampledBlack => {data.sampledBlack _ TRUE; data.sampledBlackClear _ FALSE};
$SampledBlackClear => {data.sampledBlack _ data.sampledBlackClear _ TRUE};
ENDCASE => data.sampledBlack _ data.sampledBlackClear _ FALSE;
data.case _ sampled;
};
ENDCASE => ERROR; -- unknown color variant
};

GraySetPriority: PROC[device: Device, priorityImportant: BOOL] ~ {
};

GraySetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ {
data: Data ~ NARROW[device.data];
};

Check: PROC[x: CARDINAL, max: NAT] RETURNS[NAT] ~
TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK };

GrayMaskRunsInternal: PROC[data: Data, bounds: DeviceBox, runs: PROC[RunProc]] ~ {
frame: Terminal.FrameBuffer ~ data.frame;
base: LONG POINTER ~ frame.base;
wordsPerLine: NAT ~ frame.wordsPerLine;
SELECT data.case FROM
nil => ERROR; -- color not initialized
constant => TRUSTED {
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
grayConstantRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED {
f: NAT ~ Check[fMin, frame.width];
s: NAT ~ Check[sMin, frame.height];
line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine];
bit: CARDINAL ~ f*bitsPerPixel;
bb.dst.word _ line+bit/bitsPerWord;
bb.dst.bit _ bit MOD bitsPerWord;
bb.width _ Check[fSize, frame.width-f]*bitsPerPixel;
bb.height _ Check[1, frame.height-s];
PrincOpsUtils.BITBLT[bb];
};
bb^ _ nullBitBltTable;
bb.dstBpl _ wordsPerLine*bitsPerWord;
bb.src.word _ LOOPHOLE[@data.grayWord];
bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.flags _ data.flags;
runs[grayConstantRun];
};
stipple => TRUSTED {
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
srcBase: LONG POINTER ~ LOOPHOLE[@data.stipple];
srcWordsPerLine: NAT ~ (4*bitsPerPixel)/bitsPerWord;
grayStippleRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED {
fmin: NAT ~ Check[fMin, frame.width];
fmax: NAT ~ Check[fmin+fSize, frame.width];
smin: NAT ~ Check[sMin, frame.height];
smax: NAT ~ Check[smin+1, frame.height];
dstLine: LONG POINTER ~ base+Basics.LongMult[smin, wordsPerLine];
srcLine: LONG POINTER ~ srcBase+(smin MOD 4)*srcWordsPerLine;
FOR f: NAT IN [fmin..MIN[fmin+4, fmax]) DO
dstBit: NAT ~ f*bitsPerPixel;
srcBit: NAT ~ (f MOD 4)*bitsPerPixel;
bb.dst.word _ dstLine+dstBit/bitsPerWord;
bb.dst.bit _ dstBit MOD bitsPerWord;
bb.src.word _ srcLine+srcBit/bitsPerWord;
bb.src.bit _ srcBit MOD bitsPerWord;
bb.height _ (fmax-f+3)/4;
PrincOpsUtils.BITBLT[bb];
ENDLOOP;
};
bb^ _ nullBitBltTable;
bb.dstBpl _ 4*bitsPerPixel;
bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.width _ bitsPerPixel;
bb.flags _ data.flags;
runs[grayStippleRun];
};
sampled => {
sampler: ImagerSample.Sampler ~ data.sampler;
buffer: SampleBuffer ~ data.buffer;
graySampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ CHECKED {
s: NAT ~ Check[sMin, frame.height];
f: NAT ~ Check[fMin, frame.width];
count: NAT ~ Check[fSize, frame.width-f];
samples: ImagerSample.UnsafeSamples ~ buffer.GetPointer[0, f, count];
ImagerSample.GetPointSamples[sampler: sampler, s: s, f: f, 
buffer: buffer, bi: 0, bj: f, count: count];
TRUSTED { ImagerSample.UnsafePutF[samples: samples, count: count, 
base: base, wordsPerLine: wordsPerLine, bitsPerSample: 8, s: s, f: f, dstFunc: IF data.sampledBlackClear THEN and ELSE null]};
};
ImagerSample.SetSamplerPosition[sampler: sampler, 
m: data.paToDevice, s: bounds.smin, f: bounds.fmin];
runs[graySampledRun];
};
ENDCASE => ERROR; -- illegal case
};

GrayMaskBoxesInternal: PROC[data: Data, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ {
IF data.case=constant THEN TRUSTED {
frame: Terminal.FrameBuffer ~ data.frame;
base: LONG POINTER ~ frame.base;
wordsPerLine: NAT ~ frame.wordsPerLine;
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
grayConstantBox: PROC[box: DeviceBox] ~ TRUSTED {
fmin: NAT ~ Check[box.fmin, frame.width];
fmax: NAT ~ Check[box.fmax, frame.width];
smin: NAT ~ Check[box.smin, frame.height];
smax: NAT ~ Check[box.smax, frame.height];
line: LONG POINTER ~ base+Basics.LongMult[smin, wordsPerLine];
bit: NAT ~ fmin*bitsPerPixel;
bb.dst.word _ line+bit/bitsPerWord;
bb.dst.bit _ bit MOD bitsPerWord;
bb.width _ (fmax-fmin)*bitsPerPixel;
bb.height _ smax-smin;
PrincOpsUtils.BITBLT[bb];
};
bb^ _ nullBitBltTable;
bb.dstBpl _ wordsPerLine*bitsPerWord;
bb.src.word _ LOOPHOLE[@data.grayWord];
bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.flags _ data.flags;
boxes[grayConstantBox];
}
ELSE {
grayNonConstantBox: PROC[box: DeviceBox] ~ {
runs: PROC[run: RunProc] ~ { ImagerMask.RunsFromBox[box: box, run: run] };
GrayMaskRunsInternal[data: data, bounds: box, runs: runs];
};
boxes[grayNonConstantBox];
};
};

ModifyColorFrame: PROC [vt: Terminal.Virtual, action: PROC, xmin: NAT, ymin: NAT, xmax: NAT, ymax: NAT] ~ INLINE {
IF vt = NIL THEN action[]
ELSE Terminal.ModifyColorFrame[vt: vt, action: action, xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax];
};

GrayMaskRuns: PROC[device: Device, bounds: DeviceBox, runs: PROC[RunProc]] ~ {
data: Data ~ NARROW[device.data];
grayMaskRunsAction: PROC ~ { GrayMaskRunsInternal[data, bounds, runs] };
ModifyColorFrame[vt: data.terminal, action: grayMaskRunsAction,
xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax];
};

GrayMaskBoxes: PROC[device: Device, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ {
data: Data ~ NARROW[device.data];
grayMaskBoxesAction: PROC ~ { GrayMaskBoxesInternal[data, bounds, boxes] };
ModifyColorFrame[vt: data.terminal, action: grayMaskBoxesAction,
xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax];
};

GrayMaskBits: PROC[device: Device, srcBase: LONG POINTER, srcWordsPerLine: NAT, 
ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ {
data: Data ~ NARROW[device.data];
grayMaskBitsBox: PROC[box: DeviceBox] ~ {
grayMaskBitsBoxAction: PROC ~ {
runs: PROC[run: RunProc] ~ { ImagerMask.RunsFromBits[
base: srcBase, wordsPerLine: srcWordsPerLine, 
sBits: box.smin-ts, fBits: box.fmin-tf, sRuns: box.smin, fRuns: box.fmin, 
sSize: box.smax-box.smin, fSize: box.fmax-box.fmin, run: run];
};
GrayMaskRunsInternal[data: data, bounds: box, runs: runs];
};
ModifyColorFrame[vt: data.terminal, action: grayMaskBitsBoxAction,
xmin: box.fmin, ymin: box.smin, xmax: box.fmax, ymax: box.smax];
};
boxes[grayMaskBitsBox];
};

GrayMoveBoxes: PROC [device: Device, ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ TRUSTED {
data: Data ~ NARROW[device.data];
frame: Terminal.FrameBuffer ~ data.frame;
base: LONG POINTER ~ frame.base;
wordsPerLine: NAT ~ frame.wordsPerLine;
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
action: SAFE PROC ~ TRUSTED { PrincOpsUtils.BITBLT[bb] };
moveBox: PROC[box: DeviceBox] ~ TRUSTED {
dfmin: NAT ~ Check[box.fmin, frame.width];
dsmin: NAT ~ Check[box.smin, frame.height];
dfmax: NAT ~ Check[box.fmax, frame.width];
dsmax: NAT ~ Check[box.smax, frame.height];
sfmin: NAT ~ dfmin-tf;
ssmin: NAT ~ dsmin-ts;
sfmax: NAT ~ dfmax-tf;
ssmax: NAT ~ dsmax-ts;
dstBit: CARDINAL ~ dfmin*bitsPerPixel;
srcBit: CARDINAL ~ sfmin*bitsPerPixel;
bpl: INTEGER _ wordsPerLine*bitsPerWord;
ss: NAT _ ssmin;
ds: NAT _ dsmin;
bb.flags _ [disjoint: TRUE, disjointItems: TRUE, direction: forward, gray: FALSE];
IF dsmin<ssmax AND dsmax>ssmin THEN {
bb.flags.disjoint _ FALSE;
IF dsmin=ssmin AND dfmin<sfmax AND dfmax>sfmin THEN bb.flags.disjointItems _ FALSE;
IF dsmin>ssmin OR (dsmin=ssmin AND dfmin>sfmin) THEN {
bb.flags.direction _ backward; bpl _ -bpl; ss _ ssmax-1; ds _ dsmax-1;
};
};
bb.dst.word _ base+Basics.LongMult[ds, wordsPerLine]+dstBit/bitsPerWord;
bb.dst.bit _ dstBit MOD bitsPerWord;
bb.dstBpl _ bpl;
bb.src.word _ base+Basics.LongMult[ss, wordsPerLine]+srcBit/bitsPerWord;
bb.src.bit _ srcBit MOD bitsPerWord;
bb.srcDesc.srcBpl _ bpl;
bb.width _ (dfmax-dfmin)*bitsPerPixel;
bb.height _ dsmax-dsmin;
ModifyColorFrame[vt: data.terminal, action: action,
xmin: MIN[dfmin, sfmin], ymin: MIN[dsmin, ssmin], 
xmax: MAX[dfmax, sfmax], ymax: MAX[dsmax, ssmax]];
};
bb^ _ nullBitBltTable;
boxes[moveBox];
};

END.
�����ImagerGrayDeviceImpl.mesa
Copyright c 1984, 1985 by Xerox Corporation.  All rights reserved.
Michael Plass, June 12, 1985 11:53:55 am PDT
Doug Wyatt, May 30, 1985 11:24:15 pm PDT
defaultDot: ImagerPixelMap.PixelMap ~ ImagerSampler.DotScreen[
r: 0.5, sSize: 16, fSize: 16, maxPixelValue: 255];

data.halftone _ halftone;
IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault

ÊÌ��˜�codešœ™Kšœ
Ïmœ7™BK™,K™(—K˜�šÏk	˜	Jšœžœžœžœ˜5JšœžœK˜`Jšœžœ7˜PJšœžœ+˜CJšœ
žœW˜iJšœžœ˜-Jšœžœ˜3Jšœžœ˜(Jšœžœ˜)Jšœ
žœ˜Jšœ
žœ©˜»Jšœžœ2˜LJšœ	žœb˜pJšœžœžœ˜-Jšœžœ
˜Jšœ	žœ@˜NJšœžœžœ˜—K˜�KšÐblœžœž˜#Kšžœ˜”Kšžœ˜%Kšœžœžœ˜K˜�Kšžœžœ
žœ˜Kšžœžœžœ˜Kšœžœ'˜;Kšœžœ˜$Kšœžœ!˜4Kšœžœ ˜2Kšœžœ!˜4Kšœžœ#˜3Kšœžœ˜#Kšœžœ˜/Kšœžœ˜1K˜�Kšœžœ(˜?Kšœžœžœ+˜LK˜�Kšœžœ%˜/K˜�Kšœžœžœžœ	žœžœ˜2K˜�Kšœžœžœ	˜šœ	žœžœ˜K˜KšœÏc˜0Kšœ ˜'Kšœžœžœ˜Kšœžœžœ˜ K˜-Kšœ" ˜1Kšœ
žœ "˜6Kšœžœ ˜2Kšœžœ ˜2Kšœžœ +˜MKšœ5žœ !˜\Kšœ žœ ˜;Kšœ$žœ ˜GK˜K˜�—šœžœ˜9Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜�—šœ>™>Kšœ2™2K™�—šÏn
œžœžœžœ˜JKšœF˜FKšžœžœžœžœžœžœ˜5šžœ˜Kšœ
žœ/˜?Kšœžœ˜2KšœT˜TKšœ#˜#šžœžœ(˜2Kšœ?˜?Kšœ!˜!Kšœ4˜4Kšœ˜Kšœ˜—K˜—K˜K˜�—K˜�šœ)˜)Kšœžœ˜$Kšœžœ ˜/Kšœ˜Kšœ˜K˜�—Kšœžœ˜Kšœ
žœ˜&K˜�š
¡œžœžœžœžœ˜MKšœžœžœ	žœžœžœ˜1Kšžœžœ	žœžœ	žœžœžœžœ˜JK˜K˜�—š
¡œžœžœžœžœ˜3Kšžœžœžœ ˜ Kšžœžœžœžœžœ ˜(Kšžœžœžœ ˜)K˜K˜�—Kšœžœ *˜JKšœžœ
žœ˜EKšœ!žœ˜DK˜�š¡œžœ@˜RKšœ
žœ˜!šžœžœž˜˜K˜%Kšœ˜Kšœžœ˜Kšœžœžœ ˜Hšžœžœž˜šœ˜Kšœžœ
˜šžœž˜Kšœ/˜/KšœG˜GKšœ'˜'Kšœ%˜%Kšžœžœ˜—Kšžœžœžœžœ˜+KšžœD˜HKšœ˜—šžœ˜Kšœžœ˜)Kšœ!˜!K˜——K˜—šœ˜Kšœ˜Kšœ˜Kšœ3˜3Kšœžœ˜*Kšœžœ˜Kšœžœ˜Kšœ7˜7Kšœž˜žKšœžœžœ˜1Kšœžœ˜-KšœF˜FKšœ8˜8Kšœ•˜•K˜8šžœžœžœž˜KšœM˜MKšœ]˜]Kšžœ£˜ªKšžœ˜—Kšœ˜KšœI˜IKšœ˜Kšžœžœžœžœ˜JKšœ˜Kšœ/˜/Kšœ1˜1Kšœ ˜ Kšœ ˜ Kšœ"˜"Kšœ"˜"KšœA˜AKšžœ
žœžœ;˜Ršžœ:ž˜DKšœ&žœžœ˜LKšœDžœ˜JKšžœ1žœ˜>—K˜K˜—Kšžœžœ ˜*—Kšœ˜K˜�—š¡œžœ$žœ˜BKšœ˜K˜�—š¡œžœ2˜GKšœ
žœ˜!K™K˜K˜�—š¡œžœžœžœžœžœ˜1Kšžœžœžœ$˜8Kšžœžœ	žœžœžœžœ™BK˜�—š¡œžœ&žœ˜RKšœ)˜)Kšœžœžœ˜ Kšœžœ˜'šžœž˜Kšœžœ ˜&šœžœ˜K˜KšœE˜Eš	œžœ
žœ	žœžœ˜BKšœžœ˜"Kšœžœ˜#Kšœžœžœ)˜;Kšœžœ˜Kšœ#˜#Kšœžœ
˜!Kšœ4˜4Kšœ%˜%Kšœžœ˜K˜—Kšœ˜Kšœ%˜%Kšœžœ˜'KšœD˜DKšœ˜Kšœ˜K˜—šœžœ˜K˜KšœE˜EKšœ	žœžœžœ˜0Kšœžœ ˜4š	œžœ
žœ	žœžœ˜AKšœžœ˜%Kšœžœ"˜+Kšœžœ˜&Kšœžœ˜(Kšœ	žœžœ,˜AKšœ	žœžœžœ˜=š	žœžœžœžœž˜*Kšœžœ˜Kšœžœžœ˜%Kšœ)˜)Kšœžœ
˜$Kšœ)˜)Kšœžœ
˜$Kšœ˜Kšœžœ˜Kšžœ˜—K˜—Kšœ˜Kšœ˜KšœD˜DKšœ˜Kšœ˜Kšœ˜K˜—˜Kšœ-˜-Kšœ#˜#š	œžœ
žœ	žœžœ˜AKšœžœ˜#Kšœžœ˜"Kšœžœ˜)KšœE˜EKšœh˜hKšžœ‹žœžœžœ˜ÁK˜—Kšœg˜gKšœ˜K˜—Kšžœžœ ˜!—K˜K˜�—š¡œžœ'žœ˜Tšžœžœžœ˜$Kšœ)˜)Kšœžœžœ˜ Kšœžœ˜'K˜KšœE˜Ešœžœžœ˜1Kšœžœ ˜)Kšœžœ ˜)Kšœžœ!˜*Kšœžœ!˜*Kšœžœžœ,˜>Kšœžœ˜Kšœ#˜#Kšœžœ
˜!Kšœ$˜$Kšœ˜Kšœžœ˜K˜—Kšœ˜Kšœ%˜%Kšœžœ˜'KšœD˜DKšœ˜Kšœ˜K˜—šžœ˜šœžœ˜,Kšœžœ@˜JK˜:K˜—Kšœ˜K˜—K˜K˜�—•StartOfExpansiont[vt: Terminal.Virtual, action: PROC, xmin: NAT _ 0, ymin: NAT _ 0, xmax: NAT _ 32767, ymax: NAT _ 32767]š¡œžœ žœžœžœžœžœžœ˜rKšžœžœžœ	˜Kšžœc˜gKšœ˜K˜�—š¡œžœ*žœ˜NKšœ
žœ˜!Kšœžœ0˜HKšœŒ˜ŒK˜K˜�—š¡
œžœ+žœ˜PKšœ
žœ˜!Kšœžœ2˜KKšœ˜K˜K˜�—š¡œžœžœžœžœžœ	žœ˜{Kšœ
žœ˜!šœžœ˜)šœžœ˜šœžœä˜îKšœ˜—K˜:Kšœ˜—Kšœƒ˜ƒK˜—Kšœ˜K˜K˜�—š
¡
œžœžœ	žœ
žœ˜WKšœ
žœ˜!Kšœ)˜)Kšœžœžœ˜ Kšœžœ˜'K˜KšœE˜EKš	œžœžœžœžœ˜9šœ	žœžœ˜)Kšœžœ ˜*Kšœžœ!˜+Kšœžœ ˜*Kšœžœ!˜+Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜&Kšœžœ˜&Kšœžœ˜(Kšœžœ	˜Kšœžœ	˜Kšœžœžœžœ˜Ršžœ
žœ
žœ˜%Jšœžœ˜Kš
žœ
žœ
žœ
žœžœ˜Sšžœ
žœžœžœ˜6JšœF˜FK˜—K˜—KšœH˜HKšœžœ
˜$Kšœ˜KšœH˜HKšœžœ
˜$Kšœ˜Kšœ&˜&Kšœ˜Kš	œ:žœžœžœžœ˜™K˜—Kšœ˜K˜K˜K˜�—K™�Kšžœ˜—�…—����=��Nl��