DIRECTORY Atom, Basics, CII USING [ApplyCCITTFacsimileDecompressionFilterProc, CIIEndType, CIIJointType, CleanupObject, ColorLookupTableType, ConicToProc, CProc, CurveToProc, DestroyClipperProc, DestroyColorOperatorProc, DestroyColorProc, DestroyFontProc, DestroyHalftonePropertiesProc, DestroyLookupTableProc, DestroyMaskProgramProc, DestroyProc, FillType, GeneratePathProc, GetColorLookupTableProc, HalftonePropertiesForSeparation, Handle, ImageSource, ImageSourceDestroyProc, ImageSourceObjectRep, ImageSourceReadProc, LineRunsRep, LineToProc, MakeLookupTableProc, MaskInfo, MoveToProc, ObjectRep, PathGenerator, PathSinkObjectRep, RasterRep, RegisterCleanupObjectProc, RES, RESFromErrorCode, RunRep, SampleRange, ScaledValue, SetColorLookupTableProc, SetColorTableProc, SetOutputBuffersProc, SetSeparationProc, ShowArgs, StrokeControlRep, SyncProc, VectorEndpoints, XChar, XChars], CStrings, CIIPrivate, Imager, ImagerError, ImagerBox USING [Rectangle], ImagerBrick, ImagerClipper, ImagerColor, ImagerDevice, ImagerDeviceColor, ImagerDeviceInterchange, ImagerDeviceVector, ImagerDeviceWorks, ImagerFont, ImagerFontWorks, ImagerImageWorks, ImagerManhattan, ImagerMaskCache, ImagerPath, ImagerPen, ImagerPenExtras, ImagerPixel, ImagerPixelArray, ImagerRaster, ImagerSample, ImagerScaled, ImagerTransformation, IO, IOUtils, PixelArrayCCITTG4Private, RefTab, RefText, Rope, RuntimeError, Scaled, SF, UXStrings, Vector2; CIIImpl: MONITOR IMPORTS Atom, Basics, CII, CStrings, Imager, ImagerColor, ImagerDevice, ImagerDeviceColor, ImagerDeviceInterchange, ImagerDeviceWorks, ImagerError, ImagerFont, ImagerFontWorks, ImagerImageWorks, ImagerManhattan, ImagerPath, ImagerPenExtras, ImagerPixel, ImagerPixelArray, ImagerRaster, ImagerSample, ImagerScaled, ImagerTransformation, IO, IOUtils, PixelArrayCCITTG4Private, RefTab, RefText, Rope, RuntimeError, Scaled, UXStrings, Vector2 EXPORTS CIIPrivate, CII SHARES ImagerSample ~ BEGIN OPEN CII; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Color: TYPE = ImagerColor.Color; ColorRep: PUBLIC TYPE = ImagerColor.ColorRep; ConstantColor: TYPE = ImagerColor.ConstantColor; ColorOperator: TYPE = ImagerColor.ColorOperator; ColorOperatorRep: PUBLIC TYPE = ImagerColor.ColorOperatorRep; Device: TYPE = ImagerDevice.Device; Rectangle: TYPE = ImagerBox.Rectangle; DeviceClipper: TYPE = ImagerDevice.DeviceClipper; Transformation: TYPE = ImagerTransformation.Transformation; VEC: TYPE = Vector2.VEC; FontRep: PUBLIC TYPE = ImagerFont.FontRep; ok: RES = CII.RESFromErrorCode[$ok]; eof: RES = CII.RESFromErrorCode[$eof]; nilFault: RES = CII.RESFromErrorCode[$nilFault]; ioError: RES = CII.RESFromErrorCode[$ioError]; wrongType: RES = CII.RESFromErrorCode[$wrongType]; bounds: RES = CII.RESFromErrorCode[$bounds]; accessError: RES = CII.RESFromErrorCode[$accessError]; notImplemented: RES = CII.RESFromErrorCode[$notImplemented]; scanModeTranslate: ARRAY CIIPrivate.ScanMode OF ImagerTransformation.ScanMode ~ [ slowRightFastUp: [slow: right, fast: up], slowDownFastRight: [slow: down, fast: right], slowLeftFastDown: [slow: left, fast: down], slowUpFastLeft: [slow: up, fast: left], slowRightFastDown: [slow: right, fast: down], slowDownFastLeft: [slow: down, fast: left], slowLeftFastUp: [slow: left, fast: up], slowUpFastRight: [slow: up, fast: right] ]; ScanModeTranslate: PUBLIC SAFE PROC [scanMode: CIIPrivate.ScanMode] RETURNS [ImagerTransformation.ScanMode] ~ CHECKED { RETURN [scanModeTranslate[scanMode]] }; CProcFromProc: PROC [p: PROC ANY RETURNS ANY] RETURNS [CProc] = INLINE { r: POINTER TO ARRAY [0..1] OF CARD = LOOPHOLE[p]; RETURN [[r[0]]] }; GetState: PROC [h: Handle] RETURNS [State] = { RETURN [NARROW[h.data]] }; NoteRef: PROC [state: State, ref: REF] = { Inner: RefTab.UpdateAction = CHECKED { IF found THEN { WITH val SELECT FROM r: REF NAT => r­ ¬ r­ + 1 ENDCASE => ERROR; RETURN [op: none] } ELSE { RETURN [op: store, new: NEW[NAT ¬ 1]] }; }; IF ref # NIL THEN RefTab.Update[state.refTab, ref, Inner]; }; DestroyAny: PROC [h: Handle, ref: REF] RETURNS [res: RES ¬ ok] = { state: State = GetState[h]; Inner: RefTab.UpdateAction = CHECKED { IF found THEN { WITH val SELECT FROM r: REF NAT => {IF (r­ ¬ r­ - 1) = 0 THEN RETURN [op: delete]}; ENDCASE => ERROR; RETURN [op: none] } ELSE { res ¬ accessError; RETURN [op: none] }; }; IF state = NIL THEN RETURN [nilFault]; IF ref # NIL THEN RefTab.Update[state.refTab, ref, Inner]; }; Matrix: TYPE ~ ARRAY [0..6) OF REAL; MakeTransformation: PROC [m: POINTER TO Matrix] RETURNS [Transformation] ~ { RETURN [ImagerTransformation.Create[m[0], m[2], m[4], m[1], m[3], m[5]]] }; SetTransformation: PROC [state: State, t: Transformation] ~ { IF t = NIL THEN t ¬ identity; state.transformation­ ¬ t­; }; DecodeTransformation: PROC [t: Transformation, m: POINTER TO Matrix] ~ { m[0] ¬ t.a; m[1] ¬ t.d; m[2] ¬ t.b; m[3] ¬ t.e; m[4] ¬ t.c; m[5] ¬ t.f; }; GetMatrix: PUBLIC PROC [h: Handle, matrixResult: POINTER TO Matrix] RETURNS [RES¬ok] ~ { state: State = GetState[h]; IF matrixResult = NIL THEN RETURN [nilFault]; DecodeTransformation[state.transformation, matrixResult]; }; SetMatrix: PUBLIC PROC [h: Handle, matrix: POINTER TO Matrix] RETURNS [RES¬ok] ~ { state: State = GetState[h]; IF matrix = NIL THEN { RETURN [nilFault] } ELSE { temp: Transformation ~ MakeTransformation[matrix]; SetTransformation[state, temp]; ImagerTransformation.Destroy[temp]; }; }; InitialTransformation: PROC [device: Device] RETURNS [Transformation] ~ { m: Transformation = ImagerTransformation.XYToSF[device.parm.scanMode, device.parm.sSize, device.parm.fSize]; ImagerTransformation.ApplyPreScale2[m, Vector2.Div[device.parm.surfaceUnitsPerInch, 72.0]]; RETURN [m] }; SetInitialMatrix: PUBLIC PROC [h: Handle, matrix: POINTER TO Matrix] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.initialTransformation ¬ MakeTransformation[matrix]; }; GetInitialMatrix: PUBLIC PROC [h: Handle, matrixResult: POINTER TO Matrix] RETURNS [RES¬ok] ~ { state: State = GetState[h]; IF state.initialTransformation = NIL THEN { state.initialTransformation ¬ InitialTransformation[state.device]; }; DecodeTransformation[state.initialTransformation, matrixResult]; }; identity: Transformation ~ ImagerTransformation.Scale[1.0]; SetGray: PUBLIC PROC [h: Handle, gray: POINTER TO REAL] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.color ¬ ImagerColor.ColorFromGray[1.0-(gray­)]; }; SetRGB: PUBLIC PROC [h: Handle, rgb: POINTER TO ARRAY [0..3) OF REAL] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.color ¬ ImagerColor.ColorFromRGB[[rgb[0], rgb[1], rgb[2]]]; }; SetHSV: PUBLIC PROC [h: Handle, hsv: POINTER TO ARRAY [0..3) OF REAL] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.color ¬ ImagerColor.ColorFromHSV[hsv[0], hsv[1], hsv[2]]; }; SetCMYK: PUBLIC PROC [h: Handle, cmyk: POINTER TO ARRAY [0..4) OF REAL] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.color ¬ ImagerColor.ColorFromCMYK[[cmyk[0], cmyk[1], cmyk[2], cmyk[3]]]; }; MakeGrayColorOperator: PUBLIC PROC [h: Handle, sampleRange: POINTER TO SampleRange, sampleTableSize: CARD, sampleTable: POINTER TO ARRAY [0..0) OF REAL, colorOperatorResult: POINTER TO ColorOperator] RETURNS [res: RES¬ok] = { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; state: State = GetState[h]; SampleTable: SAFE PROC [i: NAT] RETURNS [REAL] = TRUSTED { IF sampleTable = NIL THEN ERROR RuntimeError.NilFault; RETURN [sampleTable[Basics.BoundsCheck[i, sampleTableSize]]] }; co: ColorOperator = ImagerColor.NewColorOperatorGrayLinear[sWhite: sampleRange.sWhite, sBlack: sampleRange.sBlack, sampleTableSize: sampleTableSize, sampleTableProc: SampleTable]; NoteRef[state, colorOperatorResult­ ¬ co]; }; MakeSampleEncoding: PROC [sampleTableSize: NAT, sampleTable: POINTER TO ARRAY [0..0) OF REAL] RETURNS [s: ImagerColor.SampleEncoding] = { s ¬ NEW[ImagerColor.SampleEncodingRep[sampleTableSize]]; FOR i: NAT IN [0..sampleTableSize) DO s[i] ¬ sampleTable[i]; ENDLOOP; }; MakeRGBColorOperator: PUBLIC PROC [h: Handle, sampleRange: POINTER TO SampleRange, sampleTableSize: CARD, sampleTableR: POINTER TO ARRAY [0..0) OF REAL, sampleTableG: POINTER TO ARRAY [0..0) OF REAL, sampleTableB: POINTER TO ARRAY [0..0) OF REAL, colorOperatorResult: POINTER TO ColorOperator] RETURNS [res: RES¬ok] ~ { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; state: State = GetState[h]; pixelEncoding: ImagerColor.PixelEncoding ¬ NIL; co: ColorOperator ¬ NIL; IF sampleTableSize # 0 THEN { pixelEncoding ¬ NEW[ImagerColor.PixelEncodingRep[3]]; pixelEncoding[0] ¬ MakeSampleEncoding[sampleTableSize, sampleTableR]; pixelEncoding[1] ¬ MakeSampleEncoding[sampleTableSize, sampleTableG]; pixelEncoding[2] ¬ MakeSampleEncoding[sampleTableSize, sampleTableB]; }; co ¬ ImagerColor.NewColorOperatorRGB[sWhite: sampleRange.sWhite, sBlack: sampleRange.sBlack, map: pixelEncoding, appearanceHints: NIL]; NoteRef[state, colorOperatorResult­ ¬ co]; }; cmykSignalNames: ARRAY[0..4) OF ImagerColor.ConstantColor = [ ImagerColor.Find["Xerox/Solid/Cyan"], ImagerColor.Find["Xerox/Solid/Magenta"], ImagerColor.Find["Xerox/Solid/Yellow"], ImagerColor.Find["Xerox/Solid/Black"] ]; CMYKSignalNames: SAFE PROC [signal: NAT] RETURNS [ConstantColor] ~ CHECKED { RETURN [cmykSignalNames[signal]]; }; MakeCMYKColorOperator: PUBLIC PROC [h: Handle, sampleRange: POINTER TO SampleRange, sampleTableSize: CARD, sampleTableC: POINTER TO ARRAY [0..0) OF REAL, sampleTableM: POINTER TO ARRAY [0..0) OF REAL, sampleTableY: POINTER TO ARRAY [0..0) OF REAL, sampleTableK: POINTER TO ARRAY [0..0) OF REAL, colorOperatorResult: POINTER TO ColorOperator] RETURNS [res: RES¬ok] = { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; state: State = GetState[h]; pixelEncoding: ImagerColor.PixelEncoding ¬ NIL; co: ColorOperator ¬ NIL; IF sampleTableSize # 0 THEN { pixelEncoding ¬ NEW[ImagerColor.PixelEncodingRep[4]]; pixelEncoding[0] ¬ MakeSampleEncoding[sampleTableSize, sampleTableC]; pixelEncoding[1] ¬ MakeSampleEncoding[sampleTableSize, sampleTableM]; pixelEncoding[2] ¬ MakeSampleEncoding[sampleTableSize, sampleTableY]; pixelEncoding[3] ¬ MakeSampleEncoding[sampleTableSize, sampleTableK]; }; co ¬ ImagerColor.NewColorOperatorProcess[su: sampleRange.sWhite, sz: sampleRange.sBlack, signals: 4, map: pixelEncoding, signalType: $reflectance, signalNames: CMYKSignalNames]; NoteRef[state, colorOperatorResult­ ¬ co]; }; MakeHighlightColorOperator: PUBLIC PROC [h: Handle, sampleRange: POINTER TO SampleRange, baseColor: Color, highlightColor: Color, sampleTableSize: CARD, sampleTableBaseColor: POINTER TO ARRAY [0..0) OF REAL, sampleTableHighlightColor: POINTER TO ARRAY [0..0) OF REAL, colorOperatorResult: POINTER TO ColorOperator] RETURNS [res: RES¬ok] = { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; state: State = GetState[h]; pixelEncoding: ImagerColor.PixelEncoding ¬ NIL; co: ColorOperator ¬ NIL; IF sampleTableSize # 0 THEN { pixelEncoding ¬ NEW[ImagerColor.PixelEncodingRep[2]]; pixelEncoding[0] ¬ MakeSampleEncoding[sampleTableSize, sampleTableBaseColor]; pixelEncoding[1] ¬ MakeSampleEncoding[sampleTableSize, sampleTableHighlightColor]; }; co ¬ ImagerColor.NewColorOperatorHighlight[ sWhite: sampleRange.sWhite, sBlack: sampleRange.sBlack, map: pixelEncoding, baseColor: ImagerColor.NarrowToOpConstantColor[NARROW[baseColor]], highlightColor: ImagerColor.NarrowToOpConstantColor[NARROW[highlightColor]], appearanceHints: NIL ]; NoteRef[state, colorOperatorResult­ ¬ co]; }; MakeColor: PUBLIC PROC [h: Handle, colorOperator: ColorOperator, samplesPerPixel: CARD, pixel: POINTER TO ARRAY [0..0) OF REAL, colorResult: POINTER TO Color] RETURNS [res: RES¬ok] = { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; Pixel: SAFE PROC [sampleIndex: NAT] RETURNS [REAL] = TRUSTED { RETURN [pixel[Basics.BoundsCheck[sampleIndex, samplesPerPixel]]] }; state: State = GetState[h]; co: REF ¬ colorOperator; color: Color ¬ ImagerColor.ColorFromPixel[NARROW[co], Pixel]; NoteRef[state, colorResult­ ¬ color]; }; MakeSampledBlack: PUBLIC PROC [h: Handle, bitmap: POINTER TO RasterRep, pixelToDevice: POINTER TO Matrix, clear: BOOL, colorResult: POINTER TO Color] RETURNS [res: RES¬ok] = { ENABLE { ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE }; RuntimeError.BoundsFault => { res ¬ bounds; CONTINUE }; RuntimeError.NilFault => { res ¬ nilFault; CONTINUE }; }; state: State = GetState[h]; sm: ImagerSample.RasterSampleMap = MakeSampleMap[bitmap, ObtainDesc[state]]; pm: ImagerPixel.PixelMap = ImagerPixel.MakePixelMap[ImagerSample.Copy[sm]]; pa: ImagerPixelArray.PixelArray = ImagerPixelArray.FromPixelMap[ pixelMap: pm, box: pm.box, scanMode: [slow: right, fast: up], immutable: TRUE ]; color: Color = ImagerColor.MakeSampledBlack[ pa: pa, um: MakeTransformation[pixelToDevice], clear: clear ]; ReleaseDesc[state, sm]; NoteRef[state, colorResult­ ¬ color]; }; GetColor: PUBLIC PROC [h: Handle, colorResult: POINTER TO Color] RETURNS [RES¬ok] ~ { state: State = GetState[h]; NoteRef[state, colorResult­ ¬ state.color]; }; SetColor: PUBLIC PROC [h: Handle, color: REF] RETURNS [RES¬ok] ~ { state: State = GetState[h]; WITH color SELECT FROM color: Color => state.color ¬ color; ENDCASE => RETURN [wrongType]; }; State: TYPE ~ REF StateRep; StateRep: TYPE ~ CIIPrivate.StateRep; Validate: PROC [state: State] ~ { IF state.savedDevice # NIL THEN RETURN; -- ignore color changes during capture. IF state.dcolor # state.color THEN { device: Device ~ state.device; WITH state.color SELECT FROM color: Color => { device.class.SetColor[device, color, identity]; state.dcolor ¬ color; }; ENDCASE => ERROR; }; }; MaskDeviceTrapezoid: PUBLIC PROC [h: Handle, sMin, fMin, sMax, fMax: INT, f0, df0, f1, df1: ScaledValue] RETURNS [RES¬ok] = { state: State = GetState[h]; device: Device ~ state.device; Validate[state]; IF FALSE AND device.state.allow.regionFill THEN { } ELSE { Boxes: SAFE PROC [boxAction: SF.BoxAction] = CHECKED { s: INT ¬ sMin; halfMinusEps: ImagerScaled.Value = [pair[hi: 0, lo: (LAST[CARD16]/2)]]; fA: ImagerScaled.Value ¬ ImagerScaled.PLUS[f0, halfMinusEps]; fB: ImagerScaled.Value ¬ ImagerScaled.PLUS[f1, halfMinusEps]; WHILE s < sMax DO f0: INTEGER ¬ ImagerScaled.Floor[fA]; f1: INTEGER ¬ ImagerScaled.Floor[fB]; IF f0 > f1 THEN {t: INTEGER ¬ f0; f0 ¬ f1; f1 ¬ t}; IF f0 < fMin THEN f0 ¬ fMin; IF f1 > fMax THEN f1 ¬ fMax; IF f0 < f1 THEN { boxAction[[[s, f0], [s+1, f1]]] }; s ¬ s + 1; fA ¬ Scaled.PLUS[fA, df0]; fB ¬ Scaled.PLUS[fB, df1]; ENDLOOP; }; device.class.MaskBoxes[device, [[sMin, fMin], [sMax, fMax]], Boxes] }; }; MaskRuns: PUBLIC PROC [h: Handle, sMin: INT, numOfLines: CARD, lineRuns: POINTER TO ARRAY [0..0) OF LineRunsRep] RETURNS [RES¬ok] ~ { state: State = GetState[h]; bounds: SF.Box ¬ [min: SF.maxVec, max: SF.minVec]; Bound: SAFE PROC [box: SF.Box] = CHECKED { IF box.min.s < bounds.min.s THEN bounds.min.s ¬ box.min.s; IF box.min.f < bounds.min.f THEN bounds.min.f ¬ box.min.f; IF box.max.s > bounds.max.s THEN bounds.max.s ¬ box.max.s; IF box.max.f > bounds.max.f THEN bounds.max.f ¬ box.max.f; }; Boxes: SF.BoxGenerator = TRUSTED { FOR i: NAT IN [0..numOfLines) DO lr: LineRunsRep = lineRuns[i]; FOR j: NAT IN [0..lr.numOfRuns) DO r: POINTER TO RunRep = @(lr.run[j]); fMin: INT = r.fMin; boxAction[[[sMin+i, fMin], [sMin+i+1, fMin+r.fSize]]]; ENDLOOP; ENDLOOP; }; Boxes[Bound]; IF bounds.min.s < bounds.max.s THEN { Validate[state]; state.device.class.MaskBoxes[state.device, bounds, Boxes]; }; }; PathOps: TYPE ~ RECORD [ moveTo: ImagerPath.MoveToProc, lineTo: ImagerPath.LineToProc, curveTo: ImagerPath.CurveToProc, conicTo: ImagerPath.ConicToProc ]; MoveTo: CII.MoveToProc ~ { pathOps: POINTER TO PathOps = LOOPHOLE[sink.data]; pathOps.moveTo[p­]; RETURN [ok] }; LineTo: CII.LineToProc ~ { pathOps: POINTER TO PathOps = LOOPHOLE[sink.data]; pathOps.lineTo[p­]; RETURN [ok] }; CurveTo: CII.CurveToProc ~ { pathOps: POINTER TO PathOps = LOOPHOLE[sink.data]; pathOps.curveTo[p[0], p[1], p[2]]; RETURN [ok] }; ConicTo: CII.ConicToProc ~ { pathOps: POINTER TO PathOps = LOOPHOLE[sink.data]; pathOps.conicTo[c.p1, c.p2, c.s]; RETURN [ok] }; InvokePath: PROC [pathGenerator: PathGenerator, opsP: POINTER TO PathOps] RETURNS [RES] = { procRep: RECORD [cproc: CProc, link: CARD] ¬ [pathGenerator.proc, 0]; generatePath: CII.GeneratePathProc ¬ LOOPHOLE[@procRep]; pathSinkObjectRep: PathSinkObjectRep ¬ [ data: opsP, moveTo: CProcFromProc[MoveTo], lineTo: CProcFromProc[LineTo], curveTo: CProcFromProc[CurveTo], conicTo: CProcFromProc[ConicTo] ]; RETURN [generatePath[pathGenerator, @pathSinkObjectRep]]; }; Clip: PUBLIC PROC [h: Handle, pathGenerator: PathGenerator, fillType: FillType] RETURNS [res: RES¬ok] ~ { state: State = GetState[h]; Path: ImagerPath.PathProc ~ TRUSTED { ops: PathOps ¬ [moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, conicTo: conicTo]; res ¬ InvokePath[pathGenerator: pathGenerator, opsP: @ops]; }; outline: ImagerPath.Outline ~ ImagerPath.OutlineFromPath[path: Path, m: state.transformation]; newClipper: ImagerClipper.Clipper ~ CONS[ [outline: outline, oddWrap: fillType=eo, exclude: FALSE], state.clientClipper ]; RETURN SetClipper[h, newClipper]; }; GetClipper: PUBLIC PROC [h: Handle, clipperResult: POINTER TO ImagerClipper.Clipper] RETURNS [RES¬ok] ~ { state: State = GetState[h]; NoteRef[state, clipperResult­ ¬ state.clientClipper]; }; SetClipper: PUBLIC PROC [h: Handle, clipper: ImagerClipper.Clipper] RETURNS [RES¬ok] ~ { state: State = GetState[h]; state.clientClipper ¬ clipper; ValidateClipper[state]; }; ValidateClipper: PUBLIC PROC [state: State] = { ImagerDeviceWorks.Clip[device: state.device, viewClipper: state.viewClipper, clipperToDevice: identity, clientClipper: state.clientClipper]; }; MaskFill: PUBLIC PROC [h: Handle, pathGenerator: PathGenerator, fillType: FillType] RETURNS [res: RES¬ok] ~ { state: State = GetState[h]; Path: ImagerPath.PathProc ~ TRUSTED { ops: PathOps ¬ [moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, conicTo: conicTo]; res ¬ InvokePath[pathGenerator: pathGenerator, opsP: @ops]; }; Validate[state]; ImagerDeviceWorks.MaskFill[device: state.device, path: Path, oddWrap: fillType=eo, pathToDevice: state.transformation]; }; MaskRectangle: PUBLIC PROC [h: Handle, rect: POINTER TO Rectangle] RETURNS [RES¬ok] ~ { state: State = GetState[h]; Validate[state]; ImagerDeviceWorks.MaskRectangle[state.device, rect­, state.transformation]; }; CIIEndType: TYPE = MACHINE DEPENDENT {squareEnd, buttEnd, roundEnd, triangularEnd}; CIIJointType: TYPE = MACHINE DEPENDENT {miterJoint, bevelJoint, roundJoint, triangularJoint, noJoint, miterclipJoint, miterbevelJoint}; MaskStroke: PUBLIC PROC [h: Handle, pathGenerator: PathGenerator, s: POINTER TO StrokeControlRep] RETURNS [res: RES¬ok] ~ { IF s.stamp # 6218 THEN RETURN [wrongType] ELSE { ENABLE ImagerError.Error => { res ¬ RESFromErrorCode[error.code]; CONTINUE }; state: State = GetState[h]; Path: ImagerPath.PathProc ~ TRUSTED { ops: PathOps ¬ [moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, conicTo: conicTo]; res ¬ InvokePath[pathGenerator: pathGenerator, opsP: @ops]; }; pen: ImagerPen.Pen ~ ImagerPenExtras.MakeThickenedTransformedCircle[s.strokeWidth, state.transformation, s.thickening, s.minThickness]; Validate[state]; IF s.dashCount = 0 THEN { ImagerDeviceWorks.MaskStroke[device: state.device, path: Path, closed: s.closed, pathToDevice: state.transformation, end: ORD[s.end], joint: ORD[s.joint], miterLimit: s.miterLimit, pen: pen]; } ELSE { Pattern: SAFE PROC [i: NAT] RETURNS [REAL] = TRUSTED { RETURN [s.dashArray[i]] }; ImagerDeviceWorks.MaskDashedStroke[device: state.device, path: Path, patternLen: s.dashCount, pattern: Pattern, offset: s.dashOffset, length: s.dashCorrectLength, closed: s.closed, pathToDevice: state.transformation, end: ORD[s.end], joint: ORD[s.joint], miterLimit: s.miterLimit, pen: pen]; }; }; }; MaskVector: PUBLIC PROC [h: Handle, endpoints: POINTER TO VectorEndpoints, s: POINTER TO StrokeControlRep] RETURNS [RES¬ok] ~ { state: State = GetState[h]; pen: ImagerPen.Pen ~ ImagerPenExtras.MakeThickenedTransformedCircle[s.strokeWidth, state.transformation, s.thickening]; Validate[state]; ImagerDeviceWorks.MaskVector[device: state.device, p1: endpoints.p1, p2: endpoints.p2, pointsToDevice: state.transformation, end: ORD[s.end], pen: pen]; }; PixelMapFromRasters: PUBLIC PROC [samplesPerPixel: CARD, buffers: POINTER TO ARRAY[0..0) OF POINTER TO RasterRep] RETURNS [ImagerPixel.PixelMap] ~ { a: ARRAY [0..5) OF ImagerSample.RasterSampleMap ¬ ALL[NIL]; IF samplesPerPixel > LENGTH[a] THEN ImagerError.Error[[$notImplemented, "not implemented: too many samples per pixel"]]; FOR i: CARD IN [0..samplesPerPixel) DO a[i] ¬ MakeSampleMap[buffers[i]]; ENDLOOP; RETURN [ImagerPixel.MakePixelMap[a[0], a[1], a[2], a[3], a[4]]] }; MakeSampleMap: PUBLIC PROC [raster: POINTER TO RasterRep, scratch: ImagerSample.RasterSampleMap ¬ NIL] RETURNS [ImagerSample.RasterSampleMap] ~ { words: NAT = (raster.bitsPerLine * (raster.sMaxBox-raster.sMinBox) + raster.bitIndex + BITS[WORD] -1) / BITS[WORD]; -- ImagerSample.WordsForMap won't do, because it cannot take raster.bitIndex into account. RETURN [ ImagerSample.UnsafeNewSampleMap[ box: [[raster.sMinBox, raster.fMinBox], [raster.sMaxBox, raster.fMaxBox]], bitsPerSample: raster.bitsPerSample, bitsPerLine: raster.bitsPerLine, base: [word: raster.basePointer, bit: raster.bitIndex], ref: LOOPHOLE[raster.ref], words: words, scratchDescriptor: scratch ] ]; }; ObtainDesc: PROC [state: State] RETURNS [ImagerSample.RasterSampleMap] = INLINE { desc: ImagerSample.RasterSampleMap ¬ state.scratchDesc; state.scratchDesc ¬ NIL; RETURN [desc] }; ReleaseDesc: PROC [state: State, desc: ImagerSample.RasterSampleMap] = INLINE { desc.base.word ¬ NIL; desc.ref ¬ NIL; state.scratchDesc ¬ desc; }; MaskBitmap: PUBLIC PROC [h: Handle, raster: POINTER TO RasterRep, background: Color] RETURNS [RES¬ok] ~ { state: State = GetState[h]; bitmap: ImagerSample.RasterSampleMap = MakeSampleMap[raster, ObtainDesc[state]]; InternalMaskBitmap[state, bitmap, background]; ReleaseDesc[state, bitmap]; }; InternalMaskBitmap: PROC [state: State, bitmap: ImagerSample.RasterSampleMap, background: Color] = { IF background # NIL THEN { temp: ImagerSample.RasterSampleMap = ImagerSample.ObtainScratchMap[box: ImagerSample.GetBox[bitmap]]; foreground: Color = state.color; ImagerSample.Transfer[dst: temp, src: bitmap, function: [null, complement]]; state.color ¬ background; Validate[state]; ImagerDeviceWorks.MaskBitmap[device: state.device, bitmap: temp, bitsToDevice: state.transformation]; state.color ¬ foreground; ImagerSample.ReleaseScratchMap[temp]; }; Validate[state]; ImagerDeviceWorks.MaskBitmap[device: state.device, bitmap: bitmap, bitsToDevice: state.transformation]; }; MaskProgram: TYPE = REF TEXT; MaskProgramRep: PUBLIC TYPE = TEXT; BadMaskProgram: ERROR; Op: TYPE = MACHINE DEPENDENT {loop, jz, emit, load0, load1, load2, load3, load4, load5, load6, load7, load8, load9, store0, store1, store2, store3, store4, store5, store6, store7, store8, store9, add0, add1, add2, add3, add4, add5, add6, add7, add8, add9, sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, shift0, shift1, shift2, shift3, shift4, shift5, shift6, shift7, shift8, shift9, not, int1, int2, int4, word1, word2, word4, clear, octal0, octal1, octal2, octal3, octal4, octal5, octal6, octal7}; MakeMaskProgram: PUBLIC PROC [h: Handle, codeVersion: INT, bigEndian: BOOL, codeString: UXStrings.CString, maskProgramResult: POINTER TO MaskProgram] RETURNS [res: RES¬ok] = { ENABLE BadMaskProgram => { res ¬ RESFromErrorCode[$syntax]; CONTINUE }; state: State = GetState[h]; prog: REF TEXT = Rope.ToRefText[UXStrings.ToRope[codeString, 32767]]; compiled: REF TEXT ¬ RefText.New[prog.length]; -- prog.length is a good size estimate LoopContext: TYPE = RECORD [start: NAT, fixups: LIST OF NAT]; stack: LIST OF LoopContext ¬ NIL; i: NAT ¬ 0; loc: NAT ¬ 0; emitbyte: PROC [byte: BYTE] = { compiled ¬ RefText.AppendChar[compiled, VAL[byte]]; loc ¬ loc + 1; }; emitop: PROC [op: Op, offset: BYTE ¬ 0] = {emitbyte[ORD[op]+offset]}; emitfixups: PROC [f: LIST OF NAT, to: NAT] = { FOR tail: LIST OF NAT ¬ f, tail.rest UNTIL tail = NIL DO compiled[tail.first] ¬ VAL[to-(tail.first+1)]; ENDLOOP; }; GetRegSpec: PROC RETURNS [[0..9]] = { i¬i+1; IF i >= prog.length THEN ERROR BadMaskProgram ELSE { ch: CHAR = prog[i]; SELECT ch FROM IN ['0..'9] => RETURN [ch-'0]; ENDCASE => ERROR BadMaskProgram; }; }; GetLenSpec: PROC RETURNS [[0..2]] = { i¬i+1; IF i >= prog.length THEN ERROR BadMaskProgram; SELECT prog[i] FROM '1 => RETURN [0]; '2 => RETURN [1]; '4 => RETURN [2]; ENDCASE => ERROR BadMaskProgram; }; maskProgramResult­ ¬ NIL; IF NOT bigEndian THEN RETURN [notImplemented]; WHILE i { stack ¬ CONS[[start: loc, fixups: NIL], stack]}; '} => { IF stack = NIL THEN ERROR BadMaskProgram; emitop[$loop]; emitbyte[loc+1-stack.first.start]; emitfixups[stack.first.fixups, loc]; stack ¬ stack.rest; }; 'X => { IF stack = NIL THEN ERROR BadMaskProgram; emitop[$jz]; stack.first.fixups ¬ CONS[loc, stack.first.fixups]; emitbyte[0]; }; 'L => { emitop[$load0, GetRegSpec[]]; }; 'S => { emitop[$store0, GetRegSpec[]]; }; '+ => { emitop[$add0, GetRegSpec[]]; }; '- => { emitop[$sub0, GetRegSpec[]]; }; '^ => { emitop[$shift0, GetRegSpec[]]; }; '~ => { emitop[$not]; }; 'F => { emitop[$int1, GetLenSpec[]]; }; 'W => { emitop[$word1, GetLenSpec[]]; }; '= => { emitop[$clear]; }; 'E => { emitop[$emit]; }; ENDCASE => { val: INT = prog[i] - '0; IF val IN [0..7] THEN { emitop[$octal0, val] } ELSE ERROR BadMaskProgram; }; i ¬ i + 1; ENDLOOP; NoteRef[state, maskProgramResult­ ¬ compiled]; }; SignExtendByte: SAFE PROC [byte: BYTE] RETURNS [INT] = CHECKED { RETURN [byte - (byte/127*256)] }; Shift: SAFE PROC [a, b: INT] RETURNS [INT] = CHECKED { w: CARD ¬ LOOPHOLE[a, CARD]; w ¬ Basics.BITSHIFT[w, b]; RETURN [LOOPHOLE[w, INT]]; }; SignedHalfwords: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARDINAL OF INT16]; UnsignedHalfwords: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARDINAL OF CARD16]; MaskDeviceBoxes: PUBLIC PROC [h: Handle, sMin, fMin, sMax, fMax: INT, boxOrder: INT, maskProgram: MaskProgram, maskDataByteCount: INT, maskData: POINTER] RETURNS [res: RES ¬ ok] = { state: State = GetState[h]; Validate[state]; IF maskProgram = NIL THEN RETURN [nilFault]; IF sMin < sMax AND fMin < fMax THEN { GenerateBoxes: SAFE PROC [boxAction: SF.BoxAction] = CHECKED { c: REF TEXT = maskProgram; pc: NAT ¬ 0; reg: ARRAY [0..9] OF INT ¬ [sMin, fMin, sMax, fMax, 0, 0, 0, 0, 0, 0]; A: INT ¬ 0; src: POINTER TO Basics.RawBytes = LOOPHOLE[maskData]; len: INT = maskDataByteCount; i: INT ¬ 0; WHILE pc < c.length DO op: Op = VAL[ORD[c[pc]]]; pc ¬ pc + 1; SELECT op FROM loop => { pc ¬ pc + 1 - ORD[c[pc]] }; jz => { pc ¬ pc + 1 + (IF A = 0 THEN ORD[c[pc]] ELSE 0) }; emit => { s0: INT = MAX[reg[0], sMin]; f0: INT = MAX[reg[1], fMin]; s1: INT = MIN[reg[2], sMax]; f1: INT = MIN[reg[3], fMax]; IF s0 < s1 AND f0 < f1 THEN boxAction[[[s0, f0], [s1, f1]]]; }; load0 => A ¬ reg[0]; load1 => A ¬ reg[1]; load2 => A ¬ reg[2]; load3 => A ¬ reg[3]; load4 => A ¬ reg[4]; load5 => A ¬ reg[5]; load6 => A ¬ reg[6]; load7 => A ¬ reg[7]; load8 => A ¬ reg[8]; load9 => A ¬ reg[9]; store0 => reg[0] ¬ A; store1 => reg[1] ¬ A; store2 => reg[2] ¬ A; store3 => reg[3] ¬ A; store4 => reg[4] ¬ A; store5 => reg[5] ¬ A; store6 => reg[6] ¬ A; store7 => reg[7] ¬ A; store8 => reg[8] ¬ A; store9 => reg[9] ¬ A; add0 => A ¬ A+reg[0]; add1 => A ¬ A+reg[1]; add2 => A ¬ A+reg[2]; add3 => A ¬ A+reg[3]; add4 => A ¬ A+reg[4]; add5 => A ¬ A+reg[5]; add6 => A ¬ A+reg[6]; add7 => A ¬ A+reg[7]; add8 => A ¬ A+reg[8]; add9 => A ¬ A+reg[9]; sub0 => A ¬ A-reg[0]; sub1 => A ¬ A-reg[1]; sub2 => A ¬ A-reg[2]; sub3 => A ¬ A-reg[3]; sub4 => A ¬ A-reg[4]; sub5 => A ¬ A-reg[5]; sub6 => A ¬ A-reg[6]; sub7 => A ¬ A-reg[7]; sub8 => A ¬ A-reg[8]; sub9 => A ¬ A-reg[9]; shift0 => A ¬ Shift[A, reg[0]]; shift1 => A ¬ Shift[A, reg[1]]; shift2 => A ¬ Shift[A, reg[2]]; shift3 => A ¬ Shift[A, reg[3]]; shift4 => A ¬ Shift[A, reg[4]]; shift5 => A ¬ Shift[A, reg[5]]; shift6 => A ¬ Shift[A, reg[6]]; shift7 => A ¬ Shift[A, reg[7]]; shift8 => A ¬ Shift[A, reg[8]]; shift9 => A ¬ Shift[A, reg[9]]; not => { A ¬ IF A=0 THEN 1 ELSE 0 }; int1 => TRUSTED { IF i >= len THEN EXIT; A ¬ SignExtendByte[src[i]]; i ¬ i+1 }; int2 => TRUSTED { IF i >= len THEN EXIT; A ¬ (LOOPHOLE[maskData, POINTER TO SignedHalfwords]+i)[0]; i ¬ i+2 }; int4 => TRUSTED { IF i >= len THEN EXIT; A ¬ (LOOPHOLE[maskData, POINTER TO INT32]+i)­; i ¬ i+4 }; word1 => TRUSTED { IF i >= len THEN EXIT; A ¬ src[i]; i ¬ i+1 }; word2 => TRUSTED { IF i >= len THEN EXIT; A ¬ (LOOPHOLE[maskData, POINTER TO UnsignedHalfwords]+i)[0]; i ¬ i+2 }; word4 => TRUSTED { IF i >= len THEN EXIT; A ¬ (LOOPHOLE[maskData, POINTER TO INT32]+i)­; i ¬ i+4 }; clear => { A ¬ 0 }; octal0 => A ¬ A * 8 + 0; octal1 => A ¬ A * 8 + 1; octal2 => A ¬ A * 8 + 2; octal3 => A ¬ A * 8 + 3; octal4 => A ¬ A * 8 + 4; octal5 => A ¬ A * 8 + 5; octal6 => A ¬ A * 8 + 6; octal7 => A ¬ A * 8 + 7; ENDCASE => ERROR; ENDLOOP; }; IF (boxOrder > 1) OR (state.device.state.allow.multipleCoverage) OR (state.device.state.allow.unorderedBoxes AND (boxOrder > 0)) THEN { state.device.class.MaskBoxes[state.device, [[sMin, fMin], [sMax, fMax]], GenerateBoxes]; } ELSE { p: ImagerManhattan.Polygon = ImagerManhattan.CreateFromBoxes[GenerateBoxes]; IF p # NIL THEN { Generate: SAFE PROC [boxAction: SF.BoxAction] = CHECKED { ImagerManhattan.Map[p, boxAction, NOT state.device.state.allow.unorderedBoxes]; }; state.device.class.MaskBoxes[state.device, ImagerManhattan.BoundingBox[p], Generate]; ImagerManhattan.Destroy[p]; }; }; }; }; BuildClipperBegin: PUBLIC PROC [h: Handle] RETURNS [res: RES ¬ ok] ~ { state: State = GetState[h]; IF state.savedDevice # NIL THEN RETURN [RESFromErrorCode[$invalidOperationSequence]]; state.savedDevice ¬ state.device; state.device ¬ MakeCaptureDevice[state.device.parm]; state.device.state.allow ¬ [unorderedBoxes: TRUE, multipleCoverage: TRUE]; ImagerDeviceWorks.Clip[device: state.device, viewClipper: state.viewClipper, clipperToDevice: identity, clientClipper: state.clientClipper]; }; BuildClipperEnd: PUBLIC PROC [h: Handle] RETURNS [res: RES ¬ ok] ~ { state: State = GetState[h]; IF state.savedDevice = NIL THEN RETURN [RESFromErrorCode[$invalidOperationSequence]]; state.clientClipper ¬ ClipperFromCapturedMasks[state.device]; state.device ¬ state.savedDevice; state.savedDevice ¬ NIL; ImagerDeviceWorks.Clip[device: state.device, viewClipper: state.viewClipper, clipperToDevice: identity, clientClipper: state.clientClipper]; ValidateHalftoneProperties[state]; }; CaptureData: TYPE ~ REF CaptureDataRep; CaptureDataRep: TYPE ~ RECORD [ boxes: LIST OF SF.Box ¬ NIL, boxesLast: LIST OF SF.Box ¬ NIL ]; MakeCaptureDevice: PROC [parm: ImagerDevice.DeviceParm] RETURNS [ImagerDevice.Device] = { parm ¬ ImagerDevice.MakeDeviceParm[class: captureClass, sSize: parm.sSize, fSize: parm.fSize, scanMode: parm.scanMode, surfaceUnitsPerInch: parm.surfaceUnitsPerInch, surfaceUnitsPerPixel: parm.surfaceUnitsPerPixel, fontCache: parm.fontCache, parameters: parm.parameters]; RETURN [ImagerDevice.MakeDevice[class: captureClass, parm: parm, data: NEW[CaptureDataRep ¬ []]]] }; ManhattanFromCapturedMasks: PROC [data: CaptureData] RETURNS [ImagerManhattan.Polygon] = { p: ImagerManhattan.Polygon ¬ data.boxes; data.boxes ¬ data.boxesLast ¬ NIL; [] ¬ ImagerManhattan.Validate[p ! ImagerManhattan.InvalidManhattanPolygon => { p ¬ ImagerManhattan.Canonicalize[p]; CONTINUE; }; ]; RETURN [p]; }; ClipperFromCapturedMasks: PROC [device: ImagerDevice.Device] RETURNS [ImagerClipper.Clipper] = { WITH device.data SELECT FROM data: CaptureData => { p: ImagerManhattan.Polygon ¬ ManhattanFromCapturedMasks[data]; Path: ImagerPath.PathProc = CHECKED { FOR tail: LIST OF SF.Box ¬ p, tail.rest UNTIL tail = NIL DO moveTo[[tail.first.min.s, tail.first.min.f]]; lineTo[[tail.first.max.s, tail.first.min.f]]; lineTo[[tail.first.max.s, tail.first.max.f]]; lineTo[[tail.first.min.s, tail.first.max.f]] ENDLOOP }; outline: ImagerPath.Outline = ImagerPath.OutlineFromPath[Path]; ImagerManhattan.Destroy[p]; RETURN [LIST[[outline: outline]]] } ENDCASE => RETURN [NIL] }; captureClass: ImagerDevice.DeviceClass ~ NEW[ImagerDevice.DeviceClassRep ¬ [ SetColor: CaptureSetColor, MaskBoxes: CaptureMaskBoxes ]]; CaptureSetColor: SAFE PROC [device: Device, color: Color, viewToDevice: Transformation] ~ CHECKED { data: CaptureData ~ NARROW[device.data]; }; CaptureMaskBoxes: SAFE PROC [device: Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ CHECKED { data: CaptureData ~ NARROW[device.data]; new: ImagerManhattan.Polygon ~ ImagerManhattan.CreateFromBoxes[boxes]; IF new # NIL THEN { IF data.boxes # NIL THEN { last: ImagerManhattan.Polygon ¬ new; WHILE last.rest # NIL DO last ¬ last.rest ENDLOOP; last.rest ¬ data.boxes; }; data.boxes ¬ new; }; }; FindFont: PUBLIC PROC [h: Handle, fontName: UXStrings.CString, fontResult: POINTER TO ImagerFont.Font] RETURNS [res: RES ¬ ok] ~ { state: State = GetState[h]; rope: ROPE ~ UXStrings.ToRope[fontName, 256]; IF fontResult = NIL THEN RETURN [nilFault]; fontResult­ ¬ NIL; NoteRef[state, fontResult­ ¬ ImagerFont.Find[rope, noSubstitute ! ImagerError.Error => {res ¬ CII.RESFromErrorCode[error.code]; CONTINUE}]]; }; ModifyFont: PUBLIC PROC [h: Handle, font: REF, mp: POINTER TO Matrix, fontResult: POINTER TO ImagerFont.Font] RETURNS [RES¬ok] ~ { state: State = GetState[h]; IF fontResult = NIL THEN RETURN [nilFault]; fontResult­ ¬ NIL; WITH font SELECT FROM font: ImagerFont.Font => { m: Transformation ~ MakeTransformation[mp]; new: ImagerFont.Font ~ ImagerFont.Modify[font, m]; NoteRef[state, fontResult­ ¬ new]; ImagerTransformation.Destroy[m]; }; ENDCASE => RETURN [wrongType]; }; MakeFontAtom: PUBLIC PROC [h: Handle, font: REF, mp: POINTER TO Matrix, fontResult: POINTER TO ImagerFont.Font] RETURNS [RES¬ok] ~ { state: State = GetState[h]; IF fontResult = NIL THEN RETURN [nilFault]; fontResult­ ¬ NIL; WITH font SELECT FROM font: ImagerFont.Font => { m: Transformation ~ MakeTransformation[mp]; ImagerTransformation.ApplyTranslateTo[m, [0, 0]]; NoteRef[state, fontResult­ ¬ ImagerFont.Modify[font, m]]; ImagerTransformation.Destroy[m]; }; ENDCASE => RETURN [wrongType]; }; ApplyHardChar: PROC [proc: CProc, h: Handle, arg: POINTER TO ShowArgs] ~ MACHINE CODE { "+#define ApplyHardChar_HELP(p,a,b) APPLY(p)(a,b)\n"; "#define APPLY(proc) (*((funptr)(proc)))\n"; "typedef word (*funptr)();\n"; ".ApplyHardChar_HELP"; }; ApplyHardMetrics: PROC [proc: CProc, h: Handle, arg: POINTER TO ShowArgs, charMask: ImagerMaskCache.CharMask] ~ MACHINE CODE { "+#define ApplyHardMetrics_HELP(p,a,b,c) APPLY(p)(a,b,c)\n"; ".ApplyHardMetrics_HELP"; }; debugging: BOOL ¬ FALSE; Debugging: PROC [new: CARD] RETURNS [old: BOOL] ~ { old ¬ debugging; debugging ¬ new#0; }; Debug: PROC [cp: ImagerDeviceVector.DVec, p: POINTER TO ShowArgs] ~ { s: CARD ¬ LOOPHOLE[p]; BEGIN ENABLE ABORTED => CONTINUE; ERROR END; }; worryNat: NAT = LAST[NAT15] / 2 - 1; worryReal: REAL ¬ worryNat; CPIn: PROC [cp: ImagerDeviceVector.DVec, s: POINTER TO ShowArgs] ~ { IF debugging THEN Debug[cp, s]; IF ABS[s.cp.x] < worryReal AND ABS[s.cp.y] < worryReal THEN { cp.scaled ¬ TRUE; cp.sv.s ¬ Scaled.FromReal[s.cp.x]; cp.sv.f ¬ Scaled.FromReal[s.cp.y]; } ELSE { cp.fv ¬ s.cp; cp.scaled ¬ FALSE; }; }; CPOut: PROC [cp: ImagerDeviceVector.DVec, s: POINTER TO ShowArgs] ~ { IF debugging THEN Debug[cp, s]; IF cp.scaled THEN { cp.scaled ¬ FALSE; cp.fv.x ¬ Scaled.Float[cp.sv.s]; cp.fv.y ¬ Scaled.Float[cp.sv.f]; }; s.cp ¬ cp.fv; }; Ref: PROC [ref: REF] RETURNS [REF] = INLINE { RETURN [ref] }; Show: PUBLIC PROC [h: Handle, s: POINTER TO ShowArgs] RETURNS [RES¬ok] ~ { state: State = GetState[h]; device: Device ~ state.device; fontAtom: ImagerFont.Font ~ s.fontAtom; cp: ImagerDeviceVector.DVec ~ state.cp; String: ImagerFont.XStringProc ~ TRUSTED { UNTIL s.start >= s.end DO charAction[s.characters[s.start]]; s.start ¬ s.start + 1; ENDLOOP; }; HardChar: ImagerFont.XCharProc ~ TRUSTED { CPOut[cp, s]; ApplyHardChar[s.hardChar, h, s]; CPIn[cp, s]; }; HardMetrics: SAFE PROC [charMask: ImagerMaskCache.CharMask] ~ TRUSTED { CPOut[cp, s]; ApplyHardMetrics[s.hardMetrics, h, s, charMask]; CPIn[cp, s]; }; WITH Ref[fontAtom] SELECT FROM font: ImagerFont.Font => NULL; ENDCASE => RETURN [wrongType]; WITH Ref[cp] SELECT FROM cp: ImagerDeviceVector.DVec => NULL; ENDCASE => RETURN [wrongType]; Validate[state]; CPIn[cp, s]; ImagerDeviceWorks.Show[ device: device, fontAtom: fontAtom, string: String, cp: cp, hardChar: HardChar, hardMetrics: HardMetrics, easyMetrics: s.easyMetrics, noImage: s.noImage ]; CPOut[cp, s]; }; scratchContext: Imager.Context ¬ NIL; ObtainScratchContext: ENTRY PROC RETURNS [context: Imager.Context] ~ { context ¬ scratchContext; scratchContext ¬ NIL }; ReleaseScratchContext: ENTRY PROC [context: Imager.Context] ~ { scratchContext ¬ context; }; DoHardChar: PUBLIC PROC [h: Handle, s: POINTER TO ShowArgs] RETURNS [RES¬ok] ~ { state: State = GetState[h]; iState: ImagerDeviceInterchange.InterchangeState ~ ImagerDeviceInterchange.ObtainInterchangeState[]; context: Imager.Context ¬ ObtainScratchContext[]; char: XChar ~ s.characters[s.start]; esc: VEC ~ ImagerFont.Escapement[s.fontAtom, char]; iState.device ¬ state.device; iState.clientToView ¬ ImagerTransformation.Scale[1]; iState.viewToSurface ¬ ImagerTransformation.Scale[1]; iState.surfaceToDevice ¬ ImagerTransformation.Scale[1]; iState.color ¬ state.color; context ¬ ImagerRaster.ContextFromInterchangeState[iState, context]; Imager.SetXY[context, s.cp]; Imager.Trans[context]; ImagerFontWorks.MaskChar[s.fontAtom, char, context]; IF debugging THEN Debug[NIL, s]; s.cp.x ¬ s.cp.x + esc.x; s.cp.y ¬ s.cp.y + esc.y; ReleaseScratchContext[context]; state.dcolor ¬ NIL; }; DoHardMetrics: PUBLIC PROC [h: Handle, s: POINTER TO ShowArgs, maskInfo: POINTER TO MaskInfo] RETURNS [RES¬ok] ~ { state: State = GetState[h]; char: XChar ~ s.characters[s.start]; esc: VEC ~ ImagerFont.Escapement[s.fontAtom, char]; s.cp.x ¬ s.cp.x + esc.x; s.cp.y ¬ s.cp.y + esc.y; }; BufferedSeparationImage: PUBLIC PROC [h: Handle, buffers: POINTER TO ARRAY[0..0) OF POINTER TO RasterRep, samplesPerPixel: CARD, sMin, sMax: INT, colorOperator: ColorOperator, interpolate: BOOL] RETURNS [res: RES ¬ ok] = { ENABLE ImagerError.Error => { res ¬ RESFromErrorCode[error.code]; CONTINUE }; state: State = GetState[h]; device: Device = state.device; pixelMap: ImagerPixel.PixelMap = PixelMapFromRasters[samplesPerPixel, buffers]; box: SF.Box ¬ pixelMap.box; IF box.min.s < sMin THEN box.min.s ¬ sMin; IF box.max.s > sMax THEN box.max.s ¬ sMax; ImagerImageWorks.DrawBufferedImage[device: device, buffer: pixelMap, box: box, colorOperator: colorOperator, pixelToView: state.transformation, viewToDevice: identity]; }; BufferedInterleavedImage: PUBLIC PROC [h: Handle, buffer: POINTER TO RasterRep, samplesPerPixel: CARD, sMin, sMax: INT, colorOperator: ColorOperator, interpolate: BOOL] RETURNS [res: RES ¬ ok] = { ENABLE ImagerError.Error => { res ¬ RESFromErrorCode[error.code]; CONTINUE }; state: State = GetState[h]; device: Device = state.device; sampleMap: ImagerSample.SampleMap = MakeSampleMap[buffer]; box: SF.Box ¬ sampleMap.GetBox; IF box.min.s < sMin THEN box.min.s ¬ sMin; IF box.max.s > sMax THEN box.max.s ¬ sMax; box.min.f ¬ box.min.f / samplesPerPixel; box.max.f ¬ box.max.f / samplesPerPixel; ImagerImageWorks.DrawInterleavedImage[device: device, buffer: sampleMap, samplesPerPixel: samplesPerPixel, box: box, colorOperator: colorOperator, pixelToView: state.transformation, viewToDevice: identity]; }; MesaProcRep: TYPE = RECORD [cProc: CProc, link: CARD]; ImageSourceStreamRep: TYPE = RECORD [source: ImageSource, read: ImageSourceReadProc, destroy: ImageSourceDestroyProc, readProcRep: MesaProcRep, destroyProcRep: MesaProcRep]; ImageSourceUnsafeGetBlock: IO.UnsafeGetBlockProc = { data: REF ImageSourceStreamRep = NARROW[self.streamData]; res: RES ¬ ok; nbytesResult: CARD ¬ 0; res ¬ data.read[self: data.source, buf: block.base+block.startIndex, nbytes: block.count, nbytesResult: @nbytesResult]; IF res#ok THEN ERROR IO.Error[$Failure, self, LIST[NEW[RES¬res]]]; RETURN [nbytesResult] }; ImageSourceClose: IO.CloseProc = TRUSTED { data: REF ImageSourceStreamRep = NARROW[self.streamData]; res: RES ¬ ok; res ¬ data.destroy[data.source]; self.streamProcs ¬ IOUtils.closedStreamProcs; self.streamData ¬ NIL; IF res#ok THEN ERROR IO.Error[$Failure, self, LIST[NEW[RES¬res]]]; }; imageSourceStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[ variety: $input, class: $CIIImageSource, unsafeGetBlock: ImageSourceUnsafeGetBlock, close: ImageSourceClose ]; StreamFromImageSource: PROC [source: ImageSource] RETURNS [IO.STREAM] = { data: REF ImageSourceStreamRep = NEW[ImageSourceStreamRep]; data.source ¬ source; data.readProcRep ¬ [source.read, 0]; data.destroyProcRep ¬ [source.destroy, 0]; data.read ¬ LOOPHOLE[@data.readProcRep]; data.destroy ¬ LOOPHOLE[@data.destroyProcRep]; RETURN [IO.CreateStream[streamProcs: imageSourceStreamProcs, streamData: data]]; }; StreamImage: PUBLIC PROC [h: Handle, sSize: CARD, fSize: CARD, bitsPerSample: CARD, samplesPerPixel: CARD, padMod: CARD, co: ImagerColor.ColorOperator, interpolate: BOOL, source: ImageSource] RETURNS [res: RES ¬ ok] = { ENABLE ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE; }; state: State = GetState[h]; stream: IO.STREAM = StreamFromImageSource[source]; device: Device = state.device; ImagerImageWorks.StreamImage[device: device, sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, samplesPerPixel: samplesPerPixel, padMod: padMod, pixelToView: state.transformation, viewToDevice: identity, co: co, source: stream]; IO.Close[stream]; }; ChooseBandSize: PROC [sSize: NAT, fSize: NAT] RETURNS [NAT] = { RETURN [MIN[sSize, 64]] }; GetUnsafeBlock: PROC [map: ImagerSample.RasterSampleMap] RETURNS [Basics.UnsafeBlock] ~ { size: SF.Vec ~ ImagerSample.GetSize[map]; base: POINTER TO Basics.RawBytes = LOOPHOLE[map.GetBase.word]; startIndex: NAT = map.GetBase.bit/8; IF size.s = 0 OR size.f = 0 THEN RETURN [[base: base, startIndex: startIndex, count: 0]] ELSE { bitsPerLine: CARD ~ map.GetBitsPerLine; dataBitsPerLine: CARD ~ CARD[map.GetBitsPerSample]*CARD[size.f]; fillBitsPerLine: [0..32) ~ bitsPerLine - dataBitsPerLine; padStart: [0..0] ~ map.GetBase.bit MOD 8; nBytes: NAT ~ (CARD[size.s]*bitsPerLine + 7)/8; RETURN [[base: LOOPHOLE[map.GetBase.word], startIndex: map.GetBase.bit/8, count: nBytes]] }; }; MaskStreamBits: PUBLIC PROC [h: Handle, sSize: CARD, fSize: CARD, padMod: CARD, source: ImageSource, background: Color] RETURNS [res: RES ¬ ok] = { ENABLE ImagerError.Error => { res ¬ CII.RESFromErrorCode[error.code]; CONTINUE; }; state: State = GetState[h]; stream: IO.STREAM = StreamFromImageSource[source]; IF sSize # 0 AND fSize # 0 THEN { sSizeNat: NAT ¬ sSize; fSizeNat: NAT ~ fSize; bandSize: NAT ~ ChooseBandSize[sSize: sSizeNat, fSize: fSizeNat]; fSizeBand: NAT ~ fSizeNat; padModPred: NAT = padMod-1; bitsPerLine: NAT ~ (fSize+padModPred)/padMod*padMod; bandStore: ImagerSample.RasterSampleMap ~ ImagerSample.ObtainScratchMap[box: [min: [0, 0], max: [s: bandSize, f: fSizeBand]], bitsPerSample: 1, bitsPerLine: bitsPerLine]; band: ImagerSample.RasterSampleMap ¬ NIL; -- valid band data box: SF.Box ¬ []; -- the part to image this time around. DO newBand: ImagerSample.RasterSampleMap ¬ NIL; readBand: ImagerSample.RasterSampleMap ¬ NIL; box.min.s ¬ box.max.s; box.min.f ¬ 0; box.max.s ¬ box.max.s+bandSize; box.max.f ¬ fSize; IF box.max.s > sSizeNat THEN box.max.s ¬ sSizeNat; IF box.min.s >= box.max.s THEN EXIT; readBand ¬ newBand ¬ NARROW[ImagerSample.ReIndex[map: bandStore, delta: [s: box.min.s, f: 0], box: [min: [0, 0], max: [sSizeNat, fSizeBand]]]]; IF band # NIL THEN { ImagerSample.Transfer[dst: newBand, src: band]; readBand ¬ NARROW[ImagerSample.Clip[readBand, [min: [band.GetBox.max.s, 0], max: SF.maxVec]]]; }; band ¬ newBand; TRUSTED { block: Basics.UnsafeBlock ~ GetUnsafeBlock[readBand]; bytes: INT ~ IO.UnsafeGetBlock[stream, block]; IF bytes < block.count THEN { box.max.s ¬ sSizeNat ¬ readBand.GetBox.min.s + ((bytes*8)/bitsPerLine); band ¬ NARROW[ImagerSample.Clip[band, [max: [sSizeNat, fSizeBand]]]]; }; }; InternalMaskBitmap[state, band, background]; ENDLOOP; ImagerSample.ReleaseScratchMap[bandStore]; }; }; ApplyCCITTFacsimileDecompressionFilter: PUBLIC ApplyCCITTFacsimileDecompressionFilterProc = { IF h = NIL OR h.data = NIL OR filteredResult = NIL THEN RETURN [nilFault]; filteredResult­ ¬ NIL; SELECT padMod FROM 1 => IF (fSize MOD 8) # 0 THEN GO TO notYet; 8, 16, 32 => {}; ENDCASE => GO TO notYet; SELECT TRUE FROM requireEOL => GO TO notYet; fSize NOT IN [1..32000] => GO TO notYet; sSize NOT IN [0..32000] => GO TO notYet; endOfBlock => GO TO notYet; damagedRowsBeforeError # 0 => GO TO notYet; ENDCASE => { state: State = GetState[h]; st: IO.STREAM = StreamFromImageSource[input]; g4: G4Data = PixelArrayCCITTG4Private.FromStream[st, fSize]; words: CARDINAL = (fSize+BITS[WORD]-1)/BITS[WORD]; buf: REF Basics.RawBytes = NEW[Basics.RawBytes[words * BYTES[WORD]]]; bp: BytesPtr = LOOPHOLE[buf]; fsd: FaxSourceData = NEW[FaxSourceDataRep ¬ [h: h, st: st, g4: g4, buf: buf, bp: bp, sSize: sSize, fSize: fSize]]; result: REF CII.ImageSourceObjectRep = NEW[CII.ImageSourceObjectRep ¬ [ data: LOOPHOLE[fsd], read: CProcFromProc[FaxSourceRead], destroy: CProcFromProc[FaxSourceDestroy]]]; g4.scanLength ¬ fSize; g4.reverseBits ¬ msbFirst; g4.k ¬ k; g4.useFastScan ¬ TRUE; g4.reverseBits ¬ NOT msbFirst; g4.sSize ¬ sSize; g4.lineBuffer ¬ ImagerSample.ObtainUnsafeDescriptor[size: [s: 1, f: fSize], bitsPerSample: 1, bitsPerLine: fSize, base: [LOOPHOLE[buf], 0], ref: buf, words: words]; fsd.mod ¬ padMod; fsd.rem ¬ 0; fsd.pos ¬ 0; fsd.invert ¬ NOT blackIs1; NoteRef[state, fsd]; NoteRef[state, result]; filteredResult­ ¬ LOOPHOLE[result]; RETURN [ok]; }; EXITS notYet => RETURN [notImplemented]; }; G4Data: TYPE = PixelArrayCCITTG4Private.Data; FaxSourceData: TYPE = REF FaxSourceDataRep; FaxSourceDataRep: TYPE = RECORD [ h: Handle ¬ NIL, st: IO.STREAM ¬ NIL, g4: G4Data ¬ NIL, buf: BytesRef ¬ NIL, bp: BytesPtr ¬ NIL, mod: CARDINAL ¬ 0, pos: CARDINAL ¬ 0, rem: CARDINAL ¬ 0, fSize: INTEGER ¬ 0, sSize: INTEGER ¬ 0, s: INTEGER ¬ 0, invert: BOOL ¬ FALSE ]; BytesPtr: TYPE = POINTER TO Basics.RawBytes; BytesRef: TYPE = REF Basics.RawBytes; FaxSourceRead: CII.ImageSourceReadProc = { fsd: FaxSourceData = LOOPHOLE[self.data]; rem: CARDINAL ¬ 0; IF nbytesResult = NIL THEN RETURN [nilFault]; nbytesResult­ ¬ 0; IF fsd = NIL THEN RETURN [nilFault]; IF nbytes = 0 THEN RETURN [bounds]; IF fsd.g4.end THEN RETURN [eof]; rem ¬ fsd.rem; IF rem = 0 THEN { fSize: CARDINAL = fsd.fSize; fMod: [0..BITS[WORD]) = fSize MOD BITS[WORD]; PixelArrayCCITTG4Private.FillLineBuffer[fsd.g4, fsd.s, fsd.invert]; IF fsd.g4.error # NIL THEN {fsd.g4.end ¬ TRUE; RETURN [ioError]}; fsd.s ¬ fsd.s + 1; SELECT fsd.mod FROM 16 => rem ¬ ((fSize+15) / 16) * 2; 32 => rem ¬ ((fSize+31) / 32) * 4; ENDCASE => rem ¬ (fSize+7) / 8; IF fMod # 0 THEN { WordPtr: TYPE = POINTER TO WORD; mask: WORD ¬ Basics.BITRSHIFT[WORD.LAST, fMod]; wp: WordPtr = LOOPHOLE[fsd.bp, WordPtr] + SIZE[WORD]*(fSize / BITS[WORD]); w: WORD ¬ wp­; w ¬ w - Basics.BITAND[w, mask]; IF fsd.invert THEN w ¬ w + mask; wp­ ¬ w; }; fsd.pos ¬ 0; }; IF rem < nbytes THEN nbytes ¬ rem; Basics.MoveBytes[ dstBase: LOOPHOLE[buf, BytesPtr], dstStart: 0, srcBase: fsd.bp, srcStart: fsd.pos, count: nbytes]; fsd.rem ¬ rem - nbytes; fsd.pos ¬ fsd.pos + nbytes; nbytesResult­ ¬ nbytes; RETURN [ok]; }; FaxSourceDestroy: CII.ImageSourceDestroyProc = { fsd: FaxSourceData = LOOPHOLE[self.data]; IF fsd # NIL THEN { h: Handle = fsd.h; state: State = GetState[fsd.h]; g4: G4Data = fsd.g4; ImagerSample.ReleaseDescriptor[g4.lineBuffer]; g4.lineBuffer ¬ NIL; PixelArrayCCITTG4Private.Close[g4]; [] ¬ DestroyAny[h, fsd]; fsd.h ¬ NIL; self.data ¬ NIL; }; RETURN [ok]; }; HalftoneProperties: TYPE = REF HalftonePropertiesRep; HalftonePropertiesRep: PUBLIC TYPE = CIIPrivate.HalftonePropertiesRep; MakeHalftoneProperties: PUBLIC PROC [h: Handle, separationCount: INT, halftonePropertiesForSeparation: POINTER TO ARRAY [0..0) OF HalftonePropertiesForSeparation, halftonePropertiesResult: POINTER TO HalftoneProperties] RETURNS [res: RES ¬ ok] = { state: State = GetState[h]; p: ImagerBrick.HalftoneProperties ¬ NIL; FOR i: INT DECREASING IN [0..separationCount) DO s: POINTER TO HalftonePropertiesForSeparation = @(halftonePropertiesForSeparation[i]); type: ATOM = NIL; toner: ImagerBrick.Toner = VAL[ORD[s.toner]]; maxSample: CARDINAL = s.maxSample; thresholds: ImagerSample.RasterSampleMap = MakeSampleMap[@(s.thresholds), ObtainDesc[state]]; brick: ImagerBrick.Brick = [maxSample: s.maxSample, sampleMap: ImagerSample.Copy[thresholds], phase: s.phase]; p ¬ CONS[[type: type, toner: toner, brick: brick, propList: NIL], p]; ReleaseDesc[state, thresholds]; ENDLOOP; NoteRef[state, halftonePropertiesResult­ ¬ NEW[HalftonePropertiesRep ¬ [p]]]; }; ValidateHalftoneProperties: PROC [state: State] = { IF state.halftoneProperties = NIL THEN state.halftoneProperties ¬ NEW[HalftonePropertiesRep ¬ [NIL]]; IF state.savedDevice = NIL AND state.halftoneProperties # state.dhalftoneProperties AND state.device.class.SetHalftoneProperties # NIL THEN { state.device.class.SetHalftoneProperties[state.device, state.halftoneProperties.p]; state.dhalftoneProperties ¬ state.halftoneProperties; }; }; SetHalftoneProperties: PUBLIC PROC [h: Handle, halftoneProperties: HalftoneProperties] RETURNS [res: RES ¬ ok] = { state: State = GetState[h]; state.halftoneProperties ¬ halftoneProperties; ValidateHalftoneProperties[state]; }; GetHalftoneProperties: PUBLIC PROC [h: Handle, halftonePropertiesResult: POINTER TO HalftoneProperties] RETURNS [res: RES ¬ ok] = { state: State = GetState[h]; ValidateHalftoneProperties[state]; NoteRef[state, halftonePropertiesResult­ ¬ state.halftoneProperties]; }; Destroy: PUBLIC DestroyProc = { res: RES ¬ ok; IF h = NIL THEN RETURN [nilFault] ELSE { state: State = GetState[h]; IF state = NIL THEN RETURN [nilFault]; UNTIL state.cleanups = NIL DO cleanupObject: CleanupObject = state.cleanups.first; IF UnRegisterCleanupObject[h, cleanupObject] # ok THEN ERROR; [] ¬ ApplyCleanupObject[cleanupObject.Cleanup, cleanupObject, h]; ENDLOOP; IF state.refTab.GetSize[] # 0 THEN res ¬ accessError; }; IF NOT handles.Delete[h] THEN res ¬ accessError; h.data ¬ NIL; RETURN [res] }; ApplyCleanupObject: PROC [cleanup: CProc, self: CII.CleanupObject, h: CII.Handle] RETURNS [RES] = MACHINE CODE { "+#define ApplyCleanupObject_HELP(p,a,b) APPLY(p)(a,b)\n"; ".ApplyCleanupObject_HELP" }; DestroyColor: PUBLIC DestroyColorProc = {RETURN DestroyAny[h, color]}; DestroyColorOperator: PUBLIC DestroyColorOperatorProc = {RETURN DestroyAny[h, colorOperator]}; DestroyClipper: PUBLIC DestroyClipperProc = {RETURN DestroyAny[h, clipper]}; DestroyFont: PUBLIC DestroyFontProc = {RETURN DestroyAny[h, font]}; DestroyMaskProgram: PUBLIC DestroyMaskProgramProc = {RETURN DestroyAny[h, maskProgram]}; DestroyHalftoneProperties: PUBLIC DestroyHalftonePropertiesProc = { RETURN DestroyAny[h, halftoneProperties] }; DestroyLookupTable: PUBLIC DestroyLookupTableProc = { RETURN DestroyAny[h, lookupTable] }; DefaultSetOutputBuffers: PUBLIC SetOutputBuffersProc = { RETURN [notImplemented] }; DefaultSetSeparation: PUBLIC SetSeparationProc = { RETURN [notImplemented] }; LookupTableRep: PUBLIC TYPE = ImagerDeviceColor.LookupTableRep; clttTranslate: ARRAY ColorLookupTableType OF ImagerDeviceColor.ColorLookupTableType = [redTransfer: redTransfer, greenTransfer: greenTransfer, blueTransfer: blueTransfer, grayTransfer: grayTransfer, blackGeneration: blackGeneration, undercolorRemoval: undercolorRemoval]; MakeLookupTable: PUBLIC MakeLookupTableProc = { state: State = GetState[h]; new: ImagerDeviceColor.LookupTable = NEW[LookupTableRep[tableSize]]; FOR i: INT IN [0..tableSize) DO new[i] ¬ table[i] ENDLOOP; NoteRef[state, lookupTableResult­ ¬ new]; RETURN [ok] }; SetColorLookupTable: PUBLIC SetColorLookupTableProc = { state: State = GetState[h]; control: ImagerDeviceColor.DeviceColorControl = ImagerDeviceColor.GetDeviceColorControl[state.device]; ImagerDeviceColor.SetLookupTable[control, clttTranslate[which], lookupTable]; RETURN [ok] }; GetColorLookupTable: PUBLIC GetColorLookupTableProc = { state: State = GetState[h]; control: ImagerDeviceColor.DeviceColorControl = ImagerDeviceColor.GetDeviceColorControl[state.device]; NoteRef[state, lookupTableResult­ ¬ control.table[clttTranslate[which]]]; RETURN [ok] }; DefaultSetColorTable: PUBLIC SetColorTableProc = { IF CStrings.Strlen[format] = 0 THEN RETURN [ok] ELSE RETURN [notImplemented]; }; AtomFromCString: PUBLIC PROC [s: CStrings.CString] RETURNS [ATOM] = { G: SAFE PROC [C: PROC [CHAR]] = TRUSTED { FOR i: NAT15 ¬ 0, i+1 UNTIL s[i]=0C DO C[s[i]] ENDLOOP; }; RETURN [Atom.MakeAtomFromChars[G]] }; MatchCString: PUBLIC PROC [s: CStrings.CString, text: REF TEXT] RETURNS [BOOL] = { FOR i: NAT IN [0..text.length) DO IF s[i] # text[i] THEN RETURN [FALSE]; ENDLOOP; RETURN [s[text.length] = 0C] }; DefaultSync: PUBLIC SyncProc = { IF MatchCString[operationName, "sync"] THEN RETURN [ok] ELSE RETURN [notImplemented]; }; RegisterCleanupObject: PUBLIC RegisterCleanupObjectProc = { state: State = GetState[h]; IF cleanupObject = NIL THEN RETURN [nilFault]; state.cleanups ¬ CONS[cleanupObject, state.cleanups]; RETURN [ok] }; UnRegisterCleanupObject: PUBLIC RegisterCleanupObjectProc = { state: State = GetState[h]; prev: LIST OF CleanupObject ¬ NIL; FOR tail: LIST OF CleanupObject ¬ state.cleanups, tail.rest UNTIL tail = NIL DO IF tail.first = cleanupObject THEN { IF prev = NIL THEN state.cleanups ¬ tail.rest ELSE prev.rest ¬ tail.rest; tail.rest ¬ NIL; tail.first ¬ NIL; RETURN [ok] }; prev ¬ tail; ENDLOOP; RETURN [accessError] }; DefaultSetupArrayParamSize: PUBLIC CIIPrivate.SetupArrayParamSizeProc = { RETURN [accessError] }; DefaultSetupIntParam: PUBLIC CIIPrivate.SetupIntParamProc = { RETURN [accessError] }; DefaultSetupFloatParam: PUBLIC CIIPrivate.SetupFloatParamProc = { RETURN [accessError] }; DefaultSetupNameParam: PUBLIC CIIPrivate.SetupNameParamProc = { RETURN [accessError] }; DefaultCreateHandleFromRasters: PUBLIC CIIPrivate.CreateHandleFromRastersProc = { RETURN [accessError] }; setuphandles: RefTab.Ref = RefTab.Create[]; DestroySetupObject: CIIPrivate.DestroySetupObjectProc = { res: RES ¬ ok; IF s = NIL THEN RETURN [nilFault]; IF NOT setuphandles.Delete[s] THEN res ¬ accessError; s.data ¬ NIL; RETURN [res] }; SetupStandardParams: PUBLIC CIIPrivate.SetupStandardParamsProc = { s.data.sSizeDevice ¬ sSizeDevice; s.data.fSizeDevice ¬ fSizeDevice; s.data.scanMode ¬ ScanModeTranslate[scanMode]; s.data.surfaceUnitsPerInchX ¬ surfaceUnitsPerInchX; s.data.surfaceUnitsPerInchY ¬ surfaceUnitsPerInchY; RETURN [ok] }; CreateSetupHandle: PUBLIC PROC [ data: REF, SetupArrayParamSize: CIIPrivate.SetupArrayParamSizeProc, SetupIntParam: CIIPrivate.SetupIntParamProc, SetupFloatParam: CIIPrivate.SetupFloatParamProc, SetupNameParam: CIIPrivate.SetupNameParamProc, CreateHandleFromRasters: CIIPrivate.CreateHandleFromRastersProc ] RETURNS [CIIPrivate.SetupHandle] = { h: CIIPrivate.SetupHandle = NEW[CIIPrivate.SetupObjectRep[7]]; << September 21, 1993 2:12:39 pm PDT >> << >> h[0] ¬ CProcFromProc[SetupStandardParams]; h[1] ¬ CProcFromProc[SetupArrayParamSize]; h[2] ¬ CProcFromProc[SetupIntParam]; h[3] ¬ CProcFromProc[SetupFloatParam]; h[4] ¬ CProcFromProc[SetupNameParam]; h[5] ¬ CProcFromProc[CreateHandleFromRasters]; h[6] ¬ CProcFromProc[DestroySetupObject]; h.data ¬ NEW[CIIPrivate.SetupHandleDataRep ¬ [ data: data, sSizeDevice: 0, fSizeDevice: 0, scanMode: [slow: right, fast: up], surfaceUnitsPerInchX: 1, surfaceUnitsPerInchY: 1 ]]; [] ¬ RefTab.Insert[setuphandles, h, h]; RETURN [h] }; handles: RefTab.Ref = RefTab.Create[]; MakeHandle: PUBLIC PROC [data: REF, SetOutputBuffers: SetOutputBuffersProc, SetSeparation: SetSeparationProc, SetColorTable: SetColorTableProc, Sync: SyncProc] RETURNS [Handle] = { state: State = NARROW[data]; h: REF ObjectRep = NEW[ObjectRep[59]]; IF state.refTab # NIL THEN ERROR; -- That's my field, bub! state.refTab ¬ RefTab.Create[]; h.data ¬ state; -- Generated code: << October 28, 1993 12:22:43 pm PDT >> h[0] ¬ CProcFromProc[Destroy]; h[1] ¬ CProcFromProc[DestroyColor]; h[2] ¬ CProcFromProc[DestroyColorOperator]; h[3] ¬ CProcFromProc[DestroyClipper]; h[4] ¬ CProcFromProc[DestroyFont]; h[5] ¬ CProcFromProc[SetMatrix]; h[6] ¬ CProcFromProc[GetMatrix]; h[7] ¬ CProcFromProc[GetInitialMatrix]; h[8] ¬ CProcFromProc[SetInitialMatrix]; h[9] ¬ CProcFromProc[MakeGrayColorOperator]; h[10] ¬ CProcFromProc[MakeRGBColorOperator]; h[11] ¬ CProcFromProc[MakeCMYKColorOperator]; h[12] ¬ CProcFromProc[MakeHighlightColorOperator]; h[13] ¬ CProcFromProc[MakeColor]; h[14] ¬ CProcFromProc[MakeSampledBlack]; h[15] ¬ CProcFromProc[SetColor]; h[16] ¬ CProcFromProc[SetGray]; h[17] ¬ CProcFromProc[SetRGB]; h[18] ¬ CProcFromProc[SetHSV]; h[19] ¬ CProcFromProc[SetCMYK]; h[20] ¬ CProcFromProc[GetColor]; h[21] ¬ CProcFromProc[MaskRectangle]; h[22] ¬ CProcFromProc[MaskFill]; h[23] ¬ CProcFromProc[Clip]; h[24] ¬ CProcFromProc[GetClipper]; h[25] ¬ CProcFromProc[SetClipper]; h[26] ¬ CProcFromProc[BuildClipperBegin]; h[27] ¬ CProcFromProc[BuildClipperEnd]; h[28] ¬ CProcFromProc[MaskStroke]; h[29] ¬ CProcFromProc[MaskBitmap]; h[30] ¬ CProcFromProc[MaskDeviceTrapezoid]; h[31] ¬ CProcFromProc[DestroyMaskProgram]; h[32] ¬ CProcFromProc[MakeMaskProgram]; h[33] ¬ CProcFromProc[MaskDeviceBoxes]; h[34] ¬ CProcFromProc[FindFont]; h[35] ¬ CProcFromProc[ModifyFont]; h[36] ¬ CProcFromProc[MakeFontAtom]; h[37] ¬ CProcFromProc[DoHardChar]; h[38] ¬ CProcFromProc[DoHardMetrics]; h[39] ¬ CProcFromProc[Show]; h[40] ¬ CProcFromProc[BufferedSeparationImage]; h[41] ¬ CProcFromProc[BufferedInterleavedImage]; h[42] ¬ CProcFromProc[StreamImage]; h[43] ¬ CProcFromProc[MaskStreamBits]; h[44] ¬ CProcFromProc[ApplyCCITTFacsimileDecompressionFilter]; h[45] ¬ CProcFromProc[MakeHalftoneProperties]; h[46] ¬ CProcFromProc[SetHalftoneProperties]; h[47] ¬ CProcFromProc[GetHalftoneProperties]; h[48] ¬ CProcFromProc[DestroyHalftoneProperties]; h[49] ¬ CProcFromProc[SetSeparation]; h[50] ¬ CProcFromProc[SetOutputBuffers]; h[51] ¬ CProcFromProc[SetColorTable]; h[52] ¬ CProcFromProc[MakeLookupTable]; h[53] ¬ CProcFromProc[DestroyLookupTable]; h[54] ¬ CProcFromProc[SetColorLookupTable]; h[55] ¬ CProcFromProc[GetColorLookupTable]; h[56] ¬ CProcFromProc[Sync]; h[57] ¬ CProcFromProc[RegisterCleanupObject]; h[58] ¬ CProcFromProc[UnRegisterCleanupObject]; [] ¬ RefTab.Insert[handles, h, h]; RETURN [h] }; END. z CIIImpl.mesa Copyright Ó 1990, 1993 by Xerox Corporation. All rights reserved. Michael Plass, June 29, 1994 9:02 am PDT Russ Atkinson (RRA) October 22, 1993 2:30 pm PDT Commander, CommanderOps, NotReallyAViewer, Depends on Mimosa's PROC encoding. IF r[1] # 0 THEN ERROR; StateRep: TYPE ~ RECORD [ refTab: RefTab.Ref, -- Things passed out to clients & not destroyed, w/ ref counts device: ImagerDevice.Device, initialTransformation: ImagerTransformation.Transformation, -- for GetInitialMatrix savedDevice: ImagerDevice.Device ¬ NIL, -- For use during BuildClipper scope color: ImagerColor.Color, -- color that has been set by the client dcolor: ImagerColor.Color, -- color that has been pushed into the device transformation: ImagerTransformation.Transformation, -- client to device viewClipper: ImagerDevice.DeviceClipper, clientClipper: ImagerClipper.Clipper, halftoneProperties: REF HalftonePropertiesRep, -- set by the client dhalftoneProperties: REF HalftonePropertiesRep, -- pushed into the device cp: ImagerDeviceVector.DVec, scratchDesc: ImagerSample.RasterSampleMap, cleanups: LIST OF CII.CleanupObject ]; ERROR; -- Should implement this. NOTE: We could defer this work until masking time, if that seems important. FIXTHIS - should do a table to translate end & joint types. In this case, the device really wants the boxes in a fussier order than the client is willing to generate, so we need to work a little harder. PROC [charAction: XCharProc] PROC [self: IO.STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT] ASSUMES byte addressing, big-endian c semantics Like ImagerSample.GetUnsafeBlock, but allows up to 31 pad bits per scan line. Premature end; chop off the image, as per section 4.10.2 [h: Handle, input: ImageSource, k: INT, requireEOL: BOOL, padMod: CARD, sSize: CARD, fSize: CARD, endOfBlock: BOOL, blackIs1: BOOL, msbFirst: BOOL, damagedRowsBeforeError: INT, filteredResult: POINTER TO ImageSource] RETURNS [RES] We think that we can handle this Note: "reversed" means reversed from normal PC world order. Adobe behavior is reverseBits = true! msbFirst means that the first bit is the high-order bit in the byte. [self: ImageSource, buf: POINTER, nbytes: CARD, nbytesResult: POINTER TO CARD] RETURNS [RES] Refill the line buffer Pad out the last valid word in the buffer [self: ImageSource] RETURNS [RES] IF table[0] + table[tableSize-1] NOT IN [-10.0..10.0] THEN ERROR; -- sanity check Ê<{•NewlineDelimiter –"cedarcode" style™codešœ ™ Kšœ Ïeœ7™BK™(KšÏz0™0—K˜šÏk ˜ Kšœ*™*K˜K˜KšŸœŸœ€ŸœÑ˜ÝK˜ K˜ K˜K˜ Kšœ Ÿœ ˜K˜ K˜K˜ K˜ K˜Kšœ˜Kšœ˜K˜Kšœ ˜ Kšœ˜K˜K˜Kšœ˜Kšœ ˜ Kšœ ˜ K˜K˜ K˜K˜ K˜ K˜ K˜KšŸœ˜K˜Kšž˜K˜K˜K˜K˜ K˜KšŸœ˜K˜ K˜—K˜KšÏnœŸ˜Kš!ŸœžŸœž œž œž,œž œ žœžœ žœ ž œžœÐkzžœ ž"œ žœžœ ž˜¶KšŸœ Ÿ˜KšŸœ ˜šœŸœŸœŸœ˜K˜KšŸœŸœŸœ˜Kš¡ž¡ž¡ž¡ž˜KšœŸœ˜ Kšœ ŸœŸœ˜-KšœŸœ˜0KšœŸœ˜0KšœŸœŸœ ˜=KšœŸœ˜#Kšœ Ÿœ˜&KšœŸœ˜1KšœŸœ'˜;KšŸœŸœ Ÿœ˜Kšœ ŸœŸœ˜*K˜KšœŸœŸœ˜$Kšž¡ž¡ž˜&Kšœ ŸœŸœ˜0Kšž ¡ž¡ž˜.Kšœ ŸœŸœ˜2KšœŸœŸœ˜,Kšœ ŸœŸœ ˜6šœŸœŸœ#˜KšŸœŸœ˜—KšŸœ ˜K˜—šŸœ˜K˜KšŸœ ˜Kšœ˜——Kšœ˜—KšŸœ ŸœŸœŸœ ˜&KšŸœŸœŸœ)˜:Kšœ˜K˜—Kš œŸœŸœŸœŸœ˜$š  œŸœŸœŸœ Ÿœ˜LKšŸœB˜HK˜K˜—š œŸœ&˜=KšŸœŸœŸœ˜K˜K˜K˜—š œŸœŸœŸœ ˜HK˜K˜K˜K˜K˜—š  œŸœŸœŸœŸœ ŸœŸœ˜XK˜KšŸœŸœŸœŸœ ˜-K˜9K˜K˜—š  œŸœŸœŸœŸœ ŸœŸœ˜RK˜šŸœ Ÿ˜KšŸœŸœ ˜šŸœ˜K˜2K˜K˜#K˜——K˜K˜—š œŸœŸœ˜IK˜lKšœ[˜[KšŸœ˜ Kšœ˜K˜—š œŸœŸœŸœŸœ ŸœŸœ˜YK˜K˜9K˜K˜—š œŸœŸœŸœŸœ ŸœŸœ˜_K˜šŸœŸœŸœ˜+K˜BKšœ˜—K˜@K˜K˜—šœ;˜;K˜—š œŸœŸœŸœŸœŸœŸœŸœ˜LK˜K˜5Kšœ˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜ZK˜K˜AKšœ˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜ZK˜K˜?Kšœ˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜\K˜K˜NKšœ˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜ášŸœ˜KšœŸœŸœ˜JKšœ,Ÿœ˜7Kšœ+Ÿœ˜6K˜—K˜š  œŸœŸœŸœŸœŸœŸœ˜:KšŸœŸœŸœŸœ˜6KšŸœ6˜KšŸœ:˜@Kšœ˜—K˜KšœŸœ˜Kšœ*Ÿœ ˜=K˜%Kšœ˜K˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜¯šŸœ˜KšœŸœŸœ˜JKšœ,Ÿœ˜7Kšœ+Ÿœ˜6K˜—K˜K˜LK˜K˜@K˜ K˜ K˜"Kšœ Ÿ˜K˜—˜,K˜K˜&K˜ K˜—K˜K˜%K˜K˜—š œŸœŸœŸœŸœŸœŸœ˜UK˜K˜+Kšœ˜K˜—š  œŸœŸœŸœŸœŸœ˜BK˜šŸœŸœŸ˜K˜$KšŸœŸœ ˜—Kšœ˜K˜—KšœŸœŸœ ˜Kšœ Ÿœ˜%šœ ŸœŸœ™JšœÏc>™RJ™Jšœ<¢™SJšœ#Ÿœ¢$™LJšœ¢(™BJšœ¢-™HJšœ5¢™HJ™(J™%JšœŸœ¢™CJšœŸœ¢™IJ™J™*Jšœ ŸœŸœŸœ™#Kšœ™K™—š œŸœ˜!Kš ŸœŸœŸœŸœ¢'˜OšŸœŸœ˜$K˜šŸœ ŸœŸ˜šœ˜Kšœ/˜/K˜Kšœ˜—KšŸœŸœ˜—Kšœ˜—Kšœ˜K˜—š  œŸœŸœ%Ÿœ!ŸœŸœ˜}K˜K˜K˜šŸœŸœŸœ˜*šŸœ˜K™ K˜—šŸœ˜š  œŸœŸœ ŸœŸœ˜6KšœŸœ˜Kšœ5ŸœŸœ˜GKšœ&Ÿœ˜=Kšœ&Ÿœ˜=šŸœ Ÿ˜KšœŸœ˜%KšœŸœ˜%KšŸœ ŸœŸœ˜3KšŸœ Ÿœ ˜KšŸœ Ÿœ ˜KšŸœ Ÿœ%˜4K˜ Kšœ Ÿœ ˜Kšœ Ÿœ ˜KšŸœ˜—Kšœ˜—K˜CKšœ˜——Kšœ˜K˜—š œŸœŸœŸœŸœ ŸœŸœŸœŸœŸœŸœ˜…K˜KšœŸœ ŸœŸœ ˜2š  œŸœŸœŸœŸœ˜*KšŸœŸœ˜:KšŸœŸœ˜:KšŸœŸœ˜:KšŸœŸœ˜:Kšœ˜—š œŸœŸœ˜"šŸœŸœŸœŸ˜ K˜šŸœŸœŸœŸ˜"KšœŸœŸœ˜$KšœŸœ ˜K˜6KšŸœ˜—KšŸœ˜—Kšœ˜—K˜ šŸœŸœ˜%K˜K˜:Kšœ˜—K˜K˜—šœ ŸœŸœ˜K˜K˜K˜ K˜Kšœ˜K˜—š œŸœ˜Kšœ ŸœŸœ Ÿœ ˜2K˜KšŸœ˜ K˜K™—š œŸœ˜Kšœ ŸœŸœ Ÿœ ˜2K˜KšŸœ˜ Kšœ˜K˜—š œŸœ˜Kšœ ŸœŸœ Ÿœ ˜2Kšœ"˜"KšŸœ˜ Kšœ˜K˜—š œŸœ˜Kšœ ŸœŸœ Ÿœ ˜2Kšœ!˜!KšŸœ˜ Kšœ˜K˜—š   œŸœ&ŸœŸœ ŸœŸœ˜[Kšœ ŸœŸœ˜EKšœŸœŸœ ˜8˜(K˜ K˜K˜K˜ K˜Kšœ˜—KšŸœ3˜9K˜K˜—š  œŸœŸœ?ŸœŸœ˜iK˜š œŸœ˜%K˜TK˜;Kšœ˜—K˜^šœ$Ÿœ˜)Kšœ2Ÿœ˜9K˜K˜—KšŸœ˜!Kšœ˜K˜—š  œŸœŸœŸœŸœŸœŸœ˜iK˜K˜5Kšœ˜K˜—š   œŸœŸœ-ŸœŸœ˜XK˜K˜K˜K˜K˜—š œŸœŸœ˜/K™KK˜ŒKšœ˜K˜—š  œŸœŸœ?ŸœŸœ˜mK˜š œŸœ˜%K˜TK˜;Kšœ˜—K˜K˜wKšœ˜K˜—š  œŸœŸœŸœŸœ ŸœŸœ˜WK˜K˜K˜KKšœ˜K˜—Kšœ ŸœŸœŸ œ/˜SšœŸœŸœŸ œa˜‡K˜—š  œŸœŸœ.ŸœŸœŸœŸœ˜{šŸœŸœŸœ Ÿœ˜0KšŸœ<Ÿœ˜MK˜š œŸœ˜%K˜TK˜;Kšœ˜—K˜‡K˜K™;šŸœ˜šŸœ˜KšœzŸœŸœ/˜¿K˜—šŸœ˜Kš œŸœŸœŸœŸœŸœŸœŸœ˜QKšœÞŸœŸœ/˜£Kšœ˜——Kšœ˜—Kšœ˜K˜—š  œŸœŸœŸœŸœŸœŸœŸœŸœ˜K˜K˜wK˜Kšœ‚Ÿœ˜˜Kšœ˜K˜—š œŸ œŸœ ŸœŸœŸœŸœŸœŸœ Ÿœ˜”Jš œŸœŸœ ŸœŸœ˜;KšŸœŸœŸœU˜xšŸœŸœŸœŸ˜&J˜!KšŸœ˜—KšŸœ9˜?K˜K˜—š   œŸ œ ŸœŸœ4ŸœŸœ#˜‘Kš œŸœOŸœŸœŸœŸœ¢Z˜ÐšŸœ˜˜ K˜JK˜$K˜ K˜7KšœŸœ ˜K˜ K˜K˜—K˜—Kšœ˜K˜—š  œŸœŸœ"Ÿœ˜QJ˜7JšœŸœ˜KšŸœ˜ K˜K˜—š  œŸœ6Ÿœ˜OKšœŸœ˜Kšœ Ÿœ˜J˜Kšœ˜K˜—š  œŸœŸœŸœŸœŸœŸœ˜iK˜K˜PK˜.K˜K˜K˜—š œŸœL˜dšŸœŸœŸœ˜K˜eK˜ K˜LK˜K˜K˜eK˜K˜%K˜—K˜K˜gKšœ˜K˜—Kšœ ŸœŸœŸœ˜KšœŸœŸœŸœ˜#Kš œŸœ˜KšœŸœŸœŸ œã˜ÿš œŸœŸœŸœ Ÿœ4ŸœŸœŸœŸœ˜¯KšŸœ6Ÿœ˜GK˜KšœŸœŸœ7˜EKšœ ŸœŸœ¢&˜UKš œ ŸœŸœ Ÿœ ŸœŸœŸœ˜=KšœŸœŸœŸœ˜!KšœŸœ˜ KšœŸœ˜ šœ ŸœŸœ˜Kšœ(Ÿœ˜3K˜K˜—KšœŸœŸœŸœ˜Eš œ ŸœŸœŸœŸœŸœ˜.š ŸœŸœŸœŸœŸœŸœŸ˜8KšœŸœ˜.KšŸœ˜—Kšœ˜—š  œŸœŸœ ˜%K˜šŸœŸœŸœŸœ˜4KšœŸœ ˜šŸœŸ˜KšŸœ Ÿœ ˜KšŸœŸœ˜ —Kšœ˜—Kšœ˜—š  œŸœŸœ ˜%K˜KšŸœŸœŸœ˜.šŸœ Ÿ˜KšœŸœ˜KšœŸœ˜KšœŸœ˜KšŸœŸœ˜ —Kšœ˜—KšœŸœ˜KšŸœŸœ ŸœŸœ˜.šŸœŸ˜šŸœ Ÿ˜KšœŸœŸœ ˜8˜KšŸœ ŸœŸœŸœ˜)K˜K˜"K˜$K˜K˜—˜KšŸœ ŸœŸœŸœ˜)K˜ KšœŸœ˜3K˜ K˜—˜K˜K˜—˜K˜K˜—˜K˜K˜—˜K˜K˜—˜K˜K˜—˜K˜ K˜—˜K˜K˜—˜K˜K˜—˜K˜K˜—˜K˜K˜—šŸœ˜ KšœŸœ˜šŸœŸœ˜KšŸœ˜KšŸœŸœ˜—K˜——K˜ KšŸœ˜—K˜.Kšœ˜K˜—š œŸœŸœŸœŸœŸœŸœ˜@KšŸœ˜Kšœ˜K˜—š œŸœŸœŸœŸœŸœŸœ˜6KšœŸœŸœŸœ˜Kšœ Ÿœ˜KšŸœŸœŸœ˜Kšœ˜K˜—KšœŸœŸœŸœŸœŸœŸœŸœŸœ˜LKšœŸœŸœŸœŸœŸœŸœŸœŸœ˜Oš œŸœŸœ%Ÿœ Ÿœ/Ÿœ ŸœŸœŸœ ˜µK˜K˜KšŸœŸœŸœŸœ ˜,šŸœ Ÿœ Ÿœ˜%š   œŸœŸœ ŸœŸœ˜>KšœŸœŸœ˜KšœŸœ˜ KšœŸœŸœŸœ.˜FKš œŸœ˜ KšœŸœŸœŸœ ˜5KšœŸœ˜KšœŸœ˜ šŸœŸ˜Kšœ ŸœŸœ ˜K˜ šŸœŸ˜KšœŸœ ˜%Kš œŸœŸœŸœŸœ˜:˜ KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ˜KšŸœ Ÿœ Ÿœ!˜š œŸœ˜%š ŸœŸœŸœŸœŸœŸœŸ˜;J˜-J˜-J˜-J˜,KšŸ˜—Kšœ˜—K˜?K˜KšŸœŸœ˜!K˜—KšŸœŸœŸœ˜—Kšœ˜K˜—šœ)Ÿœ ˜LKš œ˜Kš  œ˜Kšœ˜K˜—š œŸœŸœ@Ÿœ˜cKšœŸœ˜(Kšœ˜K˜—š  œŸ œŸœ ŸœŸœ˜`KšœŸœ˜(K˜FšŸœŸœŸœ˜šŸœŸœŸœ˜K˜$KšŸœ ŸœŸœŸœ˜2K˜Kšœ˜—K˜K˜—Kšœ˜—K˜š œŸœŸœ6ŸœŸœŸœŸœ ˜‚K˜KšœŸœ#˜-KšŸœŸœŸœŸœ ˜+KšœŸœ˜Kšœ^ŸœŸœ˜ŒKšœ˜K˜—š  œŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜‚K˜KšŸœŸœŸœŸœ ˜+KšœŸœ˜šŸœŸœŸ˜˜K˜+K˜2K˜"K˜ K˜—KšŸœŸœ ˜—Kšœ˜K˜—š  œŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜„K˜KšŸœŸœŸœŸœ ˜+KšœŸœ˜šŸœŸœŸ˜˜K˜+K˜1K˜9K˜ K˜—KšŸœŸœ ˜—Kšœ˜K˜—š   œŸœŸœŸœ ŸœŸœ˜WK˜5K˜,K˜Kšœ˜Kšœ˜K˜—š  œŸœŸœŸœ1ŸœŸœ˜~K˜Kšœ Ÿœ˜$šŸœ Ÿœ ˜KšŸœŸœ1˜<šŸœ˜Kšœ Ÿœ˜'KšœŸœŸœŸœ ˜@K˜9Kšœ#Ÿœ˜)KšœŸœŸœ˜/KšŸœ ŸœB˜YKšœ˜——Kšœ˜K˜—š œŸœŸœŸœ Ÿœ Ÿœ*ŸœŸœ ˜“šŸœ˜KšœŸœ˜'KšŸœ˜ Kšœ˜—K˜KšœŸœŸœ!˜2šŸœ Ÿœ Ÿœ˜!Kšœ Ÿœ ˜Kšœ Ÿœ ˜Kšœ Ÿœ4˜AKšœ Ÿœ ˜Kšœ Ÿœ ˜Kšœ Ÿœ$˜4K˜ªKšœ%Ÿœ¢˜K˜Îšœ Ÿœ"˜.K˜ K˜K˜K˜"K˜K˜K˜—K˜'KšŸœ˜ K˜K˜—K˜&š   œŸœŸœŸœ~Ÿœ ˜´KšœŸœ˜KšœŸœ Ÿœ˜&Kš ŸœŸœŸœŸœ¢˜:K˜K˜Kš¢œ³˜ÅK˜"KšŸœ˜ K˜K˜——K˜KšŸœ˜—…—çê-ß