CustomBrickImpl.mesa
Copyright Ó 1988, 1991 by Xerox Corporation. All rights reserved.
Dave Rumph, August 11, 1988 0:06:06 am PDT
Michael Plass, October 26, 1991 10:20 pm PDT
DIRECTORY
Ascii,
Convert USING [Error, IntFromRope, RealFromRope],
CustomBrick,
ImagerBrick USING [Brick],
ImagerSample USING [NewSampleMap, Put],
IO USING [CharClass, EndOfStream, GetTokenRope, PutFR, RIS, STREAM],
PrintColor USING [HalftoneProperties, Toner, TonerUniverse],
Real USING [Round],
Rope USING [Cat, Concat, Equal, ROPE],
RuntimeError USING [UNCAUGHT];

CustomBrickImpl: CEDAR PROGRAM
IMPORTS Convert, ImagerSample, IO, Real, Rope, RuntimeError
EXPORTS CustomBrick
~ BEGIN
Bound: TYPE ~ RECORD [first, last: INT];
int: Bound ~ [INT.FIRST, INT.LAST];
nat: Bound ~ [NAT.FIRST, NAT.LAST];
card: Bound ~ [CARD16.FIRST, CARD16.LAST];
ROPE: TYPE ~ Rope.ROPE;
HalftoneProperties: TYPE ~ PrintColor.HalftoneProperties;
Toner: TYPE ~ PrintColor.Toner;
Brick: TYPE ~ ImagerBrick.Brick;
Complain: PROC [rope: ROPE] ~ {
Body
};
HalftonePropertiesFromRope: PUBLIC PROC [specs: ROPE, tonerUniverse: PrintColor.TonerUniverse] RETURNS [h: HalftoneProperties] ~ {
RETURNS RECORD [type: ATOM, toner: Toner, brick: ImagerBrick.Brick]
CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = {
IF char = '← OR char = '[ OR char = '] THEN RETURN [break];
RETURN [
SELECT char FROM Ascii.SP, Ascii.TAB, ',, ';, Ascii.LF, Ascii.CR => sepr ENDCASE => other
]
};
GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE] = {
rope ¬ NIL;
rope ¬ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token;
};
RealToNum: PROC [real: REAL, bounds: Bound ¬ int, name: ROPE ¬ NIL] RETURNS [number: INT ¬ 0] ~ {
IF name=NIL THEN name ¬ "Value";
number ¬ Real.Round[real ! RuntimeError.UNCAUGHT => CONTINUE];
IF real#number THEN Complain[IO.PutFR[format: "%g (%g) should be integral.", v1: [rope [name]], v2: [real [real]]]];
IF number NOT IN [bounds.first .. bounds.last] THEN Complain[IO.PutFR[format: "Value (%g) should be in range [%g .. %g]", v1: [rope [name]], v2: [integer [bounds.first]], v3: [integer [bounds.last]]]];
};
RealFromRope: PROC [rope: ROPE] RETURNS [real: REAL] = {
oops: BOOL ¬ FALSE;
real ¬ Convert.RealFromRope[rope ! Convert.Error => {oops ¬ TRUE; CONTINUE}];
IF oops THEN {oops ¬ FALSE; real ¬ Convert.IntFromRope[rope ! Convert.Error => {oops ¬ TRUE; CONTINUE}]};
IF oops THEN Complain[Rope.Concat["Number expected: ", rope]];
};
ParseBrick: PROC ~ {
a: REF ARRAY [0..1000) OF INT ¬ NEW[ARRAY [0..1000) OF INT];
sSize: NAT ¬ 0;
fSize: NAT ¬ 0;
phase: NAT ¬ 0;
maxSample: CARDINAL ¬ 0;
toner: Toner ¬ black;
n: NAT ¬ 0;
brick: REF Brick ¬ NEW[Brick];
tok ¬ GetCmdToken[cmds];
WHILE Rope.Equal[tok, "["] DO
tok ¬ GetCmdToken[cmds];
WHILE tok # NIL AND NOT Rope.Equal[tok, "]"] DO
val: INT ~ RealToNum[RealFromRope[tok], nat];
a[n] ¬ val;
n ¬ n + 1;
IF sSize = 0 THEN fSize ¬ fSize + 1;
tok ¬ GetCmdToken[cmds];
ENDLOOP;
sSize ¬ sSize + 1;
IF n MOD fSize # 0 THEN Complain["Malformed array"];
tok ¬ GetCmdToken[cmds];
ENDLOOP;
IF Rope.Equal[tok, "]"] THEN tok ¬ GetCmdToken[cmds] ELSE Complain["Malformed array"];
phase ¬ RealToNum[RealFromRope[tok], card]; tok ¬ GetCmdToken[cmds];
maxSample ¬ RealToNum[RealFromRope[tok], card]; tok ¬ GetCmdToken[cmds];
SELECT TRUE FROM
Rope.Equal[tok, "black", FALSE] => toner ¬ black;
Rope.Equal[tok, "cyan", FALSE] => toner ¬ cyan;
Rope.Equal[tok, "magenta", FALSE] => toner ¬ magenta;
Rope.Equal[tok, "yellow", FALSE] => toner ¬ yellow;
ENDCASE => Complain[Rope.Cat["Expected toner name, but found \"", tok, "\""]];
tok ¬ GetCmdToken[cmds];
IF NOT Rope.Equal[tok, "brick", FALSE] THEN Complain["Missing \"brick\" Keyword"];
brick.maxSample ¬ maxSample;
brick.sampleMap ¬ ImagerSample.NewSampleMap[box: [max: [sSize, fSize]], bitsPerSample: IF maxSample > 255 THEN BITS[CARDINAL] ELSE 8];
brick.phase ¬ phase;
FOR s: NAT IN [0..sSize) DO
FOR f: NAT IN [0..fSize) DO
val: NAT ~ a[s*fSize+f];
IF val NOT IN [0..maxSample] THEN Complain["Brick values should be IN [0..maxSample]"];
ImagerSample.Put[map: brick.sampleMap, index: [s, f], value: val];
ENDLOOP;
ENDLOOP;
IF tonerUniverse[toner] THEN h ¬ CONS[[type: NIL, toner: toner, brick: brick­], h];
};
cmds: IO.STREAM ¬ IO.RIS[rope: specs];
tok: ROPE ¬ NIL;
h ¬ NIL;
UNTIL (tok ¬ GetCmdToken[cmds]) = NIL DO
IF Rope.Equal["[", tok] THEN ParseBrick[];
ENDLOOP;
};
END.