PressRescueImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, April 25, 1984 12:15:33 pm PST
Rick Beach, July 31, 1985 2:27:09 pm PDT
DIRECTORY
Commander, Convert, FS, Imager, ImagerFont, ImagerTransformation, IO, PressReader, Rope, Real, PressPrinter, RefText, ShowPress, Vector2;
PressRescueImpl: CEDAR PROGRAM
IMPORTS Commander, Convert, FS, ImagerFont, ImagerTransformation, IO, PressReader, Rope, Real, PressPrinter, RefText
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
bytesPerPage: NAT ~ 512; -- as per press file format.
micasPerPoint: REAL = 2540.0/72.0;
pointsPerMica: REAL = 72.0/2540.0;
FontTable: TYPE ~ ARRAY [0..256) OF ShowPress.FontRec;
RescuePressPage: PROC [stream: IO.STREAM, pressFile: PressReader.Handle, pageNumber: INT, fontTable: REF FontTable]
RETURNS [ok: BOOLEANTRUE] = {
PageProc: PressReader.PageProc = {
EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet
xe: INT ← entityTrailer.Xe;
ye: INT ← entityTrailer.Ye;
x: INT ← xe;
y: INT ← ye;
lastShowX, lastShowY: INT ← -1;
currentFont: ShowPress.FontRec; -- will be established by setFont
currentSpaceX, currentSpaceY: INT; -- will be established by setFont
hue: REAL ← 0.0;
saturation: REAL ← 1.0;
brightness: REAL ← 0.0;
skipAlternative, inAlternative: BOOLFALSE;
reposition: BOOLEANFALSE;
showCharactersProc: PressReader.ShowCharactersProc = {
xw, yw: INT ← 0;
IF skipAlternative THEN RETURN;
IF lastShowY # y THEN {
stream.PutChar['\n];
lastShowX ← 2540;
};
IF ABS[x - lastShowX] < 50 THEN NULL
ELSE FOR i: INT ← x - lastShowX, i - 175 UNTIL i <= 0 DO
stream.PutChar[' ]
ENDLOOP;
FOR i: INT IN [0..text.Length[]) DO
c: CHAR ← text.Fetch[i];
IF c = ' THEN {
xw ← xw+currentSpaceX;
yw ← yw+currentSpaceY;
}
ELSE IF currentFont.imagerFont # NIL THEN {
widthVec: ImagerFont.VEC ~ ImagerFont.Width[currentFont.imagerFont, [0, ORD[c]]];
xw ← xw+Real.RoundLI[widthVec.x];
yw ← yw+Real.RoundLI[widthVec.y];
}
ENDLOOP;
stream.PutRope[text];
x ← x + xw;
y ← y + yw;
lastShowX ← x;
lastShowY ← y;
}; -- showCharactersProc
fontProc: PressReader.FontProc = {
IF skipAlternative THEN RETURN;
currentFont ← fontTable[entityTrailer.fontSet*16+font];
};
positionProc: PressReader.PositionProc = {
IF skipAlternative THEN RETURN;
IF opCode = setX THEN x ← xe + value
ELSE y ← ye + value;
reposition ← TRUE;
};
spacingProc: PressReader.SpacingProc = {
IF skipAlternative THEN RETURN;
SELECT opCode FROM
setSpaceX, setSpaceXShort => currentSpaceX ← value;
setSpaceY, setSpaceYShort => currentSpaceY ← value;
resetSpace => {
currentSpaceX ← 200;
currentSpaceY ← 0;
};
ENDCASE => ERROR;
IF opCode = resetSpace THEN NULL ELSE NULL;
};
spaceProc: PressReader.SpaceProc = {
showCharactersProc[showCharacterImmediate, 1, " "];
};
colorProc: PressReader.ColorProc = {
IF skipAlternative THEN RETURN;
SELECT opCode FROM
setHue => NULL;
setSaturation => NULL;
setBrightness => NULL;
ENDCASE => ERROR;
};
showRectangleProc: PressReader.ShowRectangleProc = {
IF skipAlternative THEN RETURN;
NULL;
};
alternativeProc: PressReader.AlternativeProc = {
IF (types = 0) AND (elBytes = 0) AND (dlBytes = 0) THEN
inAlternative ← skipAlternative ← FALSE
ELSE IF inAlternative THEN skipAlternative ← TRUE
ELSE inAlternative ← TRUE;
};
showObjectProc: PressReader.ShowObjectProc = {
NULL;
}; -- showObjectProc
showDotsProc: PressReader.ShowDotsProc = {
NULL;
}; -- showDotsProc
fontProc[0];
pressFile.GetCommands[
showCharactersProc: showCharactersProc,
fontProc: fontProc,
positionProc: positionProc,
spacingProc: spacingProc,
spaceProc: spaceProc,
colorProc: colorProc,
showRectangleProc: showRectangleProc,
alternativeProc: alternativeProc,
showObjectProc: showObjectProc,
showDotsProc: showDotsProc
];
}; -- EntityProc
pressFile.GetPage[EntityProc];
stream.PutRope["\n\n------------------------------------------------------------------------"];
}; -- PageProc
SkipFonts: PressReader.FontDirectoryProc = {
ok ← FALSE;
};
pressFile.GetParts[pageNumber, PageProc, SkipFonts];
};
Rescue: PROC [outputName, inputName1: ROPE] ~ {
pressFile1: PressReader.Handle ← PressReader.OpenPressFile[inputName1];
documentDirectory1: PressReader.DocumentDirectory ← pressFile1.GetDocumentDirectory;
pageNumber1: INT ← 1;
fontTable: REF FontTable ← NEW[ARRAY [0..256) OF ShowPress.FontRec];
FontInitProc1: PressReader.FontEntryProc = { -- build a list of needed fonts
sizeInMicas: REAL ~ (
IF fontDirectoryEntry.size > 0 THEN ((REAL[fontDirectoryEntry.size]*2540.0)/72.0)
ELSE (REAL[-fontDirectoryEntry.size])
);
name: ROPE ~ NameFromPressFontID[fontDirectoryEntry.family, fontDirectoryEntry.face];
imagerFont: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find[name], sizeInMicas];
IF fontDirectoryEntry.rotation#0 THEN {
degrees: REAL ← fontDirectoryEntry.rotation/60.0;
imagerFont ← ImagerFont.Modify[imagerFont, ImagerTransformation.Rotate[degrees]];
};
fontTable[fontDirectoryEntry.fontSet*16 + fontDirectoryEntry.font] ← [
imagerFont: imagerFont,
family: fontDirectoryEntry.family,
face: fontDirectoryEntry.face.encoding,
size: sizeInMicas,
rotation: REAL[fontDirectoryEntry.rotation]/60.0
];
}; -- FontInitProc
stream: IO.STREAMFS.StreamOpen[outputName, $create];
pressFile1.GetFonts[FontInitProc1];
WHILE RescuePressPage[stream, pressFile1, pageNumber1, fontTable] DO
pageNumber1 ← pageNumber1 + 1;
ENDLOOP;
pressFile1.ClosePressFile[];
stream.Close;
};
NameFromPressFontID: PROC [family: ROPE, face: PressReader.FontFace] RETURNS [name: ROPE] ~ {
t: REF TEXT ← RefText.ObtainScratch[100];
t ← RefText.AppendRope[t, "Xerox/Pressfonts/"];
t ← RefText.AppendRope[t, family];
IF face.texDesignSize > 0 THEN {
t ← Convert.AppendInt[t, Real.Round[face.texDesignSize]];
}
ELSE {
t ← RefText.AppendChar[t, '-];
t ← RefText.AppendChar[t, SELECT face.weight FROM
medium => 'M, bold => 'B, light => 'L, ENDCASE => 'M
];
t ← RefText.AppendChar[t, SELECT face.slope FROM
regular => 'R, italic => 'I, ENDCASE => 'R
];
t ← RefText.AppendChar[t, SELECT face.expansion FROM
regular => 'R, condensed => 'C, expanded => 'E, ENDCASE => 'R
];
};
name ← Rope.FromRefText[t];
RefText.ReleaseScratch[t];
};
Break: PROC [char: CHAR] RETURNS [IO.CharClass] = {
IF char = '← THEN RETURN [break];
IF char = ' OR char = '  OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
FindFullName: PROC [inputName: ROPE] RETURNS [ROPE] ~ {
fullFName: ROPENIL;
fullFName ← FS.FileInfo[inputName ! FS.Error => CONTINUE].fullFName;
IF fullFName = NIL OR NOT PressPrinter.IsAPressFile[fullFName] THEN {
IF inputName.Find[".press", 0, FALSE] = -1 THEN {
inputName ← inputName.Concat[".press"];
};
fullFName ← FS.FileInfo[inputName].fullFName;
};
RETURN [fullFName]
};
PressRescueCommand: Commander.CommandProc ~ {
stream: IO.STREAMIO.RIS[cmd.commandLine];
GetToken: PROC RETURNS [rope: ROPE] = {
rope ← NIL;
rope ← stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token;
};
outputName: ROPE ← GetToken[];
gets: ROPE ← GetToken[];
inputName1: ROPE ← GetToken[];
IF NOT gets.Equal["←"] OR inputName1 = NIL THEN {cmd.out.PutRope["Specify output ← input, please"]; RETURN};
inputName1 ← FindFullName[inputName1 ! FS.Error => {
IF error.group = user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; GOTO Quit} ELSE REJECT
}];
Rescue[outputName, inputName1];
cmd.out.PutRope[outputName];
cmd.out.PutRope[" written.\n"];
IF GetToken[].Length # 0 THEN {cmd.out.PutRope["Ignored: "]; cmd.out.PutRope[cmd.commandLine.Substr[stream.GetIndex]]; cmd.out.PutChar['\n]};
EXITS Quit => NULL
};
Commander.Register["PressRescue", PressRescueCommand, "Rescue the text portions of a press file (output ← inputRescue)"];
END.