SheetImplA.mesa
Copyright (C) 1981, 1984 Xerox Corporation. All rights reserved.
Author: John Maxwell
last modified: December 15, 1981 4:52 PM
Edited by Doug Wyatt, June 14, 1984 1:16:14 pm PDT
DIRECTORY
Beam USING [SetStems],
Graphics USING [DisplayContext, DrawRectangle, GetTexture, MakeFont, MoveTo, Scale, SetLineWidth, SetPaint, SetTexture, Texture, Vec],
InlineDefs USING [LowHalf],
MusicDefs,
Piece USING [AddSync, RemoveSync],
Score USING [BuildCache, cache, cacheLength, DrawKey, Look],
Selection USING [AddLine],
Sheet USING [default, FindLine, FindSection, Map, NextLine, NormalPitch, OctavaHeight, PriorLine, Reset, SetBegin],
StringDefs USING [AppendDecimal],
Sync USING [GetScoreIndex, Hidden, SetStave],
Utility USING [DrawChar, DrawLine, DrawString, NewSync, SetFont];
SheetImplA: CEDAR PROGRAM
IMPORTS Beam, Graphics, InlineDefs, MusicDefs, Piece, Score, Selection, Sheet, StringDefs, Sync, Utility
EXPORTS MusicDefs, Sheet
= BEGIN OPEN MusicDefs, Score, Sheet;
begin: PUBLIC Time;
endTime: PUBLIC Time;
scale, staffLength: PUBLIC INTEGER;
Last: PUBLIC PROC[l: CARDINAL] RETURNS[CARDINAL] =
{FOR i: CARDINAL IN [l..sheetLength-1) DO
IF sheet[i].time#sheet[i+1].time THEN RETURN[i];
ENDLOOP;
RETURN[sheetLength-1]};
LineNumber: PUBLIC PROC[l: CARDINAL] RETURNS[n: CARDINAL ← 1] =
{FOR i: CARDINAL IN (0..l] DO
IF sheet[i].y#sheet[i-1].y THEN n ← n+1;
ENDLOOP};
NextLine: PUBLIC PROC[l: CARDINAL] RETURNS[CARDINAL] =
{FOR i: CARDINAL IN (l..sheetLength) DO
IF sheet[i].y=sheet[l].y THEN LOOP;
RETURN[Last[i]];
ENDLOOP;
RETURN[sheetLength-1]};
NextStaff: PUBLIC PROC[s: CARDINAL, t: Time] RETURNS[CARDINAL] =
{staves: StavesPTR = sheet[FindSection[t]].staves;
FOR i: CARDINAL IN (s..staves.sl] DO
IF staves.staff[i].y#staves.staff[s].y THEN RETURN[i];
ENDLOOP;
RETURN[s]};
NormalPitch: PUBLIC PROC[staff: CARDINAL] RETURNS[INTEGER] =
{RETURN[IF staff IN [0..1] THEN 48 ELSE 27]};
PriorLine: PUBLIC PROC[l: CARDINAL] RETURNS[CARDINAL] =
{FOR i: CARDINAL DECREASING IN [0..l) DO
IF sheet[i].y#sheet[l].y THEN {l ← i; EXIT};
ENDLOOP;
FOR i: CARDINAL DECREASING IN [0..l) DO
IF sheet[i].y#sheet[l].y THEN RETURN[Last[i+1]];
ENDLOOP;
RETURN[Last[0]]};
PriorStaff: PUBLIC PROC[s: CARDINAL, t: Time] RETURNS[CARDINAL] =
{staves: StavesPTR = sheet[FindSection[t]].staves;
FOR i: CARDINAL DECREASING IN [0..s) DO
IF staves.staff[i].y#staves.staff[s].y THEN RETURN[i];
ENDLOOP;
RETURN[s]};
OctavaHeight: PUBLIC PROC[pitch, height: INTEGER] RETURNS[INTEGER] =
{IF pitch=60 AND height<40 THEN RETURN[40];
IF pitch=60 AND height>90 THEN RETURN[90];
IF pitch=15 AND height<-40 THEN RETURN[-40];
IF pitch=15 AND height>-8 THEN RETURN[-8];
RETURN[height]};
****************************************************************************
the sheet consists of an array of Sections
****************************************************************************
sheet: PUBLIC ARRAY [0..sheetLength) OF Section;
Initialize: PUBLIC PROC[dc: Graphics.DisplayContext] = BEGIN
context ← dc;
music ← Graphics.MakeFont["music"];
text ← Graphics.MakeFont["TimesRoman"];
Utility.SetFont[context, music, 8];
style ← ALL[[NIL, 0, 0, 0,[[0, 0],[0, 0],[0, 0],[0, 0]]]];
pianoroll
style[0] ← [NIL, 0, 60, 3,,];
style[0].staff ←[[72,-32],[48,-88],[27,-136],[3,-196]];
one staff
style[1] ← [NIL, 0, 80, 3,,];
style[1].staff ←[[48,-32],[48,-32],[48,-32],[48,-32]];
two staffs
style[2] ← [NIL, 0, 85, 3,,];
style[2].staff ←[[48,-32],[48,-32],[27,-125],[27,-125]];
style[12] ← [NIL, 0, 85, 3,,];
style[12].staff ←[[48,-32],[48,-32],[27,-150],[27,-150]];
three staffs
style[3] ← [NIL, 0, 75, 3,,];
style[3].staff ←[[48,-32],[48,-32],[27,-110],[27,-185]];
style[13] ← [NIL, 0, 75, 3,,];
style[13].staff ←[[48,-32],[48,-32],[27,-130],[27,-220]];
four staffs
style[4] ← [NIL, 0, 75, 3,,];
style[4].staff ←[[48,-32],[48,-110],[27,-185],[27,-260]];
show ← [, TRUE, TRUE, FALSE, FALSE, TRUE, graphical];
selection ← ALL[NIL];
selectionLength ← 0;
begin ← 0;
scale ← 1;
staffLength ← 550;
TF ← 256;
Score.Look[sheet,, 2];
Selection.AddLine[0, 0];
END;
Reset: PUBLIC PROC= {
sync: SyncPTR ← NIL;
staves: StavesPTR ← NIL;
page, pitch: INTEGER ← 2;
v, j, last, next: CARDINAL ← 0;
time, break, lastBreak, cacheTime: Time ← 0;
top, height, x, sc, lastHeight: INTEGER ← 0;
Score.BuildCache[];
IF scale=2 THEN sc ← 3 ELSE sc ← 2*scale;
[staves, last, next] ← NextStyle[NIL, 0, 0, 100];
IF staves=NIL THEN RETURN;
FOR i: CARDINAL IN [0..cacheLength] DO
IF i#cacheLength AND cache[i].type NOT IN SheetSwitch THEN LOOP;
IF i=cacheLength
THEN cacheTime ← LONG[staffLength]*sheetLength
ELSE cacheTime ← cache[i].time;
WHILE time<cacheTime OR cacheTime=break DO -- fill in all of the sections between
IF j=sheetLength THEN EXIT;
sheet[j].page ← 0;
sheet[j].time ← time;
IF j#0 AND sheet[j].time=sheet[j-1].time
THEN sheet[j].key ← sheet[j-1].key
ELSE sheet[j].key ← Key[time, break];
IF time<break THEN x ← x+InlineDefs.LowHalf[time-sheet[j-1].time];
IF time>=break THEN { -- new line
height ← height-lastHeight;
x← MAX[8, ABS[8*(sheet[j].key)]];
lastBreak ← break;
break ← lastBreak+staffLength-x;
[staves, last, next] ← NextStyle[staves, last, next, break-20];
lastHeight ← -staves.staff[staves.sl].y+staves.offset;
IF top-height>(650*sc)/2 THEN { -- new page
top ← height; sheet[j].page ← page; page ← page+1}};
sheet[j].x ← x;
sheet[j].y ← height;
sheet[j].staves ← staves;
time ← MIN[break, cacheTime];
j ← j + 1;
ENDLOOP;
IF i=cacheLength THEN EXIT;
IF cache[i].type=staves THEN LOOP;
Sync.SetStave[staves, cache[i]];
staves ← LOOPHOLE[@cache[i].event];
IF cache[i].type#clef THEN LOOP;
IF Sync.Hidden[0, Sync.GetScoreIndex[cache[i]], lastBreak] THEN time ← lastBreak;
ENDLOOP;
IF scale=2 THEN Paginate[];
Sheet.SetBegin[begin];
FOR i: CARDINAL IN [0..beamHeapLength) DO
IF beamHeap[i].sync2.time<min THEN LOOP;
IF beamHeap[i].sync1.time>max THEN LOOP;
Beam.SetStems[beamHeap[i]];
ENDLOOP;
};
NextStyle: PROC[old: StavesPTR, last, next: CARDINAL, break: Time] RETURNS[StavesPTR, CARDINAL, CARDINAL] = {
temp, new: StavesPTR;
newLast, newNext: CARDINAL ← 0;
new ← old;
newLast ← last;
newNext ← next;
FOR i: CARDINAL IN [next..cacheLength) DO
IF cache[i].time>=break+40 THEN EXIT;
IF cache[i].type#staves THEN LOOP;
newNext ← i;
IF cache[i].time>=break THEN EXIT;
temp ← LOOPHOLE[@cache[i].event];
IF temp=old THEN LOOP;
IF new#NIL AND i#next AND new.staff[new.sl].y<temp.staff[temp.sl].y THEN LOOP;
new ← temp;
newLast ← i;
ENDLOOP;
IF newLast=last AND old#NIL THEN RETURN[old, newLast, newNext];
Sync.SetStave[old, cache[newLast]];
RETURN[new, newLast, newNext];
};
Key: PROC[time, break: Time] RETURNS[key: INTEGER ← 0] = INLINE {
sync: SyncPTR ← NIL;
FOR i: CARDINAL IN [0..cacheLength) DO
IF cache[i].time>=time+staffLength THEN EXIT;
IF cache[i].type#keySignature THEN LOOP;
IF cache[i].time<time THEN {key ← cache[i].value; LOOP};
IF time=break THEN {sync ← cache[i]; EXIT};
ENDLOOP;
IF sync=NIL THEN RETURN;
IF ~Sync.Hidden[0, Sync.GetScoreIndex[sync], break] THEN RETURN;
RETURN[sync.value];
};
limit: INTEGER ← 1050;
Paginate: PROC = {
min: INTEGER=75;
start: INTEGER=40;
page: CARDINAL ← 2;
height: INTEGER ← -start;
line, last: CARDINAL ← 1;
count, first: CARDINAL ← 0;
FOR line ← 0, Sheet.NextLine[line] WHILE line#last DO
height ← height-sheet[line].staves.staff[3].y+min;
count ← count+1;
IF height<limit THEN {last ← line; LOOP};
IF count#1 THEN {-- subtract out the last line
count ← count-1;
height ← height+sheet[line].staves.staff[3].y-min};
layout the page
LayoutPage[count, first, line, limit+count*min-start-height];
sheet[line].page ← page;
page ← page+1;
set up for next page
first ← line; line ← last;
count ← 0;
height ← -start;
ENDLOOP;
};
LayoutPage: PROC[lines, first, last, space: CARDINAL] = {
oldHeight, height: INTEGER ← sheet[first].y;
layout this page
FOR i: CARDINAL IN (first..sheetLength) DO
IF sheet[i].y#oldHeight THEN {--new line
IF i>last THEN EXIT;
oldHeight ← sheet[i].y;
height ← sheet[i-1].y+sheet[i-1].staves.staff[3].y;
height ← height-space/lines};
sheet[i].y ← height;
sheet[i].page ← 0;
ENDLOOP;
};
FindLine: PUBLIC PROC[t: Time] RETURNS[l: INTEGER] = {
start: CARDINAL ← 0;
FOR i: CARDINAL IN [0..sheetLength-1) DO
IF sheet[i].time#sheet[i+1].time THEN {start ← i; EXIT};
ENDLOOP;
l ← start;
FOR i: CARDINAL ←start, NextLine[i] DO
IF sheet[i].time<=t THEN l ← i ELSE RETURN;
IF i=sheetLength-1 THEN RETURN;
ENDLOOP;
};
FindSection: PUBLIC PROC[t: Time] RETURNS[INTEGER] = {
IF t>=sheet[current].time
THEN {
IF current=sheetLength-1 THEN RETURN[current];
WHILE t>=sheet[current+1].time DO
current ← current+1;
IF current=sheetLength-1 THEN RETURN[current];
ENDLOOP;
RETURN[current];
}
ELSE {
WHILE current#0 AND t<sheet[current].time DO
current ← current -1;
ENDLOOP;
RETURN[current];
};
};
current: CARDINAL ← 0;
****************************************************************************
procedures that change the staves attributes
****************************************************************************
SetStyle: PUBLIC PROC[index: INTEGER, t1, t2: Time] = {
old: INTEGER ← -1;
temp, sync: SyncPTR ← NIL;
endOfScore: Time=EndOfScore[];
IF index NOT IN [0..20] THEN {flash ← TRUE; RETURN};
IF style[index].sl=0 THEN {flash ← TRUE; RETURN};
SetDirty[begin, endTime];
sync← NearestMeasure[t1, 10];
temp← NearestMeasure[t2, 10];
IF sync#NIL THEN t1 ← sync.time+1;
IF temp#NIL THEN t2 ← temp.time-1;
get the old style
FOR i: CARDINAL IN [0..cacheLength) DO
IF cache[i].type#staves THEN LOOP;
IF cache[i].time>=t1-1 THEN EXIT;
old ← cache[i].value;
ENDLOOP;
change all of the current staves to the new style
FOR i: CARDINAL DECREASING IN [0..cacheLength) DO
IF cache[i].time>t2 THEN LOOP;
IF cache[i].time<t1-5 THEN EXIT;
IF cache[i].type#staves THEN LOOP;
cache[i].value ← index;
ENDLOOP;
insert new staves
IF old#index THEN {
IF sync#NIL THEN Piece.RemoveSync[score, sync];
IF sync=NIL THEN {sync ← Utility.NewSync[]; sync.time ← t1};
sync.type ← staves;
sync.value ← index;
sync.event ← LOOPHOLE[style[index]];
Piece.AddSync[score, sync]};
IF old#index AND old#-1 AND t2#endOfScore THEN {
IF temp#NIL THEN Piece.RemoveSync[score, temp];
IF temp=NIL THEN {temp ← Utility.NewSync[]; temp.time ← t2};
temp.type ← staves;
temp.value ← old;
temp.event ← LOOPHOLE[style[old]];
Piece.AddSync[score, temp]};
reset world
Sheet.Reset[];
Sheet.SetBegin[begin];
FOR i: CARDINAL IN [0..beamHeapLength) DO
Beam.SetStems[beamHeap[i]];
ENDLOOP;
Selection.AddLine[t1, t2];
};
NearestMeasure: PROC[time, delta: Time] RETURNS[SyncPTR] = {
s: SyncPTR ← NIL;
FOR i: CARDINAL IN [0..scoreLength) DO
IF score[i].type#measure AND score[i].type#staves THEN LOOP;
IF ABS[score[i].time-time]>delta THEN LOOP;
delta ← ABS[score[i].time-time];
s ← score[i];
ENDLOOP;
RETURN[s];
};
style: PUBLIC ARRAY [0..20] OF Staves;
GetStyle: PUBLIC PROC[time: Time] RETURNS[INTEGER] = {
equal: BOOL;
staves: StavesPTR = sheet[Sheet.FindLine[time]].staves;
IF staves=NIL THEN RETURN[-1];
FOR i: CARDINAL IN [0..20] DO
IF style[i].sl#staves.sl THEN LOOP;
equal ← TRUE;
FOR j: CARDINAL IN [0..style[i].sl] DO
IF style[i].staff[j].y#staves.staff[j].y THEN {equal ← FALSE; EXIT};
ENDLOOP;
IF equal THEN RETURN[i];
ENDLOOP;
RETURN[-1];
};
****************************************************************************
clefs switches
****************************************************************************
SetClef: PUBLIC PROC[pitch, staff: INTEGER, time: Time] = {
s: SyncPTR ← NIL;
staves: StavesPTR;
make up a sync
s ← Utility.NewSync[];
staves ← LOOPHOLE[@s.event];
staves^ ← sheet[Sheet.FindSection[time]].staves^;
staves.staff[staff].pitch ← pitch;
s.type ← clef;
s.time ← time;
s.value ← staff;
Piece.AddSync[score, s];
Sheet.Reset[];
};
DrawClef: PUBLIC PROC[pitch, staff: INTEGER, time: Time] = {
x, y: INTEGER;
l: CARDINAL ← Sheet.FindLine[time];
IF time IN (sheet[l].time..sheet[l].time+15] THEN time ← sheet[l].time;
[x, y] ← Sheet.Map[time,, staff];
IF sheet[l].time=time THEN x ← -21;
Graphics.MoveTo[context,[x, y+16]];
IF voice THEN Graphics.SetTexture[context, light];
SELECT TRUE FROM
x=-21 AND pitch=27 => Utility.DrawChar[context, 121C];
x=-21 AND pitch=48 => Utility.DrawChar[context, 120C];
pitch=27 => Utility.DrawChar[context, 131C];
pitch=48 => Utility.DrawChar[context, 130C];
ENDCASE;
};
****************************************************************************
octava
****************************************************************************
SetOctava: PUBLIC PROC[pitch, staff, height: INTEGER, t1, t2: Time] = {
s: SyncPTR ← NIL;
current: INTEGER;
section: CARDINAL;
staves: StavesPTR;
normal: INTEGER = Sheet.NormalPitch[staff];
IF t1>=t2 THEN RETURN;
check to make sure that the staff is clear
FOR i: CARDINAL IN [0..cacheLength) DO
IF cache[i].time<t1 THEN LOOP;
IF cache[i].time>t2 THEN EXIT;
IF cache[i].type NOT IN SheetSwitch THEN LOOP;
staves ← LOOPHOLE[@cache[i].event];
current ← staves.staff[staff].pitch;
IF current=normal THEN LOOP;
flash ← TRUE; RETURN;
ENDLOOP;
section ← Sheet.FindSection[t1];
IF sheet[section].staves.staff[staff].pitch#normal THEN {flash ← TRUE; RETURN};
add the first sync
s ← Utility.NewSync[];
staves ← LOOPHOLE[@s.event];
staves^ ← sheet[section].staves^;
staves.staff[staff].pitch ← pitch;
staves.height ← Sheet.OctavaHeight[pitch, height];
s.type ← octava1;
s.time ← t1;
s.value ← staff;
Piece.AddSync[score, s];
add the second sync
s ← Utility.NewSync[];
staves ← LOOPHOLE[@s.event];
staves^ ← sheet[Sheet.FindSection[t2]].staves^;
staves.staff[staff].pitch ← normal;
s.type ← octava2;
s.time ← t2;
s.value ← staff;
Piece.AddSync[score, s];
Sheet.Reset[];
};
DrawOctava: PUBLIC PROC[pitch, staff, height: INTEGER, t1, t2: Time] = {
x1, x2, y: INTEGER ← 0;
section1, section2: CARDINAL;
IF t1>t2 THEN RETURN;
IF pitch#60 AND pitch#15 THEN RETURN;
height ← Sheet.OctavaHeight[pitch, height];
Utility.SetFont[context, text, 12];
section1 ← Sheet.FindSection[t1];
section2 ← Sheet.FindSection[t2];
IF voice THEN Graphics.SetTexture[context, light];
FOR i: CARDINAL IN [section1..section2] DO
IF i+1=sheetLength THEN EXIT;
IF sheet[i].time<begin THEN LOOP;
IF sheet[i].time>=endTime THEN EXIT;
IF sheet[i].time=sheet[i+1].time THEN LOOP;
[x1,] ← Sheet.Map[MAX[t1, sheet[i].time],, staff];
[x2, y] ← Sheet.Map[MIN[t2, sheet[i+1].time-1],, staff];
IF x1>staffLength-15 AND i=section1 THEN LOOP;
x2 ← x2+1; y ← y+height;
IF x1<10 OR i=section1 THEN {
Graphics.MoveTo[context,[x1, y-8]];
Utility.DrawChar[context,'8];
x1 ← x1+7; };
IF x1<x2 THEN DrawDottedLine[x1, y, x2, y];
IF i=section2 THEN Utility.DrawLine[x2, y, x2, y-(IF height>0 THEN 7 ELSE -7)];
ENDLOOP;
Utility.SetFont[context, music, 8];
};
DrawDottedLine: PROC[x1, y, x2, y2: INTEGER] = INLINE {
x: INTEGER;
IF NOT print THEN {
Graphics.SetTexture[context, 146314B];
Utility.DrawLine[x1, y, x2, y];
Graphics.SetTexture[context, black];
RETURN; };
x ← x1;
WHILE x<x2 DO
Utility.DrawLine[x, y, MIN[x+3, x2], y];
x ← x+5;
ENDLOOP;
};
****************************************************************************
drawing the sheet
****************************************************************************
HiLite: PUBLIC PROC[tex: Graphics.Texture, t1, t2: Time] = {
OPEN Graphics;
x1, y1, x2, y2, lastY: INTEGER;
v1, v2: Graphics.Vec;
offset: INTEGERIF tex=white THEN 58 ELSE 40;
section1, section2, i, j: CARDINAL;
IF t1 >= t2 THEN RETURN;
EnableClipping[context];
Graphics.SetPaint[context, IF tex=white THEN replace ELSE invert];
Graphics.SetTexture[context, tex];
i ← Sheet.FindLine[t1];
j ← Sheet.PriorLine[i];
IF i=j THEN lastY ← 100 ELSE lastY ← sheet[j].y;
j ← section1 ← FindSection[t1];
section2 ← FindSection[t2];
FOR i IN [section1..section2] DO
IF sheet[i].time>endTime THEN EXIT;
IF i#section2 AND sheet[i].time=sheet[i+1].time THEN LOOP;
IF tex#white AND i#section2 AND sheet[i].y=sheet[i+1].y THEN LOOP;
offset ← sheet[i].staves.offset;
IF tex=white THEN offset ← offset/2 ELSE offset ← offset/4;
[x1, y1] ← Sheet.Map[MAX[t1, sheet[j].time],, 0];
[x2, y2] ← Sheet.Map[MIN[t2, sheet[i+1].time-1],, sheet[i].staves.sl];
y1 ← y1+offset+34; y2 ← y2-offset;
IF x2<staffLength-1 OR tex=white THEN x2 ← x2+1 ELSE x2 ← x2+16;
IF tex=white AND sheet[i].y#lastY AND x1=sheet[i].x THEN x1 ← -25;
lastY ← sheet[i].y;
v1 ← [x1, y1]; v2 ← [x2, y2];
IF tex=white THEN SetBrush[white, replace];
Graphics.DrawRectangle[context, v1, v2];
IF tex=white THEN DrawStaves[sheet[i], x1, x2];
j ← i+1;
ENDLOOP;
EnableClipping[context];
Graphics.SetPaint[context, paint];
};
Draw: PUBLIC PROC = {
x: INTEGER;
j: CARDINAL;
staves: StavesPTR = sheet[0].staves;
sheetHeight: INTEGER = staves.staff[staves.sl].y;
IF begin=0 THEN Utility.DrawLine[-23, 0,-23, sheetHeight];
endTime ← begin;
IF scale=2 THEN x ← 3 ELSE x ← 2*scale;
FOR j ← Sheet.FindLine[begin], Sheet.NextLine[j] DO
IF sheet[j].y-top<(-650*x)/2 THEN {endTime ← sheet[j].time; EXIT};
DrawStaves[sheet[j],-25, staffLength];
ENDLOOP;
};
DrawStaves: PROC[l: Section, start, length: INTEGER] = {
sheetHeight: INTEGER ← l.staves.staff[l.staves.sl].y;
i: CARDINAL;
y: INTEGER ← l.y-top;
oldStaff ← [0, 0];
Graphics.SetTexture[context, black];
IF start=-25 THEN Utility.DrawLine[start, y, start, y+sheetHeight];
IF start=-25 AND show.accidental THEN Score.DrawKey[l.key, l.time];
IF l.page>1 THEN {
s: STRING ← [5];
StringDefs.AppendDecimal[s, l.page];
Graphics.MoveTo[context,[staffLength+10, y+30]];
Utility.SetFont[context, text, 12];
Utility.DrawString[context, s];
Utility.SetFont[context, music, 8];
};
IF scale>3 THEN
{
Graphics.SetLineWidth[context, 8];
IF length=staffLength THEN Utility.DrawLine[length, y, length, y+sheetHeight];
IF NOT show.notehead THEN Graphics.SetTexture[context, grey]; 
Utility.DrawLine[start, y, length, y];
Utility.DrawLine[start, y+sheetHeight, length, y+sheetHeight];
Graphics.SetTexture[context, black];
Graphics.SetLineWidth[context, 4];
}
ELSE FOR i IN [0..l.staves.sl] DO
DrawStaff[l.staves.staff[i], y, start, length]
ENDLOOP;
};
DrawStaff: PROC[s: Staff, y, start, length: INTEGER] = {
w: REAL ← 1;
ll, ur: Graphics.Vec;
i: CARDINAL;
tex: Graphics.Texture ← Graphics.GetTexture[context];
IF s=oldStaff THEN RETURN;
oldStaff ← s;
y ← y + s.y;
Graphics.SetTexture[context, IF show.notehead THEN black ELSE grey];
IF print THEN w ← w/2;
ll ← [start, y-w];
ur ←[length, y+w];
FOR i IN [0..5) DO
Graphics.DrawRectangle[context, ll, ur];
ll.y ← ll.y+8;
ur.y ← ur.y+8;
ENDLOOP;
Graphics.SetTexture[context, black];
IF start<0 THEN Graphics.SetPaint[context, paint];
IF (s.pitch=27 OR s.pitch=15) AND start<0 THEN {
Graphics.MoveTo[context,[-21, y+16]];
Utility.DrawChar[context, 121C]};
IF (s.pitch=48 OR s.pitch=60) AND start<0 THEN {
Graphics.MoveTo[context,[-21, y+16]];
Utility.DrawChar[context, 120C]};
Graphics.SetTexture[context, tex];
};
oldStaff: Staff;
d: CARDINAL = 8;
****************************************************************************
changing the view on the sheet
****************************************************************************
top: PUBLIC INTEGER ← 0;
SetBegin: PUBLIC PROC[now: Time] = {
l: Section ← sheet[Sheet.FindLine[now]];
begin ← l.time;
top ← l.y;
};
Scroll: PUBLIC PROC[lines: INTEGER] = {
section: CARDINAL ← Sheet.FindLine[begin];
IF lines<0
THEN FOR i: CARDINAL IN [0..ABS[lines]) DO
IF section=0 THEN EXIT;
section ← Sheet.PriorLine[section];
ENDLOOP
ELSE FOR i: CARDINAL IN [0..ABS[lines]) DO
section ← Sheet.NextLine[section];
IF section=sheetLength THEN RETURN;
ENDLOOP;
Sheet.SetBegin[sheet[section].time];
min ← 0; max ← EndOfScore[];
};
Scale: PUBLIC PROC[newScale: INTEGER] = {
one: REAL = 1;
two: REAL = 2;
IF scale=newScale THEN RETURN;
reset to 1
SELECT scale FROM
2 => Graphics.Scale[context,[3/two, 3/two]];
4 => Graphics.Scale[context,[4, 4]];
ENDCASE;
staffLength ← 550;
now move to the desired scale
SELECT newScale FROM
1 => {scale ← 1;
staffLength ← staffLength;
Graphics.SetLineWidth[context, 1]};
2 => {scale ← 2; --actually 3/2
staffLength ← (3*staffLength)/2;
Graphics.Scale[context,[two/3, two/3]];
Graphics.SetLineWidth[context, 2]};
4 => {scale ← 4;
staffLength ← 4*staffLength;
Graphics.Scale[context,[one/4, one/4]];
Graphics.SetLineWidth[context, 4]};
ENDCASE;
Sheet.Reset[];
Sheet.SetBegin[begin];
min ← 0; max ← EndOfScore[];
};
END.