<> <> DIRECTORY ImagerBasic, ImagerPixelMaps, ImagerFrameBuffer, Process, ImagerScanConverter, Random, Inline, ImagerStroke, ImagerConic, Real; 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.