SirPress.mesa
Last edited by Michael Plass, November 16, 1982 10:49 am
Press File Interface
Written by Michael Plass
Implementation: SirPressImpl.mesa
Interface adapted from the PressIO package written by Joe Maleson.
DIRECTORY
FileIO USING [Open],
IO USING [STREAM],
Rope USING [ROPE],
UserTerminal USING [CursorArray];
SirPress: CEDAR DEFINITIONS IMPORTS FileIO = BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Types and constants
The following units are expressed in nanometers
pt: INT = (25400000/72)+1; -- a 72 per inch point, used for PARC fonts
texpt: INT = 351460; -- a 72.27 per inch point, used for TEX fonts
in: INT = 25400000; -- an inch
mm: INT = 1000000;
cm: INT = 10000000;
mica: INT = 10000; -- a mica
PrintingMode: TYPE = {normal, reverse, solid, transparent};
tShirt: PrintingMode = reverse;
PressStateVector: TYPE;
PressHandle: TYPE = REF PressStateVector;
SirPress provides a thumbnail sketch of the page as it is built, which the client has the option of displaying as feedback for the user. Since the image is a 16 by 16 bitmap, it is called a cursor. The CursorObject provides a procedure to call, along with a REF to client data. A call with NIL is done at the end to reset the display.
CursorObject: TYPE = REF CursorObjectRec;
CursorObjectRec: TYPE = RECORD[
cursorProc: CursorProc,
clientData: REF ANY
];
CursorProc: TYPE = PROC [clientData: REF ANY, bits: REF UserTerminal.CursorArray];
Basic operations
NewPressHandle: PROC [pressFileName: ROPE] RETURNS [PressHandle] = INLINE
{RETURN[Create[FileIO.Open[pressFileName, overwrite], pressFileName]]};
Create: PUBLIC PROC [
outputStream: STREAM,
fileNameForHeaderPage: ROPENIL,
creatorName: ROPENIL,
printingMode: PrintingMode ← normal,
cursorObject: CursorObject ← NIL] -- Starts making a new press file
RETURNS [p: PressHandle];
SetPageSize: PUBLIC PROC [ -- applies for the current and following pages. Setting width bigger than hieght will result in landscape output.
p: PressHandle,
height: INT ← 110,
width: INT ← 85,
unit: INT ← in/10];
SetSpace: PUBLIC PROC [
p: PressHandle,
xSpace: INT,
ySpace: INT ← 0,
unit: INT ← mica];
ResetSpace: PUBLIC PROC [p: PressHandle];
PutSpace: PUBLIC PROC [p: PressHandle];
SetColor: PUBLIC PROC [p: PressHandle, hue, saturation, brightness: INT];
SetHue: PUBLIC PROC [p: PressHandle, hue: INT];
SetSaturation: PUBLIC PROC [p: PressHandle, saturation: INT];
SetBrightness: PUBLIC PROC [p: PressHandle, brightness: INT];
SetFont: PUBLIC PROC [
p: PressHandle,
family: ROPE,
size: INT,
face: INT ← 0,
rotation: INT ← 0,
unit: INT ← pt -- unit for size, in nanometers--];
PutText: PUBLIC PROC [
p: PressHandle,
textString: ROPE,
xCoordinateOfLeftEdge: INT,
yCoordinateOfBaseline: INT,
unit: INT ← mica];
PutTextHere: PUBLIC PROC [
p: PressHandle,
textString: ROPE];
PutRectangle: PUBLIC PROC [
p: PressHandle,
xstart, ystart, xlen, ylen: INT,
unit: INT ← mica];
WritePage: PUBLIC PROC [p: PressHandle];
ClosePress: PUBLIC PROC [p: PressHandle];
Showing sampled images
ScanLine: TYPE = RECORD [
pixels: SELECT coding: DotCoding FROM
bitMap => [bit: PACKED SEQUENCE length: NAT OF [0..1]],
packedMap => [bitWord: SEQUENCE length: NAT OF CARDINAL],
bitSampled => [intensity: PACKED SEQUENCE length: NAT OF [0..2)],
bitBitSampled=>[intensity: PACKED SEQUENCE length: NAT OF [0..4)],
nybbleSampled=>[intensity: PACKED SEQUENCE length: NAT OF [0..16)],
byteSampled => [intensity: PACKED SEQUENCE length: NAT OF [0..256)]
ENDCASE
];
Direction: TYPE = MACHINE DEPENDENT {right(0), left(1), up(2), down(3)};
DotCoding: TYPE = {bitMap, bitSampled, bitBitSampled, nybbleSampled, byteSampled, packedMap};
To allocate a new scan line variable, say, for instance,
 sl: REF bitMap ScanLine ← NEW[ScanLine[bitMap][128]];
