<> <> <> <> DIRECTORY CD, CDBasics, CDBasicsInline, CDCells, CDColorsExtras, CDCommandOps, CDInstances, CDLayers, CDOps, CDProperties, CDSequencer, CDViewer, Imager, ImagerInterpress, IO, Real, RefTab, Rope, TerminalIO; CDInterpressPlotImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDBasicsInline, CDCells, CDColorsExtras, CDCommandOps, CDInstances, CDOps, CDLayers, CDProperties, CDSequencer, CDViewer, Imager, ImagerInterpress, IO, Real, RefTab, Rope, TerminalIO = BEGIN <<>> <<--constant sizes and scales >> standardPageX: REAL = 8.5*Imager.metersPerInch; -- 8.5 inches is USA standard page width standardPageY: REAL = 11.0*Imager.metersPerInch; -- 11 inches is USA standard page height versatecDeviceX: REAL = 0.97; --of the very special versatec plotter sitting close to my office... It really doe not store in this constant the with of any other versatec plotter available... c400PageX: REAL = 0.292; c400PageY: REAL = 0.419; <<>> <<--default sizes and scales >> defaultPageX: REAL _ standardPageX; defaultPageY: REAL _ standardPageY; defaultStripeX: REAL _ versatecDeviceX; defaultBorder: REAL _ Imager.metersPerInch; <<>> <<--others >> fileNameDefault: Rope.ROPE _ "///temp/temp.IP"; ColorMode: TYPE = {allBlack, color, special}; colorMode: ColorMode _ allBlack; <<>> <<>> <<--set ups for this very plot which will be created right now>> pageX: REAL; pageY: REAL; contextColors: REF CD.ContextColors = NEW[CD.ContextColors_ALL[Imager.black]]; RectToRectangle: PROC [r: CD.Rect] RETURNS [Imager.Rectangle] = { RETURN [[x: r.x1, y: r.y1, w: r.x2-r.x1, h: r.y2-r.y1]] }; SetUpBW: PROC [] = { FOR layer: CD.Layer IN CD.Layer DO contextColors[layer] _ Imager.black; ENDLOOP; contextColors[CD.backgroundLayer] _ NIL; }; SetUpColor: PROC [] = { FOR layer: CD.Layer IN CD.Layer DO WITH CDProperties.GetLayerProp[layer, $CDxInterpressPlotColor] SELECT FROM c: Imager.Color => {contextColors[layer] _ c; LOOP}; a: ATOM => IF a=$FALSE THEN {contextColors[layer] _ NIL; LOOP}; ENDCASE => NULL; IF CDLayers.Kind[layer]=paint THEN contextColors[layer] _ CDColorsExtras.RegisteredColor[layer ! CDColorsExtras.ColorNotRegistered => RESUME]; ENDLOOP; contextColors[CD.backgroundLayer] _ NIL; }; SetUpSpecial: PROC [] = { FOR layer: CD.Layer IN CD.Layer DO contextColors[layer] _ IF CDProperties.GetLayerProp[layer, $CDxInterpressPlot]=$do THEN Imager.black ELSE NIL; ENDLOOP; contextColors[CD.backgroundLayer] _ NIL; }; HardCopyCommand: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["HardCopy\n"]; [] _ CDCommandOps.DoWithResource[proc: ProtectedHardCopy, comm: comm, resource: $CDSimplePlotImpl]; }; PropagatedGetProp: PROC [design: CD.Design, key: REF] RETURNS [x: REF] = { x _ CDProperties.GetDesignProp[design, key]; IF x=NIL THEN x _ CDProperties.GetTechnologyProp[design.technology, key]; }; PropagatedGetIntProp: PROC [design: CD.Design, key: REF, default: INT_1] RETURNS [INT_0] = { WITH PropagatedGetProp[design, key] SELECT FROM ri: REF INT => RETURN [ri^]; ri: REF INTEGER => RETURN [ri^]; rc: REF CARDINAL => RETURN [rc^]; rn: REF NAT => RETURN [rn^]; ENDCASE => NULL; RETURN [default] }; RequestClipRect: PROC [comm: CDSequencer.Command] RETURNS [clip: CD.Rect, inst: CD.Instance_NIL] = { n: INT _ TerminalIO.RequestSelection[header: "plot area", choice: LIST["plot complete design", "plot drawn rectangle", "plot like viewer", "plot area of selection", "plot selection only"] ]; SELECT n FROM 1 => { clip _ CDBasics.Extend[CDOps.BoundingBox[comm.design], 2]; TerminalIO.PutRope["plot complete design\n"]; }; 2 => { clip _ CDBasics.ToRect[comm.pos, comm.sPos]; TerminalIO.PutRope["plot rectangle of command\n"]; }; 3 => { clip _ CDViewer.VisibleRect[CDViewer.GetViewer[comm]]; TerminalIO.PutRope["plot as viewed\n"]; }; 4 => { clip _ CDBasics.Extend[CDOps.BoundingBox[comm.design, TRUE], 2]; TerminalIO.PutRope["plot area of selection\n"]; }; 5 => { sel: CD.InstanceList _ NIL; design: CD.Design _ comm.design; TerminalIO.PutRope["plot selection only\n"]; FOR l: CD.InstanceList _ CDOps.InstList[design], l.rest WHILE l#NIL DO IF l.first.selected THEN sel _ CONS[l.first, sel] ENDLOOP; IF sel=NIL THEN { TerminalIO.PutRope["no selection\n"]; ERROR ABORTED }; inst _ CDInstances.NewInst[CDCells.CreateCellXTransformed[il: sel]]; clip _ CDBasics.Extend[CDInstances.InstRectO[inst], 2]; }; ENDCASE => { clip _ CDBasics.ToRect[comm.pos, comm.sPos]; TerminalIO.PutRope["plot rectangle of command\n"]; }; IF ~CDBasics.NonEmpty[clip] THEN { TerminalIO.PutRope["clip rectangle is empty\n"]; ERROR ABORTED }; }; SubstituteFonts: PROC [] RETURNS [substituteFonts: BOOL] = { n: INT; n _ TerminalIO.RequestSelection[header: "substitute tioga fonts", headerDoc: "do for schematics; don't for layout", choice: LIST["yes", "no"] ]; substituteFonts _ n#2 }; MyDrawRectInContext: PROC [pr: CD.DrawRef, r: CD.Rect, l: CD.Layer] = { IF pr.contextColors[l]#NIL THEN { IF pr.devicePrivate#pr.contextColors[l] THEN { Imager.SetColor[pr.deviceContext, pr.contextColors[l]]; pr.devicePrivate _ pr.contextColors[l] }; Imager.MaskBox[pr.deviceContext, [xmin: r.x1, xmax: r.x2, ymin: r.y1, ymax: r.y2]]; } }; MyDrawContext: PROC [pr: CD.DrawRef, proc: CD.DrawContextLayerProc, ob: CD.Object, trans: CD.Transformation, layer: CD.Layer] = { ActionWithContext: PROC [] = { IF ob#NIL THEN Imager.ConcatT[pr.deviceContext, CDBasicsInline.ImagerTransform[trans]]; proc[pr.deviceContext, ob, layer]; }; IF pr.contextColors[layer]#NIL THEN { IF pr.devicePrivate#pr.contextColors[layer] THEN { Imager.SetColor[pr.deviceContext, pr.contextColors[layer]]; pr.devicePrivate _ pr.contextColors[layer] }; Imager.DoSave[pr.deviceContext, ActionWithContext] }; }; ProtectedHardCopy: PROC [comm: CDSequencer.Command] = { <<--not re-entrant: using a globals>> abortFlag: REF BOOL = NEW[BOOL_FALSE]; fileName: Rope.ROPE _ fileNameDefault; pageNumX: INT _ 1; --number of vertical stripes pageNumY: INT _ 1; --number of horizontal stripes nX, nY: INT; --number of current page borderX, borderY: REAL; --border of page ref: ImagerInterpress.Ref; dr: CD.DrawRef; clip: CD.Rect; start: CD.Position; sizePerPage: CD.Position; scale: REAL; substituteFonts: BOOL _ TRUE; deviceTranslation: Imager.VEC _ [0, 0]; help: Rope.ROPE _ NIL; instance: CD.Instance; eraseFirst: BOOL _ FALSE; PlotPage: PROC [context: Imager.Context] = { <<--the real work>> r: CD.Rect _ CDBasics.RectAt[start, sizePerPage]; r _ CDBasics.Intersection[r, clip]; IF ~CDBasics.NonEmpty[r] THEN RETURN; IF eraseFirst THEN { Imager.SetColor[context, CDColorsExtras.InitialColor[! CDColorsExtras.ColorNotRegistered=>RESUME]]; Imager.MaskRectangle[context, [x: FIRST[INT]/4, y: FIRST[INT]/4, w: LAST[INT]/2, h: LAST[INT]/2]]; }; Imager.TranslateT[context, deviceTranslation]; Imager.ScaleT[context, scale]; Imager.TranslateT[context, [-r.x1, -r.y1]]; Imager.ClipRectangle[context, RectToRectangle[r]]; dr _ CD.CreateDrawRef[[ design: comm.design, stopFlag: abortFlag, drawRect: MyDrawRectInContext, drawContext: MyDrawContext, contextColors: contextColors, borders: TRUE, selections: FALSE, fontSubstitution: substituteFonts, interestClip: r, deviceContext: context, devicePrivate: NIL ]]; IF CDSequencer.Aborted[comm.design] THEN RETURN; IF instance=NIL THEN CDOps.DrawDesign[comm.design, dr] ELSE CD.DrawOb[dr, instance.ob, instance.trans, instance.properties]; }; PreAmble: PROC [ref: ImagerInterpress.Ref, contextColors: REF CD.ContextColors, technology: CD.Technology] = { declared: RefTab.Ref _ RefTab.Create[]; FOR layer: CD.Layer IN CD.Layer DO IF contextColors[layer]#NIL THEN { t: CD.Technology _ CD.LayerTechnology[layer]; IF t=NIL OR (t=technology AND CDLayers.Kind[layer]=paint) THEN IF RefTab.Insert[declared, contextColors[layer], NIL] THEN ImagerInterpress.DeclareColor[ref, contextColors[layer]] }; ENDLOOP; declared _ NIL; }; SetUp: PROC [] = { RequestBorder: PROC [borderDefault, ask: BOOL _ FALSE] = { borderY _ borderX _ IF borderDefault THEN defaultBorder ELSE 0; IF ask THEN { SELECT TerminalIO.RequestSelection[header: "border", choice: LIST["yes", "no"]] FROM 1 => borderY _ borderX _ defaultBorder; 2 => borderY _ borderX _ 0; ENDCASE => NULL; }; }; SetUpVaryingScaling: PROC [clip: CD.Rect] = { insidePageX, insidePageY: REAL; --what fits in a page without border IF multiPaged THEN { pageNumX _ TerminalIO.RequestInt["Number of pages in x direction? >"]; IF pageNumX<1 OR pageNumX>20 THEN { TerminalIO.PutRope[" to bad\n"]; ERROR ABORTED }; } ELSE pageNumX _ 0; RequestBorder[borderDefault: TRUE, ask: (pageNumX>1)]; insidePageX _ pageX-2*borderX; insidePageY _ pageY-2*borderY; IF pageNumX=0 THEN { <<--single page>> pageNumY _ 1; pageNumX _ 1; sizePerPage _ CDBasics.SizeOfRect[clip]; scale _ MIN[insidePageX/sizePerPage.x, insidePageY/sizePerPage.y]; } ELSE { <<--multiple pages>> sizePerPage.x _ (clip.x2-clip.x1)/pageNumX+1; sizePerPage.y _ Real.Fix[insidePageY*((sizePerPage.x-1.0)/insidePageX)]; scale _ insidePageX/sizePerPage.x; pageNumY _ ( (clip.y2-clip.y1)+(sizePerPage.y-1) )/sizePerPage.y; }; }; SetUpStriped: PROC [clip: CD.Rect] = { borderY _ defaultBorder; borderX _ 0; pageNumY _ 1; IF multiPaged THEN { pageNumX _ TerminalIO.RequestInt["How many stripes? >"]; IF pageNumX<1 OR pageNumX>20 THEN { TerminalIO.PutRope[" to bad\n"]; ERROR ABORTED } } ELSE pageNumX _ 1; sizePerPage.x _ (clip.x2-clip.x1)/pageNumX; sizePerPage.y _ clip.y2-clip.y1; scale _ pageX/sizePerPage.x; pageY _ scale*sizePerPage.y+2*borderY; }; SetUpFixedScaling: PROC [clip: CD.Rect] = { borderAnyway: BOOL; defaultScale: REAL _ Imager.metersPerPoint/comm.design.technology.lambda; <<--1>> scale _ defaultScale; scale _ scale*PropagatedGetIntProp[design: comm.design, key: $CDxDefaultPrintScaleNum, default: 1]; scale _ scale/PropagatedGetIntProp[design: comm.design, key: $CDxDefaultPrintScaleDenom, default: 1]; borderAnyway _ ( (clip.x2-clip.x1)*scale < (pageX - 0.05) ) AND ( (clip.y2-clip.y1)*scale < (pageY - 0.05) ); RequestBorder[borderDefault: borderAnyway, ask: ~borderAnyway]; sizePerPage.x _ Real.Round[(pageX-2*borderX)/scale]; sizePerPage.y _ Real.Round[(pageY-2*borderY)/scale]; pageNumX _ (clip.x2-clip.x1+sizePerPage.x-1)/sizePerPage.x; pageNumY _ (clip.y2-clip.y1+sizePerPage.y-1)/sizePerPage.y; }; AdjustPosition: PROC [] = { IF pageNumX=1 THEN { borderX _ MIN[(pageX - (clip.x2-clip.x1)*scale)/2, defaultBorder]; }; IF pageNumY=1 THEN { pictureHeight: REAL _ (clip.y2-clip.y1)*scale; borderY _ MAX[pageY-defaultBorder-pictureHeight, (pageY-pictureHeight)/2]; }; }; GetMedium: PROC [] = { fixedScale _ FALSE; striped _ FALSE; SELECT TerminalIO.RequestSelection["Plot", LIST["fill standard page", "fill multiple standard pages", "fixed scale standard pages", "fill single versatec stripe", "fill multiple versatec stripes", "fill c400 page"]] FROM 1 => { pageX _ defaultPageX; pageY _ defaultPageY; TerminalIO.PutRope["fill standard page\n"]; }; 2 => { multiPaged _ TRUE; pageX _ defaultPageX; pageY _ defaultPageY; TerminalIO.PutRope["fill multiple standard pages\n"]; }; 3 => { fixedScale _ TRUE; --multipage will be computed... pageX _ defaultPageX; pageY _ defaultPageY; TerminalIO.PutRope["fixed scale standard pages\n"]; }; 4 => { striped _ TRUE; pageX _ defaultStripeX; TerminalIO.PutRope["fill single versatec stripe\n"]; }; 5 => { striped _ TRUE; multiPaged _ TRUE; pageX _ defaultStripeX; TerminalIO.PutRope["fill multiple versatec stripes\n"]; }; 6 => { pageX _ c400PageX; pageY _ c400PageY; TerminalIO.PutRope["fill c400 page\n"]; }; ENDCASE => ERROR ABORTED }; --GetMedium --Setup fixedScale: BOOL _ FALSE; striped: BOOL _ FALSE; multiPaged: BOOL _ FALSE; IF comm.key=$InterpressPlotC THEN { TerminalIO.PutRope["** COLORS\n"]; eraseFirst _ TRUE; SetUpColor[] } ELSE SELECT colorMode FROM special => { TerminalIO.PutRope["** SPECIAL COLORS\n"]; SetUpSpecial[] }; color => { TerminalIO.PutRope["** COLORS\n"]; eraseFirst _ TRUE; SetUpColor[] }; allBlack => { TerminalIO.PutRope["** BW\n"]; SetUpBW[] }; ENDCASE => ERROR; pageX _ defaultPageX; pageY _ defaultPageY; [clip, instance] _ RequestClipRect[comm]; substituteFonts _ SubstituteFonts[]; GetMedium[]; sizePerPage _ CDBasics.SizeOfRect[clip]; IF striped THEN SetUpStriped[clip] ELSE IF fixedScale THEN SetUpFixedScaling[clip] ELSE SetUpVaryingScaling[clip]; AdjustPosition[]; TerminalIO.PutF[" printing %01g rows and %01g columns\n", IO.int[pageNumX], IO.int[pageNumY]]; }; --Setup SetUp[]; CDSequencer.UseAbortFlag[comm.design, abortFlag]; ref _ ImagerInterpress.Create[fileName]; PreAmble[ref, contextColors, comm.design.technology]; deviceTranslation _ [borderX, borderY]; FOR nX IN [0..pageNumX) DO FOR nY IN [0..pageNumY) DO IF CDSequencer.Aborted[comm.design] THEN EXIT; start.x _ clip.x1+nX*sizePerPage.x; start.y _ clip.y1+nY*sizePerPage.y; ImagerInterpress.DoPage[ref, PlotPage]; ENDLOOP; ENDLOOP; ImagerInterpress.Close[ref]; TerminalIO.PutF1[" ""%01g"" created\n", IO.rope[fileName]]; IF ~Rope.IsEmpty[help] THEN TerminalIO.PutRope[help]; IF CDSequencer.Aborted[comm.design] THEN TerminalIO.PutRope["some pages skipped\n"] ELSE TerminalIO.PutRope[" done\n"]; }; CDCommandOps.RegisterWithMenu[menu: $HardCopyMenu, entry: "b&w interpress", doc: "all layers are painted black", key: $InterpressPlot, proc: HardCopyCommand]; CDCommandOps.RegisterWithMenu[menu: $HardCopyMenu, entry: "color interpress", doc: "does not deal with overlapping layers", key: $InterpressPlotC, proc: HardCopyCommand]; TerminalIO.PutRope["Interpress plot loaded\n"]; END.