--Author: John Maxwell --last modified: December 11, 1981 9:03 AM DIRECTORY Beam USING [Draw,Grace,InVoice], Chord USING [Draw,Width], Graphics USING [DrawArea,EnterPoint,MoveTo,SetTexture,StartAreaPath], MusicDefs, Note USING [Draw,Width], Real USING [FixI], Sheet USING [FindLine,Height,MapHeight,NextLine], StringDefs USING [AppendDecimal], Utility USING [DrawLine,DrawString,SetFont]; BeamImplB: PROGRAM IMPORTS Beam, Chord, Graphics, MusicDefs, Note, Real, Sheet, StringDefs, Utility EXPORTS Beam = BEGIN OPEN Graphics,MusicDefs,Utility; --**************************************************************************** --displaying beams --**************************************************************************** Draw:PUBLIC PROCEDURE[b:BeamPTR] RETURNS[INTEGER,INTEGER] = BEGIN start:Time; a:BeamArray; slope:REAL _ 5; i,end:CARDINAL; inVoice:BOOLEAN; nonGrace:BOOLEAN_FALSE; thickness,lineHeight:INTEGER; level,space,s,k,up,d:CARDINAL_0; x0,y0,xn,yn,xi,yi,overX:REAL _ 1; j,value,beamValue:NoteValue _ unknown; dotted,oldDotted,stemUp,none:BOOLEAN_FALSE; IF NOT show.notehead THEN {DrawPhysicalBeam[b]; RETURN[0,0]}; IF NOT b.beamed THEN BEGIN DrawNTuple[b]; RETURN[0,0]; END; start _ b.sync1.time; [x0,y0] _ Sheet.MapHeight[b.sync1.time,b.height+Sheet.Height[b.sync1.time,,b.staff]]; overX _ sheet[Sheet.FindLine[b.sync2.time]].x; inVoice _ ~(voice AND NOT Beam.InVoice[b,selectedVoice]); IF b.tilt > -x0/slope AND b.tilt < x0/slope THEN space _ 5 ELSE space _ 7; IF Beam.Grace[b] THEN {space _ space-2; thickness_1} ELSE thickness_2; --first we figure out where everything is going to be FOR i IN [0..beamLength) DO IF b.chord[i] = endOfBeam THEN BEGIN a[i].dotted _ FALSE; end _ i; EXIT; END; WITH n:b.chord[i] SELECT FROM note => BEGIN IF show.display#graphical THEN n.n.delta_0; IF i=0 THEN start _ start + n.n.delta + (IF n.n.stemUp THEN Note.Width[n.n] ELSE 0); IF i=0 THEN x0 _ x0 + n.n.delta + (IF n.n.stemUp THEN Note.Width[n.n] ELSE 0); a[i].x _ n.n.sync.time - start + n.n.delta; IF n.n.stemUp THEN a[i].x _ a[i].x + Note.Width[n.n]; a[i].y _ y0 + b.tilt*a[i].x; a[i].value _ n.n.value; a[i].stemUp _ n.n.stemUp; a[i].dotted_n.n.dotted; END; chord=> BEGIN IF show.display#graphical THEN n.c.delta_0; IF i=0 THEN start _ start + n.c.delta + (IF n.c.stemUp THEN Chord.Width[n.c] ELSE 0); IF i=0 THEN x0 _ x0 + n.c.delta + (IF n.c.stemUp THEN Chord.Width[n.c] ELSE 0); a[i].x _ n.c.note[0].sync.time - start + n.c.delta; IF n.c.stemUp THEN a[i].x _ a[i].x + Chord.Width[n.c]; a[i].y _ y0 + b.tilt*a[i].x; a[i].value _ n.c.note[0].value; a[i].stemUp _ n.c.stemUp; a[i].dotted_n.c.note[0].dotted; END; beam => BEGIN x:Time_0; WITH ev:n.b.chord[0] SELECT FROM note => IF (a[i].stemUp_ev.n.stemUp) THEN x_Note.Width[ev.n]; chord => IF (a[i].stemUp_ev.c.stemUp) THEN x_Chord.Width[ev.c]; ENDCASE; IF i=0 THEN start _ start +x; IF i=0 THEN x0 _ x0 + x; a[i].x _ n.b.sync1.time - start+x; a[i].y _ y0 + b.tilt*a[i].x; a[i].value _ eighth; a[i].dotted _ FALSE; n.b.tilt _ b.tilt; n.b.staff _ b.staff; n.b.height _ Real.FixI[b.height+a[i].y-y0]; IF i#beamLength-1 AND b.chord[i+1]#endOfBeam THEN LOOP; FOR j:CARDINAL IN [0..beamLength) DO IF n.b.chord[j]=endOfBeam THEN EXIT; WITH ev:n.b.chord[j] SELECT FROM note => IF ev.n.stemUp THEN x_8 ELSE x_0; chord => IF ev.c.stemUp THEN x_8 ELSE x_0; ENDCASE; ENDLOOP; a[i].stemUp _ (x#0); a[i].x _ n.b.sync2.time- start+ x; a[i].y _ y0 + b.tilt*a[i].x; END; ENDCASE; ENDLOOP; --then we draw the beams and components i _ Sheet.FindLine[b.sync1.time]; lineHeight _ sheet[i].y-sheet[Sheet.NextLine[i]].y; FOR j IN [eighth..unknown) DO none _ TRUE; FOR i IN [0..end) DO IF none THEN IF a[i].value>=j THEN BEGIN none_FALSE; s_i; END ELSE LOOP; IF (i=j) THEN LOOP; up _ d _ 0; FOR k IN [s..i] DO IF a[k].stemUp THEN up_up+1 ELSE d_d+1; ENDLOOP; stemUp _ (up>d); xn _ a[i].x + x0; yn _ a[i].y; xi _ a[s].x + x0; none _ TRUE; IF xi=xn THEN SELECT TRUE FROM -- half beam i=0 => {xn_xn+10; yn_yn+b.tilt*10}; i=end-1 => xi_xi-10; a[i-1].value {xn_xn+10; yn_yn+b.tilt*10}; a[i-1].value>a[i+1].value => xi_xi-10; a[i+1].dotted => {xn_xn+10; yn_yn+b.tilt*10}; ENDCASE => xi_xi-10; IF stemUp THEN yn _ yn - space*level ELSE yn _ yn + space*level; yi _ yn + b.tilt*(xi-xn); Graphics.SetTexture[context,IF inVoice THEN black ELSE light]; DrawClippedRect[xi,yi,xn-1,yn,overX,b.tilt,thickness,lineHeight]; FOR k IN [s..i] DO IF a[k].value#j THEN LOOP; IF a[k].stemUp=TRUE AND stemUp=FALSE THEN a[k].y _ a[k].y + space*level; IF a[k].stemUp=FALSE AND stemUp=TRUE THEN a[k].y _ a[k].y - space*level; yi _ a[k].y; IF a[k].stemUp AND a[k].x+x0>=staffLength+8 OR NOT a[k].stemUp AND a[k].x+x0>=staffLength THEN yi _ a[k].y - lineHeight; IF ~print AND AnyBug[] THEN RETURN[0,0]; -- impatient user WITH ev:b.chord[k] SELECT FROM note => Note.Draw[ev.n,Real.FixI[yi]]; chord=> Chord.Draw[ev.c,Real.FixI[yi]]; beam=> [] _ Beam.Draw[ev.b]; ENDCASE; ENDLOOP; ENDLOOP; level _ level+1; ENDLOOP; IF b.ntuple#0 AND ~(print AND b.invisible) THEN BEGIN string:STRING _ [10]; IF xnstaffLength THEN BEGIN xi_xi-staffLength; y0_y0-lineHeight; END; MoveTo[context,[xi,y0]]; StringDefs.AppendDecimal[string,b.ntuple]; SELECT TRUE FROM b.invisible => Graphics.SetTexture[context,grey]; inVoice => Graphics.SetTexture[context,black]; ENDCASE => Graphics.SetTexture[context,light]; SetFont[context,text,12]; DrawString[context,string]; SetFont[context,music,8]; END; RETURN[i,i]; END; BeamArray:TYPE = ARRAY [0..beamLength) OF BeamRecord; BeamRecord:TYPE = RECORD[value:NoteValue,stemUp,dotted:BOOLEAN,x,y:REAL]; DrawNTuple:PROCEDURE[b:BeamPTR] = BEGIN inVoice:BOOLEAN; x,y,x1,y1:INTEGER; height1,height2,i,j:INTEGER_beamLength; up0,upN:BOOLEAN; string:STRING _ [10]; IF print AND b.invisible THEN RETURN; inVoice _ ~(voice AND NOT Beam.InVoice[b,selectedVoice]); height1 _ b.height+Sheet.Height[0,,b.staff]; [x,y] _ Sheet.MapHeight[b.sync1.time,height1]; [x1,] _ Sheet.MapHeight[b.sync2.time,height1]; y1 _ Real.FixI[y+ b.tilt*(x1+12-x)]; height2 _ Real.FixI[height1+y1-y]; SELECT TRUE FROM b.invisible => Graphics.SetTexture[context,grey]; inVoice => Graphics.SetTexture[context,black]; ENDCASE => Graphics.SetTexture[context,light]; DrawLine[x-2,y,x1+10,y1]; WITH n:b.chord[0] SELECT FROM note => up0 _ (Sheet.Height[n.n.sync.time,n.n.pitch,n.n.staff]>height1); chord=> up0 _ (Sheet.Height[n.c.note[0].sync.time,n.c.note[0].pitch,n.c.note[0].staff]>height1); beam => up0 _ (n.b.height+Sheet.Height[n.b.sync1.time,,n.b.staff]>height1); ENDCASE; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN BEGIN j_i; EXIT; END; ENDLOOP; IF j#0 THEN j _ j-1; WITH n:b.chord[j] SELECT FROM note => upN _ (Sheet.Height[n.n.sync.time,n.n.pitch,n.n.staff]>height2); chord=> upN _ (Sheet.Height[n.c.note[0].sync.time,n.c.note[0].pitch,n.c.note[0].staff]>height2); beam => upN _ (n.b.height+Sheet.Height[n.b.sync1.time,,n.b.staff]>height2); ENDCASE; IF up0 THEN DrawLine[x-2,y,x-2,y+4] ELSE DrawLine[x-2,y,x-2,y-4]; IF upN THEN DrawLine[x1+10,y1,x1+10,y1+4] ELSE DrawLine[x1+10,y1,x1+10,y1-4]; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN EXIT; WITH n:b.chord[i] SELECT FROM note => Note.Draw[n.n]; chord=> Chord.Draw[n.c]; beam => []_Beam.Draw[n.b]; ENDCASE; ENDLOOP; MoveTo[context,[(x+x1)/2,y+b.tilt*(x1-x)/2+(IF up0 THEN -15 ELSE 5)]]; SELECT TRUE FROM b.invisible => Graphics.SetTexture[context,grey]; inVoice => Graphics.SetTexture[context,black]; ENDCASE => Graphics.SetTexture[context,light]; StringDefs.AppendDecimal[string,b.ntuple]; SetFont[context,text,12]; DrawString[context,string]; SetFont[context,music,8]; END; DrawPhysicalBeam:PROCEDURE[b:BeamPTR] = BEGIN i:CARDINAL; FOR i IN [0..beamLength) DO IF b.chord[i] = endOfBeam THEN EXIT; WITH ev:b.chord[i] SELECT FROM note => Note.Draw[ev.n]; chord=> Chord.Draw[ev.c]; beam => DrawPhysicalBeam[ev.b]; ENDCASE; ENDLOOP; END; DrawClippedRect:PROCEDURE[x0,y0,xn,yn,delta:REAL,tilt:REAL,thickness,lineHeight:INTEGER] = BEGIN xi:REAL _ xn; yi:REAL _ yn; clip:BOOLEAN; clip _ x0staffLength; IF clip THEN BEGIN xi _ staffLength; yi _ y0 + tilt*(xi-x0); END; IF x0> staffLength THEN BEGIN y0 _ y0 - lineHeight; yi _ yi - lineHeight; x0 _ x0 - staffLength+ delta; xi _ xi - staffLength+ delta; END; StartAreaPath[context]; EnterPoint[context,[x0,y0-thickness]]; EnterPoint[context,[x0,y0+thickness]]; EnterPoint[context,[xi+1,yi+thickness]]; EnterPoint[context,[xi+1,yi-thickness]]; DrawArea[context]; IF NOT clip THEN RETURN; xi _ delta; xn _ xn - staffLength+ delta; yn _ yn - lineHeight; yi _ yn - tilt*(xn-xi); StartAreaPath[context]; EnterPoint[context,[xi,yi+thickness]]; EnterPoint[context,[xi,yi-thickness]]; EnterPoint[context,[xn+1,yn-thickness]]; EnterPoint[context,[xn+1,yn+thickness]]; DrawArea[context]; END; Drawn:PUBLIC PROCEDURE[b:BeamPTR] RETURNS[BOOLEAN] = BEGIN i:CARDINAL; IF b=NIL THEN FOR i IN [0..3) DO beamQueue[i] _ NIL; ENDLOOP; IF b=NIL THEN RETURN[FALSE]; FOR i IN [0..3) DO IF beamQueue[i]=b THEN RETURN[TRUE]; ENDLOOP; beamIndex _ beamIndex+1; IF beamIndex = 3 THEN beamIndex _ 0; beamQueue[beamIndex] _ b; RETURN[FALSE]; END; beamQueue:ARRAY [0..3) OF BeamPTR; beamIndex:CARDINAL_0; END. (0,3872)(1,4736)(2,5920)\642i16I81b4B824i52I1974i38I33i1I51i1I5506b5B