AISPressScreen:
PUBLIC
PROCEDURE [pressFileName:
ROPE,
sourceHeight:
NAT ← ViewerSpecs.screenH,
sourceWidth:
NAT ← ViewerSpecs.screenW,
sourceBottom:
NAT ← 0,
sourceLeft:
NAT ← 0,
magnification:
REAL ← 0.5,
scaleToFit: MagnificationType ← useMagnification,
leftMarginInches, rightMarginInches:
REAL ← 0.75,
landscape:
BOOLEAN ←
FALSE,
borderWidth:
REAL ← 2.0,
lockViewers:
BOOLEAN ←
TRUE,
displayCursor:
BOOLEAN ←
FALSE,
displayCarets:
BOOLEAN ←
FALSE]
RETURNS [fileName:
ROPE] =
TRUSTED {
Converts the specified region of the bit mapped screen into a combination AIS and Press file.
Such files can be used by CedarGraphics or printed by the TSetter.
AISPressScreen can raise two signals: MagnificationFactorTooLarge when the specified rectangle will not fit on an 8.5 by 11 inch page with the supplied margins and magnifications; and AISPageAlignmentHackFailed for an internal error expected when the size of SirPress record definitions change (low probability).
trueName: Rope.ROPE ← IF pressFileName = NIL THEN NewAISPressName[] ELSE pressFileName;
context: Graphics.Context ← Graphics.NewContext[];
outputStream: IO.STREAM ← FS.StreamOpen[trueName, $create];
bytesSoFar: INT;
screen: SirPress.PressHandle;
screenBitMap: GraphicsOps.BitmapRef ← GraphicsOps.ScreenBitmap[];
screenWidthInWords: NAT ← screenBitMap.width/16;
sourceLeftInWords: NAT ← MIN[sourceLeft/16, screenWidthInWords];
sourceRightInWords: NAT ← MIN[(sourceLeft+sourceWidth+15)/16, screenWidthInWords];
paperHeight: REAL ← IF landscape THEN 8.5*2540 ELSE 11*2540;
paperWidth: REAL ← (11+8.5)*2540 - paperHeight;
pageBorder: REAL ← (leftMarginInches + rightMarginInches)*2540;
x: REAL;
y: REAL;
screenPtr: LONG POINTER ← Terminal.GetBitBltTable[Terminal.Current[]].dst.word;
bytesPerPage: INT = 2048;
wordsOfPressCommands: INT = 8; -- count of Press commands generated before dots so that the AIS image starts on a page boundary
AISHeader:
TYPE = RECORD [
header: CGAIS.Header,
rasterPart: CGAIS.RasterPart,
uca: CGAIS.UCA];
aisHeader: AISHeader ← [
header: [
password: CGAIS.password,
attributeLength: 0],
rasterPart: [
aph: [
type: raster,
length: SIZE[CGAIS.RasterPart]],
scanCount: 0,
scanLength: 0,
scanDirection: 3,
samplesPerPixel: 1,
codingType: CGAIS.UCACodingType],
uca: [
bitsPerSample: 0,
wordsPerScanLine: 0,
scanLinesPerBlock: 177777B]];
aisHeaderPtr: LONG POINTER TO AISHeader ← @aisHeader;
aisBlock:
IO.UnsafeBlock ← [
base: LOOPHOLE[aisHeaderPtr],
startIndex: 0,
count: 2*SIZE[AISHeader]];
SELECT scaleToFit
FROM
fullPage => {
magnification ← MIN[ (paperWidth-pageBorder)/(32.0*16.0*(sourceRightInWords-sourceLeftInWords)),
(paperHeight-pageBorder)/(32.0*sourceHeight)];
};
halfPage => {
magnification ← MIN[ (paperWidth-pageBorder)/(32.0*16.0*(sourceRightInWords-sourceLeftInWords)),
(paperHeight-2*pageBorder)/(2.0*32.0*sourceHeight)];
};
useMagnification => NULL;
ENDCASE;
x ← (paperWidth-32.0*16.0*(sourceRightInWords-sourceLeftInWords)*magnification)/2.0;
y ← (paperHeight-32.0*sourceHeight*magnification)/2.0;
IF x<0
OR y<0
OR x+32.0*16.0*(sourceRightInWords-sourceLeftInWords)*magnification>paperWidth
OR y+32.0*sourceHeight*magnification>paperHeight
THEN
SIGNAL MagnificationFactorTooLarge;
Create the AIS Header from the screen rectangle information
aisHeader.uca.wordsPerScanLine ← sourceRightInWords-sourceLeftInWords;
aisHeader.rasterPart.scanLength ← aisHeader.uca.wordsPerScanLine*16;
aisHeader.rasterPart.scanCount ← sourceHeight;
IO.UnsafePutBlock[outputStream, aisBlock];
IO.PutChar[outputStream, '\000];
IO.PutChar[outputStream, '\000];
THROUGH [0..bytesPerPage -
IO.GetIndex[outputStream] - 2*wordsOfPressCommands)
DO
IO.PutChar[outputStream, '$];
ENDLOOP;
define the screen rectangle in the Press file
screen ← SirPress.Create[
fileNameForHeaderPage: trueName,
outputStream: outputStream
];
IF landscape THEN screen.SetPageSize[height: 85, width: 110, unit: SirPress.in/10];
screen.BeginScannedRectangle[
x: Real.RoundLI[x], y: Real.RoundLI[y],
numberOfLines: sourceHeight,
dotsPerLine: (sourceRightInWords-sourceLeftInWords)*16,
height: Real.RoundLI[32.0*sourceHeight*magnification],
unit: SirPress.mica];
Stuff the current position of the Press file into the AIS Header
bytesSoFar ← IO.GetIndex[outputStream];
IF bytesSoFar # bytesPerPage THEN SIGNAL AISPageAlignmentHackFailed;
aisHeader.header.attributeLength ← bytesSoFar/2;
IO.SetIndex[outputStream, 0];
IO.UnsafePutBlock[outputStream, aisBlock];
IO.SetIndex[outputStream, bytesSoFar];
IF displayCarets
THEN {
CaretsExtras.SuspendVisibleCarets[];
};
IF lockViewers
THEN ViewerLocks.LockViewerTree[];
context.DrawBox[[sourceLeft, sourceBottom, sourceLeft+borderWidth, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft+sourceWidth-borderWidth, sourceBottom, sourceLeft+sourceWidth, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft, sourceBottom, sourceLeft+sourceWidth, sourceBottom+borderWidth]];
context.DrawBox[[sourceLeft, sourceBottom+sourceHeight-borderWidth, sourceLeft+sourceWidth, sourceBottom+sourceHeight]];
context.SetColor[Graphics.white];
context.DrawBox[[sourceLeft-16, sourceBottom, sourceLeft, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft+sourceWidth, sourceBottom, sourceLeft+sourceWidth+16, sourceBottom+sourceHeight]];
IF displayCursor
THEN {
vt: Terminal.Virtual ← Terminal.Current[];
cursorArray: Terminal.BWCursorBitmap ← Terminal.GetBWCursorPattern[vt];
position: Terminal.Position ← Terminal.GetMousePosition[vt];
[] ← context.Save[];
[] ← context.SetPaintMode[transparent];
context.SetColor[Graphics.black];
context.SetCP[position.x, vt.bwHeight-position.y];
context.procs.DrawBits[context, @cursorArray, 1, 0, 0, 0, 16, 16, 0, 0];
context.Restore[];
};
call ShowLine for each line of screen (or half-line, if left side)
FOR i:
INT
IN [0..sourceHeight)
DO
offset: LONG CARDINAL ← (i+screenBitMap.height-sourceHeight-sourceBottom)*screenWidthInWords+sourceLeftInWords;
screen.UnsafeShowLine[screenPtr + offset];
ENDLOOP;
IF lockViewers THEN ViewerLocks.ReleaseViewerTree[];
IF displayCursor THEN ViewerOps.PaintEverything will fix cursor up
IF displayCarets
THEN {
Carets.ResumeCarets[];
};
finish the rectangle and close the file
screen.EndScannedRectangle[];
screen.ClosePress[];
ViewerOps.PaintEverything[];
RETURN [trueName];
};