DIRECTORY Commander USING [CommandProc, Handle, Register], FS USING [Error, FileInfo], IO USING [CharClass, EndOfStream, GetIndex, GetTokenRope, int, PutChar, PutFR, PutRope, RIS, SetIndex, STREAM, UnsafeGetBlock], PressOverlay USING [], PressPrinter USING [IsAPressFile], PressReader USING [AlternativeProc, ClosePressFile, ColorProc, DocumentDirectory, Dots, DotsFollowProc, DrawCurveProc, DrawToProc, EntityProc, FontDirectoryEntry, FontDirectoryProc, FontEntryProc, FontProc, GetCommands, GetDocumentDirectory, GetDots, GetFonts, GetObject, GetPage, GetParts, Handle, MoveToProc, OpenPressFile, PageProc, PositionProc, SetCodingProc, SetModeProc, SetSizeProc, SetWindowProc, ShowCharactersProc, ShowDotsProc, ShowObjectProc, ShowRectangleProc, SpaceProc, SpacingProc], Real USING [RoundLI], Rope USING [Concat, Equal, Find, IsEmpty, Length, ROPE, Substr], SirPress USING [BeginScannedRectangle, ClosePress, EndOutline, EndScannedRectangle, NewPressHandle, PressHandle, PutCubic, PutDrawTo, PutMoveTo, PutRectangle, PutText, PutTextHere, ResetSpace, SetBrightness, SetColor, SetFont, SetHue, SetSaturation, SetSpace, StartOutline, UnsafeShowLine, WritePage]; PressOverlayImpl: CEDAR PROGRAM IMPORTS Commander, FS, IO, PressReader, Real, Rope, SirPress, PressPrinter EXPORTS PressOverlay ~ 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; CopyPressPage: PUBLIC PROC [pressHandle: SirPress.PressHandle, pressFile: PressReader.Handle, pageNumber: INT, fontTable: REF ARRAY [0..6*16) OF PressReader.FontDirectoryEntry] RETURNS [ok: BOOLEAN _ TRUE] = { PageProc: PressReader.PageProc = { EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet xe: INT _ entityTrailer.Xe; ye: INT _ entityTrailer.Ye; x: INT _ xe; y: INT _ ye; currentFont: PressReader.FontDirectoryEntry; -- 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: BOOL _ FALSE; reposition: BOOLEAN _ FALSE; showCharactersProc: PressReader.ShowCharactersProc = { IF skipAlternative THEN RETURN; IF reposition THEN {pressHandle.PutText[text, x, y]; reposition _ FALSE} ELSE pressHandle.PutTextHere[text]; }; -- showCharactersProc fontProc: PressReader.FontProc = { IF skipAlternative THEN RETURN; currentFont _ fontTable[entityTrailer.fontSet*16+font]; IF currentFont.family.Length # 0 THEN pressHandle.SetFont[currentFont.family, currentFont.size, currentFont.face.encoding, currentFont.rotation]; }; 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 pressHandle.ResetSpace ELSE pressHandle.SetSpace[currentSpaceX, currentSpaceY]; }; spaceProc: PressReader.SpaceProc = { showCharactersProc[showCharacterImmediate, 1, " "]; }; colorProc: PressReader.ColorProc = { IF skipAlternative THEN RETURN; SELECT opCode FROM setHue => pressHandle.SetHue[value]; setSaturation => pressHandle.SetSaturation[value]; setBrightness => pressHandle.SetBrightness[value]; ENDCASE => ERROR; }; showRectangleProc: PressReader.ShowRectangleProc = { IF skipAlternative THEN RETURN; pressHandle.PutRectangle[x, y, width, height]; }; 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 = { moveToProc: PressReader.MoveToProc = { pressHandle.PutMoveTo[x: x+xe, y: y+ye]}; drawToProc: PressReader.DrawToProc = { pressHandle.PutDrawTo[x: x+xe, y: y+ye]}; drawCurveProc: PressReader.DrawCurveProc = { pressHandle.PutCubic[cX, cY, bX, bY, aX, aY]; }; IF skipAlternative THEN RETURN; pressHandle.StartOutline; pressFile.GetObject[moveToProc, drawToProc, drawCurveProc]; pressHandle.EndOutline; }; -- showObjectProc showDotsProc: PressReader.ShowDotsProc = { codingType, dotsPerLine, scanLines, passDots, displayDots, passLines, displayLines: INT _ 0; scanMode: CARDINAL _ 0; windowWidth, windowHeight: INT _ 0; dotInfo: PressReader.Dots; setCodingProc: PressReader.SetCodingProc = { codingType _ code; windowWidth _ dotsPerLine _ displayDots _ dots; windowHeight _ scanLines _ displayLines _ lines; }; setModeProc: PressReader.SetModeProc = {scanMode _ mode}; setWindowProc: PressReader.SetWindowProc = { passDots _ pd; displayDots _ dd; passLines _ pl; displayLines _ dl; }; setSizeProc: PressReader.SetSizeProc = { windowWidth _ width; windowHeight _ height; }; dotsFollowProc: PressReader.DotsFollowProc = { dotInfo _ dots; }; ScratchRec: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; scratch: REF ScratchRec; bytesPerLine: INT _ 0; IF skipAlternative THEN RETURN; pressFile.GetDots[setCoding: setCodingProc, setMode: setModeProc, setWindow: setWindowProc, setSize: setSizeProc, dotsFollow: dotsFollowProc]; scratch _ NEW[ScratchRec[(dotsPerLine+3)/2]]; pressHandle.BeginScannedRectangle[ x: x, y: y, dotsPerLine: dotsPerLine, numberOfLines: scanLines, width: windowWidth, height: windowHeight, nextLineDirection: LOOPHOLE[scanMode MOD 4], nextDotDirection: LOOPHOLE[scanMode / 4], coding: SELECT codingType FROM 0 => bitMap, 1 => bitSampled, 2 => bitBitSampled, 4 => nybbleSampled, 8 => byteSampled, ENDCASE => ERROR ]; bytesPerLine _ (MAX[codingType, 1] * dotsPerLine + 7)/8; scratch[bytesPerLine/2] _ 0; -- make sure array is big enough dotInfo.file.SetIndex[INT[dotInfo.pageNumber]*bytesPerPage+dotInfo.byteOffset]; FOR i: INT IN [0..scanLines) DO TRUSTED {[] _ dotInfo.file.UnsafeGetBlock[[base: (LOOPHOLE[@scratch[0]]), startIndex: 0, count: bytesPerLine]]}; TRUSTED {pressHandle.UnsafeShowLine[@scratch[0]]}; ENDLOOP; pressHandle.EndScannedRectangle; }; -- showDotsProc fontProc[0]; pressHandle.SetColor[0, 0, 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]; }; -- PageProc SkipFonts: PressReader.FontDirectoryProc = { ok _ FALSE; }; pressFile.GetParts[pageNumber, PageProc, SkipFonts]; }; Overlay: PUBLIC PROC [outputName, inputName1, inputName2: ROPE] ~ { pressFile1: PressReader.Handle _ PressReader.OpenPressFile[inputName1]; documentDirectory1: PressReader.DocumentDirectory _ pressFile1.GetDocumentDirectory; pressFile2: PressReader.Handle _ PressReader.OpenPressFile[inputName2]; documentDirectory2: PressReader.DocumentDirectory _ pressFile2.GetDocumentDirectory; pageNumber1: INT _ 1; pageNumber2: INT _ 1; fontTable: ARRAY [1..2] OF REF ARRAY [0..6*16) OF PressReader.FontDirectoryEntry _ [NEW[ARRAY [0..6*16) OF PressReader.FontDirectoryEntry], NEW[ARRAY [0..6*16) OF PressReader.FontDirectoryEntry]]; FontInitProc1: PressReader.FontEntryProc = { -- build a list of needed fonts fontTable[1][fontDirectoryEntry.fontSet*16 + fontDirectoryEntry.font] _ fontDirectoryEntry; }; -- FontInitProc FontInitProc2: PressReader.FontEntryProc = { -- build a list of needed fonts fontTable[2][fontDirectoryEntry.fontSet*16 + fontDirectoryEntry.font] _ fontDirectoryEntry; }; -- FontInitProc pressHandle: SirPress.PressHandle _ SirPress.NewPressHandle[outputName]; pressFile1.GetFonts[FontInitProc1]; pressFile2.GetFonts[FontInitProc2]; WHILE CopyPressPage[pressHandle, pressFile1, pageNumber1, fontTable[1]] DO UNTIL CopyPressPage[pressHandle, pressFile2, pageNumber2, fontTable[2]] DO pageNumber2 _ 1; ENDLOOP; pageNumber1 _ pageNumber1 + 1; pageNumber2 _ pageNumber2 + 1; pressHandle.WritePage; ENDLOOP; pressFile1.ClosePressFile[]; pressFile2.ClosePressFile[]; pressHandle.ClosePress; }; 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: ROPE _ NIL; 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] }; PressOverlayCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.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[]; inputName2: ROPE _ GetToken[]; IF NOT gets.Equal["_"] OR inputName2 = NIL THEN {cmd.out.PutRope["Specify output _ input1 input2, please"]; RETURN}; IF outputName.Find[".press", 0, FALSE] = -1 THEN { outputName _ outputName.Concat[".press"]; }; inputName1 _ FindFullName[inputName1 ! FS.Error => { IF error.group = user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; GOTO Quit} ELSE REJECT }]; inputName2 _ FindFullName[inputName2 ! FS.Error => { IF error.group = user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; GOTO Quit} ELSE REJECT }]; Overlay[outputName, inputName1, inputName2]; 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 }; FindBBoxPage: PUBLIC PROC [--pressHandle: SirPress.PressHandle,-- pressFile: PressReader.Handle, pageNumber: INT, fontTable: REF ARRAY [0..6*16) OF PressReader.FontDirectoryEntry] RETURNS [leftMargin, topMargin, rightMargin, bottomMargin: INT, ok: BOOLEAN] = { leftMax: INT _ LAST[INT]; topMax: INT _ FIRST[INT]; rightMax: INT _ FIRST[INT]; bottomMax: INT _ LAST[INT]; SetBBox: PROC [x, y, width, height: INT] ~ { leftMax _ MIN[leftMax, x]; topMax _ MAX[topMax, y-height]; rightMax _ MAX[rightMax, x+width]; bottomMax _ MIN[bottomMax, y]; }; PageProc: PressReader.PageProc = { EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet xe: INT _ entityTrailer.Xe; ye: INT _ entityTrailer.Ye; x: INT _ xe; y: INT _ ye; currentFont: PressReader.FontDirectoryEntry; -- will be established by setFont currentSpaceX, currentSpaceY: INT; -- will be established by setFont skipAlternative, inAlternative: BOOL _ FALSE; reposition: BOOLEAN _ FALSE; showCharactersProc: PressReader.ShowCharactersProc = { widthOfText: INT _ 1; heightOfText: INT _ 1; IF skipAlternative THEN RETURN; IF reposition THEN { SetBBox[x, y, widthOfText, heightOfText]; reposition _ FALSE} ELSE { SetBBox[x, y, widthOfText, heightOfText]; }; }; -- 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; }; spaceProc: PressReader.SpaceProc = { showCharactersProc[showCharacterImmediate, 1, " "]; }; colorProc: PressReader.ColorProc = { IF skipAlternative THEN RETURN; }; showRectangleProc: PressReader.ShowRectangleProc = { IF skipAlternative THEN RETURN; SetBBox[x, y, width, height]; }; 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 = { curveX, curveY: INT; moveToProc: PressReader.MoveToProc = { curveX _ x+xe; curveY _ y+ye; SetBBox[curveX, curveY, 0, 0]; }; drawToProc: PressReader.DrawToProc = { curveX _ x+xe; curveY _ y+ye; SetBBox[curveX, curveY, 0, 0]; }; drawCurveProc: PressReader.DrawCurveProc = { minX: INT ~ Real.RoundLI[MIN[cX, bX, aX]]; minY: INT ~ Real.RoundLI[MIN[cY, bY, aY]]; maxX: INT ~ Real.RoundLI[MAX[cX, bX, aX]]; maxY: INT ~ Real.RoundLI[MAX[cY, bY, aY]]; SetBBox[curveX+minX, curveY+minY, maxX-minX, maxY-minY]; }; IF skipAlternative THEN RETURN; pressFile.GetObject[moveToProc, drawToProc, drawCurveProc]; }; -- showObjectProc showDotsProc: PressReader.ShowDotsProc = { codingType, dotsPerLine, scanLines, passDots, displayDots, passLines, displayLines: INT _ 0; scanMode: CARDINAL _ 0; windowWidth, windowHeight: INT _ 0; dotInfo: PressReader.Dots; setCodingProc: PressReader.SetCodingProc = { codingType _ code; windowWidth _ dotsPerLine _ displayDots _ dots; windowHeight _ scanLines _ displayLines _ lines; }; setModeProc: PressReader.SetModeProc = {scanMode _ mode}; setWindowProc: PressReader.SetWindowProc = { passDots _ pd; displayDots _ dd; passLines _ pl; displayLines _ dl; }; setSizeProc: PressReader.SetSizeProc = { windowWidth _ width; windowHeight _ height; }; dotsFollowProc: PressReader.DotsFollowProc = { dotInfo _ dots; }; IF skipAlternative THEN RETURN; pressFile.GetDots[setCoding: setCodingProc, setMode: setModeProc, setWindow: setWindowProc, setSize: setSizeProc, dotsFollow: dotsFollowProc]; SetBBox[x, y, windowWidth, windowHeight]; }; -- 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]; }; -- PageProc SkipFonts: PressReader.FontDirectoryProc = { ok _ FALSE; }; pressFile.GetParts[pageNumber, PageProc, SkipFonts]; RETURN [leftMax, topMax, rightMax, bottomMax, ok]; }; FindBBox: PUBLIC PROC [pressFileName: ROPE] RETURNS[left, top, right, bottom: INT, ok: BOOLEAN] ~ { pressFile: PressReader.Handle _ PressReader.OpenPressFile[pressFileName]; documentDirectory: PressReader.DocumentDirectory _ pressFile.GetDocumentDirectory; pageNumber: INT _ 1; fontTable: REF ARRAY [0..6*16) OF PressReader.FontDirectoryEntry _ NEW[ARRAY [0..6*16) OF PressReader.FontDirectoryEntry]; FontInitProc: PressReader.FontEntryProc = { -- build a list of needed fonts fontTable[fontDirectoryEntry.fontSet*16 + fontDirectoryEntry.font] _ fontDirectoryEntry; }; -- FontInitProc pressFile.GetFonts[FontInitProc]; [left, top, right, bottom, ok] _ FindBBoxPage[pressFile, pageNumber, fontTable] ; pressFile.ClosePressFile[]; RETURN [left, top, right, bottom, ok]; }; PressBBoxCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; GetToken: PROC RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token; }; pressFileName: ROPE _ GetToken[]; Pt: PROC [p: INT] RETURNS [INT] ~ { micasPerPt: REAL ~ (2540/72.0); RETURN[Real.RoundLI[p/micasPerPt]]; }; left, top, right, bottom: INT; ok: BOOLEAN; IF pressFileName.IsEmpty THEN { cmd.out.PutRope["Specify press file please"]; RETURN}; IF pressFileName.Find[".press", 0, FALSE] = -1 THEN { pressFileName _ pressFileName.Concat[".press"]; }; [left, top, right, bottom, ok] _ FindBBox[pressFileName]; cmd.out.PutRope[pressFileName]; cmd.out.PutRope[IO.PutFR[" leftMargin: %g pt, topMargin: %g pt, width: %g pt, height: %g pt\n", IO.int[Pt[left]], IO.int[Pt[(11*2540)-top]], IO.int[Pt[right-left]], IO.int[Pt[top-bottom]]]]; IF GetToken[].Length # 0 THEN {cmd.out.PutRope["Ignored: "]; cmd.out.PutRope[cmd.commandLine.Substr[stream.GetIndex]]; cmd.out.PutChar['\n]}; }; Commander.Register["PressOverlay", PressOverlayCommand, "Overlay two press files on each other (output _ input1 input2)"]; Commander.Register["PressBBox", PressBBoxCommand, "Finds the bounding box margins for the press file, suitable for IncludePress nodes"]; END. žPressOverlayImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, July 29, 1985 10:05:37 am PDT Last Edited by: Beach, May 1, 1985 4:23:47 pm PDT hue: REAL _ 0.0; saturation: REAL _ 1.0; brightness: REAL _ 0.0; pressHandle.PutText[text, x, y]; pressHandle.PutTextHere[text]; IF currentFont.family.Length # 0 THEN pressHandle.SetFont[currentFont.family, currentFont.size, currentFont.face.encoding, currentFont.rotation]; IF opCode = resetSpace THEN pressHandle.ResetSpace ELSE pressHandle.SetSpace[currentSpaceX, currentSpaceY]; SELECT opCode FROM setHue => pressHandle.SetHue[value]; setSaturation => pressHandle.SetSaturation[value]; setBrightness => pressHandle.SetBrightness[value]; ENDCASE => ERROR; pressHandle.PutRectangle[x, y, width, height]; pressHandle.PutMoveTo[x: x+xe, y: y+ye]; pressHandle.PutDrawTo[x: x+xe, y: y+ye] pressHandle.PutCubic[cX, cY, bX, bY, aX, aY]; pressHandle.StartOutline; pressHandle.EndOutline; ScratchRec: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; scratch: REF ScratchRec; bytesPerLine: INT _ 0; scratch _ NEW[ScratchRec[(dotsPerLine+3)/2]]; pressHandle.BeginScannedRectangle[ x: x, y: y, dotsPerLine: dotsPerLine, numberOfLines: scanLines, width: windowWidth, height: windowHeight, nextLineDirection: LOOPHOLE[scanMode MOD 4], nextDotDirection: LOOPHOLE[scanMode / 4], coding: SELECT codingType FROM 0 => bitMap, 1 => bitSampled, 2 => bitBitSampled, 4 => nybbleSampled, 8 => byteSampled, ENDCASE => ERROR ]; bytesPerLine _ (MAX[codingType, 1] * dotsPerLine + 7)/8; scratch[bytesPerLine/2] _ 0; -- make sure array is big enough dotInfo.file.SetIndex[dotInfo.pageNumber*bytesPerPage+dotInfo.byteOffset]; FOR i: INT IN [0..scanLines) DO TRUSTED {[] _ dotInfo.file.UnsafeGetBlock[[base: (LOOPHOLE[@scratch[0]]), startIndex: 0, count: bytesPerLine]]}; TRUSTED {pressHandle.UnsafeShowLine[@scratch[0]]}; ENDLOOP; pressHandle.EndScannedRectangle; pressHandle.SetColor[0, 0, 0]; ส)๏˜code– "cedar" stylešœ™K– "cedar" stylešœ ฯmœ1™