this will give you a scan line 128 bits long. By using automatic dereferencing, you can say things like sl[20]𡤀 or sl[20]𡤁 to set the values of the elements. The packedBits variant is provided where efficiency is important; note the length must be specified in words, not bits, for this variant. Note that, although the press format allows scan lines to be any length, the implementation restricts the length to be a multiple of 16 bits.
As an alternative, a client may send the scanlines by setting up a long pointer to the data and calling UnsafeShowLine. The number of bits per sample and the number of samples per scanline must be chosen so that each scanline ends up on a word boundary. Although unsafe, this is not really a very risky way of doing business, since the data pointed to is only read, never written.
BeginScannedRectangle: PROC [
p: PressHandle,
x, y: INT, -- coordinate of lower left corner
dotsPerLine: INT,
numberOfLines: INT,
width: INT ← -1,
height: INT ← -1,
unit: INT ← mica,
nextLineDirection: Direction ← down,
nextDotDirection: Direction ← right,
coding: DotCoding ← bitMap,
samplingProperties: SamplingProperties ← [omitted: TRUE]
];
SamplingProperties: TYPE = RECORD [ -- For fine control of the halftone screens
omitted: BOOLEANFALSE,
screenAngle: INT ← 0,
screenAmplitude: INT ← 100,
screenFrequency: INT ← 85,
minIntensity: INT ← 0,
maxIntensity: INT ← 255
];
ShowLine: PROC [p: PressHandle, s: REF ScanLine];
UnsafeShowLine: UNSAFE PROC [p: PressHandle, dataPointer: LONG POINTER];
EndScannedRectangle: PROC [p: PressHandle];
Showing outlined areas
StartOutline: PUBLIC PROC [p: PressHandle];
PutMoveTo: PUBLIC PROC [p: PressHandle, x, y: INT, unit: INT ← mica];
PutDrawTo: PUBLIC PROC [p: PressHandle, x, y: INT, unit: INT ← mica];
PutCubic: PUBLIC PROC [p: PressHandle, x1, y1, x2, y2, x3, y3: REAL,
unit: INT ← mica];
EndOutline: PUBLIC PROC [p: PressHandle];
The remaining calls are for fast character-oriented output of text and glue.
FontCode: TYPE = NAT ← 0;
GetFontCode: PUBLIC PROC [
p: PressHandle,
family: ROPE,
size: INT,
face: INT ← 0,
rotation: INT ← 0,
unit: INT ← pt -- unit for size, in nanometers--]
RETURNS [FontCode];
SetFontFromCode: PUBLIC PROC [p: PressHandle, f: FontCode];
Pipe: TYPE = REF PipeRec;
NewPipe: PUBLIC PROC [maximumNumberOfSpacesInPipe: INT ← 200] RETURNS [Pipe];
OpenPipe: PUBLIC PROC [p: PressHandle, pipe: Pipe];
Opens a pipe that can subsequently be used with PipeChar to send a char at a time to the press file.
While a pipe is open, the only operations allowed are PipeChar and PipePosition; in particular, you must close the pipe to change fonts. All positioning (incuding spacing) should be done using PipePosition.
PipeChar: PUBLIC PROCEDURE [pipe: Pipe, c: CHARACTER] = INLINE
{OPEN pipe^; i:NAT ← text.length; text.length ← i + 1; text[i] ← c};
PipePosition: PUBLIC PROCEDURE [pipe: Pipe, x: INTEGER] = INLINE
BEGIN OPEN pipe^;
i:NAT ← scount;
scount←i+1;
slist[i] ← [text.length, x]
END;
ClosePipe: PUBLIC PROCEDURE [
p: PressHandle,
pipe: Pipe,
y: INT, -- all chars on the same line
unit: INT ← mica];
This operation closes the pipe, adding its contents to the press file.
Users shouldn't read past here.
PipeRec: TYPE = RECORD [text: REF TEXTNIL, scount: NAT ← 0, slist: SEQUENCE maxscount: NAT OF CharPtrAndPosition--couldntresistreadingthiscouldya--];
CharPtrAndPosition: TYPE = RECORD [charPtr: NAT, x: INTEGER];
END.
Michael Plass, September 27, 1982 2:06 pm: Changed to use FileIO.
Michael Plass, October 21, 1982 2:46 pm: Added SetSamplingProperties.
Michael Plass, October 25, 1982 10:55 am: Fixed up formatting of source.
Michael Plass, November 1, 1982 9:50 am: Removed Transaction import.
Michael Plass, November 3, 1982 10:27 am: Replaced cursor proc with cursor object.
Michael Plass, November 15, 1982 11:26 am: Added UnsafeShowLine.
Michael Plass, November 16, 1982 10:49 am: Put portrait/landscape logic into SetPageSize.