SlateIOImpl.mesa
Copyright Ó 1992, 1993 by Xerox Corporation. All rights reserved.
Weiser, August 8, 1992 5:07 pm PDT
Christian Jacobi, June 14, 1993 2:52 pm PDT
DIRECTORY
CommanderOps,
Imager,
ImagerColor,
ImagerBitmapContext,
ImagerColorMap,
ImagerDitherContext,
ImagerInterpress,
ImagerPixel,
ImagerSample,
InterpressInterpreter,
IPMaster,
IPInterpreter,
IO,
PFS,
Rope,
SF,
SlateIO,
SlatePrivateTypes,
Slate,
ThisMachine,
X11PopUpSelection,
XlBitmap,
XlBitmapExtras;
SlateIOImpl: CEDAR MONITOR
IMPORTS CommanderOps, Imager, ImagerBitmapContext, ImagerDitherContext, ImagerInterpress, ImagerPixel, ImagerSample, InterpressInterpreter, IPMaster, IPInterpreter, IO, PFS, Rope, SlatePrivateTypes, Slate, ThisMachine, X11PopUpSelection, XlBitmap, XlBitmapExtras
EXPORTS SlateIO =
BEGIN OPEN Slate, SlateIO;
metersPerPixel: REAL = 0.0254/72.0;
WritePSFile: PUBLIC PROC [pages: LIST OF Page, fileName: Rope.ROPE, trans: Imager.Transformation, log: IO.STREAM, server: REF, overwrite: OverWriteMode] = {
out: Rope.ROPE;
tmpName: Rope.ROPE = Rope.Concat[fileName, ".temp.ip"];
WriteIPFile[pages, tmpName, trans, log, NIL, overwrite];
[out, ] ¬ CommanderOps.DoCommandRope[
commandLine: IO.PutFR["IPToPS %g ← %g; Delete %g\n", IO.rope[fileName], IO.rope[tmpName], IO.rope[tmpName]],
parent: NIL];
IO.PutRope[log, out];
};
WriteIPFile: PUBLIC PROC [pages: LIST OF Page ¬ NIL, fileName: Rope.ROPE, trans: Imager.Transformation, log: IO.STREAM, server: REF ¬ NIL, overwrite: OverWriteMode] = {
<<no usage of d.context>>
path: PFS.PATH; bytes: INT ¬ 0;
uniqueID: PFS.UniqueID ¬ PFS.nullUniqueID;
stream: IO.STREAM;
path ¬ PFS.PathFromRope[fileName !
PFS.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]]; GOTO Oops
}
];
[uniqueID: uniqueID, bytes: bytes] ¬ PFS.FileInfo[name: path !
PFS.Error => {
uniqueID ¬ PFS.nullUniqueID;
CONTINUE;
}
];
IF (uniqueID#PFS.nullUniqueID OR bytes>0) THEN {
SELECT overwrite FROM
always => {};
never => {
IO.PutRope[log, "existing file not overwritten\n"]; GOTO Oops
};
interactive => {
x: INT;
x ¬ X11PopUpSelection.Request[header: "file exists", choice: LIST["overwrite", "abort"], connection: server];
IF x#1 THEN {
IO.PutRope[log, "existing file not overwritten\n"]; GOTO Oops
};
};
ENDCASE => ERROR;
};
stream ¬ PFS.StreamOpen[fileName: path, accessOptions: create, wantedUniqueID: uniqueID !
PFS.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]]; GOTO Oops
}
];
IPPutPages[stream, pages, trans ! Imager.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]]; IO.Close[stream, TRUE];
GOTO Oops;
}];
IO.Close[stream];
IO.PutF1[log, "written to: %g\n", IO.rope[fileName]];
EXITS Oops => {};
};
WriteSlateFile: PUBLIC PROC [pages: LIST OF Page ¬ NIL, fileName: Rope.ROPE, log: IO.STREAM, server: REF ¬ NIL, overwrite: OverWriteMode] = {
<<no usage of d.context>>
path: PFS.PATH; bytes: INT ¬ 0;
uniqueID: PFS.UniqueID ¬ PFS.nullUniqueID;
stream: IO.STREAM;
path ¬ PFS.PathFromRope[fileName !
PFS.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]];
GOTO Oops
}
];
[uniqueID: uniqueID, bytes: bytes] ¬ PFS.FileInfo[name: path !
PFS.Error => {
uniqueID ¬ PFS.nullUniqueID;
CONTINUE;
}
];
IF (uniqueID#PFS.nullUniqueID OR bytes>0) THEN {
SELECT overwrite FROM
always => {};
never => {
IO.PutRope[log, "existing file not overwritten\n"]; GOTO Oops
};
interactive => {
x: INT;
x ¬ X11PopUpSelection.Request[header: "file exists", choice: LIST["overwrite", "abort"], connection: server];
IF x#1 THEN {
IO.PutRope[log, "existing file not overwritten\n"]; GOTO Oops
};
};
ENDCASE => ERROR;
};
stream ¬ PFS.StreamOpen[fileName: path, accessOptions: create, wantedUniqueID: uniqueID !
PFS.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]]; GOTO Oops
}
];
IO.PutRope[stream, "Slate 1\n"];
FOR l: LIST OF Page ¬ pages, l.rest WHILE l#NIL DO
page: Page ¬ l.first;
IF page#NIL THEN {
rosStream: IO.STREAM ¬ IO.ROS[];
rosRope: Rope.ROPE;
sm: ImagerSample.RasterSampleMap ¬ XlBitmap.GetSM[page.activeArea];
sz: SF.Vec ¬ ImagerSample.GetSize[sm];
bpp: INT ¬ ImagerSample.GetBitsPerSample[sm];
IO.PutF[stream, "Page %g %g %g\n", IO.int[sz.f], IO.int[sz.s], IO.int[bpp]];
IPPutPages[rosStream, LIST[page], NIL ! Imager.Error => {
IO.PutF1[log, "write failed: %g\n", IO.rope[error.explanation]]; IO.Close[stream, TRUE];
GOTO Oops;
}];
rosRope ¬ IO.RopeFromROS[rosStream, TRUE];
IO.PutF1[stream, " %g\n", IO.int[Rope.Length[rosRope]]];
IO.PutRope[stream, "unnamed\n"];
IO.PutRope[stream, rosRope];
};
ENDLOOP;
IO.PutRope[stream, "End\n"];
IO.Close[stream];
IO.PutF[log, "written to: (%g) %g\n", IO.rope[ThisMachine.Name[]], IO.rope[fileName]];
EXITS Oops => {};
};
IPPutPages: PROC [stream: IO.STREAM, pages: LIST OF Page, trans: Imager.Transformation ¬ NIL] = {
--May raise Imager.Error
fileRef: ImagerInterpress.Ref;
fileRef ¬ ImagerInterpress.CreateFromStream[stream: stream, header: "Interpress/Xerox/3.0 "];
FOR l: LIST OF Page ¬ pages, l.rest WHILE l#NIL DO
page: Page ~ l.first;
EachPage: PROC [ctx: Imager.Context] = {
sm: ImagerSample.RasterSampleMap ¬ XlBitmap.GetSM[page.activeArea];
bpp: INT ¬ ImagerSample.GetBitsPerSample[sm];
IF trans#NIL THEN Imager.ConcatT[ctx, trans];
Imager.ScaleT[ctx, metersPerPixel];
Imager.SetColor[ctx, Imager.black];
Imager.TranslateT[ctx, [0, ImagerSample.GetSize[sm].s]];
IF bpp>1
THEN {
mapEntries: ImagerColorMap.MapEntries ¬ NARROW[XlBitmapExtras.GetColormap[page.activeArea]];
colorOperator: ImagerColor.ColorOperator ¬ ImagerDitherContext.NewColorOperatorDither[bpp: bpp, mapEntries: mapEntries];
pixelMap: ImagerPixel.PixelMap ¬ ImagerPixel.MakePixelMap[sm];
Imager.DrawPixels[context: ctx, pixelMap: pixelMap, colorOperator: colorOperator]
}
ELSE {
Imager.MaskBitmap[context: ctx, bitmap: sm];
};
};
IF page#NIL THEN ImagerInterpress.DoPage[self: fileRef, action: EachPage];
ENDLOOP;
ImagerInterpress.Finish[fileRef];
};
ReadSlateFile: PUBLIC PROC [session: Session, fileName: Rope.ROPE, log: IO.STREAM, mapEntries: REF ANY ¬ NIL] = {
firstPage: Page ¬ NIL;
Inner: PROC [] = {
Log: InterpressInterpreter.LogProc = {
IF class<10 THEN IO.PutF1[log, "%g\n", IO.rope[explanation]];
};
line, ipRope: Rope.ROPE; stream: IO.STREAM;
somePage: Page ¬ NIL;
m: InterpressInterpreter.Master;
IO.PutF1[log, "read from: %g\n", IO.rope[fileName]];
stream ¬ PFS.StreamOpen[PFS.PathFromRope[fileName], read !
PFS.Error => ERROR ReadFailed[Rope.Concat[error.explanation, "\n"]]
];
line ¬ IO.GetLineRope[stream];
IF ~Rope.Match["Slate *", line] THEN {
IO.Close[stream]; ERROR ReadFailed["Not a slate file\n"];
};
line ¬ IO.GetLineRope[stream];
DO
lineStream: IO.STREAM; ipLength: INT; bpp: INT; pageSize: SF.Vec;
pageName, lengthLine: Rope.ROPE;
IF Rope.Match["End*", line] THEN EXIT;
IF ~Rope.Match["Page*", line] THEN {
IO.Close[stream]; ERROR ReadFailed["Not a slate file\n"];
};
lineStream ¬ IO.RIS[Rope.Substr[line, 5]];
pageSize.f ¬ IO.GetInt[lineStream];
pageSize.s ¬ IO.GetInt[lineStream];
bpp ¬ IO.GetInt[lineStream];
lengthLine ¬ IO.GetLineRope[stream];
lineStream ¬ IO.RIS[lengthLine];
ipLength ¬ IO.GetInt[lineStream];
pageName ¬ IO.GetLineRope[stream];
ipRope ¬ IO.GetRope[stream, ipLength];
m ¬ InterpressInterpreter.FromRope[ipRope, Log];
somePage ¬ FromMaster[m, pageSize, bpp, mapEntries, Log, session];
IF firstPage=NIL THEN firstPage ¬ somePage;
line ¬ IO.GetLineRope[stream];
ENDLOOP;
IO.Close[stream];
};
WithBackStop[Inner, log];
IF firstPage#NIL THEN Slate.ActivatePage[firstPage];
};
ReadIPFile: PUBLIC PROC [session: Session, fileName: Rope.ROPE, log: IO.STREAM, pageSize: SF.Vec, bpp: INT, mapEntries: REF ANY ¬ NIL] = {
firstPage: Page ¬ NIL;
Inner: PROC [] = {
Log: InterpressInterpreter.LogProc = {
IF class<10 THEN IO.PutF1[log, "%g\n", IO.rope[explanation]];
};
m: InterpressInterpreter.Master;
IF pageSize.s<=0 OR pageSize.f<=0 THEN pageSize ¬ SlatePrivateTypes.defaultPageSize;
IF bpp<=0 THEN bpp ¬ 1;
IO.PutF1[log, "read from: %g\n", IO.rope[fileName]];
m ¬ InterpressInterpreter.Open[fileName, Log];
firstPage ¬ FromMaster[m, pageSize, bpp, mapEntries, Log, session];
};
WithBackStop[Inner, log];
IF firstPage#NIL THEN Slate.ActivatePage[firstPage];
};
ReadFailed: ERROR [msg: Rope.ROPE] = CODE;
WithBackStop: PROC [proc: PROC, log: IO.STREAM] = {
Urtility providing a backstop for read operations
ENABLE {
PFS.Error => {
IO.PutF1[log, "read failed: %g\n", IO.rope[error.explanation]]; GOTO Oops
};
Imager.Error => {
IO.PutF1[log, "read failed: %g\n", IO.rope[error.explanation]]; GOTO Oops
};
IPMaster.Error => {
IO.PutF1[log, "read failed (IPMaster.Error): %g\n", IO.rope[error.explanation]]; GOTO Oops
};
IPInterpreter.Error => {
IO.PutF1[log, "read failed (IPInterpreter.Error): %g\n", IO.rope[explanation]]; GOTO Oops
};
IO.Error => {
IO.PutF1[log, "read failed (IO.Error): %g\n", IO.rope[msg]]; GOTO Oops
};
ReadFailed => {
IO.PutF1[log, "read failed : %g\n", IO.rope[msg]]; GOTO Oops
};
};
proc[];
EXITS Oops => {};
};
FromMaster: PROC [m: InterpressInterpreter.Master, pageSize: SF.Vec, bpp: INT, mapEntries: REF ANY ¬ NIL, logProc: InterpressInterpreter.LogProc, session: Slate.Session] RETURNS [firstPage: Slate.Page ¬ NIL] = {
IF m#NIL THEN {
FOR i: INT IN [1..m.pages] DO
thisPage: Slate.Page ¬ NIL; context: Imager.Context; sm: ImagerSample.RasterSampleMap;
sm ¬ ImagerSample.NewSampleMap[[min: [0, 0], max: pageSize], bpp];
IF bpp>1 AND mapEntries#NIL
THEN {
context ¬ ImagerDitherContext.Create[deviceSpaceSize: pageSize, scanMode: [slow: down, fast: right], surfaceUnitsPerInch: [72, 72], pixelUnits: TRUE];
ImagerDitherContext.SetSampleMap[context: context, sampleMap: sm];
IF mapEntries#NIL THEN
ImagerDitherContext.SetDitherMap[context: context, mapEntries: NARROW[mapEntries]];
}
ELSE {
context ¬ ImagerBitmapContext.Create[deviceSpaceSize: pageSize, scanMode: [slow: down, fast: right], surfaceUnitsPerInch: [72, 72], pixelUnits: TRUE, fontCacheName: $Bitmap];
ImagerBitmapContext.SetBitmap[context: context, bitmap: sm];
};
Imager.SetColor[context, Imager.black];
Imager.ScaleT[context, 1.0/metersPerPixel];
InterpressInterpreter.DoPage[m, i, context, logProc];
thisPage ¬ NewPage[session, pageSize, sm, NIL, bpp];
IF firstPage=NIL THEN firstPage ¬ thisPage;
ENDLOOP;
InterpressInterpreter.Close[m];
};
};
IPPrint: PUBLIC PROC [pages: LIST OF Page, printerName: Rope.ROPE, trans: Imager.Transformation, log: IO.STREAM, server: REF ¬ NIL] = {
out: Rope.ROPE; result: REF ANY;
fileName: Rope.ROPE ¬ IO.PutFR1["/tmp/SlatePrintFile.%0g.ip", IO.card[Counter[]]];
WriteIPFile[pages, fileName, trans, log, server, always];
[out, result] ¬ CommanderOps.DoCommandRope[
commandLine: IO.PutFR["SendIPMaster %g -h %g; delete %g\n", IO.rope[fileName], IO.rope[printerName], IO.rope[fileName]],
parent: NIL
];
IO.PutRope[log, out];
};
PSPrint: PUBLIC PROC [pages: LIST OF Page, printerName: Rope.ROPE, trans: Imager.Transformation, log: IO.STREAM, server: REF ¬ NIL] = {
result: REF ¬ NIL; out: Rope.ROPE ¬ NIL;
fileName: Rope.ROPE ¬ IO.PutFR1["/tmp/SlatePrintFile.%0g.ps", IO.card[Counter[]]];
WritePSFile[pages, fileName, trans, log, server, OverWriteMode.always];
[out, result] ¬ CommanderOps.DoCommandRope[
commandLine: IO.PutFR["sh1 lpr -P%g %g ; delete %g\n", IO.rope[printerName], IO.rope[fileName], IO.rope[fileName]],
parent: NIL
];
IO.PutRope[log, out];
};
cnt: CARD ¬ 1;
Counter: ENTRY PROC [] RETURNS [i: CARD] = {
i ¬ cnt ¬ cnt + 1;
};
END.