CDPlotIPImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Last Edited by: Jacobi, July 12, 1985 8:50:32 am PST
Last Edited by: Jacobi, October 16, 1985 11:18:36 am PDT
Last Edited by: Curry, March 27, 1986 6:57:17 pm PST
DIRECTORY
CD, CDBasics, CDCommandOps, CDIO, CDMenus, CDOps, CDPlot, CDProperties, CDSequencer, CDTexts, FS, Imager, ImagerInterpress, IO, PeachPrint, Process, Real, RefTab, Rope, SymTab, TerminalIO;
CDPlotIPImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCommandOps, CDIO, CDMenus, CDOps, CDProperties, CDSequencer, CDTexts, FS, Imager, ImagerInterpress, IO, PeachPrint, Process, Real, RefTab, Rope, SymTab, TerminalIO =
BEGIN
Constants
defaultBorder: REAL = Imager.metersPerInch;
versatecColor42X: REAL = 0.97; -- 42" Color plotter model ECP 42 / serial #110
Globals
abortFlag: REF BOOL = NEW[BOOL←FALSE];
contextColors: REF CD.ContextColors = NEW[CD.ContextColors←ALL[Imager.black]];
contextNormal: BOOL ← FALSE;
fontTab: SymTab.Ref;
wDir: Rope.ROPE;
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]]};
ResetContextFilter:
PROC [ignoreProperties:
BOOL ←
TRUE] = {
contextNormal ← ignoreProperties;
FOR layer:
CD.Layer
IN
CD.Layer
DO
contextColors[layer] ← IF ignoreProperties THEN Imager.black ELSE NIL;
CDProperties.PutLayerProp[layer, $CDxInterpressPlot, NIL];
ENDLOOP;
contextColors[CD.backgroundLayer] ← NIL};
SetUpContextFilter:
PROC [] = {
contextNormal ← FALSE;
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] = {
IF comm.data =
NIL
THEN TerminalIO.WriteRope["HardCopy\n"]
ELSE TerminalIO.WriteRope["Non interactive hardcopy\n"];
abortFlag^ ← FALSE;
[] ← CDCommandOps.CallWithResource[
proc: ProtectedHardCopy,
comm: comm,
resource: $CDSimplePlotImpl,
abortFlag: abortFlag ]};
DrawOutLine:
PUBLIC PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] =
BEGIN
ActionWithContext:
PROC [] =
BEGIN
Imager.SetColor[pr.deviceContext, pr.contextColors[l]];
Imager.MaskVector[pr.deviceContext, [r.x1, r.y1], [r.x2, r.y1]];
Imager.MaskVector[pr.deviceContext, [r.x2, r.y1], [r.x2, r.y2]];
Imager.MaskVector[pr.deviceContext, [r.x2, r.y2], [r.x1, r.y2]];
Imager.MaskVector[pr.deviceContext, [r.x1, r.y2], [r.x1, r.y1]];
END;
IF pr.deviceContext#
NIL
THEN {
IF pr.contextColors[l]#NIL THEN Imager.DoSave[pr.deviceContext, ActionWithContext]
}
END;
ProtectedHardCopy:
PROC [comm: CDSequencer.Command] =
{ -- not re-entrant: uses globals
InteractiveSetUp:
PROC [seqCom: CDSequencer.Command]
RETURNS [rec: REF CDPlot.IPControlRec] = {
rec ← NEW[CDPlot.IPControlRec ← [ ]];
rec.scale ← Imager.metersPerPoint/seqCom.design.technology.lambda; -- init as fixed
DialogFontSubstitute [rec];
DialogClipRect [rec, seqCom];
DialogMedium [rec];
SELECT rec.type
FROM
stripe => DialogStripedScaling [rec];
fixed => DialogFixedScaling [rec];
ENDCASE => DialogVariableScaling [rec];
TerminalIO.WriteF[" printing %01g rows and %01g columns\n",
IO.int[rec.pageNumX], IO.int[rec.pageNumY]] };
DialogFontSubstitute:
PROC[rec:
REF CDPlot.IPControlRec] = {
SELECT TerminalIO.RequestSelection["substitute fonts ?",
LIST
["no substitution", "standard substitution file", "user substitution file"]] FROM
2 => {
rec.altFonts ← TRUE;
rec.altFontsFile ← NIL;
TerminalIO.WriteRope["use standard font substitution file\n"]};
3 => {
rec.altFonts ← TRUE;
rec.altFontsFile ← TerminalIO.RequestRope
["fullpath name for font substitution file > "]};
ENDCASE => {
rec.altFonts ← FALSE;
rec.altFontsFile ← NIL;
TerminalIO.WriteRope["don't substitute fonts\n"]} };
DialogClipRect:
PROC [rec:
REF CDPlot.IPControlRec, seqCom: CDSequencer.Command] = {
n:
INT ← TerminalIO.RequestSelection[label: "plot area",
choice: LIST["complete design", "area of selection", "drawn rectangle"] ];
SELECT n
FROM
3 => {
TerminalIO.WriteRope["plot rectangular area drawn\n"];
rec.clip ← CDBasics.ToRect[seqCom.pos, seqCom.sPos] };
2 => {
TerminalIO.WriteRope["plot area of selection\n"];
rec.clip ← CDCommandOps.BoundingBox[design: seqCom.design, onlySelected: TRUE] };
ENDCASE => {
TerminalIO.WriteRope["plot complete design\n"];
rec.clip ← CDCommandOps.BoundingBox[design: seqCom.design, onlySelected: FALSE] };
IF ~CDBasics.NonEmpty[rec.clip]
THEN {
TerminalIO.WriteRope["rec.clip rectangle is empty\n"];
ERROR ABORTED} };
DialogMedium:
PROC[rec:
REF CDPlot.IPControlRec]
= {
SELECT TerminalIO.RequestSelection["Plot",
LIST
["standard page and scale", "fill standard page", "fill versatec stripe", "fill c400 page", "other"]]
FROM
1 => {rec.type ← fixed; TerminalIO.WriteRope["standard page and scale\n"] };
3 => {rec.type ← stripe; TerminalIO.WriteRope["fill versatec stripe\n"] };
4 => {rec.pageX ← CDPlot.c400PageX; rec.pageY ← CDPlot.c400PageY;
TerminalIO.WriteRope["fill c400 page\n"] };
5 => {
TerminalIO.WriteRope["special:\n"];
rec.special ← TRUE;
SELECT TerminalIO.RequestSelection["Plot",
LIST
["fill standard pages", "fill versatec stripes", "standard scale standard pages", "fill c400 pages", "standard scale c400 pages"]]
FROM
1 => {rec.type ← variable; TerminalIO.WriteRope["fill standard pages\n"] };
2 => {rec.type ← stripe; TerminalIO.WriteRope["fill versatec stripes\n"] };
3 => {rec.type ← fixed; TerminalIO.WriteRope["standard scale standard pages\n"] };
4 => {
rec.pageX ← CDPlot.c400PageX;
rec.pageY ← CDPlot.c400PageY;
TerminalIO.WriteRope["standard scale standard pages\n"] };
5 => {
rec.pageX ← CDPlot.c400PageX;
rec.pageY ← CDPlot.c400PageY;
rec.type ← fixed;
TerminalIO.WriteRope["standard scale standard pages\n"] };
ENDCASE => ERROR ABORTED };
ENDCASE => {rec.type ← variable; TerminalIO.WriteRope["fill standard page\n"]} };
DialogStripedScaling:
PROC[rec:
REF CDPlot.IPControlRec] = {
IF rec.special
AND TerminalIO.Confirm["multiple stripes ?"]
THEN {
rec.pageNumX ← TerminalIO.RequestInt["How many stripes? >"];
IF rec.pageNumX
NOT
IN [1..20]
THEN {TerminalIO.WriteRope[" to bad\n"]; ERROR ABORTED} }
ELSE rec.pageNumX ← 1;
rec.borders ← no;
help ← IO.PutFR["%g versatec; PeachPrint Sleepy %g\n",
IO.rope[help], IO.rope[PeachPrint.FileName[long, secondary, 1, ".pd"]]] };
DialogFixedScaling:
PROC[rec:
REF CDPlot.IPControlRec] = {
DialogBorder[rec, IPRoomForBorders[rec]];
help ← IO.PutFR["%g raven384; TSetter Stinger %g\n",
IO.rope[help], IO.rope[PeachPrint.FileName[long, secondary, 1, ".pd"]]] };
Dialog
VariableScaling:
PROC[rec:
REF CDPlot.IPControlRec] = {
dontAdj: BOOL ← FALSE;
rec.specialMults ← rec.special AND TerminalIO.Confirm["multiple pages ?"];
IF rec.specialMults
THEN {
rec.pageNumX ← TerminalIO.RequestInt["Number of pages in x direction? >"];
IF rec.pageNumX
NOT
IN [1..20]
THEN {TerminalIO.WriteRope[" to bad\n"]; ERROR ABORTED} };
DialogBorder[rec, NOT rec.specialMults];
help ← IO.PutFR["%g raven384; TSetter Stinger %g\n",
IO.rope[help], IO.rope[PeachPrint.FileName[long, secondary, 1, ".pd"]]] };
DialogBorder:
PROC [rec:
REF CDPlot.IPControlRec, anyWay:
BOOL ←
FALSE]
= {
rec.borders ←
IF (anyWay
AND ~rec.special)
THEN no
ELSE
SELECT TerminalIO.RequestSelection[label: "border", choice:
LIST
["yes", "fill space", "never"]]
FROM
2 => no,
3 => mosaic,
ENDCASE => yes };
PreAmble:
PROC [ref: ImagerInterpress.Ref, contextColors:
REF
CD.ContextColors] = {
declared: RefTab.Ref ← RefTab.Create[];
FOR layer:
CD.Layer
IN
CD.Layer
DO
IF contextColors[layer]#NIL
THEN
IF RefTab.Insert[declared, contextColors[layer], contextColors[layer]]
THEN
ImagerInterpress.DeclareColor[ref, contextColors[layer]]
ENDLOOP;
declared ← NIL};
PlotPage:
PROC [context: Imager.Context] = {
-- the real stuff
dr: CD.DrawRef;
r: CD.Rect ← CDBasics.RectAt[start, ipc.sizePerPage];
r ← CDBasics.Intersection [r, ipc.clip];
IF ~ CDBasics.NonEmpty [r] THEN RETURN;
Process.CheckForAbort[! ABORTED => {abortFlag^ ← TRUE; CONTINUE}];
IF abortFlag^ THEN RETURN;
Imager.TranslateT [context, ipc.transPos];
Imager.ScaleT [context, ipc.scale];
Imager.TranslateT [context, [-r.x1, -r.y1]];
Imager.ClipRectangle [context, RectToRectangle[r]];
dr ←
CD.CreateDrawRef[[
design: comm.design,
stopFlag: abortFlag,
drawOutLine: DrawOutLine,
contextColors: contextColors,
borders: TRUE,
interestClip: r,
deviceContext: context
]];
IF ipc.altFonts
THEN {
dr.specialFonts ← TRUE;
CDProperties.PutProp[dr.properties, $FontExchange, fontReplace] };
CDOps.DrawDesign[comm.design, dr]};
fileName: Rope.ROPE ← PeachPrint.FileName[long, primary,1, ".ip"];
help: Rope.ROPE;
start: CD.Position;
ref: ImagerInterpress.Ref;
ipc: REF CDPlot.IPControlRec ← NARROW[comm.data];
help ←
IO.PutFR[" Example usage:\n InterpressToPD %g ← %g ",
IO.rope[PeachPrint.FileName[long, secondary, 1, ".pd"]],
IO.rope[fileName]];
IF ~contextNormal
THEN
{TerminalIO.WriteRope["** SPECIAL COLORS\n"]; SetUpContextFilter[] };
IF ipc=
NIL
THEN ipc ← InteractiveSetUp[comm]
ELSE ipc.scale ← Imager.metersPerPoint/comm.design.technology.lambda; -- init fixed scale
IPBorders[ipc];
SELECT ipc.type
FROM
stripe => IPSetUpStripedScaling [ipc];
fixed => IPSetUpFixedScaling [ipc];
ENDCASE => IPSetUpVariableScaling [ipc];
IF ipc.borders#mosaic THEN IPAdjustTransPos[ipc];
fontTab ← IF ipc.altFonts THEN InitFontTab[ipc.altFontsFile] ELSE NIL;
ref ← ImagerInterpress.Create[fileName];
PreAmble[ref, contextColors];
FOR nX:
INT
IN [0..ipc.pageNumX)
DO
FOR nY:
INT
IN [0..ipc.pageNumY)
DO
IF abortFlag^ THEN EXIT;
start.x ← ipc.clip.x1+nX*ipc.sizePerPage.x;
start.y ← ipc.clip.y1+nY*ipc.sizePerPage.y;
ImagerInterpress.DoPage[ref, PlotPage];
ENDLOOP;
ENDLOOP;
ImagerInterpress.Close[ref];
TerminalIO.WriteF1[" ""%01g"" created\n", IO.rope[fileName]];
IF ~Rope.IsEmpty[help] THEN TerminalIO.WriteRope[help];
IF ~abortFlag^ THEN TerminalIO.WriteRope[" done\n"] };
-- Scaling procedures
IPRoomForBorders:
PROC[ipc:
REF CDPlot.IPControlRec]
RETURNS[
BOOL] = {
RETURN[
( (ipc.clip.x2-ipc.clip.x1) *ipc.scale < (ipc.pageX - 0.05) ) AND
( (ipc.clip.y2-ipc.clip.y1) *ipc.scale < (ipc.pageY - 0.05) )] };
IPBorders:
PROC[ipc:
REF CDPlot.IPControlRec] =
{IF ipc.borders=yes THEN ipc.transPos.y ← ipc.transPos.x ← defaultBorder};
IPSetUp
StripedScaling:
PROC[ipc:
REF CDPlot.IPControlRec] = {
ipc.pageX ← versatecColor42X;
ipc.pageNumY ← 1;
ipc.transPos.x ← 0;
ipc.transPos.y ← defaultBorder;
ipc.sizePerPage.x ← (ipc.clip.x2-ipc.clip.x1)/ipc.pageNumX;
ipc.sizePerPage.y ← ipc.clip.y2-ipc.clip.y1;
ipc.scale ← ipc.pageX/ipc.sizePerPage.x;
ipc.pageY ← ipc.scale*ipc.sizePerPage.y+2*ipc.transPos.y };
IPSetUpFixedScaling:
PROC[ipc:
REF CDPlot.IPControlRec] = {
ipc.scale ← ipc.scale;
ipc.sizePerPage.x ← Real.Round[(ipc.pageX-2*ipc.transPos.x)/ipc.scale];
ipc.sizePerPage.y ← Real.Round[(ipc.pageY-2*ipc.transPos.y)/ipc.scale];
ipc.pageNumX ← (ipc.clip.x2-ipc.clip.x1+ipc.sizePerPage.x-1)/ipc.sizePerPage.x;
ipc.pageNumY ← (ipc.clip.y2-ipc.clip.y1+ipc.sizePerPage.y-1)/ipc.sizePerPage.y };
IPSetUpVariableScaling:
PROC[ipc:
REF CDPlot.IPControlRec] = {
insidePageX: REAL ← ipc.pageX-2*ipc.transPos.x; --what fits in a page without border
insidePageY: REAL ← ipc.pageY-2*ipc.transPos.y; --what fits in a page without border
IF ipc.specialMults
THEN { --multiple pages
ipc.sizePerPage.x ← (ipc.clip.x2-ipc.clip.x1)/ipc.pageNumX+1;
ipc.sizePerPage.y ← Real.Fix[insidePageY*((ipc.sizePerPage.x-1.0)/insidePageX)];
ipc.scale ← insidePageX/ipc.sizePerPage.x;
ipc.pageNumY ← ( (ipc.clip.y2-ipc.clip.y1)+(ipc.sizePerPage.y-1) )/ipc.sizePerPage.y }
ELSE { --single page
ipc.pageNumX ← 1;
ipc.pageNumY ← 1;
ipc.sizePerPage ← CDBasics.SizeOfRect[ipc.clip];
ipc.scale ← MIN[insidePageX/ipc.sizePerPage.x, insidePageY/ipc.sizePerPage.y]}};
IPAdjustTransPos:
PROC [ipc:
REF CDPlot.IPControlRec] = {
IF ipc.type=stripe
OR ipc.pageNumX=1
THEN {
ipc.transPos.x ← MIN[(ipc.pageX - (ipc.clip.x2-ipc.clip.x1)*ipc.scale)/2, defaultBorder] };
IF ipc.pageNumY=1
THEN {
pictureHeight: REAL ← (ipc.clip.y2-ipc.clip.y1)*ipc.scale;
ipc.transPos.y ← MAX[ipc.pageY-defaultBorder-pictureHeight, (ipc.pageY-pictureHeight)/2]} };
-- Font replacement stuff
fontReplace:
REF
PROC [CDTexts.CDFont]
RETURNS [CDTexts.CDFont]
← NEW[PROC [CDTexts.CDFont] RETURNS [CDTexts.CDFont] ← FontReplace];
FontReplace:
PROC [cdFont: CDTexts.CDFont]
RETURNS [CDTexts.CDFont] = {
newFont: CDTexts.CDFont ← NIL;
fontKey: Rope.ROPE ← FontKeyRope[cdFont.supposedName, cdFont.scaleI];
WITH SymTab.Fetch[fontTab, fontKey].val
SELECT
FROM
f: CDTexts.CDFont => RETURN [f];
f: REF CDTexts.FontRec => RETURN [f];
ENDCASE => NULL;
WITH SymTab.Fetch[fontTab, cdFont.supposedName].val
SELECT
FROM
l:
LIST
OF
REF
ANY => {
IF l.first#
NIL
AND l.rest#
NIL
AND l.rest.rest=
NIL
THEN {
scale: INT ← 0;
name: Rope.ROPE ← CDCommandOps.ToRope[l.first];
WITH l.rest.first
SELECT
FROM
ri: REF INT => scale ← ri^*cdFont.scaleI
ENDCASE => NULL;
IF scale>0
AND ~Rope.IsEmpty[name]
THEN {
newFont ← CDTexts.MakeFont[name, scale];
IF newFont#
NIL
THEN {
x: REF CDTexts.FontRec;
TRUSTED {x ← LOOPHOLE[newFont]};
[] ← SymTab.Store[fontTab, fontKey, x] } } } };
f: CDTexts.CDFont => newFont ← f;
f: REF CDTexts.FontRec => newFont ← f;
ENDCASE => NULL;
IF newFont=NIL THEN newFontont;
RETURN [newFont] };
FontKeyRope:
PROC[name: Rope.
ROPE, scale:
INT]
RETURNS[key: Rope.
ROPE] =
{RETURN[ IO.PutFR["%g-%g", IO.rope[name], IO.int[scale] ]]};
InitFontTab:
PROC [fileName: Rope.
ROPE←
NIL]
RETURNS [fontTab: SymTab.Ref] = {
OneLine:
PROC [line: Rope.
ROPE] = {
stream: IO.STREAM ←IO.RIS[line];
scale: INT;
subst, by: Rope.ROPE;
subst ← IO.GetRopeLiteral[stream];
by ← IO.GetRopeLiteral[stream];
scale ← IO.GetInt[stream];
[] ← fontTab.Store[subst, LIST[by, NEW[INT←scale]]] };
file: IO.STREAM ← NIL;
fontTab ← SymTab.Create[];
IF Rope.IsEmpty[fileName] THEN fileName ← "CDSubstituteFonts";
fileName ← CDIO.MakeName[base: fileName, ext: "SubstituteFonts", wDir: wDir];
file ←
FS.StreamOpen[fileName !
FS.Error => {
TerminalIO.WriteRopes["no font substitution: ", error.explanation, "\n"];
GOTO thatsIt }];
DO
line: Rope.ROPE;
line ← IO.GetLineRope[file ! IO.EndOfStream => GOTO thatsIt];
IF ~Rope.IsEmpty[line]
THEN
OneLine[line !
IO.EndOfStream => GOTO thatsIt;
IO.Error => {
TerminalIO.WriteRopes["**error reading font substitution: ", line, "\n"];
CONTINUE } ];
ENDLOOP;
EXITS thatsIt => NULL };
-- Init
Init:
PROC = {
OPEN CDS: CDSequencer;
wDir ← FileNames.CurrentWorkingDirectory[];
wDir ← CDIO.GetWorkingDirectory[NIL];
ResetContextFilter[ignoreProperties: TRUE];
CDS.ImplementCommand[key: $IPAutoPlot, proc: HardCopyCommand, queue: dontQueue];
CDS.ImplementCommand[key: $InterpressPlot, proc: HardCopyCommand, queue: doQueue];
CDMenus.CreateEntry[menu: $HardCopyMenu, entry: "B&W interpress", key: $InterpressPlot];
TerminalIO.WriteRope["BW Interpress plot loaded.\n"] };
Init[];
END.