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;
};