<> <> <> DIRECTORY Atom USING [GetPName], CGContext USING [Ref], Graphics USING [Color, Context, SetColor], IPBasic USING [Any, Identifier, Integer, Operator, Vector, VectorShape], IPConvert USING [AnyToIdentifier, AnyToInteger, AnyToOperator, AnyToVector], IPErrors USING [AppearanceWarning, MasterWarning], IPExec USING [Do, FGet], IPFont USING [FontKey, Modify, New], IPImager USING [CachedFont, CachedFontRep, Imager, Vars], IPImagerBasic USING [ConstantColor, Pair, Transformation], IPImagerOps USING [ConcatT, Restore, Save, Trans], IPState USING [State, StateRep], IPTransform USING [Concat, DRound, InverseTransform, Transform, TransformVec], IPVector USING [Get, Shape], Rope USING [ActionType, Concat, ROPE, Size], RopeReader USING [FreeRopeReader, Get, GetRopeReader, Ref, SetPosition], Scaled USING [Float, FromReal, Value, zero], UnifiedFonts USING [Create, DrawCharSeq, FixedUnit, FONT, GetWidthArray, Positioning, Transformation, WidthArray]; IPShowImpl: CEDAR PROGRAM IMPORTS Atom, Graphics, IPConvert, IPErrors, IPExec, IPFont, IPImagerOps, IPTransform, IPVector, Rope, RopeReader, Scaled, UnifiedFonts EXPORTS IPImagerOps, IPBasic = BEGIN OPEN IPImagerBasic, IPBasic; FONT: TYPE = UnifiedFonts.FONT; ROPE: TYPE = Rope.ROPE; State: TYPE = IPState.State; StateRep: PUBLIC TYPE = IPState.StateRep; -- export to IPBasic Imager: TYPE = IPImager.Imager; Vars: TYPE = IPImager.Vars; FontKey: TYPE = IPFont.FontKey; VFont: TYPE = REF VFontRep; VFontRep: TYPE = RECORD[vector: Vector, m: Transformation]; SetColor: PROC[imager: Imager] = INLINE { icolor: ConstantColor = NARROW[imager.vars.color]; Graphics.SetColor[imager.context, [r: icolor.r/256, g: icolor.g/256, b: icolor.b/256]]; }; ufDeviceType: ATOM _ $Interpress; ufPositioning: UnifiedFonts.Positioning _ rounded; GetFont: PROC[imager: Imager] RETURNS[FONT] = INLINE { RETURN[ IF imager.font=NIL THEN (imager.font _ LookupFont[imager.vars]) ELSE imager.font] }; LookupFont: PROC[vars: Vars] RETURNS[FONT] = { font: FONT _ NIL; WITH vars.showVec SELECT FROM key: FontKey => { FOR f: IPImager.CachedFont _ vars.fontList, f.link UNTIL f=NIL DO IF f.key=key THEN { font _ f.font; EXIT }; ENDLOOP; IF font=NIL THEN { font _ CreateFont[key, vars.T]; vars.fontList _ NEW[IPImager.CachedFontRep _ [ link: vars.fontList, key: key, font: font]]; }; }; ENDCASE; RETURN[font]; }; CreateFont: PROC[key: FontKey, T: Transformation] RETURNS[FONT] = { fontTransformation: UnifiedFonts.Transformation; IF T.d=0 THEN { -- assume uniform scaling fontTransformation _ [scale: T.a*key.m.a, rotation: 0]; } ELSE { -- assume 90 degree rotation fontTransformation _ [scale: ABS[T.d]*key.m.a, rotation: 90]; }; RETURN[UnifiedFonts.Create[key.name, fontTransformation, ufDeviceType]]; }; Show: PUBLIC PROC[self: State, v: Vector] = { imager: Imager = self.imager; vars: Vars = imager.vars; IF vars.np.noImage=0 THEN { font: FONT = GetFont[imager]; SetColor[imager]; IF font#NIL THEN { widths: UnifiedFonts.WidthArray = font.GetWidthArray[]; spaceX: Scaled.Value _ Scaled.FromReal[Scaled.Float[widths[' ]]*vars.np.amplifySpace]; context: Graphics.Context = imager.context; ref: CGContext.Ref = NARROW[context.data]; ref.cp.x _ vars.p.cpx; ref.cp.y _ vars.p.cpy; WITH v SELECT FROM rope: ROPE => TRUSTED { count: INT _ rope.Size[]; Char: TYPE = MACHINE DEPENDENT RECORD[ c(0:0..15): CHAR, width(1:0..31): Scaled.Value]; seqSize: NAT = 50; seq: ARRAY [0..seqSize) OF Char; reader: RopeReader.Ref = RopeReader.GetRopeReader[]; reader.SetPosition[rope, 0]; WHILE count>0 DO p: POINTER TO Char _ @seq[0]; zero: UnifiedFonts.FixedUnit _ Scaled.zero; n: NAT _ seqSize; IF n>count THEN n _ count; THROUGH [0..n) DO p.c _ reader.Get[]; p.width _ IF p.c=' THEN spaceX ELSE widths[p.c]; p _ p+SIZE[Char]; ENDLOOP; font.DrawCharSeq[context: context, count: n, charPtr: @seq[0].c, charIncrement: SIZE[Char], deltaXptr: @seq[0].width, deltaXincrement: SIZE[Char], deltaYptr: @zero, deltaYincrement: 0, positioning: ufPositioning]; count _ count-n; ENDLOOP; RopeReader.FreeRopeReader[reader]; }; ENDCASE => { SIGNAL IPErrors.AppearanceWarning[Unimplemented]; }; vars.p.cpx _ ref.cp.x; vars.p.cpy _ ref.cp.y; } ELSE { shape: VectorShape = IPVector.Shape[v]; showVec: Vector _ vars.showVec; m: Transformation _ NIL; WITH showVec SELECT FROM vfont: VFont => { showVec _ vfont.vector; m _ vfont.m }; ENDCASE; FOR i: Integer IN[shape.l..shape.l+shape.n) DO index: Integer; op: Operator; IPImagerOps.Save[self, FALSE]; IPImagerOps.Trans[self]; index _ IPConvert.AnyToInteger[IPVector.Get[v, i]]; op _ IPConvert.AnyToOperator[IPVector.Get[showVec, index]]; IF m#NIL THEN IPImagerOps.ConcatT[self, m]; IPExec.Do[self, op]; IPImagerOps.Restore[self]; ENDLOOP; }; }; }; ShowAndXRel: PUBLIC PROC[self: State, v: Vector] = { SIGNAL IPErrors.MasterWarning[Unimplemented]; }; <<>> SetXY: PUBLIC PROC[self: State, p: Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; dp: Pair = IPTransform.Transform[vars.T, p]; vars.p.cpx _ dp.x; vars.p.cpy _ dp.y; }; SetXYRel: PUBLIC PROC[self: State, v: Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; dv: Pair = IPTransform.TransformVec[vars.T, v]; vars.p.cpx _ vars.p.cpx + dv.x; vars.p.cpy _ vars.p.cpy + dv.y; }; SetXRel: PUBLIC PROC[self: State, x: REAL] = { SetXYRel[self, [x, 0]]; }; SetYRel: PUBLIC PROC[self: State, y: REAL] = { SetXYRel[self, [0, y]]; }; GetCP: PUBLIC PROC[self: State, rounded: BOOL _ FALSE] RETURNS[Pair] = { imager: Imager = self.imager; vars: Vars = imager.vars; dp: Pair _ [vars.p.cpx, vars.p.cpy]; IF rounded THEN dp _ IPTransform.DRound[dp]; RETURN[IPTransform.InverseTransform[vars.T, dp]]; }; <<>> HierarchicalName: PROC[v: Vector] RETURNS[ROPE] = { shape: VectorShape = IPVector.Shape[v]; rope: ROPE _ NIL; FOR i: Integer IN[shape.l..shape.l+shape.n) DO x: Any = IPVector.Get[v, i]; id: ROPE = Atom.GetPName[IPConvert.AnyToIdentifier[x]]; IF rope=NIL THEN rope _ id ELSE rope _ rope.Concat["/"].Concat[id]; ENDLOOP; RETURN[rope]; }; FontKeyToVector: PROC[f: FontKey] RETURNS[Vector] = INLINE { RETURN[f] }; VFontToVector: PROC[f: VFont] RETURNS[Vector] = INLINE { RETURN[f] }; FindFont: PUBLIC PROC[self: State, v: Vector] RETURNS[Vector] = { name: ROPE = HierarchicalName[v]; RETURN[FontKeyToVector[IPFont.New[name]]]; }; ModifyFont: PUBLIC PROC[v: Vector, m: Transformation] RETURNS[Vector] = { WITH v SELECT FROM old: FontKey => { RETURN[FontKeyToVector[IPFont.Modify[old, m]]]; }; old: VFont => { new: VFont = NEW[VFontRep _ [vector: old.vector, m: IPTransform.Concat[m, old.m]]]; RETURN[VFontToVector[new]]; }; ENDCASE => { new: VFont = NEW[VFontRep _ [vector: v, m: m]]; RETURN[VFontToVector[new]]; }; }; SetFont: PUBLIC PROC[self: State, n: Integer] = { imager: Imager = self.imager; vars: Vars = imager.vars; v: Vector = IPConvert.AnyToVector[IPExec.FGet[self, n]]; vars.showVec _ v; imager.font _ NIL; }; <<>> END.