<<>> <> <> <> <> <<>> DIRECTORY Args, BasicTime, CedarProcess, Commander, CommanderOps, FS, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerError, ImagerPrintContext, ImagerSample, ImagerTransformation, InterpressInterpreter, IO, PrintColor, Real, Rope, SF; InterpressToPostscriptRasterImpl: CEDAR PROGRAM IMPORTS Args, BasicTime, CedarProcess, Commander, CommanderOps, FS, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerError, ImagerPrintContext, ImagerSample, InterpressInterpreter, IO, Real, SF ~ BEGIN ROPE: TYPE ~ Rope.ROPE; SampleMap: TYPE ~ ImagerSample.SampleMap; fileheader: ROPE ~ "%%!PS-Adobe-1.0 %%%%Creator: PSFromRES $Revision: 1.0 $ %%%%CreationDate: %g %%%%For: %g %%%%Pages: 1 %%%%EndComments 20 dict begin /picstr %g string def /readproc { currentfile picstr readhexstring pop } def %%%%EndProlog "; pageheader: ROPE ~ "%%%%Page: %g %g save %g dup scale [%g %g %g %g %g %g] concat %g %g true [%g 0 0 %g 0 %g] {readproc} imagemask "; pagetrailer: ROPE ~ "showpage restore "; filetrailer: ROPE ~ "%%%%Trailer end "; PadUp: PROC [i:CARD,trim:BOOL] RETURNS[c:CARD]~{c¬Pad[Pad[i]+(IF trim THEN 1 ELSE 0)]}; Pad: PROC [i: CARD] RETURNS [c: CARD] ~ {c ¬ ((i+31)/32)*32}; Trim: PROC [bitmap: SampleMap, trim: BOOL] RETURNS [trimmed: SF.Box] ~ { trimmed ¬ (IF trim THEN ImagerSample.Trim[bitmap] ELSE ImagerSample.GetBox[bitmap]); trimmed.max.f ¬ trimmed.min.f+Pad[SF.SizeF[trimmed]]; }; IPToPSRasterCommand: Commander.CommandProc ~ { ip, ps, res, scale, height, width, trim, landscape: Args.Arg; [ip, ps, res, scale, height, width, trim, landscape] ¬ Args.ArgsGet[cmd, "%ss-res%r-scale%r-height%r-width%r-trim%b-landscape%b" ! Args.Error => {msg ¬ reason; GOTO Bad}]; IF NOT res.ok THEN res.real ¬ 300.0; IF NOT scale.ok THEN scale.real ¬ 1.0; scale.real ¬ scale.real*72.0/res.real; IF NOT height.ok THEN height.real ¬ 11.0; IF NOT width.ok THEN width.real ¬ 8.5; IPToPS[cmd, ip.rope, ps.rope, res.real, scale.real, height.real, width.real, trim.ok, landscape.ok]; EXITS Bad => RETURN[$Failure, msg]; }; IPToPS: PROC [ cmd: Commander.Handle, ipName, psName: ROPE, res, scale, height, width: REAL, trim, landscape: BOOL] ~ { <> Log: InterpressInterpreter.LogProc ~ { IO.PutF[cmd.out, "Interpress error (class %g) %g: %g\n", IO.int[class], IO.atom[ImagerError.AtomFromErrorCode[code]], IO.rope[explanation]]; }; user: ROPE ¬ NARROW[CommanderOps.GetProp[cmd, $USER]]; ip: InterpressInterpreter.Master ~ InterpressInterpreter.Open[ipName, Log]; out: IO.STREAM ¬ FS.StreamOpen[psName, $create]; deviceSpaceSize: SF.Vec ~ IF landscape THEN [Real.Round[width*res], Pad[Real.Round[height*res]]] ELSE [Real.Round[height*res], Pad[Real.Round[width*res]]]; size: SF.Vec ~ [s: deviceSpaceSize.s, f: PadUp[deviceSpaceSize.f, trim]]; bytesPerLine: NAT ~ (size.f+7)/8; mode: ImagerTransformation.ScanMode ~ IF landscape THEN [right, up] ELSE [down, right]; bitmap: ImagerSample.RasterSampleMap ~ ImagerSample.ObtainScratchMap[[max: size]]; bitmapContext: Imager.Context; IF res < 100.0 THEN { bitmapContext ¬ ImagerBitmapContext.Create[deviceSpaceSize: deviceSpaceSize, scanMode: mode, surfaceUnitsPerInch: [res, res], pixelUnits: FALSE, fontCacheName: $Bitmap]; ImagerBitmapContext.SetBitmap[bitmapContext, bitmap]; } ELSE { pph: REAL ~ IF res < 280.0 THEN 11.31371*0.5 ELSE 11.31371; -- pixels per halftone dot toners: PrintColor.TonerUniverse ¬[black:TRUE,cyan:FALSE,magenta:FALSE,yellow:FALSE]; bitmapContext ¬ ImagerPrintContext.SimpleCreate[deviceSpaceSize: deviceSpaceSize, scanMode: mode, surfaceUnitsPerInch: [res, res], logicalDevice: 0, pixelsPerHalftoneDot: pph, toners: toners]; ImagerPrintContext.SetBitmap[bitmapContext, bitmap]; ImagerPrintContext.SetSeparation[bitmapContext, black]; Imager.SetWarn[context: bitmapContext, warn: TRUE]; Imager.ClipRectangle[bitmapContext, ImagerBackdoor.GetBounds[bitmapContext]]; }; IO.PutFL[out, fileheader, LIST[IO.time[BasicTime.Now[]], IO.rope[user], IO.int[bytesPerLine]]]; FOR p: INTEGER IN [1..ip.pages] DO ImagerSample.Clear[bitmap]; InterpressInterpreter.DoPage[ip, p, bitmapContext, Log]; IO.PutF[cmd.out, "%g %g", IO.rope[IF p = 1 THEN "writing page" ELSE NIL], IO.int[p]]; OutputPSPage[out, ImagerSample.Clip[bitmap, Trim[bitmap, trim]], scale, p, ip.pages]; ENDLOOP; IO.PutRope[out, filetrailer]; IO.Close[out]; IO.PutRope[cmd.out, " done!\n"]; }; OutputPSPage: PROC [out: IO.STREAM, bitmap: SampleMap, scale: REAL, page, pages: INT] ~ { <> Nybbles: TYPE ~ RECORD[PACKED SEQUENCE size: NAT OF [0..16)]; size: SF.Vec ¬ ImagerSample.GetSize[bitmap]; bytesPerLine: NAT ~ (size.f+7)/8; lineBuffer: REF Nybbles ¬ NEW[Nybbles[bytesPerLine*2]]; lineBufferMap: SampleMap; size581: NAT ~ size.s; size608: NAT ~ bytesPerLine*8; TRUSTED {lineBufferMap ¬ ImagerSample.ObtainUnsafeDescriptor[size: [1, bytesPerLine*8], bitsPerSample: 1, bitsPerLine: bytesPerLine*8, base: [word: LOOPHOLE[lineBuffer, POINTER] + UNITS[Nybbles[0]], bit: 0], ref: lineBuffer, words: WORDS[Nybbles[bytesPerLine*2]]-WORDS[Nybbles[0]]]}; IO.PutFL[out, pageheader, LIST[ IO.int[page-1], IO.int[pages], IO.real[scale], IO.real[size608], IO.real[0], IO.real[0], IO.real[size581], IO.real[0], IO.real[0], IO.int[size608], IO.int[size581], IO.int[size608], IO.int[-(size581)], IO.int[size581] ]]; FOR s: NAT IN [0..size.s) DO CedarProcess.CheckAbort[]; ImagerSample.BasicTransfer[lineBufferMap, bitmap, [0, 0], [s, 0], [1, size.f]]; FOR j: NAT IN [0..2*bytesPerLine) DO t: CARDINAL ~ lineBuffer[j]; IO.PutChar[out, t + (IF t < 10 THEN '0 ELSE ('A-10))]; ENDLOOP; IO.PutChar[out, '\n]; ENDLOOP; IO.PutRope[out, pagetrailer]; TRUSTED {ImagerSample.ReleaseDescriptor[lineBufferMap]}; }; usage: ROPE ~ "convert an Interpress file into a raster Postscript file usage: IPToPS [-option] options include: res pixels per inch (default: 300) scale magnification (default: 1) height page height (default: 11.0 inches) width page width (default: 8.5 inches) trim trim to multiple of 32 in f direction (for some printers) landscape scan direction (default: portrait)"; Commander.Register["IPToPSRaster", IPToPSRasterCommand, usage]; END.