<<>> <> <> <> <> 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 = { <<[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]>> 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 = { <<[self: ImageSource, buf: POINTER, nbytes: CARD, nbytesResult: POINTER TO CARD] RETURNS [RES]>> 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 = { <<[self: ImageSource] RETURNS [RES]>> 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.