DIRECTORY CD, CDBasics, CDCommandOps, CDExtras, CDIO, CDViewer, CDPolygons, CDMenus, CDOps, CDOrient, CDProperties, CDSequencer, CDValue, CGArea, CGClipper, CGReducer, CornerStitching, Graphics, GraphicsBasic, IO, PDFileFormat, PDFileWriter, Process, Real, Rope, TerminalIO, ViewerClasses, ViewerSpecs; CDColorPDPlot: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCommandOps, CDExtras, CDIO, CDMenus, CDValue, CDViewer, CDOps, CDOrient, CDPolygons, CDProperties, CDSequencer, CGArea, CGClipper, CGReducer, CornerStitching, IO, PDFileWriter, Process, Real, TerminalIO = BEGIN Toner: TYPE = PDFileFormat.Toner; -- {black, cyan, magenta, yellow}; TonerKeys: TYPE = ARRAY Toner OF REF; LoadArray: TYPE = ARRAY Toner OF PDFileWriter.LoadReference; ColorDescription: TYPE = ARRAY CD.Layer OF REF LoadArray _ ALL[NIL]; whiteLoadRef: PDFileWriter.LoadReference = LAST[PDFileWriter.LoadReference]; tonerToKeyKeys: REF TonerKeys = NEW[TonerKeys _ [ $CDxColorPDPlotBlack, $CDxColorPDPlotCyan, $CDxColorPDPlotMagenta, $CDxColorPDPlotYellow ]]; deviceCode: PDFileFormat.DeviceCode _ last; sRes: CARDINAL _ 200; -- resolution (slow directition), pixels / inch fRes: CARDINAL _ 200; -- resolution (fast direction), pixels / inch scanLineWidth: CARDINAL _ 8000; --for the wide-bed Versatec, length in the "fast" direction; toners: PDFileWriter.TonerSet _ ALL[TRUE]; leftOverMode: BOOL _ FALSE; bandSSize: CARDINAL _ 64; -- number chosen because of buffer-size of versatec overLap: CARDINAL _ 300; -- number of pixels by which to overlap strips maxPixPerLambda: REAL _ 20; -- maximum # of pixels to make lambda paged: BOOL _ FALSE; pageSlowSize: INT _ -1; --only interesting if paged stippleKey: ATOM _ $CDxVersatec; tonerToKey: REF TonerKeys _ NIL; ColorVersatec: PROC [] = BEGIN deviceCode _ last; --does not yet has an assigned value, use "last" sRes _ 200; -- resolution (slow directition), pixels / inch fRes _ 200; -- resolution (fast direction), pixels / inch scanLineWidth _ 8000; --for the wide-bed Versatec, length in the "fast" direction; toners _ ALL[TRUE]; bandSSize _ 64; -- number chosen because of buffer-size of versatec overLap _ 300; -- number of pixels by which to overlap strips maxPixPerLambda _ 20; -- maximum # of pixels to make lambda paged _ FALSE; leftOverMode _ FALSE; stippleKey _ $CDxVersatec; TerminalIO.WriteRope["color versatec"]; END; InkJet: PROC [] = BEGIN deviceCode _ last; sRes _ 120; -- resolution (slow directition), pixels / inch fRes _ 120; -- resolution (fast direction), pixels / inch scanLineWidth _ 120/10*75; -- toners _ ALL[TRUE]; bandSSize _ 64; -- overLap _ 30; -- number of pixels by which to overlap strips maxPixPerLambda _ 20; -- maximum # of pixels to make lambda paged _ FALSE; leftOverMode _ FALSE; stippleKey _ $CDxVersatec; TerminalIO.WriteRope["ink jet"]; END; Puffin: PROC [] = BEGIN deviceCode _ PDFileFormat.DeviceCode[puffin]; sRes _ 384; -- resolution (slow directition), pixels / inch fRes _ 384; -- resolution (fast direction), pixels / inch scanLineWidth _ fRes * 17 / 2; toners _ [FALSE, TRUE, TRUE, TRUE]; bandSSize _ 16; -- overLap _ 30; -- number of pixels by which to overlap strips maxPixPerLambda _ 20; -- maximum # of pixels to make lambda paged _ TRUE; pageSlowSize _ sRes*11; leftOverMode _ TRUE; stippleKey _ $CDxPuffin; TerminalIO.WriteRope["Puffin"]; END; debugging: BOOL _ FALSE; technologyPropertyKey: REF _ $CDxLastTechnology; --a property of the stippleKey abortPlot: REF BOOL _ NEW[BOOL _ FALSE]; PlotStateRef: TYPE = REF PlotState; PlotState: TYPE = RECORD [ tes: ARRAY CD.Layer OF REF CornerStitching.Tesselation _ ALL[NIL], scale: REAL _ 1.0, -- pixels per CD.DesignNumber totalPlotClip, bandClip: CD.DesignRect _ [0, 0, 0, 0], pdState: PDFileWriter.PDState, colorLoads: REF ColorDescription, anouncedLayer: INT _ -1 ]; pdx, pdy: CARDINAL _ 0; -- origin of band in pixel coords cdx, cdy: INT _ 0; -- origin of band in chipndale coords xoffset, yoffset: INT _ 0; -- offset in transforming between coord systems plotScale: REAL; imageSSize: REAL; imageFSize: CARDINAL; ps: PlotStateRef; CheckStipples: PROC [technology: CD.Technology] = BEGIN x: REF _ CDValue.Fetch[technology, stippleKey]; WITH x SELECT FROM r: Rope.ROPE => { TerminalIO.WriteRope["color stipples used: ["]; TerminalIO.WriteRope[r]; TerminalIO.WriteRope["]\n"]; } ENDCASE => { TerminalIO.WriteRope["**color stipples are not defined\n"]; ERROR ABORTED }; IF technology.key#CDProperties.GetPropFromAtom[stippleKey, technologyPropertyKey] THEN TerminalIO.WriteRope["**Warning: another technology registered in the meantime; the technology independent stipples are redefined\n"]; tonerToKey _ NEW[TonerKeys _ ALL[NIL]]; FOR t: PDFileWriter.Toner IN PDFileWriter.Toner DO tonerToKey^[t] _ CDProperties.GetPropFromAtom[stippleKey, tonerToKeyKeys[t]]; IF ~toners[t] OR tonerToKey^[t]=NIL THEN { toners[t] _ FALSE; tonerToKey^[t] _ NEW[INT]; } ENDLOOP; END; ProtectedPlotDesign: PROC [comm: CDSequencer.Command] = BEGIN design: CD.Design = comm.design; plotClip: CD.DesignRect; plotSize: CD.DesignPosition; s: IO.STREAM _ NIL; strips: INT; TerminalIO.WriteRope["Starting Color plot for "]; SELECT comm.a FROM $VersatecColorPlot => ColorVersatec[]; $InkJetColorPlot => InkJet[]; $PuffinColorPlot => Puffin[]; ENDCASE => ERROR; TerminalIO.WriteLn[]; CheckStipples[design.technology]; SELECT TerminalIO.RequestSelection["Plot", LIST["complete design", "rectangle"]] FROM 2 => { plotClip _ CDBasics.ToRect[comm.pos, comm.sPos]; TerminalIO.WriteRope["plot rectangle\n"]; }; ENDCASE => { plotClip _ CDExtras.BoundingBox[comm.design]; TerminalIO.WriteRope["plot all\n"]; }; plotSize _ CDBasics.SizeOfRect[plotClip]; IF plotSize.x<=0 OR plotSize.y<=0 THEN { TerminalIO.WriteRope["**cannot plot empty area\n"]; RETURN }; TRUSTED {Process.SetPriority[Process.priorityBackground]}; IF paged THEN strips _ 1 ELSE { strips _ TerminalIO.RequestInt["How many vertical strips? [1..10] "]; strips _ MAX[1, MIN[10, strips]]; }; BEGIN ENABLE { -- for ERRORs UNWIND => { s _ AbortFile[s]; CDViewer.RemoveArrow[design]; TerminalIO.WriteRope[" ** plot aborted ** "] }; }; dr: CD.DrawRef = CD.CreateDrawRef[design]; scale: REAL _ MIN[ maxPixPerLambda/CD.lambda, (REAL[scanLineWidth-overLap]*strips+overLap) / plotSize.x ]; ps _ NEW[PlotState _ [ scale: scale, totalPlotClip: plotClip, colorLoads: NEW[ColorDescription _ ALL[NIL]] ]]; IF paged THEN { scale _ MIN[scale, REAL[pageSlowSize]/plotSize.x]; }; imageFSize _ scanLineWidth; imageSSize _ plotSize.y*scale; -- length of plot in pixels plotScale _ scale; IF debugging THEN { TerminalIO.WriteRope[" Scale factor (pixels/design#)*100 --> "]; TerminalIO.WriteInt[Real.RoundLI[plotScale*100]]; TerminalIO.WriteLn[]; }; dr.minimalSize _ 0; dr.stopFlag _ abortPlot; dr.drawRect _ dr.saveRect _ NoteRectangle; dr.drawContext _ DrawContext; dr.contextFilter _ contextFilter; dr.devicePrivate _ ps; FOR strip: INT IN [0..strips) DO clip: CD.DesignRect = [ x1: plotClip.x1+strip*(plotSize.x/strips), y1: plotClip.y1, x2: plotClip.x1+(strip+1)*(plotSize.x/strips)+ Real.Fix[overLap/scale]+1, y2: plotClip.y2 ]; localFileName: Rope.ROPE = CDIO.MakeName[ wDir: "///temp/", base: "plot", modifier: IO.PutFR["%d", IO.int[strip+1]], ext: "pd" ]; TerminalIO.WriteRope["Recording strip on file "]; TerminalIO.WriteRope[localFileName]; TerminalIO.WriteLn[]; ps.pdState _ PDFileWriter.Create[ fileName: localFileName, deviceCode: deviceCode, sResolution: sRes, fResolution: fRes, imageSSize: (IF paged THEN pageSlowSize ELSE Real.RoundC[imageSSize + 1]), imageFSize: imageFSize, bandSSize: bandSSize, leftOverMode: leftOverMode ]; ps.colorLoads^ _ ALL[NIL]; PDFileWriter.StartImage[pdState: ps.pdState, toners: toners]; FOR topLine: INT _ 0, topLine+bandSSize WHILE topLine { s _ AbortFile[s]; CDViewer.RemoveArrow[design]; TerminalIO.WriteRope[" ** plot aborted ** "]; }; END; -- enable END; -- PlotDesign NoteRectangle: PROC [r: CD.DesignRect, l: CD.Layer, pr: CD.DrawRef] = BEGIN ps: PlotStateRef = NARROW[pr.devicePrivate]; IF CDBasics.NonEmpty[r] THEN { IF ps.tes[l]=NIL THEN ps.tes[l] _ CornerStitching.NewTesselation[]; ps.tes[l].ChangeRect[rect: r, newValue: $covered]; }; END; SetColor: PROC [ps: PlotStateRef, lev: CD.Layer] = BEGIN Stipple16: TYPE = ARRAY[0..16) OF CARDINAL; Stipple8: TYPE = ARRAY[0..8) OF [0..256); Stipple4: TYPE = ARRAY[0..4) OF [0..16); ToTexture: PROC [pattern: REF ANY] RETURNS [texture: Stipple16] = BEGIN IF pattern=NIL THEN RETURN[Stipple16[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]; -- should not occur WITH pattern SELECT FROM s16: REF Stipple16 => texture _ s16^; s8: REF Stipple8 => FOR i: [0..8) IN [0..8) DO texture[i] _ texture[i+8] _ (256+1)*s8[i]; ENDLOOP; s4: REF Stipple4 => FOR i: [0..4) IN [0..4) DO texture[i] _ texture[i+4] _ texture[i+8] _ texture[i+12] _ s4[i]*1111H; ENDLOOP; ENDCASE => RETURN[Stipple16[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0FFFFH]]; -- error texture RETURN [texture] END; -- ToTexture MakeLoadref: PROC [pattern: REF ANY] RETURNS [loadRef: PDFileWriter.LoadReference] = TRUSTED BEGIN texture: Stipple16 _ ToTexture[pattern]; loadRef _ PDFileWriter.LoadContiguousColorTile[pdState: ps.pdState, phase: 0, sMin: 0, fMin: 0, sSize: 16, fSize: 16, bitsPtr: @texture]; END; -- MakeLoadref MakeLoad: PROC [ps: PlotStateRef, lev: CD.Layer] = BEGIN IF ps.colorLoads^[lev]=NIL THEN { ps.colorLoads^[lev] _ NEW[LoadArray]; FOR toner: Toner IN Toner DO tex: REF _ CDProperties.GetPropFromLayer[from: lev, prop: tonerToKey[toner]]; IF tex=NIL THEN ps.colorLoads^[lev][toner] _ whiteLoadRef ELSE ps.colorLoads^[lev][toner] _ MakeLoadref[tex] ENDLOOP; }; END; --MakeLoad IF ps.anouncedLayer=lev THEN RETURN; IF ps.colorLoads^[lev]=NIL THEN MakeLoad[ps, lev]; FOR toner: Toner IN Toner DO IF ps.colorLoads^[lev][toner] = whiteLoadRef THEN PDFileWriter.SetColorOff[ps.pdState, toner] ELSE PDFileWriter.SetColorTile[ps.pdState, toner, ps.colorLoads^[lev][toner], transparent]; ENDLOOP; ps.anouncedLayer _ lev END; contextFilter: REF CD.ContextFilter = NEW[CD.ContextFilter_ALL[[doit: TRUE]]]; PlotPolygon: PROC [ob: CD.ObPtr, pos: CD.DesignPosition, orient: CD.Orientation] = BEGIN OutputTrapezoid: PROCEDURE [xbotL: REAL, xbotR: REAL, ybot: REAL, xtopL: REAL, xtopR: REAL, ytop: REAL] = BEGIN PDFileWriter.MaskTrapezoid[ pdState: ps.pdState, sMin: Real.RoundC[ybot], sSize: Real.RoundC[ytop-ybot], fMin: Real.RoundC[xbotL], fSize: Real.RoundC[xbotR-xbotL], fMinLast: Real.RoundC[xtopL], fSizeLast: Real.RoundC[xtopR-xtopL] ]; END; --OutputTrapezoid pp: CDPolygons.PolygonPtr = NARROW[ob.specificRef]; polygon: CGReducer.Ref = CGReducer.New[size: 8]; tiling: CGArea.Ref = CGArea.New[size: 4]; clipRef: CGClipper.Ref = CGClipper.New[size: 4]; clip: GraphicsBasic.Box _ [ xmin: 0, ymin: pdy, xmax: MIN[xoffset + ps.bandClip.x2*plotScale, imageFSize], ymax: pdy+bandSSize ]; CGClipper.SetBox[self: clipRef, box: clip]; CGClipper.Load[self: clipRef, reducer: polygon]; FOR p: LIST OF CD.DesignPosition _ pp.points, p.rest WHILE p#NIL DO at: CD.DesignPosition = CDOrient.MapPoint[ pointInCell: p.first, cellSize: ob.size, cellInstOrient: orient, cellInstPos: pos ]; CGReducer.Vertex[self: polygon, v: [ x: xoffset + at.x*plotScale, y: yoffset - at.y*plotScale ]] ENDLOOP; CGReducer.Close[polygon]; CGReducer.Generate[self: polygon, area: tiling]; UNTIL CGArea.Empty[tiling] DO t: GraphicsBasic.Trap = CGArea.Remove[tiling]; OutputTrapezoid[t.xbotL, t.xbotR, t.ybot, t.xtopL, t.xtopR, t.ytop]; ENDLOOP; END; --PlotPolygon DrawContext: PROC [pr: CD.DrawRef, proc: CD.DrawContextLayerProc, ob: CD.ObPtr, pos: CD.DesignPosition, orient: CD.Orientation, layer: CD.Layer] = BEGIN IF CDPolygons.IsPolygon[ob] THEN { SetColor[ps, layer]; PlotPolygon[ob, pos, orient]; } END; AnalyzeTesselations: PROC [ps: PlotStateRef] = BEGIN FOR lev: CD.Layer IN CD.Layer DO IF ps.tes[lev]#NIL THEN { SetColor[ps, lev]; [] _ ps.tes[lev].EnumerateArea[ rect: ps.bandClip, perTile: ProcessTile, data: ps, backgroundValue: $none ]; }; ENDLOOP; END; ProcessTile: PROCEDURE [tile: CornerStitching.TilePtr, data: REF ANY] = BEGIN IF tile.Value = $covered THEN { rightBound, x1, y1, x2, y2: INT; pdx1, pdx2, pdy1, pdy2: CARDINAL; sSize, fSize: CARDINAL; ps: PlotStateRef = NARROW[data]; r: CD.DesignRect = tile.Area; x1 _ Real.RoundLI[xoffset + r.x1*plotScale]; y1 _ Real.RoundLI[yoffset - r.y1*plotScale]; x2 _ Real.RoundLI[xoffset + r.x2*plotScale]; y2 _ Real.RoundLI[yoffset - r.y2*plotScale]; rightBound _ Real.RoundLI[xoffset + ps.bandClip.x2*plotScale]; IF NOT ( x1>rightBound OR x2<0 OR y1MIN[imageSSize, pdy+bandSSize] ) THEN { pdx1 _ MAX[x1, 0]; pdx2 _ MIN[x2, rightBound, imageFSize]; pdy1 _ MIN[y1, pdy+bandSSize]; pdy2 _ MAX[y2, pdy]; fSize _ pdx2 - pdx1; sSize _ pdy1 - pdy2; IF pdy1>=imageSSize THEN sSize _ Real.Fix[imageSSize - pdy2]; IF sSize#0 AND fSize#0 THEN PDFileWriter.MaskRectangle[pdState: ps.pdState, sMin: pdy2, fMin: pdx1, sSize: sSize, fSize: fSize ]; } }; END; AbortFile: PROC [s: IO.STREAM] RETURNS [IO.STREAM] = { IF s#NIL THEN s.Close[abort: TRUE]; RETURN[NIL] }; PDColorPlotComm: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Color plot\n"]; [] _ CDCommandOps.CallWithResource[ProtectedPlotDesign, comm, $ColorPlot, abortPlot]; END; Init: PROC ~ { CDSequencer.ImplementCommand[a: $VersatecColorPlot, p: PDColorPlotComm, queue: doQueue]; CDSequencer.ImplementCommand[a: $InkJetColorPlot, p: PDColorPlotComm, queue: doQueue]; CDSequencer.ImplementCommand[a: $PuffinColorPlot, p: PDColorPlotComm, queue: doQueue]; CDMenus.CreateEntry[$HardCopyMenu, "Color Versatec", $VersatecColorPlot]; CDMenus.CreateEntry[$HardCopyMenu, "Ink Jet", $InkJetColorPlot]; CDMenus.CreateEntry[$HardCopyMenu, "Puffin, (1 page)", $PuffinColorPlot]; TerminalIO.WriteRope["ChipNDale color plot program loaded\n"]; }; Init[]; END. îCDColorPDPlot.mesa Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. written by E. McCreight, August 1, 1983 2:00 PM Last Edited by: McCreight, November 23, 1983 4:58 pm Last Edited by: Jacobi, October 27, 1983 12:36 pm Last Edited by: Jacobi, April 11, 1985 3:21:48 pm PST Last Edited by: Kimr, October 29, 1984 9:49:48 am PST --handling colors -- used to identify tiles without toner so that you can avoid recording them --gives a key to get the keys to get the color stipple as property of the layers --device description --gives a key to get the color stipple as property of the layers --state of the plot rectangles in design space touching all geometry in the plot, or this band -- scale factor between systems, is negative for y-axis due to reversed direction of increasing values (when compared with pixel coordinates) --Center the x range of the selected area of the design on the plotter bed, with at most maxPixPerLambda pixels per lambda. If multiple strips are called for, overlap adjacent ones by "overLap" pixels. -- total number of pixels across plot = REAL[scanLineWidth]+REAL[scanLineWidth-overLap]*(strips-1)) -- Determine clip rectangle for strip -- For each band in the strip -- Determine coordinate transformations -- (negative scale to account for CD increasing y north, PD increasing y going south) -- rectangle in design space that ChipNDale can use to clip its recursive drawing --Display current band under consideration to pacify user -- clear previous tessalations --tries to convert pattern to a texture stipple --makes the load if it does not already exist --SetColor --lower left x, lower right x, lower y, upper left x, upper right x, upper y --global variables ps, xoffset, yoffset, plotScale, imageFSize, imageSSize, pdy --x-Fast --y-Slow --PlotPolygon CornerStitching.PerTileProc -- Calculate absolute coords of rectangle here as offset from plot origin -- if rectangle is in band area, clip and write; otherwise disregard rectangle -- clip on imageSSize ÊĘšœ™J™Jšœ Ïmœ7™BJšœ1™1Jšœ5™5J™2J™6J™6—J˜šÏk ˜ Jšžœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšžœ˜J˜ J˜ Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ J˜—šÏb œžœž˜Jšžœžœ1Ïcœ{žœ+˜ä—Jšž˜J˜JšŸ™J˜Jšœžœ "˜EJš œ žœžœžœžœ˜%Jšœ žœžœžœ˜Jšœ %˜;Jšœžœ˜Jšœžœ˜Jšœ˜Jšœ'˜'Jšžœ˜—J˜š¡œžœ˜Jšž˜Jšœ˜Jšœ  /˜˜>J™Nšžœžœ˜ Jšœžœ˜Jšœž˜Jšœžœ˜ Jšœžœ˜!Jšœžœ˜Jšœžœ˜Jšœžœ˜'Jšœžœ˜Jšœžœ ˜J˜J˜J™Jšžœžœ%˜=šžœ žœ žœ˜šœ0˜0J˜2J˜——J˜—Jšœ˜—Jšžœ˜J˜—š¡ œžœžœžœžœžœžœ˜6Jš žœžœžœžœž˜%Jšžœžœ˜ Jšœ˜—J™š¡œžœ˜3Jšžœ˜Jšœ&˜&JšœU˜UJšžœ˜J˜—š¡œžœ˜JšœX˜XJšœV˜VJšœV˜VJšœI˜IJšœ@˜@JšœI˜IJšœ>˜>J˜J˜—Jšœ˜Jšžœ˜J˜J˜—…—<¾Xp