<> <> <> DIRECTORY CGClipper USING [Bounds, IsBox], CGDevice USING [Ref], CGContext USING [Ref], Graphics USING [black, Context, GetBounds, SetColor], GraphicsBasic USING [Box], IPBasic USING [Any, Integer, State, Vector], IPBitmapOutput USING [New], IPConvert USING [RealToAny, IntegerToAny, VectorToAny, AnyToReal, AnyToInteger, AnyToVector], IPErrors USING [Bug, MasterError], IPExec USING [DoSimpleBody], IPImagerOps USING [ConcatT, MakeGray, SetXRel], IPImager, IPImagerBasic, IPOutput USING [Size], IPScan USING [Allocate, PushPath], IPStack, IPState USING [State, StateRep], IPTransform USING [Scale, Translate, Tv], Real USING [RoundC]; IPImagerOpsImpl: CEDAR PROGRAM IMPORTS CGClipper, Graphics, IPBitmapOutput, IPConvert, IPExec, IPErrors, IPImagerOps, IPScan, IPStack, IPTransform, Real EXPORTS IPImagerOps, IPBasic = BEGIN OPEN IPImager, IPImagerBasic, IPBasic; State: TYPE = IPState.State; StateRep: PUBLIC TYPE = IPState.StateRep; <> Init: PUBLIC PROC[self: State] = { imager: Imager = NEW[IPImager.ImagerRep _ [ vars: NIL, path: NIL, output: NIL, context: NIL, font: NIL]]; vars: Vars = NEW[IPImager.VarsRep _ [link: NIL, p: NIL, np: NIL, T: NIL, showVec: NIL, color: NIL, fontList: NIL]]; vars.p _ NEW[IPImager.PersistentVarsRep _ [ cpx: 0, cpy: 0, correctMX: 0, correctMY: 0, correctMaskCount: 0, correctMaskX: 0, correctMaskY: 0, correctSumX: 0, correctSumY: 0, correctSpaceX: 0, correctSpaceY: 0, correctcpx: 0, correctcpy: 0, correctTargetX: 0, correctTargetY: 0 ]]; vars.np _ NEW[IPImager.NonPersistentVarsRep _ [ priorityImportant: 0, mediumXSize: 0, mediumYSize: 0, fieldXMin: 0, fieldYMin: 0, fieldXMax: 0, fieldYMax: 0, strokeWidth: 0, strokeEnd: 0, noImage: 0, underlineStart: 0, amplifySpace: 1.0, correctPass: 0, correctShrink: 0.5, correctTX: 0, correctTY: 0 ]]; vars.T _ IPTransform.Scale[1]; vars.color _ IPImagerOps.MakeGray[1]; imager.vars _ vars; self.imager _ imager; }; Save: PUBLIC PROC[self: State, all: BOOL] = { imager: Imager = self.imager; old: Vars = imager.vars; new: Vars = NEW[VarsRep _ [link: NIL, p: NIL, np: NIL, T: NIL, showVec: NIL, color: NIL, fontList: NIL]]; new.p _ IF all THEN NEW[PersistentVarsRep _ old.p^] ELSE old.p; new.np _ NEW[NonPersistentVarsRep _ old.np^]; new.T _ NEW[TransformationRep _ old.T^]; new.showVec _ old.showVec; new.color _ old.color; new.fontList _ old.fontList; new.link _ old; imager.vars _ new; }; Restore: PUBLIC PROC[self: State] = { imager: Imager = self.imager; imager.vars _ imager.vars.link; imager.font _ NIL; }; scale: REAL _ 1; tx, ty: REAL _ 0; SetTFromContext: PROC[imager: Imager, context: Graphics.Context] = { T: Transformation = imager.vars.T; ref: CGContext.Ref = NARROW[context.data]; T.a _ ref.matrix.m.a; T.b _ ref.matrix.m.c; T.c _ ref.matrix.m.e; T.d _ ref.matrix.m.b; T.e _ ref.matrix.m.d; T.f _ ref.matrix.m.f; T.code _ 10; }; SetContext: PUBLIC PROC[self: State, context: Graphics.Context] = { imager: Imager = self.imager; imager.context _ context; IF context#NIL THEN { ref: CGContext.Ref = NARROW[context.data]; box: GraphicsBasic.Box = Graphics.GetBounds[context]; fullHeight: REAL = 11.0*72.0; -- height of a full page SetTFromContext[imager, context]; IPImagerOps.ConcatT[self, IPTransform.Translate[0, box.ymax-fullHeight]]; IPImagerOps.ConcatT[self, IPTransform.Scale[72*scale]]; -- "inches" IPImagerOps.ConcatT[self, IPTransform.Translate[-tx, -ty]]; IPImagerOps.ConcatT[self, IPTransform.Scale[1/0.0254]]; -- meters Graphics.SetColor[context, Graphics.black]; IF ref.haveRaster THEN { device: CGDevice.Ref = ref.device; dbox: GraphicsBasic.Box = device.GetBounds[device]; size: IPOutput.Size = [x: Real.RoundC[dbox.xmax], y: Real.RoundC[dbox.ymax]]; imager.output _ IPBitmapOutput.New[ref.dbase, ref.drast, size]; } ELSE ERROR; IF ref.clipper.IsBox[] THEN { cbox: GraphicsBasic.Box = ref.clipper.Bounds[]; Gen: PROC[move: PROC[Pair], line: PROC[Pair], curve: PROC[Pair, Pair, Pair]] = { move[[cbox.xmin, cbox.ymin]]; line[[cbox.xmax, cbox.ymin]]; line[[cbox.xmax, cbox.ymax]]; line[[cbox.xmin, cbox.ymax]]; }; imager.path _ IPScan.Allocate[]; IPScan.PushPath[imager.path, Gen]; } ELSE ERROR; }; }; <> TransformationToAny: PROC[x: Transformation] RETURNS[Any] = { RETURN[[type: transformation, ref: x]]; }; ColorToAny: PROC[x: Color] RETURNS[Any] = { RETURN[[type: color, ref: x]]; }; AnyToTransformation: PROC[x: Any] RETURNS[Transformation] = { IF x.type=transformation THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; AnyToColor: PROC[x: Any] RETURNS[Color] = { IF x.type=color THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; PushPair: PUBLIC PROC[self: State, p: Pair] = { IPStack.PushReal[self, p.x]; IPStack.PushReal[self, p.y]; }; PushTransformation: PUBLIC PROC[self: State, x: Transformation] = { IPStack.PushAny[self, [type: transformation, ref: x]]; }; PushColor: PUBLIC PROC[self: State, x: Color] = { IPStack.PushAny[self, [type: color, ref: x]]; }; PushPixelArray: PUBLIC PROC[self: State, x: PixelArray] = { IPStack.PushAny[self, [type: pixelArray, ref: x]]; }; PushTrajectory: PUBLIC PROC[self: State, x: Trajectory] = { IPStack.PushAny[self, [type: trajectory, ref: x]]; }; PushOutline: PUBLIC PROC[self: State, x: Outline] = { IPStack.PushAny[self, [type: outline, ref: x]]; }; PopPair: PUBLIC PROC[self: State] RETURNS[p: Pair] = { p.y _ IPStack.PopReal[self]; p.x _ IPStack.PopReal[self]; }; PopTransformation: PUBLIC PROC[self: State] RETURNS[Transformation] = { x: Any = IPStack.PopAny[self]; IF x.type=transformation THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; PopColor: PUBLIC PROC[self: State] RETURNS[Color] = { x: Any = IPStack.PopAny[self]; IF x.type=color THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; PopPixelArray: PUBLIC PROC[self: State] RETURNS[PixelArray] = { x: Any = IPStack.PopAny[self]; IF x.type=pixelArray THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; PopTrajectory: PUBLIC PROC[self: State] RETURNS[Trajectory] = { x: Any = IPStack.PopAny[self]; IF x.type=trajectory THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; PopOutline: PUBLIC PROC[self: State] RETURNS[Outline] = { x: Any = IPStack.PopAny[self]; IF x.type=outline THEN RETURN[NARROW[x.ref]] ELSE ERROR IPErrors.MasterError[WrongType]; }; <<>> <<4.2 Imager state>> IGet: PUBLIC PROC[self: State, n: Integer] RETURNS[Any] = { IF n>22 THEN ERROR IPErrors.MasterError[BoundsFault] ELSE { index: [0..22] = n; imager: Imager = self.imager; vars: Vars = imager.vars; SELECT index FROM 0 => RETURN[IPConvert.RealToAny[vars.p.cpx]]; 1 => RETURN[IPConvert.RealToAny[vars.p.cpy]]; 2 => RETURN[IPConvert.RealToAny[vars.p.correctMX]]; 3 => RETURN[IPConvert.RealToAny[vars.p.correctMY]]; 4 => RETURN[TransformationToAny[GetT[vars]]]; 5 => RETURN[IPConvert.IntegerToAny[vars.np.priorityImportant]]; 6 => RETURN[IPConvert.RealToAny[vars.np.mediumXSize]]; 7 => RETURN[IPConvert.RealToAny[vars.np.mediumYSize]]; 8 => RETURN[IPConvert.RealToAny[vars.np.fieldXMin]]; 9 => RETURN[IPConvert.RealToAny[vars.np.fieldYMin]]; 10 => RETURN[IPConvert.RealToAny[vars.np.fieldXMax]]; 11 => RETURN[IPConvert.RealToAny[vars.np.fieldYMax]]; 12 => RETURN[IPConvert.VectorToAny[vars.showVec]]; 13 => RETURN[ColorToAny[vars.color]]; 14 => RETURN[IPConvert.IntegerToAny[vars.np.noImage]]; 15 => RETURN[IPConvert.RealToAny[vars.np.strokeWidth]]; 16 => RETURN[IPConvert.IntegerToAny[vars.np.strokeEnd]]; 17 => RETURN[IPConvert.RealToAny[vars.np.underlineStart]]; 18 => RETURN[IPConvert.RealToAny[vars.np.amplifySpace]]; 19 => RETURN[IPConvert.IntegerToAny[vars.np.correctPass]]; 20 => RETURN[IPConvert.RealToAny[vars.np.correctShrink]]; 21 => RETURN[IPConvert.RealToAny[vars.np.correctTX]]; 22 => RETURN[IPConvert.RealToAny[vars.np.correctTY]]; ENDCASE => ERROR IPErrors.Bug; }; }; ISet: PUBLIC PROC[self: State, x: Any, n: Integer] = { IF n>22 THEN ERROR IPErrors.MasterError[BoundsFault] ELSE { index: [0..22] = n; imager: Imager = self.imager; vars: Vars = imager.vars; SELECT index FROM 0 => vars.p.cpx _ IPConvert.AnyToReal[x]; 1 => vars.p.cpy _ IPConvert.AnyToReal[x]; 2 => vars.p.correctMX _ IPConvert.AnyToReal[x]; 3 => vars.p.correctMY _ IPConvert.AnyToReal[x]; 4 => { SetT[vars, AnyToTransformation[x]]; vars.fontList _ NIL; imager.font _ NIL }; 5 => vars.np.priorityImportant _ IPConvert.AnyToInteger[x]; 6 => vars.np.mediumXSize _ IPConvert.AnyToReal[x]; 7 => vars.np.mediumYSize _ IPConvert.AnyToReal[x]; 8 => vars.np.fieldXMin _ IPConvert.AnyToReal[x]; 9 => vars.np.fieldYMin _ IPConvert.AnyToReal[x]; 10 => vars.np.fieldXMax _ IPConvert.AnyToReal[x]; 11 => vars.np.fieldYMax _ IPConvert.AnyToReal[x]; 12 => { vars.showVec _ IPConvert.AnyToVector[x]; imager.font _ NIL }; 13 => vars.color _ AnyToColor[x]; 14 => vars.np.noImage _ IPConvert.AnyToInteger[x]; 15 => vars.np.strokeWidth _ IPConvert.AnyToReal[x]; 16 => vars.np.strokeEnd _ IPConvert.AnyToInteger[x]; 17 => vars.np.underlineStart _ IPConvert.AnyToReal[x]; 18 => vars.np.amplifySpace _ IPConvert.AnyToReal[x]; 19 => vars.np.correctPass _ IPConvert.AnyToInteger[x]; 20 => vars.np.correctShrink _ IPConvert.AnyToReal[x]; 21 => vars.np.correctTX _ IPConvert.AnyToReal[x]; 22 => vars.np.correctTY _ IPConvert.AnyToReal[x]; ENDCASE => ERROR IPErrors.Bug; }; }; GetT: PROC[vars: Vars] RETURNS[Transformation] = { RETURN[NEW[TransformationRep _ vars.T^]]; }; SetT: PROC[vars: Vars, m: Transformation] = { vars.T^ _ m^; }; SetMedium: PUBLIC PROC[self: State, m: Vector, pageNumber: Integer, duplex: BOOL, xImageShift: REAL] = { }; <<4.3.5 Device coordinate system>> <> <<4.4.3 Transformation operators>> <> <<4.4.4 Applying transformations>> <> <<4.4.5 The current transformation>> <> <<4.4.6 Instancing>> <> <<4.5 Current position operators>> <> <<4.6 Pixel arrays>> <> <<4.7 Color>> <> <<>> <<4.8.1 Geometry: trajectories and outlines>> <> <<4.8.2 Filled outlines and strokes>> <> <<4.8.3 Sampled masks>> <> <<>> <<4.9 Character operators>> <> <<>> <<4.10 Spacing correction>> CorrectMask: PUBLIC PROC[self: State] = { imager: Imager = self.imager; vars: Vars = imager.vars; p: PersistentVars = vars.p; SELECT vars.np.correctPass FROM 1 => { p.correctMaskCount _ p.correctMaskCount+1; }; 2 => { spx: REAL = p.correctMaskX/p.correctMaskCount; spy: REAL = p.correctMaskY/p.correctMaskCount; p.correctMaskX _ p.correctMaskX-spx; p.correctMaskY _ p.correctMaskY-spy; p.cpx _ p.cpx+spx; p.cpy _ p.cpy+spy; p.correctMaskCount _ p.correctMaskCount-1; }; ENDCASE; }; CorrectSpace: PUBLIC PROC[self: State, v: Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; p: PersistentVars = vars.p; d: Pair = IPTransform.Tv[vars.T, v]; SELECT vars.np.correctPass FROM 1 => { p.correctSumX _ p.correctSumX+d.x; p.correctSumY _ p.correctSumY+d.y; }; 2 => { IF p.correctSumX#0 THEN { spx: REAL = d.x*p.correctSpaceX/p.correctSumX; p.correctSpaceX _ p.correctSpaceX-spx; p.cpx _ p.cpx+spx; }; IF p.correctSumY#0 THEN { spy: REAL = d.y*p.correctSpaceY/p.correctSumY; p.correctSpaceY _ p.correctSpaceY-spy; p.cpy _ p.cpy+spy; }; p.correctSumX _ p.correctSumX-d.x; p.correctSumY _ p.correctSumY-d.y; }; ENDCASE; }; Correct: PUBLIC PROC[self: State] = { IPExec.DoSimpleBody[self, save]; -- fix this }; SetCorrectMeasure: PUBLIC PROC[self: State, v: Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; p: PersistentVars = vars.p; w: Pair = IPTransform.Tv[vars.T, v]; [p.correctMX, p.correctMY] _ w; }; SetCorrectTolerance: PUBLIC PROC[self: State, v: Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; np: NonPersistentVars = vars.np; w: Pair = IPTransform.Tv[vars.T, v]; [np.correctTX, np.correctTY] _ w; }; Space: PUBLIC PROC[self: State, x: REAL] = { IPImagerOps.SetXRel[self, x]; CorrectSpace[self, [x, 0]]; }; END.