IPMaster.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Doug Wyatt, December 5, 1985 0:39:25 am PST
Operations for reading and writing Interpress masters at the token level.
DIRECTORY
Basics USING [BYTE, Comparison],
IO USING [STREAM],
Rope USING [MaxLen, ROPE];
IPMaster: CEDAR DEFINITIONS
~ BEGIN
BYTE: TYPE ~ Basics.BYTE;
STREAM: TYPE ~ IO.STREAM;
ROPE: TYPE ~ Rope.ROPE;
MaxLen: INT ~ Rope.MaxLen;
MaxTextLen: NAT ~ NAT.LAST;
Basic types
Version: TYPE ~ RECORD [major, minor: CARDINAL]; -- Interpress version number
currentVersion: Version ~ [3, 0]; -- latest version supported by this interface
Op: TYPE ~ {
nil,
-- BASE primitives
get, makeveclu, makevec, shape, getprop, getp, mergeprop, fget, fset,
makesimpleco, do, dosave, dosaveall, dosavesimplebody, findoperator,
pop, copy, dup, roll, exch, mark, unmark, unmark0, count, nop, error,
if, ifelse, ifcopy, eq, gt, ge, and, or, not, type,
add, sub, neg, abs, floor, ceiling, trunc, round, mul, div, mod, rem,
-- IMAGE primitives
iget, iset, maket, translate, rotate, scale, scale2, concat,
concatt, move, trans, setxy, setxyrel, setxrel, setyrel, getcp,
makepixelarray, extractpixelarray, finddecompressor,
makegray, findcolor, findcoloroperator, findcolormodeloperator,
makesampledcolor, makesampledblack, setgray, setsampledcolor, setsampledblack,
moveto, lineto, linetox, linetoy, curveto, conicto, arcto,
makeoutline, makeoutlineodd, maskfill, maskrectangle,
startunderline, maskunderline, masktrapezoidx, masktrapezoidy,
maskstroke, maskstrokeclosed, maskvector, maskdashedstroke, maskpixel,
clipoutline, cliprectangle,
maskchar, makefont, findfont, modifyfont, setfont,
show, showandxrel, showandfixedxrel,
correctmask, correctspace, space, setcorrectmeasure, setcorrecttolerance, correct,
-- Symbols
beginBody, endBody, beginBlock, endBlock, contentInstructions
};
ImagerVariable: TYPE ~ MACHINE DEPENDENT {
DCScpx(0), DCScpy(1),
correctMX(2), correctMY(3),
T(4),
priorityImportant(5),
mediumXSize(6), mediumYSize(7),
fieldXMin(8), fieldYMin(9),
fieldXMax(10), fieldYMax(11),
font(12),
color(13),
noImage(14),
strokeWidth(15),
strokeEnd(16),
underlineStart(17),
amplifySpace(18),
correctPass(19),
correctShrink(20),
correctTX(21), correctTY(22),
strokeJoint(23),
clipper(24)
};
StrokeEnd: TYPE ~ MACHINE DEPENDENT {square(0), butt(1), round(2)};
StrokeJoint: TYPE ~ MACHINE DEPENDENT {miter(0), bevel(1), round(2)};
Xerox Encoding
shortNumberBias: INTEGER ~ 4000;
ShortNumber: TYPE ~ [0-shortNumberBias .. 77777B-shortNumberBias]; -- 15 bits
EncodingValue: TYPE ~ MACHINE DEPENDENT { -- 13 bits
nil(0),
nop(1),
setxy(10),
setxyrel(11),
setxrel(12),
setyrel(13),
linetox(14),
linetoy(15),
space(16),
get(17),
iget(18),
iset(19),
fget(20),
fset(21),
show(22),
lineto(23),
maskstroke(24),
moveto(25),
metricMaster(100), -- nonstandard
environmentMaster(101), -- nonstandard
beginBlock(102),
endBlock(103),
contentInstructions(105),
beginBody(106),
endBody(107),
correct(110),
disablecorrection(111), -- nonstandard
makesimpleco(114),
makeco(115), -- nonstandard
findoperator(116),
dosavesimplebody(120),
dobody(121), -- nonstandard
dosavebody(122), -- nonstandard
dosaveallbody(123), -- nonstandard
maskchar(140),
showandfixedxrel(145),
showandxrel(146),
findfont(147),
modifyfont(148),
finddecompressor(149),
makefont(150),
setfont(151),
setcorrectmeasure(154),
setcorrecttolerance(155),
correctmask(156),
correctspace(157),
getcp(159),
maket(160),
opent(161), -- nonstandard
translate(162),
rotate(163),
scale(164),
concat(165),
scale2(166),
invert(167), -- nonstandard
concatt(168),
move(169),
trans(170),
transform(174), -- nonstandard
transformvec(175), -- nonstandard
roundxy(176), -- nonstandard
roundxyvec(177), -- nonstandard
pop(180),
dup(181),
copy(183),
roll(184),
exch(185),
mark(186),
unmark(187),
count(188),
unmark0(192),
abs(200),
add(201),
and(202),
ceiling(203),
div(204),
eq(205),
floor(206),
ge(207),
gt(208),
mod(209),
mul(210),
neg(211),
not(212),
or(213),
sub(214),
trunc(215),
rem(216),
round(217),
eqname(218), -- nonstandard
type(220),
atan(221), -- nonstandard
cos(222), -- nonstandard
exp(223), -- nonstandard
log(224), -- nonstandard
sin(225), -- nonstandard
sqrt(226), -- nonstandard
max(227), -- nonstandard
min(228), -- nonstandard
do(231),
dosave(232),
dosaveall(233),
if(239),
ifcopy(240),
ifelse(241),
loop(242), -- nonstandard
frame(250), -- nonstandard
env(260), -- nonstandard
makeveclu(282),
makevec(283),
openvec(284), -- nonstandard
shape(285),
getp(286),
getprop(287),
mergeprop(288),
dround(300), -- nonstandard
getcprounded(301), -- nonstandard
curveto(402),
arcto(403),
conicto(404),
maskfill(409),
maskrectangle(410),
masktrapezoidx(411),
masktrapezoidy(412),
startunderline(413),
maskunderline(414),
makeoutlineodd(416),
makeoutline(417),
clipoutline(418),
cliprectangle(419),
findcoloroperator(421),
findcolormodeloperator(422),
findcolor(423),
setgray(424),
makegray(425),
makesampledblack(426),
makesampledcolor(427),
setsampledblack(428),
setsampledcolor(429),
excludeoutline(430), -- nonstandard
excluderectangle(431), -- nonstandard
maskstrokeclosed(440),
maskvector(441),
maskdashedstroke(442),
makepixelarray(450),
extractpixelarray(451),
maskpixel(452),
joinpixelarrays(453), -- nonstandard
error(600),
(17777B)
};
ShortEncodingValue: TYPE ~ EncodingValue[VAL[0]..VAL[37B]]; -- 5 bits
SequenceType: TYPE ~ MACHINE DEPENDENT { -- 5 bits
nil(0),
sequenceString(1),
sequenceInteger(2),
sequenceReal(3), -- nonstandard
sequenceRational(4),
sequenceIdentifier(5),
sequenceComment(6),
sequenceContinued(7),
sequenceLargeVector(8),
sequencePackedPixelVector(9),
sequenceCompressedPixelVector(10),
sequenceInsertFile(11),
sequenceAdaptivePixelVector(12),
sequenceCCITT4PixelVector(13),
sequenceInsertMaster(14),
(37B)
};
ShortSequenceLength: TYPE ~ INT[0..377B]; -- 8 bits
LongSequenceLength: TYPE ~ INT--[0..77777777B]--; -- 24 bits
Errors, Utilities
ErrorDesc: TYPE ~ RECORD [code: ATOM, explanation: ROPE];
Error: ERROR [error: ErrorDesc];
EncodingValueFromOp: PROC [Op] RETURNS [EncodingValue];
Converts an Op to a Xerox encoding value.
OpFromEncodingValue: PROC [EncodingValue] RETURNS [Op];
Converts a Xerox encoding value to an Op. Returns nil if undefined.
OpFromEv: TYPE ~ REF READONLY OpFromEvArray;
OpFromEvArray: TYPE ~ PACKED ARRAY EncodingValue OF Op;
GetOpFromEv: PROC RETURNS [OpFromEv];
Returns a table for quick conversion of EncodingValues to Ops.
OpFromRope: PROC [ROPE] RETURNS [Op];
Converts a ROPE to an Op. Ignores case. Returns nil if undefined.
RopeFromOp: PROC [Op] RETURNS [ROPE];
Converts an Op to a ROPE. The result is all upper-case. Returns NIL if given nil.
RopeFromImagerVariable: PROC [ImagerVariable] RETURNS [ROPE];
Converts an ImagerVariable to a ROPE.
PartActionType: TYPE ~ PROC [base: ROPE, start, len: INT] RETURNS [quit: BOOLFALSE];
MapParts: PROC [base: ROPE, start: INT ← 0, len: INT ← MaxLen,
delimiter: CHAR, action: PartActionType] RETURNS [BOOL];
Applies action to each part of a subrope; delimiter separates parts.
Returns TRUE when some action returns TRUE.
For example, delimiter='/ parses a structured name, delimiter='. parses a version number.
ValidateIdentifier: PROC [rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Verifies that the specified subrope is a valid Identifier.
See the Interpress Standard, section 2.2.2.
! $invalidIdentifier if the identifier is empty or contains an illegal character.
ValidateName: PROC [rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Verifies that the specified subrope is a valid structured name.
See the Interpress Standard, section 3.2.1.
! $invalidIdentifier if the name contains an invalid identifier.
! $invalidName if the name is empty.
ValidateString: PROC [rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Verifies that the specified subrope is a valid Xerox string.
See the Character Code Standard, chapter 6, and the Interpress Standard, section 2.5.3.
! $invalidString if the string contains an invalid code or ends within an escape sequence.
ValidateVersion: PROC [rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Verifies that the specified subrope is a valid Interpress version number.
! $invalidVersion if the version number is malformed.
VersionFromRope: PROC [rope: ROPE, start: INT ← 0, len: INT ← MaxLen]
RETURNS
[Version];
Parses a Version number of the form "m.n".
! $invalidVersion if the version number is malformed.
CompareVersion: PROC [a, b: Version] RETURNS [Basics.Comparison];
Compares two version numbers.
Writing a master
PutShortNumber: PROC [stream: STREAM, n: ShortNumber];
Appends a ShortNumber token (2 bytes).
PutShortOp: PROC [stream: STREAM, op: ShortEncodingValue];
Appends a ShortOp token (1 byte).
PutLongOp: PROC [stream: STREAM, op: EncodingValue];
Appends a LongOp token (2 bytes).
PutShortSequence: PROC [stream: STREAM, seq: SequenceType, len: ShortSequenceLength];
Appends a ShortSequence token (2 bytes).
PutLongSequence: PROC [stream: STREAM, seq: SequenceType, len: LongSequenceLength];
Appends a LongSequence token (4 bytes).
ByteCount: TYPE ~ NAT[0..4];
BytesInInt: PROC [val: INT] RETURNS [ByteCount];
Returns the minimum number of bytes needed to represent val in two's complement.
PutIntBytes: PROC [stream: STREAM, val: INT, len: ByteCount];
Appends the low order len bytes of val.
PutByte: PROC [stream: STREAM, byte: BYTE];
Appends a single byte.
PutOp: PROC [stream: STREAM, op: EncodingValue];
Appends a primitive operator or symbol literal; chooses the shortest encoding.
PutSequence: PROC [stream: STREAM, seq: SequenceType, len: INT];
Appends a sequence descriptor; chooses the shortest encoding.
Must be followed immediately by len data bytes.
PutSequenceRope: PROC [stream: STREAM, seq: SequenceType,
rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Appends a sequence with data obtained from Rope.Map[rope, start, len].
PutSequenceText: PROC [stream: STREAM, seq: SequenceType,
text: REF READONLY TEXT, start: NAT ← 0, len: NAT ← MaxTextLen];
Appends a sequence with data obtained from RefText.Map[text, start, len].
PutInt: PROC [stream: STREAM, n: INT];
Appends an integer Number literal; chooses the shortest encoding.
PutRational: PROC [stream: STREAM, n, d: INT];
Appends a rational Number literal, n/d.
! $invalidRational if d is zero.
PutReal: PROC [stream: STREAM, val: REAL];
Appends a Number literal. Chooses a rational approximation if necessary.
PutIdentifier: PROC [stream: STREAM, rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Appends an Identifier literal. See the Interpress Standard, section 2.2.2.
! $invalidIdentifier if the identifier is malformed.
PutString: PROC [stream: STREAM, rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Appends the encoding notation for a string. Treats '\377 as an escape code.
! $invalidString if the string is malformed.
PutName: PROC [stream: STREAM, rope: ROPE, start: INT ← 0, len: INT ← MaxLen];
Appends literals to build a structured name (a Vector of Identifiers).
PutName[stream, "Xerox/XC1-1-1/Classic"] appends < Xerox XC1-1-1 Classic 3 MAKEVEC >.
See the Interpress Standard, section 3.2.1.
! $invalidIdentifier if the name contains a malformed identifier.
Reading a master
TokenType: TYPE ~ {nil, op, num, seq};
Token: TYPE ~ RECORD [
index: INT ← 0, -- stream index of token's first byte
type: TokenType ← nil, -- token type
op: EncodingValue ← nil, -- op value, if type=op (nil otherwise)
num: INTEGER ← 0, -- number value, if type=num (0 otherwise)
seq: SequenceType ← nil, -- sequence type, if type=seq (nil otherwise)
len: INT ← 0 -- sequence data length, if type=seq (0 otherwise)
];
Body: TYPE ~ REF BodyRep;
BodyRep: TYPE ~ RECORD [index, length: INT];
Node: TYPE ~ REF NodeRep;
NodeRep: TYPE ~ RECORD [
index, length: INT,
bodyOrBlock: SELECT tag: * FROM
body => [body: Body],
block => [block: Block],
ENDCASE
];
Block: TYPE ~ REF BlockRep;
BlockRep: TYPE ~ RECORD [
index, length: INT,
preamble: Node,
nodes: SEQUENCE size: NAT OF Node
];
Skeleton: TYPE ~ REF SkeletonRep;
SkeletonRep: TYPE ~ RECORD [
instructions: Body, -- may be NIL
topBlock: Block
];
GetHeader: PROC [stream: STREAM, prefix: ROPE] RETURNS [ROPE];
First reads prefix.Length[] chars, which must match prefix (typically "Interpress/").
Then reads up to the first space; leaves the stream positioned after the space.
Returns the characters between the prefix and the space (for example, "Xerox/2.1").
! $invalidHeader if the prefix doesn't match.
GetSkeleton: PROC [stream: STREAM] RETURNS [Skeleton];
Parses the skeleton structure of the master, starting at the current stream index.
! $invalidSkeleton if the skeleton is malformed.
CountPages: PROC [block: Block] RETURNS [INT];
Counts the number of page bodies contained in a block.
GetToken: PROC [stream: STREAM, flushComments: BOOLTRUE] RETURNS [Token];
Reads from the stream a token in the Xerox encoding. See Interpress, section 2.5.1.
If token.type=seq, caller must read token.len data bytes from stream to reach next token.
If flushComments, skips over comments (sequenceComment and any continuations).
SkipBytes: PROC [stream: STREAM, len: INT];
Skips len bytes in the stream; equivalent to IO.SetIndex[stream, IO.GetIndex[stream]+len].
SetIndex: PROC [stream: STREAM, index: INT];
Same as IO.SetIndex[stream, index]. Here for convenience.
SkipToEndOfBody: PROC [stream: STREAM];
Skips literals to the end of the enclosing body.
Leaves the stream positioned at the token following the body.
CopyBytes: PROC [to: STREAM, from: STREAM, count: INT] RETURNS [copied: INT];
Copies bytes to an output stream from an input stream.
Returns the actual number of bytes copied.
CopySegment: PROC [to: STREAM, from: STREAM, start, length: INT];
Does SetIndex[from, start], then copies length bytes.
! IO.EndOfStream[from] if too few bytes were copied.
IntFromSequenceData: PROC [text: REF READONLY TEXT,
start: NAT ← 0, len: NAT ← MaxTextLen] RETURNS [INT];
RealFromSequenceData: PROC [text: REF READONLY TEXT,
start: NAT ← 0, len: NAT ← MaxTextLen] RETURNS [REAL];
These interpret text[start..start+len) as a two's complement binary integer.
END.