InterpressToPostscriptRasterImpl.mesa
Copyright Ó 1989, 1992 by Xerox Corporation. All rights reserved.
Jules Bloomenthal August 19, 1991 6:39 pm PDT
Willie-s, April 2, 1992 8:08 pm PST
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]
~ {
As hacked upon by Jules, from /PCedar/RestrictedRES/RestrictedRESImpl.mesa.
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] ~ {
As hacked upon by Jules, from /tilde/Plass/Hacks/PSFromRES/PSFromRESImpl.mesa.
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 <IP name> <PS name> [-option]
options include:
 res <REAL>  pixels per inch (default: 300)
 scale <REAL> magnification (default: 1)
 height <REAL> page height (default: 11.0 inches)
 width <REAL> 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.