DIRECTORY Beam USING [Drawn], Event USING [Adjust, Draw, GetScoreIndex], Graphics USING [Context, DrawBox, DrawChar, GetBounds, SetCP, SetStipple], MusicDefs, Note USING [DrawTie, InVoice], Piece USING [NearestEvent], Score USING [Draw, GetKey, Justify, LogicalToPhysical, ScalePhysical, SetStyle, ShowPitch], Selection USING [Draw, selection], Sheet USING [default, Draw, FindSection, FindStaves, Height, HiLite, MapNote, Scale, SetBegin]; ScoreImplB: CEDAR PROGRAM IMPORTS Beam, Graphics, MusicDefs, Note, Piece, Score, Selection, Sheet, Event EXPORTS Score = BEGIN OPEN MusicDefs; Draw: PUBLIC PROC[score: ScorePTR, erase: BOOLEAN] = { sheet: SheetPTR _ score.sheet; Selection.Draw[]; -- remove selection from screen IF erase THEN { SetBrush[score, white, opaque]; Graphics.DrawBox[sheet.context, Graphics.GetBounds[sheet.context]]; SetBrush[score, black, transparent]; Sheet.Draw[sheet]}; DrawInterval[score, sheet.begin, sheet.endTime]; Selection.Draw[]; }; Redraw: PUBLIC PROC[score: ScorePTR, t1, t2: Time] = { x, y: INTEGER; select: BOOLEAN; selection: SelectionPTR _ Selection.selection; SetBrush[score, black, transparent]; SELECT score.sheet.scale FROM 1 => IF t2-t1 > 700 THEN {Score.Draw[score]; RETURN}; 2 => IF t2-t1 > 2000 THEN {Score.Draw[score]; RETURN}; 4 => IF t2-t1 > 8000 THEN {Score.Draw[score]; RETURN}; ENDCASE; select _ selection.lineSelect AND selection.select2 > t1-40 AND selection.select1 < t2+50; IF select THEN Selection.Draw[]; -- remove selection from screen Sheet.HiLite[score.sheet, white, t1-20, t2+30]; DrawInterval[score, t1-30, t2+40]; IF select THEN Selection.Draw[]; IF selection.lineSelect THEN RETURN; SetBrush[score, black, invert]; FOR i: CARDINAL IN [0..selection.length) DO IF selection.note[i] = NIL THEN LOOP; IF selection[i].sync.time > t2+40 OR selection[i].sync.time < t1-30 THEN LOOP; IF ~Note.InVoice[selection[i], score.sheet.voice] THEN LOOP; [x, y] _ Sheet.MapNote[score.sheet, selection[i]]; Graphics.SetCP[score.sheet.context, x, y]; Graphics.DrawChar[score.sheet.context, 170C]; ENDLOOP; }; DrawInterval: PROC[score: ScorePTR, t1, t2: Time] = { n: NotePTR; staves: StavesPTR; j: CARDINAL _ 0; sheet: SheetPTR _ score.sheet; [] _ Beam.Drawn[score, NIL]; -- clears the beam cache SetBrush[score, black, transparent]; staves _ Sheet.FindStaves[sheet, t1]; FOR i: CARDINAL IN [0..staves.length) DO IF staves.staff[i].pitch # 15 AND staves.staff[i].pitch # 60 THEN LOOP; FOR j: CARDINAL DECREASING IN [0..score.length) DO IF score.event[j].time >= t1 THEN LOOP; IF score.event[j].type # staves THEN LOOP; WITH score.event[j] SELECT FROM ev: StavesPTR => { IF ev.staves NOT IN [octava1..octava2] THEN LOOP; IF ev.value # i THEN LOOP; IF ev.staves = octava2 THEN EXIT}; ENDCASE => ERROR; Event.Draw[score, score.event[j]]; EXIT; ENDLOOP; ENDLOOP; j _ 0; IF score.sheet.display = graphical THEN FOR i: CARDINAL IN [0..score.length) DO IF score.event[i].time < t1 THEN LOOP; IF score.event[i].time > t2 THEN EXIT; IF score.event[i].type = sync THEN { IF j = 10 THEN EXIT ELSE j _ j+1; Event.Adjust[score, NARROW[score.event[i]]]}; ENDLOOP; j _ 0; FOR i: CARDINAL IN [0..score.length) DO IF score.event[i].time < t1 THEN LOOP; IF score.event[i].time > t2 THEN {j _ i; EXIT}; IF score.sheet.display = graphical THEN { plus10: CARDINAL _ MIN[i+10, score.length-1]; IF score.event[plus10].type = sync THEN Event.Adjust[score, NARROW[score.event[plus10]]]}; Event.Draw[score, score.event[i]]; ENDLOOP; IF j # 0 THEN FOR i: CARDINAL IN [j..score.length) DO IF score.event[i].time > t2+200 THEN EXIT; WITH score.event[i] SELECT FROM sync: SyncPTR => { FOR j: CARDINAL IN [0..sync.length) DO IF (n _ sync.note[j]) = NIL THEN EXIT; IF n.tie = NIL THEN LOOP; IF n.tie.sync.time > t2 THEN LOOP; IF ~Note.InVoice[n, score.sheet.voice] THEN Graphics.SetStipple[score.sheet.context, light] ELSE Graphics.SetStipple[score.sheet.context, black]; Note.DrawTie[score, n]; ENDLOOP; }; ENDCASE; ENDLOOP; [] _ Beam.Drawn[score, NIL]; }; Print: PUBLIC PROC[score: ScorePTR, splines: BOOLEAN] = {}; Look: PUBLIC PROC[score: ScorePTR, look: LookCommand, switch: BOOLEAN, n: INTEGER] = { draw: BOOLEAN _ TRUE; SELECT look FROM accidental => score.sheet.accidental _ switch; hardcopy => { Sheet.Scale[score, IF switch THEN 2 ELSE 1]; score.sheet.hardcopy _ switch}; justified => { score.sheet.density _ n; Score.Justify[score, Selection.selection.select1, Selection.selection.select2]}; logical => Score.LogicalToPhysical[score, Selection.selection.select1, Selection.selection.select2]; noCarry => score.sheet.noCarry _ switch; notehead => score.sheet.notehead _ switch; overview => Overview[score, switch]; physical => Score.ScalePhysical[score, 512/n]; style => Score.SetStyle[score, n, 0, EndOfScore[score]]; sync => score.sheet.sync _ switch; voice => {score.sheet.voice _ IF ~switch THEN noVoice ELSE n}; ENDCASE; }; Overview: PROC[score: ScorePTR, switch: BOOLEAN] = { SELECT TRUE FROM score.sheet.scale < 4 AND ~switch => {score.flash _ TRUE; RETURN}; score.sheet.scale > 2 AND switch => {score.flash _ TRUE; RETURN}; switch => {Sheet.Scale[score, 4]; Sheet.SetBegin[score.sheet, 0]}; ENDCASE => { Sheet.Scale[score, IF score.sheet.hardcopy THEN 2 ELSE 1]; Sheet.SetBegin[score.sheet, 0]}; }; phi: ARRAY [0..12) OF INTEGER = [6, 1, -4, 3, -2, 5, 0, 7, 2, -3, 4, -1]; flatHeight: ARRAY[0..12) OF INTEGER = [0, 4, 8, 8, 12, 12, 16, 16, 20, 24, 24, 28]; sharpHeight: ARRAY[0..12) OF INTEGER = [0, 4, 4, 8, 8, 12, 12, 16, 20, 20, 24, 24]; GetAccidental: PUBLIC PROC[score: ScorePTR, n: NotePTR] RETURNS[Accidental] = { n.shown _ GetAccInternal[score, n]; RETURN[n.shown]; }; GetAccInternal: PROC[score: ScorePTR, n: NotePTR] RETURNS[Accidental] = { a: Accidental; prior: NotePTR; index: CARDINAL; pitch, key: INTEGER; normal: Accidental; noteHeight: INTEGER; IF NOT score.sheet.accidental THEN RETURN[inKey]; IF n.tie # NIL AND n.tie.pitch = n.pitch THEN RETURN[inKey]; IF n.show AND n.spelled = inKey THEN Error["show inKey?"]; IF n.show THEN RETURN[n.spelled]; IF score.sheet.noCarry THEN { IF n.spelled # inKey THEN RETURN[n.spelled]; a _ DefaultAcc[0, n.pitch]; IF a = natural THEN a _ inKey; RETURN[a]}; key _ Score.GetKey[score, n.sync.time]; pitch _ Score.ShowPitch[score.sheet, n.pitch, n.spelled, key]; noteHeight _ Sheet.Height[score.sheet, n.sync.time, pitch, n.staff]; index _ Event.GetScoreIndex[score, n.sync]; IF index = score.length THEN index _ EventIndex[score, n.sync.time]; prior _ PriorNote[score, pitch, noteHeight, index]; normal _ NormalAcc[key, pitch]; IF prior = NIL THEN SELECT TRUE FROM normal = inKey => RETURN[n.spelled]; n.spelled = inKey => RETURN[normal]; ENDCASE => RETURN[n.spelled]; IF prior.pitch = n.pitch THEN RETURN[inKey]; IF n.spelled # inKey THEN RETURN[n.spelled]; IF normal # inKey THEN RETURN[normal]; IF Mod[n.pitch, 12] = 7 AND key < -5 THEN RETURN[flat]; IF Mod[n.pitch, 12] = 0 AND key < -6 THEN RETURN[flat]; IF Mod[n.pitch, 12] = 1 AND key > 5 THEN RETURN[sharp]; IF Mod[n.pitch, 12] = 8 AND key > 6 THEN RETURN[sharp]; normal _ NormalAcc[0, n.pitch]; IF normal = inKey THEN normal _ natural; IF key < 0 AND normal = sharp THEN normal _ flat; RETURN[normal]; }; EventIndex: PROC[score: ScorePTR, time: Time] RETURNS[s: CARDINAL] = { s _ Piece.NearestEvent[score, time]; IF score.event[s] # NIL AND score.event[s].time >= time THEN RETURN[s]; FOR i: CARDINAL DECREASING IN [0..s+10) DO IF score.event[i] = NIL THEN LOOP; IF score.event[i].time > time THEN LOOP; RETURN[i+1]; ENDLOOP; }; PriorNote: PUBLIC PROC[score: ScorePTR, pitch, height: INTEGER, index: CARDINAL] RETURNS[NotePTR] = { n: NotePTR; sync: SyncPTR; newPitch, key: INTEGER; FOR i: CARDINAL DECREASING IN [0..index) DO IF Measure[score.event[i]] THEN RETURN[NIL]; IF score.event[i].type # sync THEN LOOP; key _ Score.GetKey[score, score.event[i].time]; sync _ NARROW[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO IF (n _ sync.note[j]) = NIL THEN EXIT; IF n.rest THEN LOOP; newPitch _ Score.ShowPitch[score.sheet, n.pitch, n.spelled, key]; IF NOT newPitch IN [pitch-2..pitch+2] THEN LOOP; IF Sheet.Height[score.sheet, score.event[i].time, newPitch, n.staff] # height THEN LOOP; RETURN[n]; ENDLOOP; ENDLOOP; RETURN[NIL]; }; assert: Accidental = LOOPHOLE[LOOPHOLE[LAST[Accidental], CARDINAL]+1]; NormalAcc: PUBLIC PROC[key, pitch: INTEGER] RETURNS[Accidental] = { strangeness: INTEGER _ phi[Mod[pitch, 12]]; SELECT TRUE FROM Mod[(key-strangeness), 12] > 4 => RETURN[inKey]; strangeness > 0 => RETURN[natural]; key < 0 => RETURN[flat]; ENDCASE => RETURN[sharp]; }; DefaultAcc: PROC[key, pitch: INTEGER] RETURNS[Accidental] = { SELECT NormalAcc[0, pitch] FROM inKey => RETURN[natural]; sharp => RETURN[IF key < 0 THEN flat ELSE sharp]; ENDCASE => ERROR; }; AddToPitch: PUBLIC PROC[key, pitch, delta: INTEGER] RETURNS[INTEGER] = { i: INTEGER; IF delta > 0 THEN FOR i IN (pitch..90] DO IF NormalAcc[key, i] = inKey THEN delta _ delta-1; IF delta = 0 THEN RETURN[i]; ENDLOOP ELSE FOR i DECREASING IN [0..pitch) DO IF NormalAcc[key, i] = inKey THEN delta _ delta+1; IF delta = 0 THEN RETURN[i]; ENDLOOP; ERROR; }; KeyHeight: PUBLIC PROC[key, pitch: INTEGER] RETURNS[INTEGER] = { i: CARDINAL _ Mod[pitch, 12]; SELECT TRUE FROM i = 7 AND key < -5 => RETURN[flatHeight[8]]; i = 0 AND key < -6 => RETURN[flatHeight[1]]; key < 0 => RETURN[flatHeight[i]]; i = 1 AND key > 5 => RETURN[sharpHeight[0]]; i = 8 AND key > 6 => RETURN[sharpHeight[7]]; ENDCASE => RETURN[sharpHeight[i]]; }; END. Print: PUBLIC PROC[splines: BOOLEAN] = { printAll: BOOLEAN; oldBegin: Time _ begin; ph: POINTER TO PressDefs.PressFileDescriptor; device: Device.Handle _ Utility.OpenPressDevice[splines]; ph _ LOOPHOLE[device.data, PressDeviceImpl.DataRef].pressHandle; printAll _ ~splines AND scale = 2; IF printAll THEN Sheet.SetBegin[0]; FOR i: CARDINAL IN [0..scoreLength) DO Event.Adjust[score.event[i]]; ENDLOOP; WHILE TRUE DO Sheet.Draw[]; DrawInterval[begin, endTime]; IF endTime > EndOfScore[]-40 THEN EXIT; IF printAll THEN {Sheet.SetBegin[endTime]; PressDefs.WritePage[ph]} ELSE EXIT; ENDLOOP; Utility.ClosePressDevice[@device]; Sheet.SetBegin[oldBegin]; }; LScoreImplB.mesa Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved. Author: John Maxwell Last Edited by: Maxwell, November 22, 1983 12:29 pm Last Edited by: Doug Wyatt, June 12, 1984 11:55:05 am PDT **************************************************************************** drawing the score **************************************************************************** draw octava markings first pre-Adjust the first 10 syncs (beams may draw notes in syncs downstream) draw the syncs IF NOT sheet.printing AND AnyBug[] THEN EXIT; draw ties that go off the end of the section **************************************************************************** printing the score **************************************************************************** **************************************************************************** changing the view **************************************************************************** ENABLE Piece.Overflow => IF score = old THEN score _ new; time: Time; x, y: INTEGER; YellowBug[] => { [x, y] _ Sheet.ScreenPoint[score.sheet]; time _ Sheet.NearestTime[score.sheet, x, y].time; Sheet.Scale[score, IF score.sheet.hardcopy THEN 2 ELSE 1]; Sheet.SetBegin[score.sheet, time]}; **************************************************************************** getting accidentals **************************************************************************** hack to set n.shown no prior note n.spelled = normal => RETURN[inKey]; n.spelled # normal => RETURN[n.spelled]; ENDCASE; prior note an accidental MUST be asserted I bet you don't really believe this works. Ê]˜™Jšœ@™@Jšœ™Jšœ3™3Jšœ9™9—J˜šÏk ˜ Jšœœ ˜Jšœœ ˜+Jšœ œ=˜KJ˜ Jšœœ˜Jšœœ˜JšœœQ˜\Jšœ œ˜#JšœœT˜_J˜—Jšœ œ˜JšœH˜OJšœ˜ Jšœœœ ˜J˜JšœL™LJšœ™JšœL™LJ˜šÏnœœœœ˜6J˜JšœÏc˜1šœœ˜J˜J˜CJ˜%J˜—J˜0J˜Jšœ˜J˜—šžœœœ#˜6Jšœœ˜Jšœœ˜J˜.J˜$šœ˜Jšœœ œœ˜5Jšœœœœ˜6Jšœœœœ˜6Jšœ˜—Jšœœœ˜ZJšœœŸ˜@J˜/J˜"Jšœœ˜ Jšœœœ˜$J˜šœœœ˜+Jšœœœœ˜%Jšœ œ œœ˜NJšœ0œœ˜J˜DJ˜+Jšœœ(˜DJ˜3J˜Jšœ ™ š œ œœœœ˜$Jšœœ ˜$Jšœœ ˜$Jšœœ ˜—Jšœ$™$Jšœ(™(Jšœ™Jšœ ™ Jšœœœ˜,Jšœ™Jšœœœ ˜,Jšœœœ ˜&Jšœœ œœ˜7Jšœœ œœ˜7Jšœœ œœ˜7Jšœœ œœ˜7J˜Jšœœ˜(Jšœ œœ˜1Jšœ ˜Jšœ˜J˜—šž œœœœ˜FJ˜$Jš œœœœœ˜Gš œœ œœ ˜*Jšœœœœ˜"Jšœœœ˜(Jšœ˜ Jšœ˜—Jšœ˜J˜—š ž œœœ!œ œœ ˜eJ˜ J˜Jšœœ˜š œœ œœ ˜+Jšœœœœ˜,Jšœœœ˜(J˜/Jšœœ˜šœœœ˜&Jšœœœœ˜&Jšœœœ˜J˜AJš œœ œœœ˜0JšœLœœ˜XJšœ˜ Jšœ˜—Jšœ˜—Jšœœ˜ Jšœ˜J˜—Jš œœœœœ˜GJ˜š ž œœœ œœ˜CJšœ œ˜+Jšœ*™*šœœ˜Jšœ"œ˜0Jšœœ ˜#Jšœ œ˜Jšœœ˜—Jšœ˜J˜—šž œœ œœ˜=šœ˜Jšœ œ ˜Jš œ œœ œœ˜1Jšœœ˜—Jšœ˜J˜—š ž œœœœœœ˜HJšœœ˜ š œ œœœ ˜)Jšœœ˜2Jšœ œœ˜Jš˜š œœ œœ ˜&Jšœœ˜2Jšœ œœ˜Jšœ˜——Jšœ˜Jšœ˜J˜—š ž œœœ œœœ˜@Jšœœ˜šœœ˜Jšœœ œ˜,Jšœœ œ˜,Jšœ œ˜"Jšœœ œ˜,Jšœœ œ˜,Jšœœ˜"—Jšœ˜J˜—Jšœ˜J˜šžœœœ œ˜(Jšœ œ˜J˜Jšœœœ˜-J˜9Jšœœ3˜@Jšœœ ˜"Jšœ œ˜#šœœœ˜&J˜Jšœ˜—šœœ˜ J˜ J˜Jšœœœ˜'Jšœ œ4œœ˜NJšœ˜—J˜"J˜Jšœ˜J˜——…—'ª