CDInterpressPlotImpl.mesa
Copyright © 1984, 1986, 1987 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi
Last edited by: Christian Jacobi, March 16, 1987 11:44:33 am PST
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𡤁] RETURNS [INT𡤀] = {
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[BOOLFALSE];
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: BOOLFALSE;
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: BOOLFALSE] = {
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;
--1l -> 1 point
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: BOOLFALSE;
striped: BOOLFALSE;
multiPaged: BOOLFALSE;
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.