<> <> <> <> <> <<>> <> <> DIRECTORY Args USING [Arg, ArgsGet, Error, NArgs], Atom USING [MakeAtom], BasicTime USING [GMT, Now, OutOfRange, Period, ToNSTime, Update], CD USING [commentLayer, ContextColors, CreateDrawRef, Design, DrawProc, DrawContextProc, DrawRectProc, DrawRef, Instance, InstanceList, Layer, Number, Object, Position, Rect, undefLayer], CDBasics USING [BaseOfRect, ImagerTransform, Intersection, NonEmpty, SizeOfRect], CDDirectory USING [EachEntryAction, Enumerate], CDCurves USING [CurveSpecific], CDOps USING [DrawDesign, InstList], CDProperties USING [GetListProp], CDTexts USING [TextSpecific], CDValue USING [Fetch], Commander USING [CommandProc, Register], CStitching USING [all, Area, ChangeEnumerateArea, ChangeRect, DumpCache, EnumerateArea, EnumerateNeighborhood, NewTesselation, RectProc, Region, ResetTesselation, Tesselation, Tile, TileProc], D2Orient USING [Orientation], FS USING [ComponentPositions, Error, ExpandName, FileInfo, Position], Imager USING [ClipRectangle, ColorOperator, ConcatT, Context, ConstantColor, DoSave, Font, MaskBitmap, MaskDashedStrokeTrajectory, MaskFillTrajectory, MaskRectangle, MaskStrokeTrajectory, MaskVector, MaskVectorI, PutProp, Rectangle, ScaleT, SetColor, SetFont, SetPriorityImportant, SetStrokeEnd, SetStrokeJoint, SetStrokeWidth, SetXY, ShowRope, StrokeEnd, StrokeJoint, TranslateT, VEC], ImagerColor USING [ColorOperator, ConstantColor, NewColorOperatorRGB, RGB], ImagerColorFns USING [NewColorOperatorCMYK], ImagerColorPrivate USING [RGBFromColor], ImagerFont USING [Find, FontBoundingBox, Modify, RopeBoundingBox, RopeEscapement, Scale, Substitution, Typeface, TypefaceRep], ImagerInterpress USING [Close, Create, DeclareColorOperator, DeclareFont, DoPage, Ref], ImagerPath USING [LineToX, LineToY, MoveTo, Trajectory], ImagerSample USING [Box, Clear, Fill, NewSampleMap, RasterSampleMap, Trim], ImagerTransformation USING [Cat, Create, Invert, Rotate, Scale2, Transformation, Translate], ImagerTypeface USING [TypefaceRep], <> IO USING [bool, card, int, PutFR, PutFR1, real, rope, time], MessageWindow USING [Append, Blink, Clear], Nectarine, NectarineAids USING [ComposeRegisterMarks], NectarineColors USING [Bitset, blackBlack, Blend, BlendTileColours, BlendRec, ResetColourStatistics, Color, NumberOfColours, ColourTile, colSubDef, DeclareColours, IthColour, LayerColour, ListColourStatistics, orableBackground, ReadMap, ResetLayerColourTable, SetLayerColourTable, traceColourInferences, unColour], NectarinePd USING [field, PdPrintProcess], NodeStyle USING [FontFace], NodeStyleFont USING [FontFromStyleParams], PrincOpsUtils USING [], Process USING [CheckForAbort, Detach, priorityBackground, SetPriority], Real USING [Fix, Float, Round], RefTab USING [Create, Delete, EachPairAction, Fetch, GetSize, Insert, Pairs, Ref], Rope USING [Cat, Concat, Equal, Fetch, IsEmpty, Length, Replace, ROPE, SkipTo, Substr], SafeStorage USING [ReclaimCollectibleObjects], <> TerminalIO USING [PutF, PutRope], UserCredentials USING [Get], UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc, Token], XNSPrint USING [Context, Error, GetDefaults, PrintFromFile]; NectarineImpl: CEDAR PROGRAM IMPORTS Args, Atom, BasicTime, CD, CDBasics, CDDirectory, CDOps, CDProperties, CDValue, Commander, CStitching, FS, Imager, ImagerColor, ImagerColorFns, ImagerColorPrivate, ImagerFont, ImagerInterpress, ImagerPath, ImagerSample, ImagerTransformation, IO, MessageWindow, NectarineAids, NectarineColors, NectarinePd, NodeStyleFont, Process, Real, RefTab, Rope, SafeStorage, TerminalIO, UserProfile, UserCredentials, XNSPrint EXPORTS ImagerFont, Nectarine ~ BEGIN OPEN NectarineColors, NectarinePd, Real; <> <> break: SIGNAL ~ CODE; -- for debugging invalidPrinter: PUBLIC SIGNAL ~ CODE; communicationsFailure: PUBLIC SIGNAL ~ CODE; tooComplex: PUBLIC SIGNAL ~ CODE; layout, showTesselation, ignoreAnnotation, imageRegions: BOOL _ FALSE; letChipndaleCallTheImager, centerSignalNames: BOOL _ TRUE; signalNameFont: Font _ NIL; outline: REAL _ -1.0; risk: INT _ 2; -- decrease if Nectarine runs out of VM. More risk mean much more speed. Geometric interpretation: consider a horizontal straight line through the design; you state that you have a rectangle only each risk uses only 14 MB of memory in the worst case. Font: TYPE ~ Imager.Font; Typeface: TYPE ~ REF TypefaceRep; TypefaceRep: PUBLIC TYPE ~ ImagerTypeface.TypefaceRep; Transformation: TYPE ~ ImagerTransformation.Transformation; Hyperplane: TYPE ~ RECORD [used: BOOL _ FALSE, hyp: ImagerSample.RasterSampleMap]; ColorRegion: TYPE ~ REF ColorRegionRep; ColorRegionRep: TYPE ~ RECORD [SEQUENCE size: NAT OF Hyperplane]; ROPE: TYPE ~ Rope.ROPE; Box: TYPE ~ ImagerSample.Box; State: TYPE ~ REF StateRec; StateRec: TYPE ~ RECORD [ previousColour: Color _ NIL, previousStrokeWidth: REAL _ -1.0, previousFont: Font _ NIL, previousTextOrientation: D2Orient.Orientation _ original, cardTile: CARD _ 0, -- |{tile}| startTime: BasicTime.GMT, context: Imager.Context, ipName: ROPE, design: CD.Design, interpress: ImagerInterpress.Ref, tess: Tess, abort: REF BOOL, clip: BOOL _ FALSE, -- Wysiwyg or selectedOnly cdClip: CD.Rect, -- Wysiwyg or selectedOnly selectedOnly: BOOL, singleLayer: BOOL _ FALSE, -- only the layer of interset will be printed layerOfInterest: CD.Layer _ CD.undefLayer, isFirstPage, isLastPage: BOOL _ TRUE, substituteColor: BOOL _ colSubDef, band: REF CD.Rect _ NIL, bitmapScale: REAL _ 0.0, -- Versatec hack only colorRegion: ColorRegion _ NIL]; statistics: BOOL _ FALSE; debug: BOOL _ FALSE; remindFontConventions: BOOL _ TRUE; minInteger: INT ~ INTEGER.FIRST; maxInteger: INT ~ INTEGER.LAST; regionShrink: INT _ 4; mmXin: REAL ~ 25.4; versatecWidth: REAL ~ 8000; -- 40 inches at 200 bits per inch versatecLength: REAL ~ 32600; -- 163 inches at 200 bits per inch versatecWidthInMM: REAL ~ 40 * mmXin; versatecLengthInMM: REAL ~ 163 * mmXin; versatecResolution: REAL ~ 0.001 / 200 * mmXin; <> Region: TYPE ~ LIST OF REF CStitching.Region; Tess: TYPE ~ CStitching.Tesselation; Tile: TYPE ~ CStitching.Tile; TileAndContext: TYPE ~ REF TcRec; TcRec: TYPE ~ RECORD [tile: Tile, context: Imager.Context]; empty: REF ~ NIL; nothing: REF INT ~ NEW [INT]; StartDecomposition: PROC [state: State] RETURNS [dec: Tess] ~ {RETURN [CStitching.NewTesselation[stopFlag: state.abort]]}; FlushDecomposition: PROC [dec: Tess] ~ BEGIN <> CStitching.ResetTesselation [dec] END; -- FlushDecomposition FastMaskVector: PROC [context: Imager.Context, x1, y1, x2, y2: INT] ~ BEGIN <> IF ((x1 >= minInteger) AND (y1 >= minInteger) AND (x2 <= maxInteger) AND (y2 <= maxInteger)) THEN context.MaskVectorI [x1, y1, x2, y2] ELSE context.MaskVector [[Float[x1], Float[y1]], [Float[x2], Float[y2]]] END; -- FastMaskVector SouthRim: CStitching.TileProc ~ BEGIN <> tc: TileAndContext ~ NARROW [data]; IF (tile.value # tc.tile.value) THEN BEGIN tr: CD.Rect ~ tc.tile.Area; nr: CD.Rect ~ tile.Area; x1: INT ~ MAX [tr.x1, nr.x1]; x2: INT ~ MIN [tr.x2, nr.x2]; b: Blend ~ NARROW [tile.value]; IF (x1 < x2) AND ((b = NIL) OR (b.blend # blackBlack)) THEN FastMaskVector [tc.context, x1, tr.y1, x2, tr.y1] END END; -- SouthRim EastRim: CStitching.TileProc ~ BEGIN <> tc: TileAndContext ~ NARROW [data]; IF (tile.value # tc.tile.value) THEN BEGIN tr: CD.Rect ~ tc.tile.Area; nr: CD.Rect ~ tile.Area; y1: INT ~ MAX [tr.y1, nr.y1]; y2: INT ~ MIN [tr.y2, nr.y2]; b: Blend ~ NARROW [tile.value]; IF (y1 < y2) AND ((b = NIL) OR (b.blend # blackBlack)) THEN FastMaskVector [tc.context, tr.x2, y1, tr.x2, y2] END END; -- EastRim NorthRim: CStitching.TileProc ~ BEGIN <> tc: TileAndContext ~ NARROW [data]; IF (tile.value # tc.tile.value) THEN BEGIN tr: CD.Rect ~ tc.tile.Area; nr: CD.Rect ~ tile.Area; x1: INT ~ MAX [tr.x1, nr.x1]; x2: INT ~ MIN [tr.x2, nr.x2]; b: Blend ~ NARROW [tile.value]; IF (x1 < x2) AND ((b = NIL) OR (b.blend # blackBlack)) THEN FastMaskVector [tc.context, x1, tr.y2, x2, tr.y2] END END; -- NorthRim WestRim: CStitching.TileProc ~ BEGIN <> tc: TileAndContext ~ NARROW [data]; IF (tile.value # tc.tile.value) THEN BEGIN tr: CD.Rect ~ tc.tile.Area; nr: CD.Rect ~ tile.Area; y1: INT ~ MAX [tr.y1, nr.y1]; y2: INT ~ MIN [tr.y2, nr.y2]; b: Blend ~ NARROW [tile.value]; IF (y1 < y2) AND ((b = NIL) OR (b.blend # blackBlack)) THEN FastMaskVector [tc.context, tr.x1, y1, tr.x1, y2] END END; -- WestRim <> <> <> <> <> <> <> <> <> <> <> <> <> <> <= 0.0) AND (b.blend # blackBlack) THEN BEGIN>> <> <> <> <> <> <> <> <> <> <> PrintTile: CStitching.TileProc ~ BEGIN <> state: State ~ NARROW [data]; colour: Blend ~ NARROW [tile.value]; r: CD.Rect ~ CStitching.Area [tile]; -- not the area but the rectangle ! ChangeColour [state, colour.blend]; state.context.MaskRectangle [ImagerRect [r]]; IF state.abort^ THEN ERROR ABORTED; IF (outline >= 0.0) AND (colour.blend # blackBlack) THEN BEGIN ChangeColour [state, blackBlack]; ChangeStrokeWidth [state, outline]; IF showTesselation THEN BEGIN FastMaskVector [state.context, r.x1, r.y1, r.x2, r.y1]; -- South FastMaskVector [state.context, r.x2, r.y1, r.x2, r.y2]; -- East FastMaskVector [state.context, r.x2, r.y2, r.x1, r.y2]; -- North FastMaskVector [state.context, r.x1, r.y2, r.x1, r.y1] -- West END ELSE BEGIN tc: TileAndContext ~ NEW [TcRec _ [tile, state.context]]; state.tess.EnumerateNeighborhood [tile, SouthRim, WestRim, NorthRim, EastRim, tc, nothing] END END; IF statistics THEN BEGIN l: CD.Number ~ state.design.technology.lambda; colour.area _ colour.area + ((r.x2 - r.x1) / l) * ((r.y2 - r.y1) / l); state.cardTile _ SUCC [state.cardTile] END END; -- PrintTile NewPrintTile: CStitching.TileProc ~ BEGIN <> <> state: State ~ NARROW [data]; b: Blend ~ NARROW [tile.value]; r: CD.Rect ~ CStitching.Area [tile]; -- not the area but the rectangle ! ir: Imager.Rectangle ~ ImagerRect [r]; median: INT; ChangeColour [state, b.blend]; IF (ir.w > ir.h) THEN BEGIN ChangeStrokeWidth [state, ir.h]; median _ (r.y1 + r.y2) / 2; FastMaskVector [state.context, r.x1, median, r.x2, median] END ELSE BEGIN ChangeStrokeWidth [state, ir.w]; median _ (r.x1 + r.x2) / 2; FastMaskVector [state.context, median, r.y1, median, r.y2] END; IF state.abort^ THEN ERROR ABORTED; IF (outline >= 0.0) AND (b.blend # blackBlack) THEN BEGIN ChangeColour [state, blackBlack]; ChangeStrokeWidth [state, outline]; IF showTesselation THEN BEGIN FastMaskVector [state.context, r.x1, r.y1, r.x2, r.y1]; -- South FastMaskVector [state.context, r.x2, r.y1, r.x2, r.y2]; -- East FastMaskVector [state.context, r.x2, r.y2, r.x1, r.y2]; -- North FastMaskVector [state.context, r.x1, r.y2, r.x1, r.y1] -- West END ELSE BEGIN tc: TileAndContext ~ NEW [TcRec _ [tile, state.context]]; state.context.SetStrokeEnd [square]; state.tess.EnumerateNeighborhood [tile, SouthRim, WestRim, NorthRim, EastRim, tc, nothing]; state.context.SetStrokeEnd [butt] END END; IF statistics THEN BEGIN l: CD.Number ~ state.design.technology.lambda; b.area _ b.area + ((r.x2 - r.x1) / l) * ((r.y2 - r.y1) / l); state.cardTile _ SUCC [state.cardTile] END END; -- NewPrintTile <> <> <> <> <> <> <> <> <> AddTile: CStitching.TileProc ~ BEGIN <> state: State ~ NARROW [data]; colour: Blend ~ NARROW [tile.value]; band: CD.Rect ~ QuickTransf [IF (state.band = NIL) THEN state.cdClip ELSE CDBasics.Intersection [state.cdClip, state.band^], state]; r: Box ~ BoxFromRect [QuickTransf [tile.Area, state], band]; i: INT _ colour.index.ABS - 1; IF (i < 0) OR (i > 30) THEN i _ 0; -- Cheap hack for seldom layer combinations (e.g. pads) state.colorRegion[i].used _ TRUE; state.colorRegion[i].hyp.Fill [r] END; -- AddTile PrintStippledTile: CStitching.TileProc ~ BEGIN <> state: State ~ NARROW [data]; b: Blend ~ NARROW [tile.value]; r: CD.Rect ~ CStitching.Area [tile]; -- not the area but the rectangle ! FOR i: CD.Layer IN CD.Layer DO IF b.flavours[i] THEN BEGIN ChangeColour [state, LayerColour [i]]; state.context.MaskRectangle [ImagerRect [r]] END ENDLOOP; IF state.abort^ THEN ERROR ABORTED; IF (outline >= 0.0) AND (b.blend # blackBlack) THEN BEGIN ChangeColour [state, blackBlack]; ChangeStrokeWidth [state, outline]; IF showTesselation THEN BEGIN FastMaskVector [state.context, r.x1, r.y1, r.x2, r.y1]; -- South FastMaskVector [state.context, r.x2, r.y1, r.x2, r.y2]; -- East FastMaskVector [state.context, r.x2, r.y2, r.x1, r.y2]; -- North FastMaskVector [state.context, r.x1, r.y2, r.x1, r.y1] -- West END ELSE BEGIN tc: TileAndContext ~ NEW [TcRec _ [tile, state.context]]; state.tess.EnumerateNeighborhood [tile, SouthRim, WestRim, NorthRim, EastRim, tc, nothing] END END; IF statistics THEN BEGIN l: CD.Number ~ state.design.technology.lambda; b.area _ b.area + ((r.x2 - r.x1) / l) * ((r.y2 - r.y1) / l); state.cardTile _ SUCC [state.cardTile] END END; -- PrintStippledTile PrintBand: PROC [state: State] ~ BEGIN <> gdr: CD.DrawRef ~ CD.CreateDrawRef [[]]; smp: Imager.VEC; -- sample map position deviceBand: CD.Rect; box: Box; EnumerateGeometry: PROC ~ BEGIN state.context.SetStrokeEnd [IF layout THEN square ELSE butt]; state.context.SetStrokeJoint [miter]; -- I hope that's faster for rectangles IF (state.colorRegion # NIL) THEN BEGIN state.tess.EnumerateArea [rect: CStitching.all, eachTile: AddTile, data: state, skip: empty] END ELSE BEGIN IF state.substituteColor THEN BEGIN IF layout THEN state.tess.EnumerateArea [rect: CStitching.all, eachTile: PrintTile, data: state, skip: empty] ELSE state.tess.EnumerateArea [rect: CStitching.all, eachTile: NewPrintTile, data: state, skip: empty] END ELSE state.tess.EnumerateArea [rect: CStitching.all, eachTile: PrintStippledTile, data: state, skip: empty] END END; -- EnumerateGeometry Process.CheckForAbort []; IF state.abort^ THEN ERROR ABORTED; gdr.interestClip _ IF (state.band = NIL) THEN state.cdClip ELSE CDBasics.Intersection [state.cdClip, state.band^]; state.tess _ StartDecomposition [state]; gdr.drawRect _ NewRect; gdr.drawContext _ DoNotDrawContext; gdr.devicePrivate _ state; IF state.abort^ THEN ERROR ABORTED; IF state.selectedOnly THEN DrawSelection [state.design, gdr] ELSE CDOps.DrawDesign [state.design, gdr]; -- pass 2 TerminalIO.PutRope ["."]; IF state.abort^ THEN ERROR ABORTED; IF state.substituteColor THEN BlendTileColours []; TerminalIO.PutRope ["."]; -- pass 3 state.previousColour _ NIL; state.previousStrokeWidth _ -1.0; state.previousFont _ NIL; state.previousTextOrientation _ original; IF (state.colorRegion # NIL) THEN BEGIN deviceBand _ QuickTransf [gdr.interestClip, state]; box _ BoxFromRect [deviceBand, deviceBand]; smp _ [x: 0, y: deviceBand.y2]; FOR p: INT IN [0 .. state.colorRegion.size) DO state.colorRegion[p].used _ FALSE; IF state.abort^ THEN ERROR ABORTED; state.colorRegion[p].hyp _ ImagerSample.NewSampleMap [box]; state.colorRegion[p].hyp.Clear ENDLOOP; gdr.drawRect _ NewRect; SafeStorage.ReclaimCollectibleObjects END; state.context.DoSave [EnumerateGeometry]; -- pass 4 FlushDecomposition [state.tess]; SafeStorage.ReclaimCollectibleObjects; IF (state.colorRegion # NIL) THEN BEGIN FOR p: INT IN [0 .. state.colorRegion.size) DO IF state.colorRegion[p].used THEN BEGIN state.context.SetColor [IthColour [p+1]]; IF debug THEN [] _ state.colorRegion[p].hyp.Trim [box]; state.context.MaskBitmap [bitmap: state.colorRegion[p].hyp, position: smp]; state.colorRegion[p].used _ FALSE; state.colorRegion[p].hyp _ NIL; SafeStorage.ReclaimCollectibleObjects; IF state.abort^ THEN ERROR ABORTED END; ENDLOOP; END; TerminalIO.PutRope [". "] END; -- PrintBand NewRect: CD.DrawRectProc ~ BEGIN <<[r: Rect, l: Layer, pr: DrawRef]>> state: State ~ NARROW [pr.devicePrivate, State]; rect: CD.Rect; IF (state.singleLayer AND (l # state.layerOfInterest)) THEN RETURN; rect _ IF (state.band = NIL) THEN r ELSE CDBasics.Intersection [r, state.band^]; IF (CDBasics.NonEmpty [rect]) THEN BEGIN <> dec: Tess ~ state.tess; InsertRect: CStitching.RectProc = BEGIN <<[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]>> WITH oldValue SELECT FROM b: Blend => IF NOT b.flavours[l] THEN dec.ChangeRect [rect: rect, new: ColourTile [b, l]]; ENDCASE => BEGIN b: Blend _ NEW [BlendRec]; dec.ChangeRect [rect: rect, new: ColourTile [b, l]] END END; -- InsertRect dec.ChangeEnumerateArea [rect: rect, eachRect: InsertRect, skip: nothing]; IF state.abort^ THEN ERROR ABORTED END END; -- NewRect <> <<[r: Rect, l: Layer, pr: DrawRef]>> <> <> <> <> <> <> <> <<[plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF]>> <> < IF NOT b.flavours[l] THEN dec.ChangeRect [rect: rect, new: ColourTile [b, l]];>> < BEGIN>> <> <> <> <> <> <> <> <> mirrorY: Transformation ~ ImagerTransformation.Scale2 [[-1, 1]]; rot180: Transformation ~ ImagerTransformation.Rotate [180]; SpecialHack: PROC [obj: CD.Object, or: D2Orient.Orientation] RETURNS [t: Transformation] ~ BEGIN <> adjustX: Transformation ~ ImagerTransformation.Translate [[-(obj.bbox.x2 - obj.bbox.x1), 0]]; <> adjustXY: Transformation ~ ImagerTransformation.Translate [[-(obj.bbox.x2 - obj.bbox.x1), -(obj.bbox.y2 - obj.bbox.y1)]]; adjustXhalfY: Transformation ~ ImagerTransformation.Translate [[-(obj.bbox.x2 - obj.bbox.x1), -(obj.bbox.y2 - obj.bbox.y1) / 2]]; IF (obj.class.objectType # $FlipText) THEN ERROR; -- tocca ferro t _ SELECT or FROM <> mirrorX, rotate90X => adjustX.Cat [mirrorY], -- TxSxSy rotate180X, rotate270X => adjustXY.Cat [rot180, adjustX, mirrorY], -- TxySxyRTxSxSy < adjustXY.Cat [rot180], -- TxySxyR>> < adjustXY.Cat [adjustY, rot180], -- TxyTySxyR>> rotate180, rotate90 => adjustXhalfY.Cat [rot180], -- Txy/2SxyR ENDCASE => ImagerTransformation.Create [1, 0, 0, 0, 1, 0] -- plain vanilla Identity END; -- SpecialHack DrawText: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> state: State ~ NARROW [pr.devicePrivate]; context: Imager.Context ~ state.context; text: CDTexts.TextSpecific ~ NARROW [ob.specific]; offset: Imager.VEC _ text.cdFont.xy; transf, invTransf: Transformation; IF (state.singleLayer AND (ob.layer # state.layerOfInterest)) THEN RETURN; IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, LayerColour [ob.layer]]; ChangeFont [state, text.cdFont.font]; -- order of statements important ! transf _ CDBasics.ImagerTransform [trans]; IF (ob.class.objectType = $FlipText) THEN BEGIN transf _ ImagerTransformation.Cat [SpecialHack [ob, trans.orient], transf]; SELECT trans.orient FROM mirrorX, rotate90, rotate180, rotate90X => BEGIN <> <> offset.x _ offset.x + (ImagerFont.RopeBoundingBox [font: text.cdFont.font, rope: text.text].rightExtent) - (ImagerFont.RopeBoundingBox [font: state.previousFont, rope: text.text].rightExtent); <> <> offset.y _ 0; -- that's what's in ChipNDale release 25 IF (trans.orient = rotate90) OR (trans.orient = rotate180) THEN <> offset.y _ offset.y - ImagerFont.FontBoundingBox [state.previousFont].descent / 2.0 END ENDCASE => offset _ [0, 0]; -- that's what's in ChipNDale release 25 END ELSE offset.y _ 0; -- different from CD but a closer approximation invTransf _ ImagerTransformation.Invert [transf]; context.ConcatT [transf]; context.SetXY [offset]; context.ShowRope [text.text]; context.ConcatT [invTransf] END; -- DrawText DrawPath: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> state: State ~ NARROW [pr.devicePrivate]; context: Imager.Context ~ state.context; curve: CDCurves.CurveSpecific ~ NARROW [ob.specific]; transf: Transformation ~ CDBasics.ImagerTransform [trans]; invTransf: Transformation ~ ImagerTransformation.Invert [transf]; IF (state.singleLayer AND (ob.layer # state.layerOfInterest)) THEN RETURN; IF state.abort^ THEN ERROR ABORTED; context.ConcatT [transf]; -- context.SetXY [offset]; ChangeColour [state, LayerColour [ob.layer]]; ChangeStrokeWidth [state, Float [curve.w]]; context.MaskStrokeTrajectory [curve.path]; context.ConcatT [invTransf] END; -- DrawPath DrawArea: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> state: State ~ NARROW [pr.devicePrivate]; context: Imager.Context ~ state.context; curve: CDCurves.CurveSpecific ~ NARROW [ob.specific]; transf: Transformation ~ CDBasics.ImagerTransform [trans]; invTransf: Transformation ~ ImagerTransformation.Invert [transf]; IF (state.singleLayer AND (ob.layer # state.layerOfInterest)) THEN RETURN; IF state.abort^ THEN ERROR ABORTED; context.ConcatT [transf]; -- context.SetXY [offset]; ChangeColour [state, LayerColour [ob.layer]]; ChangeStrokeWidth [state, Float [curve.w]]; context.MaskFillTrajectory [curve.path, TRUE]; context.ConcatT [invTransf] END; -- DrawArea DrawObjectBorder: CD.DrawRectProc ~ BEGIN <<[r: Rect, l: Layer, pr: DrawRef]>> <> state: State ~ NARROW [pr.devicePrivate, State]; pen: REAL ~ Float [state.design.technology.lambda]; halfPen: REAL ~ pen / 2.0; object: Imager.Rectangle ~ ImagerRect [r]; border: ImagerPath.Trajectory; IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, blackBlack]; ChangeStrokeWidth [state, pen]; <> border _ ImagerPath.MoveTo [[object.x - halfPen, object.y - halfPen]]; border _ border.LineToX [object.x + object.w + halfPen]; -- South border _ border.LineToY [object.y + object.h + halfPen]; -- East border _ border.LineToX [object.x - halfPen]; -- North border _ border.LineToY [object.y - halfPen]; -- West <> <> state.context.MaskStrokeTrajectory [trajectory: border] END; -- DrawObjectBorder DrawDashedObjectBorder: CD.DrawRectProc ~ BEGIN <<[r: Rect, l: Layer, pr: DrawRef]>> <> state: State ~ NARROW [pr.devicePrivate, State]; pen: REAL ~ Float [state.design.technology.lambda / 2]; halfPen: REAL ~ pen / 2.0; object: Imager.Rectangle ~ ImagerRect [r]; border: ImagerPath.Trajectory; patternElements: NAT ~ 8; DotDotDotDash: PROC [i: NAT] RETURNS [REAL] ~ BEGIN pattern: ARRAY [0 .. patternElements) OF REAL ~ [0, 5*pen, 0, 5*pen, 0, 10*pen, 30*pen, 10*pen]; RETURN [pattern[i]] END; -- DotDotDotDash IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, blackBlack]; ChangeStrokeWidth [state, pen]; <> border _ ImagerPath.MoveTo [[object.x - halfPen, object.y - halfPen]]; border _ border.LineToX [object.x + object.w + halfPen]; -- South border _ border.LineToY [object.y + object.h + halfPen]; -- East border _ border.LineToX [object.x - halfPen]; -- North border _ border.LineToY [object.y - halfPen]; -- West <> <> Imager.MaskDashedStrokeTrajectory [context: state.context, trajectory: border, offset: 0, length: 2*(object.w+object.h), patternLen: patternElements, pattern: DotDotDotDash] END; -- DrawDashedObjectBorder <> <<[r: Rect, l: Layer, pr: DrawRef]>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> DrawObject: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> Process.CheckForAbort []; SELECT ob.class.objectType FROM $Text, $RigidText, $FlipText => DrawText [pr, ob, trans, readOnlyInstProps]; $Spline0, $Line0 => DrawPath [pr, ob, trans, readOnlyInstProps]; $FilledCurve0, $Polygon0 => DrawArea [pr, ob, trans, readOnlyInstProps]; <> ENDCASE => ob.class.drawMe [pr, ob, trans, readOnlyInstProps] END; -- DrawObject DrawObjectWithSignalNames: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> Process.CheckForAbort []; IF (readOnlyInstProps # NIL) THEN BEGIN name: ROPE ~ NARROW [CDProperties.GetListProp [readOnlyInstProps, $SignalName]]; IF NOT name.IsEmpty THEN BEGIN state: State ~ NARROW [pr.devicePrivate]; transf: Transformation ~ CDBasics.ImagerTransform [trans]; invTransf: Transformation ~ ImagerTransformation.Invert [transf]; offset: Imager.VEC _ [0, 0]; IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, LayerColour [CD.commentLayer]]; ChangeFont [state, signalNameFont]; -- order of statements important ! IF (ob.class.objectType = $Rect) AND centerSignalNames THEN BEGIN esc: Imager.VEC ~ ImagerFont.RopeEscapement [signalNameFont, name]; offset.x _ ob.bbox.x1 + ((ob.bbox.x2 - ob.bbox.x1) - esc.x) / 2.0; offset.y _ ob.bbox.y1 + ((ob.bbox.y2 - ob.bbox.y1) - esc.y) / 2.0 END; state.context.ConcatT [transf]; state.context.SetXY [offset]; state.context.ShowRope [name]; state.context.ConcatT [invTransf] END END; SELECT ob.class.objectType FROM $Text, $RigidText, $FlipText => DrawText [pr, ob, trans, readOnlyInstProps]; $Spline0, $Line0 => DrawPath [pr, ob, trans, readOnlyInstProps]; $FilledCurve0, $Polygon0 => DrawArea [pr, ob, trans, readOnlyInstProps]; <> ENDCASE => ob.class.drawMe [pr, ob, trans, readOnlyInstProps] END; -- DrawObjectWithSignalNames <> multipageHack: State; rgbLinear: Imager.ColorOperator ~ ImagerColor.NewColorOperatorRGB [255]; cmyk: Imager.ColorOperator ~ ImagerColorFns.NewColorOperatorCMYK [255]; DoInterpress: PUBLIC PROC [design: CD.Design, chipNDaleWindow: CD.Rect, clip, onlySel, singleLayer, register: BOOL _ FALSE, layer: CD.Layer _ CD.undefLayer, lambda: REAL _ 0.0, firstPage, lastPage: BOOL _ TRUE, abortFlag: REF BOOL] RETURNS [masterName: Rope.ROPE, usedField: Imager.Rectangle] ~ BEGIN <> <> <> <> <> <> <> state: State; OpenIPMaster: PROC [] RETURNS [ImagerInterpress.Ref] ~ BEGIN <> ENABLE {FS.Error => GOTO failure}; subDir: ROPE ~ "[]<>Temp>Nectarine>"; -- follows the religion pos: FS.ComponentPositions; ext: ROPE _ ".dummy"; <> ext _ IO.PutFR ["-NS%g%g", IO.card [BasicTime.ToNSTime [BasicTime.Now[]]], IO.rope [ext]]; IF NOT design.name.IsEmpty[] THEN masterName _ design.name.Cat [ext] ELSE BEGIN cdName: ROPE ~ NARROW [CDValue.Fetch [design, $CDxLastFile]]; IF cdName.IsEmpty[] THEN masterName _ Rope.Cat ["UnnamedMaster", ext] ELSE BEGIN shortFName: ROPE; [fullFName: masterName, cp: pos] _ FS.ExpandName [cdName, subDir]; shortFName _ masterName.Substr [start: pos.base.start, len: pos.base.length]; masterName _ shortFName.Cat [ext] END END; [fullFName: masterName, cp: pos] _ FS.ExpandName [masterName, subDir]; masterName _ masterName.Replace [pos.ext.start, pos.ext.length, "Interpress"]; RETURN [ImagerInterpress.Create [masterName]]; EXITS failure => BEGIN masterName _ IO.PutFR ["[]<>Temp>Nectarine>UnnamedMaster-NS%g.%g", IO.card [BasicTime.ToNSTime [BasicTime.Now[]]], IO.rope ["Interpress"]]; RETURN [ImagerInterpress.Create [masterName]] END END; -- OpenIPMaster DrawToIP: PROC [context: Imager.Context] ~ BEGIN <> tdr: CD.DrawRef ~ CD.CreateDrawRef [[]]; window: Imager.Rectangle; -- in the CG sense ratioW, ratioH, y0: REAL; iterations, bandSize: INT; -- number and size of bands chronos: BOOL; lap, end: BasicTime.GMT; EnumerateTextInDesign: PROC ~ BEGIN <> IF state.selectedOnly THEN DrawSelection [state.design, tdr] ELSE CDOps.DrawDesign [state.design, tdr] END; -- EnumerateTextInDesign state.context _ context; window _ ImagerRect [chipNDaleWindow]; IF imageRegions THEN BEGIN width, heigth: REAL; state.bitmapScale _ versatecWidth / window.w; width _ versatecWidthInMM; heigth _ window.h*state.bitmapScale/200*mmXin; IF (heigth > versatecWidthInMM) THEN BEGIN state.bitmapScale _ versatecLength / window.h; width _ window.w*state.bitmapScale/200*mmXin; heigth _ versatecLengthInMM END; usedField _ [x: 0.0, y: 0.0, w: width, h: heigth]; state.colorRegion _ NEW [ColorRegionRep[NumberOfColours[]]] END ELSE BEGIN ratioW _ field.w / window.w; ratioH _ field.h / window.h; usedField.x _ field.x; usedField.y _ field.y; -- in mm IF ratioH < ratioW THEN {usedField.w _ window.w * ratioH; usedField.h _ field.h} ELSE {usedField.w _ field.w; usedField.h _ window.h * ratioW}; <> <> y0 _ 0.0; IF register THEN BEGIN pos: FS.ComponentPositions; fName: ROPE; [fullFName: fName, cp: pos] _ FS.ExpandName [masterName, NIL]; context.PutProp [$separationLabel, fName.Substr [pos.base.start, pos.base.length]]; NectarineAids.ComposeRegisterMarks ["Nectarine", UseProcessColors[], context] END; IF (ratioH < ratioW) THEN usedField.x _ (field.w - usedField.w) / 2.0; context.TranslateT [[usedField.x, y0 + field.y]]; IF (lambda = 0.0) THEN context.ScaleT [MIN [ratioW, ratioH]] ELSE context.ScaleT [lambda / Float [design.technology.lambda]]; context.TranslateT [[-window.x, -window.y]]; IF clip THEN context.ClipRectangle [window] -- global to context !!! END; IF NOT SetLayerColourTable[] THEN TerminalIO.PutRope ["\nSome layers are not in the Color Registry.\n"]; context.SetPriorityImportant [NOT (ignoreAnnotation OR (NOT state.substituteColor) OR DoLineArt[] OR imageRegions)]; IF (NOT state.substituteColor) AND (NOT DoLineArt[]) THEN BEGIN <> ChangeColour [state, orableBackground]; state.context.MaskRectangle [window] END; <> IF state.substituteColor AND (NOT DoLineArt []) THEN BEGIN IF imageRegions THEN BEGIN <> bandSizeR: REAL ~ MIN [320.0, window.h * state.bitmapScale]; bandSize _ Fix [bandSizeR / state.bitmapScale]; -- translate into ChipNDale units iterations _ Fix [window.h] / bandSize -- "zero relative" ! END ELSE BEGIN <> bandSize _ Fix [(1000000.0 * (risk+1)) / window.w]; IF bandSize < 4 * design.technology.lambda THEN SIGNAL tooComplex; iterations _ Fix [window.h] / bandSize; -- "zero relative" ! END; IF (iterations > 5) THEN TerminalIO.PutF [" There will be %g sets of 3 dots ", IO.int [iterations]] ELSE {IF debug THEN TerminalIO.PutF [v1: IO.int [iterations]]}; IF ((iterations = 0) AND (NOT state.clip)) THEN PrintBand [state] -- shortcut ELSE BEGIN halftime: INT ~ iterations / 2; currentBand: REF CD.Rect ~ NEW [CD.Rect _ chipNDaleWindow]; <> state.band _ currentBand; chronos _ iterations > 5; FOR b: INT DECREASING IN [0 .. iterations] DO <> currentBand.y1 _ chipNDaleWindow.y1 + b * bandSize; currentBand.y2 _ MIN [chipNDaleWindow.y2, currentBand.y1 + bandSize + 1]; IF chronos THEN BEGIN <> fudge: INT ~ 8; IF (b = iterations - 3) THEN lap _ BasicTime.Now []; IF (b = iterations - 4) AND state.isLastPage THEN BEGIN duration: INT ~ BasicTime.Period [lap, BasicTime.Now[]]; end _ BasicTime.Update [lap, fudge * duration * (b + 2) ! BasicTime.OutOfRange => GOTO endless]; TerminalIO.PutF ["\nInterpress page will be ready ca. %g (this is only an educated guess)\n", IO.time [end]]; chronos _ FALSE END END; PrintBand [state]; IF (b = halftime) AND (iterations > 10) AND state.isLastPage THEN BEGIN fudge: INT ~ 3; -- more than 2 because of memory fragmentation duration: INT ~ BasicTime.Period [state.startTime, BasicTime.Now[]]; end _ BasicTime.Update [state.startTime, fudge * duration ! BasicTime.OutOfRange => GOTO endless]; TerminalIO.PutF ["\nRevised duration inference: Interpress master will be ready ca. %g\n", IO.time [end]] END ENDLOOP; state.band _ NIL END; IF (state.tess # NIL) THEN {CStitching.DumpCache []; state.tess _ NIL}; state.colorRegion _ NIL; SafeStorage.ReclaimCollectibleObjects END -- IF state.substituteColor ELSE BEGIN gdr: CD.DrawRef ~ CD.CreateDrawRef [[]]; gdr.interestClip _ state.cdClip; gdr.devicePrivate _ state; gdr.drawRect _ IF DoLineArt [] THEN LineRect ELSE OrRect; gdr.drawContext _ DoNotDrawContext; CDOps.DrawDesign [state.design, gdr] END; IF ignoreAnnotation OR (DoLineArt []) THEN RETURN; IF imageRegions THEN RETURN; -- because it does not work yet <> context.SetStrokeEnd [round]; context.SetStrokeJoint [round]; <> <> IF clip THEN tdr.interestClip _ chipNDaleWindow; tdr.drawRect _ DoNotDrawRect; IF letChipndaleCallTheImager THEN BEGIN tdr.deviceContext _ context; tdr.fontSubstitution _ TRUE; <> tdr.contextColors _ NEW [CD.ContextColors]; FOR c: CD.Layer IN CD.Layer DO tdr.contextColors[c] _ LayerColour [c] ENDLOOP END ELSE BEGIN tdr.drawContext _ DoNotDrawContext; tdr.drawChild _ IF (signalNameFont = NIL) THEN DrawObject ELSE DrawObjectWithSignalNames END; tdr.drawOutLine _ DrawObjectBorder; tdr.borders _ TRUE; tdr.selections _ FALSE; tdr.devicePrivate _ state; state.previousColour _ NIL; -- needed by Interpress state.previousStrokeWidth _ -1.0; -- needed by Interpress context.DoSave [EnumerateTextInDesign]; TerminalIO.PutRope [". "]; -- pass 5 EXITS endless => BEGIN ImportantMessage [" Nectarine would not terminate before 2036"]; SIGNAL tooComplex END END; -- DrawToIP Action: PROC [] ~ BEGIN <> DeclareFonts: RefTab.EachPairAction ~ {state.interpress.DeclareFont [NARROW [val,Font]]; RETURN [FALSE]}; ListFonts: RefTab.EachPairAction ~ BEGIN t: Typeface ~ NARROW [val, Font].typeface; TerminalIO.PutF ["%g\n", IO.rope [t.name]]; RETURN [FALSE] END; -- ListFonts IF state.isFirstPage THEN BEGIN state.interpress _ OpenIPMaster []; state.ipName _ masterName; TerminalIO.PutRope [Rope.Cat ["Producing Interpress master ", masterName, "\n"]]; IF DoLineArt [] THEN BEGIN TerminalIO.PutRope ["Line art (overrides halftoning and cross-hatching). "]; IF UseProcessColors [] THEN TerminalIO.PutRope ["Requires process colors to print.\n"] ELSE TerminalIO.PutRope ["Requires custom colors to print.\n"] END ELSE TerminalIO.PutRope ["Halftoned art. Requires process colors to print.\n"]; IF NOT state.substituteColor THEN TerminalIO.PutRope ["No color substitution.\n"]; <> IF (SubColours [] OR DoLineArt []) THEN state.interpress.DeclareColorOperator [IF UserProfile.Boolean [key: "Nectarine.ContinuousTone", default: FALSE] THEN rgbLinear ELSE cmyk] ELSE NULL; <> IF (NumberOfColours[] + fontMap.GetSize[] < 50) THEN DeclareColours [state.interpress]; <> <> UpdateFontMap [state]; IF (NOT ignoreAnnotation) AND (fontMap.GetSize[] < 50) THEN [] _ fontMap.Pairs [DeclareFonts]; IF (signalNameFont # NIL) THEN state.interpress.DeclareFont [signalNameFont]; TerminalIO.PutRope [". "]; -- pass 1 IF debug THEN BEGIN TerminalIO.PutRope ["\nThe following fonts are in the preamble:\n"]; [] _ fontMap.Pairs [ListFonts] END END; <> TRUSTED {Process.SetPriority [Process.priorityBackground]}; state.interpress.DoPage [action: DrawToIP, scale: IF imageRegions THEN versatecResolution ELSE 0.001]; <> IF state.isLastPage THEN BEGIN state.interpress.Close []; multipageHack _ NIL; TerminalIO.PutRope [TimeToRope [state.startTime, BasicTime.Now[]]]; TerminalIO.PutRope ["\n"]; IF (statistics OR debug) THEN ListColourStatistics [state.cardTile]; TerminalIO.PutRope [Rope.Cat ["Interpress master ", state.ipName, " is ready.\n"]] END END; -- Action <
> IF firstPage THEN BEGIN IF (multipageHack # NIL) THEN BEGIN TerminalIO.PutRope [Rope.Cat ["Interpress master ", multipageHack.ipName, " was orphaned and is being salvaged.\n"]]; multipageHack.interpress.Close []; multipageHack _ NIL END; multipageHack _ state _ NEW [StateRec]; state.design _ design; IF singleLayer THEN {state.singleLayer _ TRUE; state.layerOfInterest _ layer}; state.substituteColor _ SubColours []; IF statistics THEN {ResetColourStatistics; state.cardTile _ 0}; state.abort _ IF abortFlag # NIL THEN abortFlag ELSE NEW [BOOL _ FALSE]; state.startTime _ BasicTime.Now [] END ELSE BEGIN state _ multipageHack; masterName _ state.ipName; state.previousColour _ NIL; state.previousStrokeWidth _ -1.0; state.previousFont _ NIL; state.previousTextOrientation _ original END; state.isLastPage _ lastPage; state.isFirstPage _ firstPage; state.clip _ clip; state.cdClip _ chipNDaleWindow; state.selectedOnly _ onlySel; Action [] END; -- DoInterpress DrawSelection: PROC [design: CD.Design, d: CD.DrawRef] ~ BEGIN <> FOR all: CD.InstanceList _ CDOps.InstList [design], all.rest WHILE all # NIL DO IF all.first.selected THEN d.drawChild [d, all.first.ob, all.first.trans, all.first.properties] ENDLOOP END; -- DrawSelection EnumerateObjects: PROC [design: CD.Design, d: CD.DrawRef] ~ BEGIN <> DoObject: CDDirectory.EachEntryAction ~ BEGIN <> d.drawChild [d, ob, [[0,0], original], NIL] END; -- DoObject [] _ CDDirectory.Enumerate [design, DoObject] END; -- EnumerateObjects ChangeColour: PROC [state: State, colour: Color] ~ INLINE BEGIN <> context: Imager.Context ~ state.context; IF (colour # state.previousColour) THEN BEGIN context.SetColor [colour]; state.previousColour _ colour END END; -- ChangeColour <> <> <> <> <> <> <> <> <> ChangeStrokeWidth: PROC [state: State, w: REAL] ~ INLINE BEGIN <> context: Imager.Context ~ state.context; IF (w < 0) OR (w # state.previousStrokeWidth) THEN BEGIN context.SetStrokeWidth [w]; state.previousStrokeWidth _ w END END; -- ChangeStrokeWidth ChangeFont: PROC [state: State, skFont: Font] ~ INLINE BEGIN <> context: Imager.Context ~ state.context; IF (skFont # state.previousFont) THEN BEGIN prFont: Font _ NARROW [fontMap.Fetch[skFont].val]; IF (prFont = NIL) THEN BEGIN <> prFont _ Mapping [skFont]; [] _ fontMap.Insert [skFont, prFont] END; context.SetFont [prFont]; state.previousFont _ skFont END END; -- ChangeFont <> <> fontMap: RefTab.Ref ~ RefTab.Create []; -- global fontPrefix: ATOM ~ Atom.MakeAtom ["xerox/pressfonts/"]; visitedCells: RefTab.Ref; DrawFilter: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> SELECT ob.class.objectType FROM $Text, $RigidText, $FlipText => FindFont [pr, ob, trans, readOnlyInstProps]; $Cell => <> IF visitedCells.Insert [ob, $hack] THEN ob.class.drawMe [pr, ob, trans, readOnlyInstProps]; ENDCASE => NULL END; -- DrawFilter FindFont: CD.DrawProc ~ BEGIN <<[pr: CD.DrawRef, ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL]>> text: CDTexts.TextSpecific ~ NARROW [ob.specific]; font: Font ~ text.cdFont.font; IF NOT fontMap.Fetch[font].found THEN [] _ fontMap.Insert [font, Mapping [font]] END; -- FindFont UpdateFontMap: PROC [state: State] ~ BEGIN <> tdr: CD.DrawRef ~ CD.CreateDrawRef [[]]; Evict: RefTab.EachPairAction ~ {[] _ visitedCells.Delete [key]; RETURN [FALSE]}; remindFontConventions _ TRUE; tdr.drawChild _ DrawFilter; tdr.drawRect _ DoNotDrawRect; tdr.drawContext _ DoNotDrawContext; tdr.devicePrivate _ state; visitedCells _ RefTab.Create [557]; IF state.selectedOnly THEN DrawSelection [state.design, tdr] ELSE EnumerateObjects [state.design, tdr]; <> [] _ visitedCells.Pairs [Evict]; visitedCells _ NIL END; -- UpdateFontMap Mapping: PROC [sk: Font] RETURNS [mr: Font] ~ BEGIN <> fontVendor, fontClass, fullName, shortName, family, attributes: ROPE; slashPos1, slashPos2, sizePos, facePos: INTEGER; isXerox: BOOL; face: NodeStyle.FontFace _ Regular; typeface: Typeface _ sk.typeface; size: REAL; fullName _ typeface.name; slashPos1 _ fullName.SkipTo [0, "/"]; fontVendor _ fullName.Substr [0, slashPos1]; isXerox _ fontVendor.Equal ["Xerox", FALSE]; slashPos1 _ slashPos1.SUCC; slashPos2 _ fullName.SkipTo [slashPos1, "/"]; fontClass _ fullName.Substr [slashPos1, slashPos2-slashPos1]; shortName _ fullName.Substr [slashPos2+1]; SELECT TRUE FROM isXerox AND fontClass.Equal ["PressFonts", FALSE] => BEGIN IF remindFontConventions THEN BEGIN TerminalIO.PutRope ["Nectarine takes care of all the font substitutions. You can use the strike fonts for the layout.\n"]; remindFontConventions _ FALSE END; mr _ sk END; isXerox AND fontClass.Equal ["TiogaFonts", FALSE] => BEGIN <> sizePos _ shortName.SkipTo [0, "0123456789"]; attributes _ shortName.Substr [sizePos, shortName.Length[]-sizePos]; facePos _ attributes.SkipTo [0, "bBiI"]; <> size _ (ORD [attributes.Fetch[0]] - ORD ['0]); FOR i: INT IN [1 .. facePos) DO size _ size * 10.0 + (ORD [attributes.Fetch[i]] - ORD ['0]) ENDLOOP; <> IF (facePos # attributes.Length[]) THEN BEGIN it: BOOL ~ (attributes.SkipTo [0, "iI"] # attributes.Length[]); b: BOOL ~ (attributes.SkipTo [0, "bB"] # attributes.Length[]); SELECT TRUE FROM it AND b => face _ BoldItalic; it AND NOT b => face _ Italic; NOT it AND b => face _ Bold; ENDCASE => ERROR END; family _ shortName.Substr [0, sizePos]; mr _ NodeStyleFont.FontFromStyleParams [prefix: fontPrefix, family: Atom.MakeAtom[family], face: face, size: size, alphabets: CapsAndLower]; mr _ ImagerFont.Modify [mr, sk.charToClient] END; ENDCASE => BEGIN IF isXerox THEN TerminalIO.PutRope [fullName.Cat [": font class", fontClass, " unknown, not substituted.\n"]] ELSE TerminalIO.PutRope [fullName.Cat [": vendor", fontVendor, " unknown, not substituted.\n"]]; mr _ sk END END; -- Mapping ImagerRect: PROC [r: CD.Rect] RETURNS [Imager.Rectangle] ~ BEGIN base: CD.Position ~ CDBasics.BaseOfRect [r]; size: CD.Position ~ CDBasics.SizeOfRect [r]; RETURN [[Float[base.x], Float[base.y], Float[size.x], Float[size.y]]] END; -- ImagerRect ImagerVec: PROC [p: CD.Position] RETURNS [Imager.VEC] ~ BEGIN RETURN [[Float[p.x], Float[p.y]]] END; -- ImagerVec BoxFromRect: PROC [r, viewport: CD.Rect] RETURNS [Box] ~ BEGIN <> <> <> RETURN [[min: [f: r.x1-viewport.x1, s: viewport.y2-r.y2], max: [f: r.x2-viewport.x1, s: viewport.y2-r.y1]]] END; -- BoxFromRect QuickTransf: PROC [r: CD.Rect, state: State] RETURNS [CD.Rect] ~ BEGIN PointX: PROC [p: INT] RETURNS [INT] ~ INLINE BEGIN RETURN [Round [Float [p-state.cdClip.x1] * state.bitmapScale]] END; -- PointX PointY: PROC [p: INT] RETURNS [INT] ~ INLINE BEGIN RETURN [Round [Float [p-state.cdClip.y1] * state.bitmapScale]] END; -- PointY RETURN [[PointX [r.x1], PointY [r.y1], PointX [r.x2], PointY [r.y2]]] END; -- QuickTransf <> <> <> RGBFromColour: PROC [c: Color] RETURNS [rgb: ImagerColor.RGB] ~ INLINE BEGIN <> WITH c SELECT FROM constant: Imager.ConstantColor => rgb _ ImagerColorPrivate.RGBFromColor [constant]; ENDCASE => rgb _ unColour; RETURN [rgb] END; -- RGBFromColour SubColours: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [UserProfile.Boolean [key: "Nectarine.SubstituteColors", default: colSubDef]] END; -- SubColours DoLineArt: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [UserProfile.Boolean [key: "Nectarine.LineArt", default: FALSE]] END; -- DoLineArt UseProcessColors: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [UserProfile.Boolean [key: "Nectarine.ProcessColors", default: TRUE]] END; -- UseProcessColors ImportantMessage: PROC [msg: ROPE] ~ BEGIN <> TerminalIO.PutRope [msg]; TerminalIO.PutRope ["\n"]; MessageWindow.Clear []; MessageWindow.Append [msg]; MessageWindow.Blink [] END; -- ImportantMessage DoNotDrawContext: CD.DrawContextProc ~ {}; DoNotDrawObject: CD.DrawProc ~ {}; DoNotDrawRect: CD.DrawRectProc ~ {}; OrRect: CD.DrawRectProc ~ BEGIN <<[r: Rect, l: Layer, pr: DrawRef]>> state: State ~ NARROW [pr.devicePrivate, State]; IF (state.singleLayer AND (l # state.layerOfInterest)) THEN RETURN; IF (CDBasics.NonEmpty [r]) THEN BEGIN IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, LayerColour [l]]; state.context.MaskRectangle [ImagerRect [r]] END END; -- OrRect LineRect: CD.DrawRectProc ~ BEGIN <<[r: Rect, l: Layer, pr: DrawRef]>> state: State ~ NARROW [pr.devicePrivate, State]; IF (state.singleLayer AND (l # state.layerOfInterest)) THEN RETURN; IF (CDBasics.NonEmpty [r]) AND (LayerColour [l] # NIL) THEN BEGIN IF state.abort^ THEN ERROR ABORTED; ChangeColour [state, LayerColour [l]]; state.context.MaskRectangle [ImagerRect [r]] END END; -- LineRect <> Print: PUBLIC PROC [masterName: Rope.ROPE, printerKey: ATOM, copies: INT _ 1, doNotScale: BOOL _ FALSE, mergeRegister: BOOL _ TRUE, sizeHint: REF Imager.Rectangle _ NIL, abortFlag: REF BOOL] RETURNS [peachName: ROPE] ~ BEGIN <> <> <> errorCause: ROPE; pos: FS.ComponentPositions; {ENABLE BEGIN XNSPrint.Error => {errorCause _ explanation; GOTO xnsFailure}; END; IF masterName.IsEmpty THEN BEGIN TerminalIO.PutRope ["Produce an Interpress master first.\n"]; RETURN [NIL] END; IF (abortFlag = NIL) THEN abortFlag _ NEW [BOOL _ FALSE]; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; <> pos _ FS.ExpandName[masterName].cp; SELECT printerKey FROM $NVersatec, $NColorVersatec, $NBw400, $NColor400, $NPeachExpand, $NRaven384 => BEGIN peachName _ masterName.Replace [pos.ext.start, pos.ext.length, "PD"]; TRUSTED BEGIN Process.Detach [FORK PdPrintProcess [masterName, peachName, printerKey, copies, doNotScale, FALSE, sizeHint, abortFlag]] END; TerminalIO.PutRope ["Printing process forked off.\n"] END; $NRaven300, $C2700 => BEGIN serverName: ROPE; fullName: ROPE; -- with version number c: XNSPrint.Context ~ XNSPrint.GetDefaults []; fullName _ FS.FileInfo [name: masterName, remoteCheck: FALSE].fullFName; pos _ FS.ExpandName [fullName].cp; c.printObjectName _ fullName.Substr[start: pos.base.start, len: pos.base.length].Cat["!",fullName.Substr[start: pos.ver.start, len: pos.ver.length]]; -- Sorry ! SELECT printerKey FROM $NRaven300 => serverName _ UserProfile.Token ["Nectarine.Raven300", "Quoth"]; $C2700 => serverName _ UserProfile.Token ["Nectarine.C2700", "TimsToy"]; ENDCASE => SIGNAL invalidPrinter; c.printerName _ serverName; c.printObjectCreateDate _ FS.FileInfo [name: fullName, remoteCheck: FALSE].created; c.copyCount _ copies; c.senderName _ UserCredentials.Get[].name; c.message _ Rope.Cat ["Nectarine for ", c.senderName]; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; [] _ XNSPrint.PrintFromFile [fullName, c]; TerminalIO.PutF ["%g submitted to %g.\n", IO.rope [c.printObjectName], IO.rope [serverName]]; peachName _ masterName END; $NPlateMaker => BEGIN <> <> <> <> <> <Platemaker>", user, ">", masterName.Substr [pos.base.start, pos.base.length], ".Interpress"]];>> <> peachName _ masterName.Substr [pos.base.start, pos.base.length]; TRUSTED BEGIN Process.Detach [FORK PdPrintProcess [masterName, peachName, printerKey, copies, doNotScale, mergeRegister, sizeHint, abortFlag]] END; TerminalIO.PutRope ["Printing process forked off.\n"]; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; <<[sent, info] _ SimpleMailer.SendMessage [from: "Nectarine", to: LIST ["Scamporrino.PA"], cc: LIST [user], subject: "Platemaker Print Request", body: Rope.Cat ["Dear Bridget,\n\nHow are you today ?\nPlease print for me the file ", gName, ".\n\nThe Interpress master is in A size with a margin of 1 cm on each side.\n\nThis master is for your convenience to preview the picture on a monitor. In a while, you will also find there the required separations ready to be printed. I will send you a message with the names as soon as I will have produced them.\n\nThank you,\n", user]];>> <> <