BlobKineticImpl:
CEDAR
PROGRAM
IMPORTS ImagerPixelMaps, ImagerFrameBuffer, Process, ImagerScanConverter, Random, Inline, ImagerStroke, ImagerConic, Real
~ TRUSTED BEGIN
identity: ImagerBasic.Transformation ~ [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, identity];
Pair: TYPE ~ ImagerBasic.Pair;
running: BOOLEAN ← FALSE;
pauseTime: Process.Milliseconds ← 5;
type: {blob, polygon} ← blob;
maxStrokeWidth: INT ← 30;
parityFill: BOOLEAN ← FALSE;
colorDisplay: ImagerPixelMaps.PixelMap ← ImagerFrameBuffer.ColorDisplay8[];
clippedDisplay: ImagerPixelMaps.PixelMap ← colorDisplay;
rCount: CARDINAL ← 0;
crosses: BOOLEAN ← TRUE;
Shift: PROC [a: CARDINAL, c: INTEGER] RETURNS [CARDINAL] ~ CHECKED {RETURN [Inline.BITSHIFT[a, c]]};
BITAND: PROC [a, b: CARDINAL] RETURNS [CARDINAL] ~ CHECKED {RETURN [Inline.BITAND[a, b]]};
ChooseReal:
PROC [max:
INT]
RETURNS [r:
REAL] ~
CHECKED {
scale: CARDINAL ← 1;
rCount ← rCount + 1;
IF rCount = 0 THEN rCount ← 1;
UNTIL
BITAND[rCount, scale] # 0
DO
scale ← scale + 1;
ENDLOOP;
r ← Random.Choose[0, max*scale];
r ← r/scale;
IF rCount
MOD 7 = 0
THEN {
epsilon: REAL ← 1.0/(65536.0*65536.0);
UNTIL r+epsilon # r DO epsilon ← epsilon*2 ENDLOOP;
IF rCount MOD 5 = 0 THEN r ← r+epsilon ELSE r ← r-epsilon;
};
};
Init:
PROC ~
CHECKED {
ImagerPixelMaps.Clear[colorDisplay];
[] ← Random.Init[];
running ← TRUE;
};
strokeEndChoices: ARRAY [0..2] OF ImagerBasic.StrokeEnd ~ [square, butt, round];
Run:
PROC ~
CHECKED {
devicePath: ImagerScanConverter.DevicePath;
maxSampleValue: CARDINAL ~ Shift[1, Shift[1, colorDisplay.refRep.lgBitsPerPixel]]-1;
running ← TRUE;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE running
DO
s: ARRAY [0..15) OF REAL;
f: ARRAY [0..15) OF REAL;
BlobProc:
SAFE
PROC [move:
PROC [s, f:
REAL], line:
PROC [s, f:
REAL], curve:
PROC [s1, f1, s2, f2, s3, f3:
REAL]] ~
CHECKED {
move[s[0], f[0]];
FOR i:
NAT ← 1, i+3
WHILE i<13
DO
curve[s[i], f[i], s[i+1], f[i+1], s[i+2], f[i+2]];
ENDLOOP;
curve[s[13], f[13], s[14], f[14], s[0], f[0]];
};
PolygonProc:
SAFE
PROC [move:
PROC [s, f:
REAL], line:
PROC [s, f:
REAL], curve:
PROC [s1, f1, s2, f2, s3, f3:
REAL]] ~
CHECKED {
move[s[0], f[0]];
FOR i:
NAT
IN [1..15)
DO
line[s[i], f[i]];
ENDLOOP;
};
FOR i:
NAT
IN [0..15)
DO
s[i] ← ChooseReal[colorDisplay.sSize];
f[i] ← ChooseReal[colorDisplay.fSize];
ENDLOOP;
IF type = blob
THEN {
s[0] ← (s[1]+s[14])/2.0;
f[0] ← (f[1]+f[14])/2.0;
FOR i:
NAT ← 3, i+3
WHILE i<15
DO
s[i] ← (s[i+1]+s[i-1])/2.0;
f[i] ← (f[i+1]+f[i-1])/2.0;
ENDLOOP;
devicePath ← ImagerScanConverter.CreatePath[BlobProc, clippedDisplay.Window, devicePath];
}
ELSE devicePath ← ImagerScanConverter.CreatePath[PolygonProc, clippedDisplay.Window, devicePath];
devicePath.ConvertToPixels[clippedDisplay, Random.Choose[0, maxSampleValue], parityFill];
Process.Pause[Process.MsecToTicks[pauseTime]];
ENDLOOP;
};
SF:
TYPE ~
RECORD [
closed: BOOLEAN,
s: ARRAY [0..15) OF REAL,
f: ARRAY [0..15) OF REAL
];
PathMap:
SAFE
PROC[
data: REF,
move: PROC[p: Pair],
line: PROC[p: Pair],
curve: PROC[p1, p2, p3: Pair],
conic: PROC[p1, p2: Pair, r: REAL]
] ~
CHECKED {
sf: REF SF ← NARROW[data];
{
OPEN sf^;
move[[s[0], f[0]]];
FOR i:
NAT ← 1, i+3
WHILE i<13
DO
curve[[s[i], f[i]], [s[i+1], f[i+1]], [s[i+2], f[i+2]]];
ENDLOOP;
IF closed THEN curve[[s[13], f[13]], [s[14], f[14]], [s[0], f[0]]];
};
};
Spaghetti:
PROC ~
CHECKED {
devicePath: ImagerScanConverter.DevicePath;
maxSampleValue: CARDINAL ~ Shift[1, Shift[1, colorDisplay.refRep.lgBitsPerPixel]]-1;
sf: REF SF ← NEW[SF];
running ← TRUE;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE running
DO
OPEN sf^;
closed ← Random.Choose[0, 1] = 0;
FOR i:
NAT
IN [0..15)
DO
s[i] ← ChooseReal[colorDisplay.sSize];
f[i] ← ChooseReal[colorDisplay.fSize];
ENDLOOP;
s[0] ← (s[1]+s[14])/2.0;
f[0] ← (f[1]+f[14])/2.0;
FOR i:
NAT ← 3, i+3
WHILE i<15
DO
s[i] ← (s[i+1]+s[i-1])/2.0;
f[i] ← (f[i+1]+f[i-1])/2.0;
ENDLOOP;
devicePath ← ImagerStroke.DevicePathFromStroke[
pathMap: PathMap,
pathData: sf,
clientToDevice: identity,
width: Random.Choose[1, maxStrokeWidth],
strokeEnd: strokeEndChoices[Random.Choose[0, 2]],
closed: closed,
clipBox: [0,0,10000,10000],
scratch: devicePath
];
devicePath.ConvertToPixels[clippedDisplay, Random.Choose[0, maxSampleValue], parityFill];
Process.Pause[Process.MsecToTicks[pauseTime]];
ENDLOOP;
};
ArcData:
TYPE ~
RECORD [
s: ARRAY [0..3) OF REAL,
f: ARRAY [0..3) OF REAL,
vs: ARRAY [0..3) OF REAL,
vf: ARRAY [0..3) OF REAL
];
ArcMap:
PROC [
data: REF,
move: PROC[p: Pair],
line: PROC[p: Pair],
curve: PROC[p1, p2, p3: Pair],
conic: PROC[p1, p2: Pair, r: REAL]
] ~ CHECKED {
arcData: REF ArcData ← NARROW[data];
move[[arcData.s[0],arcData.f[0]]];
ImagerConic.FromArc[[arcData.s[0],arcData.f[0]], [arcData.s[1],arcData.f[1]], [arcData.s[2],arcData.f[2]], conic]
};
Cross:
PROC [s, f:
REAL] ~
CHECKED {
IF crosses
THEN {
maxSampleValue: CARDINAL ~ Shift[1, Shift[1, colorDisplay.refRep.lgBitsPerPixel]]-1;
si: INTEGER ~ Real.RoundLI[s];
fi: INTEGER ~ Real.RoundLI[f];
colorDisplay.Fill[[si-3, fi-3, 6, 6], maxSampleValue];
colorDisplay.Fill[[si-5, fi-1, 10, 2], 0];
colorDisplay.Fill[[si-1, fi-5, 2, 10], 0];
};
};
Rainbow:
PROC [speed:
REAL ← 5.0] ~
CHECKED {
devicePath: ImagerScanConverter.DevicePath;
maxSampleValue: CARDINAL ~ Shift[1, Shift[1, colorDisplay.refRep.lgBitsPerPixel]]-1;
arcData: REF ArcData ← NEW[ArcData];
ChangeControlPoints:
SAFE
PROC ~
CHECKED {
OPEN arcData^;
FOR i:
NAT
IN [0..3)
DO
s[i] ← s[i] + vs[i];
IF s[i] > colorDisplay.sSize+colorDisplay.sMin
THEN {
s[i] ← colorDisplay.sSize+colorDisplay.sMin - (s[i]-colorDisplay.sSize-colorDisplay.sMin);
vs[i] ← -vs[i];
};
IF s[i] < colorDisplay.sMin
THEN {
s[i] ← colorDisplay.sMin+(colorDisplay.sMin-s[i]);
vs[i] ← -vs[i];
};
f[i] ← f[i] + vf[i];
IF f[i] > colorDisplay.fSize+colorDisplay.fMin
THEN {
f[i] ← colorDisplay.fSize+colorDisplay.fMin - (f[i]-colorDisplay.fSize-colorDisplay.fMin);
vf[i] ← -vf[i];
};
IF f[i] < colorDisplay.fMin
THEN {
f[i] ← colorDisplay.fMin+(colorDisplay.fMin-f[i]);
vf[i] ← -vf[i];
};
ENDLOOP;
};
FOR i:
NAT
IN [0..3)
DO
arcData.s[i] ← colorDisplay.sSize/2;
arcData.f[i] ← colorDisplay.fSize/2;
arcData.vs[i] ← ((Random.Choose[0, 2000]-1000)/1000.0)*speed;
arcData.vf[i] ← ((Random.Choose[0, 2000]-1000)/1000.0)*speed;
ENDLOOP;
running ← TRUE;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE running
DO
ChangeControlPoints[];
devicePath ← ImagerStroke.DevicePathFromStroke[
pathMap: ArcMap,
pathData: arcData,
clientToDevice: identity,
width: maxStrokeWidth,
strokeEnd: butt,
closed: FALSE,
clipBox: [0,0,10000,10000],
scratch: devicePath
];
devicePath.ConvertToPixels[clippedDisplay, Random.Choose[0, maxSampleValue], parityFill];
Cross[arcData.s[0], arcData.f[0]]; Cross[arcData.s[1], arcData.f[1]]; Cross[arcData.s[2], arcData.f[2]];
Process.Pause[Process.MsecToTicks[pauseTime]];
ENDLOOP;
};
SwimRec: TYPE ~ RECORD [pxlValue: CARDINAL, running, blob: BOOLEAN ← TRUE, window: ImagerPixelMaps.DeviceRectangle];
Swim:
PROC [speed:
REAL ← 5.0, pxlValue:
CARDINAL ← 23, window: ImagerPixelMaps.DeviceRectangle ← [0, 0, 480, 640], blob:
BOOLEAN ←
TRUE]
RETURNS [data:
REF SwimRec] ~
TRUSTED {
data ← NEW [SwimRec];
data.pxlValue ← pxlValue;
data.window ← window;
data.running ← TRUE;
data.blob ← blob;
Process.Detach[FORK SwimProcess[speed, data]];
};
SwimProcess:
PROC [speed:
REAL ← 5.0, data:
REF SwimRec] ~
CHECKED {
devicePath: ImagerScanConverter.DevicePath;
maxSampleValue: CARDINAL ~ Shift[1, Shift[1, colorDisplay.refRep.lgBitsPerPixel]]-1;
s: ARRAY [0..15) OF REAL;
f: ARRAY [0..15) OF REAL;
vs: ARRAY [0..15) OF REAL;
vf: ARRAY [0..15) OF REAL;
ChangeControlPoints:
SAFE
PROC ~
CHECKED {
FOR i:
NAT
IN [0..15)
DO
s[i] ← s[i] + vs[i];
IF s[i] > data.window.sSize+data.window.sMin
THEN {
s[i] ← data.window.sSize+data.window.sMin - (s[i]-data.window.sSize-data.window.sMin);
vs[i] ← -vs[i];
};
IF s[i] < data.window.sMin
THEN {
s[i] ← data.window.sMin+(data.window.sMin-s[i]);
vs[i] ← -vs[i];
};
f[i] ← f[i] + vf[i];
IF f[i] > data.window.fSize+data.window.fMin
THEN {
f[i] ← data.window.fSize+data.window.fMin - (f[i]-data.window.fSize-data.window.fMin);
vf[i] ← -vf[i];
};
IF f[i] < data.window.fMin
THEN {
f[i] ← data.window.fMin+(data.window.fMin-f[i]);
vf[i] ← -vf[i];
};
ENDLOOP;
};
FOR i:
NAT
IN [0..15)
DO
s[i] ← colorDisplay.sSize/2;
f[i] ← colorDisplay.fSize/2;
vs[i] ← ((Random.Choose[0, 2000]-1000)/1000.0)*speed;
vf[i] ← ((Random.Choose[0, 2000]-1000)/1000.0)*speed;
ENDLOOP;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE data.running
DO
BlobProc:
SAFE
PROC [move:
PROC [s, f:
REAL], line:
PROC [s, f:
REAL], curve:
PROC [s1, f1, s2, f2, s3, f3:
REAL]] ~
CHECKED {
move[s[0], f[0]];
FOR i:
NAT ← 1, i+3
WHILE i<13
DO
curve[s[i], f[i], s[i+1], f[i+1], s[i+2], f[i+2]];
ENDLOOP;
curve[s[13], f[13], s[14], f[14], s[0], f[0]];
ChangeControlPoints[];
s[0] ← (s[1]+s[14])/2.0;
f[0] ← (f[1]+f[14])/2.0;
FOR i:
NAT ← 3, i+3
WHILE i<15
DO
s[i] ← (s[i+1]+s[i-1])/2.0;
f[i] ← (f[i+1]+f[i-1])/2.0;
ENDLOOP;
move[s[0], f[0]];
FOR i:
NAT ← 1, i+3
WHILE i<13
DO
curve[s[i], f[i], s[i+1], f[i+1], s[i+2], f[i+2]];
ENDLOOP;
curve[s[13], f[13], s[14], f[14], s[0], f[0]];
};
PolygonProc:
SAFE
PROC [move:
PROC [s, f:
REAL], line:
PROC [s, f:
REAL], curve:
PROC [s1, f1, s2, f2, s3, f3:
REAL]] ~
CHECKED {
move[s[0], f[0]];
FOR i:
NAT
IN [1..15)
DO
line[s[i], f[i]];
ENDLOOP;
ChangeControlPoints[];
move[s[0], f[0]];
FOR i:
NAT
IN [1..15)
DO
line[s[i], f[i]];
ENDLOOP;
};
IF data.blob
THEN {
devicePath ← ImagerScanConverter.CreatePath[BlobProc, clippedDisplay.Window, devicePath];
}
ELSE devicePath ← ImagerScanConverter.CreatePath[PolygonProc, clippedDisplay.Window, devicePath];
devicePath.ConvertToPixels[clippedDisplay, data.pxlValue, TRUE, [xor, null]];
Process.Pause[Process.MsecToTicks[pauseTime]];
ENDLOOP;
};
END.