<<>> <> <> <> <> 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] = { <<<>>> 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] = { <<<>>> 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] = { <> 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.