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. BBlobKineticImpl.mesa Michael Plass, October 3, 1983 2:37 pm Ê à˜J™J™&JšÏk œ€˜‰šœœ˜Jšœr˜yJšœœ˜JšœP˜PJšœœ˜Jšœ œœ˜J˜$J˜Jšœœ˜Jšœ œœ˜JšœK˜KJšœ8˜8Jšœœ˜Jšœ œœ˜JšÏnœœœœœœœœ œ ˜dJšœœœœœœœ œ ˜Zš ž œœœœœœ˜9Jšœœ˜Jšœ˜Jšœ œ ˜šœœ˜"J˜Jšœ˜—Jšœ ˜ Jšœ ˜ šœœœ˜Jšœ œ˜&Jšœœœ˜3Jšœœœœ˜:Jšœ˜—Jšœ˜—šžœœœ˜Jšœ$˜$J˜Jšœ œ˜Jšœ˜—Jšœœœ/˜Pšžœœœ˜Jšœ+˜+Jšœœ<˜TJšœ œ˜Jšœ3˜:šœ ˜Jšœœ œœ˜Jšœœ œœ˜šžœœœœœ œœ œœœ˜~Jšœ˜šœœ œ˜!Jšœ2˜2Jšœ˜—Jšœ.˜.Jšœ˜—šž œœœœœ œœ œœœ˜Jšœ˜šœœœ ˜Jšœ˜Jšœ˜—Jšœ˜—šœœœ ˜Jšœ&˜&Jšœ&˜&Jšœ˜—šœ œ˜Jšœ˜Jšœ˜šœœ œ˜!Jšœ˜Jšœ˜Jšœ˜—JšœY˜YJšœ˜—Jšœ]˜aJšœY˜YJ˜.Jšœ˜—Jšœ˜—šœœœ˜Jšœœ˜Jšœœ œœ˜Jšœœ œ˜Jšœ˜—šžœœœ˜Jšœœ˜ Jšœœ ˜Jšœœ ˜Jšœœ˜Jšœœœ˜"šœœ˜ Jšœœœœ˜šœœ˜ Jšœ˜šœœ œ˜!Jšœ8˜8Jšœ˜—Jšœœ5˜CJ˜—Jšœ˜——šž œœœ˜Jšœ+˜+Jšœœ<˜TJš œœœœœ˜Jšœ œ˜Jšœ3˜:šœ ˜Jšœ˜ Jšœ!˜!šœœœ ˜Jšœ&˜&Jšœ&˜&Jšœ˜—Jšœ˜Jšœ˜šœœ œ˜!Jšœ˜Jšœ˜Jšœ˜—šœ/˜/Jšœ˜Jšœ ˜ Jšœ˜Jšœ(˜(Jšœ1˜1Jšœ˜J˜Jšœ˜J˜—JšœY˜YJ˜.Jšœ˜—Jšœ˜—šœ œœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœ˜Jšœ˜—šžœœ˜Jšœœ˜ Jšœœ ˜Jšœœ ˜Jšœœ˜Jšœœœ˜"Jšœœ˜ Jšœ œ œ˜$Jšœ"˜"Jšœq˜qJšœ˜—šžœœœœ˜$šœ œ˜Jšœœ<˜TJšœœ˜Jšœœ˜Jšœ6˜6Jšœ*˜*Jšœ*˜*Jšœ˜—Jšœ˜—šžœœ œ œ˜-Jšœ+˜+Jšœœ<˜TJšœ œ œ ˜$šžœœœœ˜*Jšœ ˜šœœœ˜Jšœ˜šœ-œ˜5JšœZ˜ZJšœ˜Jšœ˜—šœœ˜"Jšœ2˜2Jšœ˜Jšœ˜—Jšœ˜šœ-œ˜5JšœZ˜ZJšœ˜Jšœ˜—šœœ˜"Jšœ2˜2Jšœ˜Jšœ˜—Jšœ˜—Jšœ˜—šœœœ˜Jšœ$˜$Jšœ$˜$Jšœ=˜=Jšœ=˜=Jšœ˜—Jšœ œ˜Jšœ3˜:šœ ˜Jšœ˜šœ/˜/Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜J˜Jšœ˜J˜—JšœY˜YJšœi˜iJ˜.Jšœ˜—Jšœ˜—Jš œ œœ œœœ)˜tšžœœ œœIœœœœ œ˜±Jšœœ ˜Jšœ˜Jšœ˜Jšœœ˜J˜Jšœœ˜.Jšœ˜—š ž œœ œœ œ˜DJšœ+˜+Jšœœ<˜TJšœœ œœ˜Jšœœ œœ˜Jšœœ œœ˜Jšœœ œœ˜šžœœœœ˜*šœœœ ˜Jšœ˜šœ+œ˜3JšœV˜VJšœ˜Jšœ˜—šœœ˜!Jšœ0˜0Jšœ˜Jšœ˜—Jšœ˜šœ+œ˜3JšœV˜VJšœ˜Jšœ˜—šœœ˜!Jšœ0˜0Jšœ˜Jšœ˜—Jšœ˜—Jšœ˜—šœœœ ˜Jšœ˜Jšœ˜Jšœ5˜5Jšœ5˜5Jšœ˜—Jšœ3˜:šœ˜šžœœœœœ œœ œœœ˜~Jšœ˜šœœ œ˜!Jšœ2˜2Jšœ˜—Jšœ.˜.J˜Jšœ˜Jšœ˜šœœ œ˜!Jšœ˜Jšœ˜Jšœ˜—Jšœ˜šœœ œ˜!Jšœ2˜2Jšœ˜—Jšœ.˜.Jšœ˜—šž œœœœœ œœ œœœ˜Jšœ˜šœœœ ˜Jšœ˜Jšœ˜—J˜Jšœ˜šœœœ ˜Jšœ˜Jšœ˜—Jšœ˜—šœ œ˜JšœY˜YJšœ˜—Jšœ]˜aJšœ:œ˜MJ˜.Jšœ˜—Jšœ˜—Jšœ˜—J˜—…—&ž3À