DIRECTORY BitBlt, Buttons, ViewerOps, CKViewerPanel, CKViewerButtons, ColorDisplay, GraphicsColor, MessageWindow, Inline, Real, Process USING [MsecToTicks, Pause]; CKViewerOps: PROGRAM IMPORTS BitBlt, Buttons, ColorDisplay, Inline, Real, Process, MessageWindow, CKViewerButtons, ViewerOps EXPORTS CKViewerButtons, CKViewerPanel = BEGIN OPEN MW: MessageWindow; CKViewer: TYPE = CKViewerButtons.CKViewer; CKViewerState: TYPE = CKViewerButtons.CKViewerState; sym: BOOLEAN _ FALSE; bbspace: BitBlt.BBTableSpace; bb: BitBlt.BBptr _ InitBB[@bbspace]; grayword: CARDINAL _ 0; bitmap,bitmapB: LONG POINTER _ NIL; wpl,wplB: CARDINAL _ 0; width,height: CARDINAL _ 0; lbpp,lbppB: CARDINAL _ 0; -- log (base 2) bits per pixel bpp,bppB: CARDINAL _ 0; -- bits per pixel full: BOOLEAN _ FALSE; ashow,bshow: BOOLEAN _ TRUE; splat: BOOLEAN _ TRUE; cornerSize: CARDINAL _ 4; cornerColor: CARDINAL _ 8; Triple: TYPE = RECORD[r,g,b: [0..256)]; testmap: ARRAY[0..8] OF Triple _ [ [127,127,127], -- gray (background) [ 0, 0, 0], -- black [255, 0, 0], -- red [ 0,255, 0], -- green [255,255, 0], -- yellow [ 0, 0,255], -- blue [255, 0,255], -- magenta [ 0,255,255], -- cyan [255,255,255] -- white ]; Diag: PROC [] = { Bham: PROC [fx,fy,lx,ly: INTEGER, color: [0..8]] = { yt: REAL; xx, xi: INTEGER; yy, yi: INTEGER; dx: INTEGER _ lx-fx; dy: INTEGER _ ly-fy; IF dy>dx OR dx<=0 OR dy<=0 THEN ERROR; FOR xi IN [0..dx) DO yt _ (Real.Float[dy]/Real.Float[dx])*Real.Float[xi]; yi _ Real.FixI[yt+0.5]; xx_fx+xi; yy_fy+yi; TestRect[xx,yy,1,1,color]; TestRect[iWidth-xx,yy,1,1,color]; TestRect[xx,iHeight-yy,1,1,color]; TestRect[iWidth-xx,iHeight-yy,1,1,color]; ENDLOOP; }; black: [0..8] = 1; --testmap[1] is black white: [0..8] = 8; --testmap[8] is white iWidth: INTEGER _ width; iHeight: INTEGER _ height; deltaX: INTEGER _ iWidth/40; deltaY: INTEGER _ (deltaX*iHeight)/iWidth; xi: INTEGER _ 0; yi: INTEGER _ 0; IF full THEN Positive[] ELSE { FOR i: CARDINAL IN[0..9) DO ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b]; ENDLOOP; SetShowButtons[TRUE,FALSE,FALSE]; }; TestRect[0,0,width,height,black]; --black background FOR n: INTEGER _ 0, n+1 UNTIL xi >=iWidth DO Bham[fx: xi, fy: 0, lx: iWidth-1, ly: iHeight-n*deltaY, color: white]; xi_xi+deltaX; ENDLOOP; }; ShowTPat: PROC = { x: CARDINAL = 60; h: CARDINAL = 60; w: CARDINAL = 50; gap: CARDINAL = 15; IF full THEN Positive[] ELSE { FOR i: CARDINAL IN[0..9) DO ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b]; ENDLOOP; SetShowButtons[TRUE,FALSE,FALSE]; }; TestRect[0,0,width,height,0]; { s: CARDINAL = cornerSize; c: CARDINAL = cornerColor; -- color TestRect[0,0,s,s,c]; TestRect[width-s,0,s,s,c]; TestRect[0,height-s,s,s,c]; TestRect[width-s,height-s,s,s,c]; }; FOR i: CARDINAL IN[0..8) DO r,g,b: [0..256); r _ (i MOD 2)*255; g _ ((i/2) MOD 2)*255; b _ ((i/4) MOD 2)*255; TestRect[4,i*h+10,x,h-20,i+1]; ENDLOOP; FOR i: CARDINAL IN[0..8) DO r,g,b: [0..256); r _ (i MOD 2)*255; g _ ((i/2) MOD 2)*255; b _ ((i/4) MOD 2)*255; TestRect[x+i*w+gap,0,w-gap,8*h,i+1]; ENDLOOP; }; TestRect: PROC[x,y,w,h: CARDINAL, i: [0..8]] = { IF NOT (x width DO TestRect[xx, 0, vThick, height, white]; ENDLOOP; FOR v: CARDINAL _ 0, v+vStep UNTIL v > height DO TestRect[0, v, width, hThick ,white]; ENDLOOP; }; ShowBig: PROCEDURE [big: BOOLEAN, color: GraphicsColor.Color] = { r,g,b: CARDINAL; rectheight: CARDINAL _ height/16; --sixteen rectangles cInc: CARDINAL _ IF big THEN 20B ELSE 1; maxIntensity: CARDINAL _ IF full THEN 400B ELSE (Inline.BITSHIFT[1,bpp]); groupSize: CARDINAL _ MAX[16/maxIntensity,1]; groupIndex: CARDINAL _ 16/groupSize; IF NOT full THEN SetShowButtons[TRUE,FALSE,FALSE] ELSE SetShowButtons[TRUE,TRUE,TRUE]; FOR gI: CARDINAL IN [0..groupIndex) DO inten: CARDINAL _ gI*cInc; SELECT color FROM GraphicsColor.red => {r_inten; b_g_0}; GraphicsColor.green => {g_inten; b_r_0}; GraphicsColor.blue => {b_inten; r_g_0}; ENDCASE => ERROR; IF full THEN { OPEN ColorDisplay; SetRedMap[gI,r]; SetGreenMap[gI,g]; SetBlueMap[gI,b];} ELSE ColorDisplay.SetColor[pixelA: gI, pixelB: 0, r: r, g: g, b: b]; FOR x: CARDINAL IN [0..groupSize) DO nextRect: CARDINAL _ gI*groupSize + x; Rect[0,nextRect*rectheight,width,rectheight, gI]; ENDLOOP; ENDLOOP; }; ShowBigRed: PROCEDURE [big: BOOLEAN] = { ShowBig[big, GraphicsColor.red]; }; ShowBigGreen: PROCEDURE [big: BOOLEAN] = { ShowBig[big, GraphicsColor.green]; }; ShowBigBlue: PROCEDURE [big: BOOLEAN] = { ShowBig[big, GraphicsColor.blue]; }; ShowCBars: PROCEDURE = { graywidth: CARDINAL _ width/128; --this must integer divide evenly grayheight: CARDINAL _ height/2; --this must integer divide evenly cbarwidth: CARDINAL _ (width)/9; --this may truncate cbarheight: CARDINAL _ height/2; --this must integer divide evenly IF full THEN HalfPositive[] ELSE { --set up gray map k: CARDINAL _ (Inline.BITSHIFT[1,bpp])/2; -- half the number of pixel values FOR n: CARDINAL IN [0..k) DO ColorDisplay.SetColor[pixelA: n+200B, pixelB: 0, r: n*2, g: n*2, b: n*2]; --use top half of colormap. Only makes sense for 8 BPP ENDLOOP; }; FOR i: CARDINAL IN[0..9) DO --set up color bars IF full THEN {ColorDisplay.SetRedMap[i,testmap[i].r]; ColorDisplay.SetGreenMap[i,testmap[i].g]; ColorDisplay.SetBlueMap[i,testmap[i].b];} ELSE ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b] ENDLOOP; FOR x: CARDINAL IN [0..128) DO --gray wedge Rect[x*graywidth, 0, graywidth, grayheight, x+128]; ENDLOOP; FOR x: CARDINAL IN [0..8] DO --colorbars Rect[x*cbarwidth, cbarheight, cbarwidth, cbarheight, x]; ENDLOOP; SetShowButtons[TRUE,full,full]; }; NextRoll: PROCEDURE [] = { OPEN ColorDisplay; r,g,b,r0,g0,b0: [0..256); IF full THEN { r0_GetRedMap[0]; g0_GetGreenMap[0]; b0_GetBlueMap[0]; FOR i: CARDINAL IN[0..255) DO r _ GetRedMap[i+1]; g _ GetGreenMap[i+1]; b _ GetBlueMap[i+1]; SetRedMap[i,r]; SetGreenMap[i,g]; SetBlueMap[i,b]; ENDLOOP; SetRedMap[255,r0]; SetGreenMap[255,g0]; SetBlueMap[255,b0]; } ELSE { [r0,g0,b0] _ ColorDisplay.GetColor[0]; FOR i: CARDINAL IN[0..255) DO [r,g,b] _ ColorDisplay.GetColor[i+1]; ColorDisplay.SetColor[i,0,r,g,b]; ENDLOOP; ColorDisplay.SetColor[255,0,r0,g0,b0]; }; Wait[100]; }; NextScramble: PROCEDURE [] = { SetUpColors[]; Wait[200]; }; background: INTEGER _ 0; -- initially black ClearScreen: PROCEDURE = { IF NOT full THEN { ColorDisplay.SetColor[0, 0, background, background, background]; SetGray[0] } ELSE {ColorDisplay.SetGreenMap[0,0]; ColorDisplay.SetBlueMap[0,0]; ColorDisplay.SetRedMap[0,0];}; Rectangle[lx: 0, ty: 0, rx: width, by: height, fn: null, clear: TRUE]; }; Wait: PROCEDURE[millisecs: CARDINAL] = INLINE { Process.Pause[Process.MsecToTicks[millisecs]] }; defaultSeed: CARDINAL = 27183; numCalls: INTEGER = 3; a: ARRAY [0..55] OF CARDINAL; p: INTEGER [0..55]; InitRandom: PUBLIC PROC[seed: INTEGER] RETURNS[INTEGER] = { minSeed: CARDINAL = LAST[CARDINAL]/10; g, gPrev, gSave: CARDINAL; IF seed<=0 THEN seed _ defaultSeed; WHILE seed max THEN ERROR; intervalLen _ max - min + 1; --is 0 when min=0, max=LAST[CARDINAL] IF intervalLen = 0 THEN RETURN[Random[]]; DO r, rem: CARDINAL; p _ p-1; IF p=0 THEN { RandomGen[]; p _ 55 }; r _ a[p]; rem _ r MOD intervalLen; IF (r - rem) > LOOPHOLE[-LOOPHOLE[intervalLen,INTEGER],CARDINAL] THEN LOOP; RETURN[min + rem]; ENDLOOP; };--Choose SetLogBitsPerPixel: PROC[n: [0..4)] RETURNS[BOOLEAN] = { b: CARDINAL _ Inline.BITSHIFT[1,n]; mode: ColorDisplay.Mode _ [FALSE,b,1]; IF NOT ColorDisplay.HasMode[mode] THEN { mode.bitsPerPixelB _ 0; IF NOT ColorDisplay.HasMode[mode] THEN RETURN[FALSE]; }; IF NOT ColorDisplay.SetMode[mode] THEN ERROR; lbpp _ n; bpp _ b; full _ FALSE; lbppB _ 0; bppB _ 1; SetShowButtons[TRUE, TRUE, FALSE]; width _ ColorDisplay.width; height _ ColorDisplay.height; bitmap _ ColorDisplay.baseA; wpl _ ColorDisplay.wplA; bitmapB _ ColorDisplay.baseB; wplB _ ColorDisplay.wplB; ClearScreen; SetUpColors; ColorDisplay.TurnOn[]; RETURN[TRUE]; }; Set24BitsPerPixel: PROC = { mode: ColorDisplay.Mode _ [TRUE,0,0]; IF NOT ColorDisplay.HasMode[mode] THEN RETURN; IF NOT ColorDisplay.SetMode[mode] THEN ERROR; lbpp _ 0; bpp _ 0; full _ TRUE; bitmap _ NIL; bitmapB _ NIL; wpl _ 0; SetShowButtons[TRUE, TRUE, FALSE]; width _ ColorDisplay.width; height _ ColorDisplay.height; ClearScreen[]; ColorDisplay.TurnOn[]; }; Go: PUBLIC PROC [ckViewer: CKViewer] = { [] _ InitRandom[0]; public _ ckViewer; SELECT TRUE FROM SetLogBitsPerPixel[3] => NULL; SetLogBitsPerPixel[2] => NULL; ENDCASE => { MW.Append[message: "NO COLOR DISPLAY !!", clearFirst: TRUE]; MW.Blink[]; RETURN; }; DO IF ckViewer.state.quit THEN { ClearScreen; ViewerOps.DestroyViewer[ckViewer.container]; []_ColorDisplay.SetMode[ColorDisplay.disconnected]; EXIT; }; IF ckViewer.state.testingPanel THEN LOOP; --turned off by FinalizeTest IF ckViewer.state.bpp=1 AND bpp#1 THEN { [] _ SetLogBitsPerPixel[0]; SetSplat[] }; IF ckViewer.state.bpp=2 AND bpp#2 THEN { [] _ SetLogBitsPerPixel[1]; SetSplat[] }; IF ckViewer.state.bpp=4 AND bpp#4 THEN { [] _ SetLogBitsPerPixel[2]; SetSplat[] }; IF ckViewer.state.bpp=8 AND bpp#8 THEN { [] _ SetLogBitsPerPixel[3]; SetSplat[] }; IF ckViewer.state.bpp=24 AND NOT full THEN { Set24BitsPerPixel[]; SetSplat[] }; IF ckViewer.state.aToggle THEN { SetShowButtons[NOT ashow, bshow,FALSE]; ckViewer.state.aToggle _ FALSE}; IF ckViewer.state.bToggle THEN { SetShowButtons[ashow, NOT bshow,FALSE]; ckViewer.state.bToggle _ FALSE}; IF ckViewer.state.random THEN { sym _ FALSE; SetSplat[]; ClearScreen[]; ckViewer.state.random _ FALSE}; IF ckViewer.state.symmetric THEN { sym _ TRUE; SetSplat[]; ClearScreen[]; ckViewer.state.symmetric _ FALSE}; IF NOT ckViewer.state.freeze THEN { ckViewer.state.roll _ ckViewer.state.scramble _ FALSE; --only TRUE when frozen SELECT TRUE FROM ckViewer.state.testPattern => { splat _ FALSE; ShowTPat[]; ckViewer.state.testPattern _ FALSE; }; ckViewer.state.cbars => {ShowCBars[]; splat _ ckViewer.state.cbars _ FALSE}; ckViewer.state.converge => {ShowConverge[]; splat _ ckViewer.state.converge _ FALSE}; ckViewer.state.diag => {Diag[]; splat _ ckViewer.state.diag _ FALSE}; ckViewer.state.bigRed => {ShowBigRed[big: TRUE]; splat _ ckViewer.state.bigRed _ FALSE}; ckViewer.state.bigGreen => {ShowBigGreen[big: TRUE]; splat _ ckViewer.state.bigGreen _ FALSE}; ckViewer.state.bigBlue => {ShowBigBlue[big: TRUE]; splat _ ckViewer.state.bigBlue _ FALSE}; ckViewer.state.smallRed => {ShowBigRed[big: FALSE]; splat _ ckViewer.state.smallRed _ FALSE}; ckViewer.state.smallGreen => {ShowBigGreen[big: FALSE]; splat _ ckViewer.state.smallGreen _ FALSE}; ckViewer.state.smallBlue => {ShowBigBlue[big: FALSE]; splat _ ckViewer.state.smallBlue _ FALSE}; ENDCASE => IF splat THEN RandomSplat[ckViewer]; } ELSE { SELECT TRUE FROM ckViewer.state.scramble => NextScramble[]; ckViewer.state.roll => NextRoll[]; ENDCASE => NULL; }; ENDLOOP; IF NOT ColorDisplay.SetMode[ColorDisplay.disconnected] THEN ERROR; }; SetSplat: PROCEDURE [] = { splat _ TRUE; SetShowButtons[ashow,bshow,FALSE]; CKViewerButtons.SetStaticButtons[public, IF sym THEN public.buttons.symmetricButton ELSE public.buttons.randomButton] }; SetShowButtons: PROCEDURE [a, b, c: BOOL] = { ashow_a; bshow_b; ColorDisplay.Show[a,b,c]; Buttons.SetDisplayStyle[public.buttons.aChanButtton, IF ashow THEN $WhiteOnBlack ELSE $BlackOnWhite]; Buttons.SetDisplayStyle[public.buttons.bChanButton, IF bshow THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; SetUpPanelTest: PUBLIC PROCEDURE [ckViewer: CKViewer] = { ckViewer.state.testingPanel _ TRUE; Wait[2000]; --stupid synchronizer so main loop in Go will quit messing with screen ClearScreen []; --FILL FIFOS WITH Zeroes ColorDisplay.Show[TRUE,TRUE,TRUE]; --so when ChannelOn glitches nothing bad will happen Wait[36]; --be sure both a and b actually show SetShowButtons[ashow,bshow,TRUE]; --restore ashow/bshow }; public: CKViewer_NIL; END. ÒCKViewerOps.mesa Last edited by Ken Pier, August 12, 1983 10:23 am draw a set of diagonal lines draw a line from (fx,fy) to (lx,ly) gray background four corners various colors at left edge a bunch of stripes bitmap A bitmap B Constant definitions (meanings described in InitRandom below) Module state Holds 55 random cardinals, to be returned by Random. (A[0] is wasted to make the code generator produce better array accesses.) a[1..p-1] has not yet been returned by Random; p is [1..55] except within Random. Procedures The parameter seed determines the sequence generated by procedure Random below. If seed=0, a default seed value is used to determine the starting point of the sequence; if seed>0, seed is scaled if necessary and then used; if seed<0, a seed value is derived from the system clock. In any case, the seed value actually used (after scaling) is the integer value returned. Now scale the seed into the proper range (no log routine available...) Seed can't be too big since LAST[INTEGER] < LAST[CARDINAL]*(9/10) The array a is initialized by placing seed in a[55], and scattering the values (-1)**(i-1) * (F(i) - seed*F(i-1)) MOD maxRand, 0Jšœ˜—J˜—šœ˜šœœœ˜J˜8J˜>J˜SJšœ˜—J˜—Jšœ˜J˜—šŸœœ˜Jšœœœœ˜šœœœ ˜J˜J˜J˜Jšœ˜—J˜J˜—šŸ œœ˜Jšœ˜Jšœœœœ˜šœœœ ˜Jšœ˜J˜J˜Jšœ˜Jšœ˜—J˜J˜—š Ÿœ œœœœœ˜EJšœ œ˜Jšœ˜J˜—JšŸœœ+˜8J˜šŸœœœœ˜1Jšœ œ˜šœœ˜Jšœœ ž˜*Jšœœ œœ ˜8Jšœ œ ˜Jšœ œœœ˜IJ˜—Jšœ ˜J˜J˜—š Ÿœœœœœœ˜RJ˜.˜Jšœ œ ˜J˜ J˜J˜CJ˜Jšœœœ˜#J˜—Jšœ˜ J˜J˜—šŸœœ œ˜6Jšœœ ˜Jšœœ ˜Jšœœœœ˜Jšœ™Jšœ%œ#˜LJ˜!J˜!J˜J˜J˜Jšœœ˜Jšœ™Jšœ%œ'œ˜XJ˜!J˜*J˜J˜J˜Jšœœ˜J˜J˜—šŸœœ œ-˜JJšœœ˜Jšœœ œ ˜)Jšœ%œ+œ˜\J˜!J˜)Jšœœ ˜#J˜J˜Jšœœ˜J˜J˜—J˜J˜š Ÿ œœœ$œœ˜]šœœ˜J˜Jšœœ œ<˜VJ˜"J˜—šœ˜Jš œœœœ œ˜1J˜"Jš œœ œœœ˜@J˜—J˜J˜—š Ÿ œœœ#œœ˜]Jšœœ œ ˜+Jš œœœœœ ˜/Jšœœœ˜EJ˜J˜ Jšœœ˜*J˜Jšœ˜Jšœœ˜J˜J˜—šŸ œ œ˜/Jšœ œ ˜Jšœ œ ˜Jšœ œ˜Jšœœ˜Jšœœœœ˜BJ˜J˜šœœ˜ J˜J˜J˜J˜J˜"J˜ J˜"J˜ J˜"J˜$Jšœ˜—šœ˜J˜J˜J˜J˜J˜"Jšœ˜—šœ œœ˜J˜J˜J˜J˜J˜J˜—Jšœœ ž ˜3Jšœ˜J˜—šŸ œ œ˜Jšœž˜(Jšœž˜(Jšœœ˜Jšœœ ˜Jšœœ˜Jšœœ ˜J˜šœœ œ˜šœœœ˜J˜TJšœ˜—Jšœœœœ˜!J˜—Jšœ"ž˜4šœœœ ˜2Jšœ'˜'Jšœ˜—šœœœ ˜0Jšœ%˜%Jšœ˜—J˜—J˜šŸœ œœ!˜AJšœœ˜Jšœ œž˜6Jš œœœœœ˜(Jš œœœœœ œ ˜IJšœ œœ˜-Jšœ œ˜$Jšœœœœœœœœœœ˜VJ˜šœœœ˜'Jšœœ ˜šœ˜Jšœ&˜&Jšœ(˜(Jšœ'˜'Jšœœ˜—šœœ˜JšœE˜I—Jšœ@˜Dšœœœ˜%Jšœ œ˜&Jšœ1˜1—Jšœ˜—Jšœ˜J˜—J˜J˜šŸ œ œœ˜(Jšœ ˜ Jšœ˜—J˜šŸ œ œœ˜*Jšœ"˜"Jšœ˜—J˜šŸ œ œœ˜)Jšœ!˜!Jšœ˜—J˜J˜šŸ œ œ˜Jšœ œž!˜BJšœ œ ž"˜BJšœ œž˜4Jšœ œ ž!˜BJ˜šœœœž˜4Jšœœ œ ž"˜Lšœœœ˜JšœJž7˜Jšœ˜—J˜—š œœœœž˜/Jšœœ}˜‰JšœT˜XJšœ˜—š œœœ œž ˜,J˜3Jšœ˜—š œœœœž ˜)Jšœ8˜8Jšœ˜—Jšœœ ˜Jšœ˜—J˜šŸœ œ˜Jšœ˜J˜šœœ˜J˜5šœœœ ˜J˜?J˜3Jšœ˜—J˜Jšœ˜—JšœEœ˜LJšœNœ˜UJšœ>œ˜EJšœ*œ#œ˜XJšœ.œ%œ˜^Jšœ,œ$œ˜[Jšœ,œ%œ˜]Jšœ0œ'œ˜cJšœ.œ&œ˜`Jšœœœ˜/—Jšœ˜—šœ˜šœœ˜Jšœ*˜*Jšœ"˜"Jšœœ˜—˜J˜——Jšœ˜J˜Jšœœ1œœ˜B˜J˜——šŸœ œ˜Jšœœœ˜0Jšœ)œœ œ˜uJ˜—J˜šŸœ œ œ˜-J˜+Jšœ5œœœ˜eJšœ4œœœ˜dJ˜—J˜šŸœœ œ˜:Jšœœ˜#Jšœ žF˜RJšœž˜(Jšœœœœž4˜WJšœ ž$˜.Jšœœž˜7Jšœ˜—J˜Jšœœ˜J˜Jšœ˜J˜—…—F¸g