ColorEditOpsImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Eric Nickell, January 7, 1986 8:43:23 am PST
DIRECTORY
ColorEditOps,
FS USING [StreamOpen],
IO USING [Close, GetChar, EndOf, PutChar, RIS, ROS, RopeFromROS, STREAM],
SampleMapOps USING [Clear, DoWithScratch, Fill, GetSample],
SelectRegions USING [ApplyTRC, nullRectangle, TRCSequence, TRCSequenceRep];
ColorEditOpsImpl: CEDAR PROGRAM
IMPORTS FS, IO, SampleMapOps, SelectRegions
EXPORTS ColorEditOps
~ BEGIN
OPEN ColorEditOps;
LogApply: PUBLIC PROC [trc: REF TRC, sm: SampleMap, extent: Rectangle] RETURNS [rope: ROPE] ~ {
Converts the parameters for an Apply into a rope
stream: IO.STREAM ~ IO.ROS[];
FOR i: NAT IN [0..256) DO
IO.PutChar[self: stream, char: VAL[trc[i]]];
ENDLOOP;
SaveExtentOfMaskToStream[stream: stream, mask: sm, extent: extent];
rope ← IO.RopeFromROS[self: stream];
};
ApplyLog: PUBLIC PROC [changeLog: ROPE, sa: SampleArray] ~ {
Apply the logged information currently in data.changeLog
ApplyLogAction: PROC [sm: SampleMap] ~ {
stream: IO.STREAM ~ IO.RIS[rope: changeLog];
trcs: SelectRegions.TRCSequence ~ NEW[SelectRegions.TRCSequenceRep[sa.n]];
trc: REF TRC ~ NEW[TRC];
extent: Rectangle;
FOR i: NAT IN [0..trcs.n) DO
trcs[i] ← trc;
ENDLOOP;
UNTIL IO.EndOf[self: stream] DO
FOR i: NAT IN [0..256) DO
trc[i] ← LOOPHOLE[IO.GetChar[self: stream]];
ENDLOOP;
extent ← ReadExtentOfMaskFromStream[stream: stream, mask: sm];
SelectRegions.ApplyTRC[sm, sa, trcs, extent];
ENDLOOP;
};
SampleMapOps.DoWithScratch[sSize: sa.sSize, fSize: sa.fSize, bitsPerSample: 1, action: ApplyLogAction];
};
extentFilePassword: CARDINAL ~ 30346;
SaveExtentOfMask: PUBLIC PROC [mask: SampleMap, extent: Rectangle, fileName: ROPE] ~ {
file: IO.STREAM ~ FS.StreamOpen[fileName: fileName, accessOptions: create];
SaveExtentOfMaskToStream[file, mask, extent];
IO.Close[self: file];
};
ReadExtentOfMask: PUBLIC PROC [mask: SampleMap, fileName: ROPE] RETURNS [extent: Rectangle] ~ {
file: IO.STREAM ~ FS.StreamOpen[fileName: fileName];
extent ← ReadExtentOfMaskFromStream[file, mask];
};
SaveExtentOfMaskToStream: PUBLIC PROC [stream: IO.STREAM, mask: SampleMap, extent: Rectangle] ~ {
PutCardinal: PROC [cardinal: CARDINAL] ~ {
IO.PutChar[self: stream, char: VAL[cardinal/256]];
IO.PutChar[self: stream, char: VAL[cardinal MOD 256]];
};
bitsPerSample: [1..1] ~ mask.bitsPerSample;
currentValue: CARDINAL ← 0;
currentCount: CARDINAL ← 0;
PutCardinal[extentFilePassword];
PutCardinal[mask.sSize];
PutCardinal[mask.fSize];
PutCardinal[extent.sMin];
PutCardinal[extent.sMax];
PutCardinal[extent.fMin];
PutCardinal[extent.fMax];
IF extent#SelectRegions.nullRectangle THEN {
FOR s: CARDINAL IN [extent.sMin .. extent.sMax] DO
FOR f: CARDINAL IN [extent.fMin .. extent.fMax] DO
sample: CARDINAL ~ SampleMapOps.GetSample[sampleMap: mask, index: [s: s, f: f]];
SELECT TRUE FROM
sample#currentValue => {
PutCardinal[currentCount];
currentCount ← 1;
currentValue ← 1 - currentValue;
};
currentCount = CARDINAL.LAST-1 => {
PutCardinal[CARDINAL.LAST];
currentCount ← 0;
currentValue ← 1 - currentValue;
};
ENDCASE => currentCount ← currentCount+1;
ENDLOOP;
ENDLOOP;
};
IF currentCount#0 THEN PutCardinal[currentCount];
PutCardinal[extentFilePassword];  --Pad with the password
};
ReadExtentOfMaskFromStream: PUBLIC PROC [stream: IO.STREAM, mask: SampleMap] RETURNS [extent: Rectangle] ~ {
GetCardinal: PROC RETURNS [CARDINAL] ~ {
hi: CARDINAL ~ LOOPHOLE[IO.GetChar[self: stream]];
lo: CARDINAL ~ LOOPHOLE[IO.GetChar[self: stream]];
RETURN [hi*256 + lo];
};
bitsPerSample: [1..1] ~ mask.bitsPerSample;
currentValue: CARDINAL ← 0;
currentCount: CARDINAL ← 0;
IF GetCardinal[] # extentFilePassword THEN ERROR;
IF GetCardinal[] # mask.sSize THEN ERROR;
IF GetCardinal[] # mask.fSize THEN ERROR;
extent.sMin ← GetCardinal[];
extent.sMax ← GetCardinal[];
extent.fMin ← GetCardinal[];
extent.fMax ← GetCardinal[];
SampleMapOps.Clear[mask];
IF extent=SelectRegions.nullRectangle THEN RETURN;
currentCount ← GetCardinal[];
FOR s: CARDINAL IN [extent.sMin .. extent.sMax] DO
f: CARDINAL ← extent.fMin;
WHILE f ~> extent.fMax DO
count: CARDINALMIN[currentCount, extent.fMax+1-f];
IF currentValue=1 THEN SampleMapOps.Fill[dest: [sampleMap: mask, start: [s: s, f: f], size: [s: 1, f: count]], value: 1];
f ← f+count;
currentCount ← currentCount - count;
IF currentCount=0 THEN {
currentValue ← 1-currentValue;
currentCount ← GetCardinal[];
};
ENDLOOP;
ENDLOOP;
IF currentCount # extentFilePassword THEN ERROR;
};
END.