music.h - abc2ps - A powerful sheet setting tool using the simple abc notation | |
git clone git://vernunftzentrum.de/abc2ps.git | |
Log | |
Files | |
Refs | |
--- | |
music.h (108504B) | |
--- | |
1 /* | |
2 * This file is part of abc2ps, | |
3 * Copyright (C) 1996,1997,1998 Michael Methfessel | |
4 * See file abc2ps.c for details. | |
5 */ | |
6 | |
7 /* subroutines connected with output of music */ | |
8 | |
9 #define XP_START 0 | |
10 #define XP_END (maxSyms-1) | |
11 | |
12 /* ----- nwid ----- */ | |
13 /* Sets the prefered width for a note depending on the duration. | |
14 Return value is default space on right and left side. | |
15 Function is determined by values at 0, 1/2, 1. | |
16 Return value is 1.0 for quarter note. */ | |
17 float nwid (dur) | |
18 float dur; | |
19 { | |
20 float a,b,x,p,x0,p0; | |
21 | |
22 a=2*(f1p-2*f5p+f0p); | |
23 b=f1p-f0p-a; | |
24 x = dur/(float)BASE; | |
25 p = a*x*x + b*x + f0p; | |
26 | |
27 x0 = 0.25; | |
28 p0 = a*x0*x0 + b*x0 + f0p; | |
29 p = p/p0; | |
30 return p; | |
31 } | |
32 | |
33 /* ----- xwid -- --- */ | |
34 /* same as nwid but for stretched system */ | |
35 float xwid (dur) | |
36 float dur; | |
37 { | |
38 float a,b,x,p,x0,p0; | |
39 | |
40 a=2*(f1x-2*f5x+f0x); | |
41 b=f1x-f0x-a; | |
42 x = dur/(float)BASE; | |
43 p = a*x*x + b*x + f0x; | |
44 | |
45 x0 = 0.25; | |
46 p0 = a*x0*x0 + b*x0 + f0x; | |
47 p = p/p0; | |
48 | |
49 return p; | |
50 } | |
51 | |
52 /* ----- next_note, prec_note ------ */ | |
53 int next_note (k,n,symb) | |
54 int k,n; | |
55 struct SYMBOL symb[]; | |
56 { | |
57 int i; | |
58 for (i=k+1;i<n;i++) { | |
59 if ((symb[i].type==NOTE)||(symb[i].type==REST)) return i; | |
60 } | |
61 return -1; | |
62 } | |
63 | |
64 int prec_note (k,n,symb) | |
65 int k,n; | |
66 struct SYMBOL symb[]; | |
67 { | |
68 int i; | |
69 for (i=k-1;i>=0;i--) { | |
70 if ((symb[i].type==NOTE)||(symb[i].type==REST)) return i; | |
71 } | |
72 return -1; | |
73 } | |
74 | |
75 | |
76 /* ----- followed_by_note ------ */ | |
77 int followed_by_note (k,n,symb) | |
78 int k,n; | |
79 struct SYMBOL symb[]; | |
80 { | |
81 int i; | |
82 | |
83 for (i=k+1;i<n;i++) { | |
84 switch (symb[i].type) { | |
85 case INVISIBLE: | |
86 break; | |
87 case NOTE: | |
88 case REST: | |
89 return i; | |
90 break; | |
91 default: | |
92 return -1; | |
93 } | |
94 } | |
95 return -1; | |
96 } | |
97 | |
98 /* ----- preceded_by_note ------ */ | |
99 int preceded_by_note (k,n,symb) | |
100 int k,n; | |
101 struct SYMBOL symb[]; | |
102 { | |
103 int i; | |
104 | |
105 for (i=k-1;i>=0;i--) { | |
106 switch (symb[i].type) { | |
107 case INVISIBLE: | |
108 break; | |
109 case NOTE: | |
110 case REST: | |
111 return i; | |
112 break; | |
113 default: | |
114 return -1; | |
115 } | |
116 } | |
117 return -1; | |
118 } | |
119 | |
120 | |
121 void xch (i,j) /* sub to exchange two integers */ | |
122 int *i,*j; | |
123 { | |
124 int k; | |
125 k=*i; | |
126 *i=*j; | |
127 *j=k; | |
128 } | |
129 | |
130 | |
131 | |
132 /* ----- print_linetype ----------- */ | |
133 void print_linetype (t) | |
134 int t; | |
135 { | |
136 | |
137 if (t== COMMENT) printf("COMMENT\n"); | |
138 else if (t== MUSIC) printf("MUSIC\n"); | |
139 else if (t== E_O_F) printf("E_O_F\n"); | |
140 else if (t== INFO) printf("INFO\n"); | |
141 else if (t== TITLE) printf("TITLE\n"); | |
142 else if (t== METER) printf("METER\n"); | |
143 else if (t== PARTS) printf("PARTS\n"); | |
144 else if (t== KEY) printf("KEY\n"); | |
145 else if (t== XREF) printf("XREF\n"); | |
146 else if (t== DLEN) printf("DLEN\n"); | |
147 else if (t== HISTORY) printf("HISTORY\n"); | |
148 else if (t== TEMPO) printf("TEMPO\n"); | |
149 else if (t== BLANK) printf("BLANK\n"); | |
150 else if (t== VOICE) printf("VOICE\n"); | |
151 else if (t== MWORDS) printf("MWORDS\n"); | |
152 else if (t== PSCOMMENT) printf("PSCOMMENT\n"); | |
153 else printf("UNKNOWN LINE TYPE\n"); | |
154 } | |
155 | |
156 /* ----- print_syms: show sym properties set by parser ------ */ | |
157 void print_syms(num1,num2,symb) | |
158 int num1,num2; | |
159 struct SYMBOL symb[]; | |
160 { | |
161 int i,t,j,y,nsh; | |
162 char dsym[21] = {' ','~','.','J','M','H','u','v','R','T','K'}; | |
163 char bsym[10] = {'-', '1' ,'2', '3', '4', '5', '6', '7', '8', '9'}; | |
164 char str[21]; | |
165 | |
166 printf ("\n---------- Symbol list ----------\n"); | |
167 printf ("word slur eol num description\n"); | |
168 | |
169 for (i=num1;i<num2;i++) { | |
170 printf (" %c %c %c %c %c ", | |
171 bsym[symb[i].word_st], bsym[symb[i].word_end], | |
172 bsym[symb[i].slur_st], bsym[symb[i].slur_end], | |
173 bsym[symb[i].eoln] ); | |
174 printf ("%4d ", i); | |
175 t=symb[i].type; | |
176 switch (t) { | |
177 | |
178 case NOTE: | |
179 case REST: | |
180 if (t==NOTE) printf ("NOTE "); | |
181 if (t==REST) printf ("REST "); | |
182 if (symb[i].npitch>1) printf (" ["); | |
183 for (j=0;j<symb[i].npitch;j++) { | |
184 printf (" "); | |
185 if (symb[i].accs[j]==A_SH) printf ("^"); | |
186 if (symb[i].accs[j]==A_NT) printf ("="); | |
187 if (symb[i].accs[j]==A_FT) printf ("_"); | |
188 if (symb[i].accs[j]==A_DS) printf ("^^"); | |
189 if (symb[i].accs[j]==A_DF) printf ("__"); | |
190 y=3*(symb[i].pits[j]-18)+symb[i].yadd; | |
191 strcpy (str,"z"); | |
192 if (t==NOTE) symbolic_pitch (symb[i].pits[j],str); | |
193 printf ("%s(%d)", str, symb[i].lens[j]); | |
194 } | |
195 if (symb[i].npitch>1) printf (" ]"); | |
196 if (symb[i].p_plet) | |
197 printf (" (%d:%d:%d", symb[i].p_plet,symb[i].q_plet,symb[i].r_p… | |
198 if (strlen(symb[i].text)>0) printf (" \"%s\"", symb[i].text); | |
199 if (symb[i].dc.n>0) { | |
200 printf (" deco "); | |
201 for (j=0;j<symb[i].dc.n;j++) | |
202 printf ("%c",dsym[symb[i].dc.t[j]]); | |
203 } | |
204 if (symb[i].gr.n>0) { | |
205 printf (" grace "); | |
206 for (j=0;j<symb[i].gr.n;j++) { | |
207 if (j>0) printf ("-"); | |
208 if (symb[i].gr.a[j]==A_SH) printf ("^"); | |
209 if (symb[i].gr.a[j]==A_NT) printf ("="); | |
210 if (symb[i].gr.a[j]==A_FT) printf ("_"); | |
211 symbolic_pitch (symb[i].gr.p[j],str); | |
212 printf ("%s",str); | |
213 } | |
214 } | |
215 break; | |
216 | |
217 case BAR: | |
218 printf ("BAR ======= "); | |
219 if (symb[i].u==B_SNGL) printf ("single"); | |
220 if (symb[i].u==B_DBL) printf ("double"); | |
221 if (symb[i].u==B_LREP) printf ("left repeat"); | |
222 if (symb[i].u==B_RREP) printf ("right repeat"); | |
223 if (symb[i].u==B_DREP) printf ("double repeat"); | |
224 if (symb[i].u==B_FAT1) printf ("thick-thin"); | |
225 if (symb[i].u==B_FAT2) printf ("thin-thick"); | |
226 if (symb[i].u==B_INVIS) printf ("invisible"); | |
227 if (symb[i].v) printf (", ending %d", symb[i].v); | |
228 if (strlen(symb[i].text)>0) printf (", label \"%s\"",symb[i].text); | |
229 break; | |
230 | |
231 case CLEF: | |
232 if (symb[i].u==TREBLE) printf ("CLEF treble"); | |
233 if (symb[i].u==BASS) printf ("CLEF bass"); | |
234 if (symb[i].u==ALTO) printf ("CLEF alto"); | |
235 break; | |
236 | |
237 case TIMESIG: | |
238 printf ("TIMESIG "); | |
239 if (symb[i].w==1) printf ("C"); | |
240 else if (symb[i].w==2) printf ("C|"); | |
241 else printf ("%d/%d", symb[i].u,symb[i].v); | |
242 break; | |
243 | |
244 case KEYSIG: | |
245 printf ("KEYSIG "); | |
246 if (symb[i].t==A_SH) printf ("sharps "); | |
247 if (symb[i].t==A_FT) printf ("flats "); | |
248 printf ("%d to %d", symb[i].u,symb[i].v); | |
249 if (symb[i].w <= symb[i].v) | |
250 printf (", neutrals from %d", symb[i].w); | |
251 break; | |
252 | |
253 case INVISIBLE: | |
254 printf ("INVIS "); | |
255 break; | |
256 | |
257 default: | |
258 printf ("UNKNOWN "); | |
259 break; | |
260 } | |
261 printf ("\n"); | |
262 | |
263 } | |
264 printf ("\n"); | |
265 } | |
266 | |
267 /* ----- print_vsyms: print symbols for all voices ----- */ | |
268 void print_vsyms () | |
269 { | |
270 int i; | |
271 | |
272 printf("\n"); | |
273 for (i=0;i<nvoice;i++) { | |
274 if (nvoice>1) | |
275 printf ("Voice <%s> (%d of %d)", voice[i].id,i,nvoice); | |
276 print_syms (0,voice[i].nsym,symv[i]); | |
277 } | |
278 } | |
279 | |
280 | |
281 /* ----- set_head_directions ----------- */ | |
282 | |
283 #define ABS(a) ((a)>0) ? (a) : (-a) | |
284 | |
285 /* decide whether to shift heads to other side of stem on chords */ | |
286 /* also position accidentals to avoid too much overlap */ | |
287 void set_head_directions (s) | |
288 struct SYMBOL *s; | |
289 { | |
290 int i,n,nx,sig,d,da,shift,nac; | |
291 int i1,i2,m; | |
292 float dx,xx,xmn; | |
293 | |
294 n=s->npitch; | |
295 sig=-1; | |
296 if (s->stem>0) sig=1; | |
297 for (i=0;i<n;i++) { | |
298 s->shhd[i]=0; | |
299 s->shac[i]=8; | |
300 if (s->head==H_OVAL) s->shac[i]+=3; | |
301 s->xmn=0; | |
302 s->xmx=0; | |
303 } | |
304 if (n<2) return; | |
305 | |
306 /* sort heads by pitch */ | |
307 for (;;) { | |
308 nx=0; | |
309 for (i=1;i<n;i++) { | |
310 if ( (s->pits[i]-s->pits[i-1])*sig>0 ) { | |
311 xch (&s->pits[i],&s->pits[i-1]); | |
312 xch (&s->lens[i],&s->lens[i-1]); | |
313 xch (&s->accs[i],&s->accs[i-1]); | |
314 xch (&s->sl1[i],&s->sl1[i-1]); | |
315 xch (&s->sl2[i],&s->sl2[i-1]); | |
316 xch (&s->ti1[i],&s->ti1[i-1]); | |
317 xch (&s->ti2[i],&s->ti2[i-1]); | |
318 nx++; | |
319 } | |
320 } | |
321 if (!nx) break; | |
322 } | |
323 | |
324 shift=0; /* shift heads */ | |
325 for (i=n-2;i>=0;i--) { | |
326 d=s->pits[i+1]-s->pits[i]; | |
327 if (d<0) d=-d; | |
328 if ((d>=2) || (d==0)) | |
329 shift=0; | |
330 else { | |
331 shift=1-shift; | |
332 if (shift) { | |
333 dx=7.8; | |
334 if (s->head==H_EMPTY) dx=7.8; | |
335 if (s->head==H_OVAL) dx=10.0; | |
336 if (s->stem==-1) s->shhd[i]=-dx; | |
337 else s->shhd[i]=dx; | |
338 } | |
339 } | |
340 if (s->shhd[i] < s->xmn) s->xmn = s->shhd[i]; | |
341 if (s->shhd[i] > s->xmx) s->xmx = s->shhd[i]; | |
342 } | |
343 | |
344 shift=0; /* shift accidentals */ | |
345 i1=0; i2=n-1; | |
346 if (sig<0) { i1=n-1; i2=0; } | |
347 for (i=i1; ; i=i+sig) { /* count down in terms of pitch */ | |
348 xmn=0; /* left-most pos of a close head */ | |
349 nac=99; /* relative pos of next acc above */ | |
350 for (m=0;m<n;m++) { | |
351 xx=s->shhd[m]; | |
352 d=s->pits[m]-s->pits[i]; | |
353 da=ABS(d); | |
354 if ((da<=5) && (s->shhd[m]<xmn)) xmn=s->shhd[m]; | |
355 if ((d>0) && (da<nac) && s->accs[m]) nac=da; | |
356 } | |
357 s->shac[i]=8.5-xmn+s->shhd[i]; /* aligns accidentals in column */ | |
358 if (s->head==H_EMPTY) s->shac[i] += 1.0; | |
359 if (s->head==H_OVAL) s->shac[i] += 3.0; | |
360 if (s->accs[i]) { | |
361 if (nac>=6) /* no overlap */ | |
362 shift=0; | |
363 else if (nac>=4) { /* weak overlap */ | |
364 if (shift==0) shift=1; | |
365 else shift=shift-1; | |
366 } | |
367 else { /* strong overlap */ | |
368 if (shift==0) shift=2; | |
369 else if (shift==1) shift=3; | |
370 else if (shift==2) shift=1; | |
371 else if (shift==3) shift=0; | |
372 } | |
373 | |
374 while (shift>=4) shift -=4; | |
375 s->shac[i] += 3*shift; | |
376 } | |
377 if (i==i2) break; | |
378 } | |
379 | |
380 } | |
381 | |
382 | |
383 /* ----- set_minsyms: want at least one symbol in each voice --- */ | |
384 void set_minsyms(ivc) | |
385 int ivc; | |
386 { | |
387 int n2; | |
388 | |
389 n2=voice[ivc].nsym; | |
390 printf ("set_minsyms: n2=%d\n",n2); | |
391 if (n2>0) return; | |
392 | |
393 symv[ivc][n2]=zsym; | |
394 symv[ivc][n2].type = INVISIBLE; | |
395 symv[ivc][n2].u = 3; | |
396 symv[ivc][n2].v = 3; | |
397 symv[ivc][n2].w = 3; | |
398 voice[ivc].nsym++; | |
399 | |
400 } | |
401 | |
402 | |
403 /* ----- set_sym_chars: set symbol characteristics --- */ | |
404 void set_sym_chars (n1,n2,symb) | |
405 int n1,n2; | |
406 struct SYMBOL symb[]; | |
407 { | |
408 int i,np,m,ymn,ymx; | |
409 float yav,yy; | |
410 | |
411 for (i=n1;i<n2;i++) { | |
412 if ((symb[i].type==NOTE)||(symb[i].type==REST)) { | |
413 symb[i].y=3*(symb[i].pits[0]-18)+symb[i].yadd; | |
414 if (symb[i].type==REST) symb[i].y=12; | |
415 yav=0; | |
416 ymn=1000; | |
417 ymx=-1000; | |
418 np=symb[i].npitch; | |
419 for (m=0;m<np;m++) { | |
420 yy=3*(symb[i].pits[m]-18)+symb[i].yadd; | |
421 yav=yav+yy/np; | |
422 if (yy<ymn) ymn=yy; | |
423 if (yy>ymx) ymx=yy; | |
424 } | |
425 symb[i].ymn=ymn; | |
426 symb[i].ymx=ymx; | |
427 symb[i].yav=yav; | |
428 symb[i].ylo=ymn; | |
429 symb[i].yhi=ymx; | |
430 | |
431 } | |
432 } | |
433 } | |
434 | |
435 /* ----- set_beams: decide on beams ---- */ | |
436 void set_beams (n1,n2,symb) | |
437 int n1,n2; | |
438 struct SYMBOL symb[]; | |
439 { | |
440 int j,lastnote,start_flag; | |
441 | |
442 /* separate words at notes without flags */ | |
443 start_flag=0; | |
444 lastnote=-1; | |
445 for (j=n1;j<n2;j++) { | |
446 if (symb[j].type==NOTE) { | |
447 if (start_flag) { | |
448 symb[j].word_st=1; | |
449 start_flag=0; | |
450 } | |
451 if (symb[j].flags==0) { | |
452 if (lastnote>=0) symb[lastnote].word_end=1; | |
453 symb[j].word_st=1; | |
454 symb[j].word_end=1; | |
455 start_flag=1; | |
456 } | |
457 lastnote=j; | |
458 } | |
459 } | |
460 | |
461 } | |
462 | |
463 /* ----- set_stems: decide on stem directions and lengths ---- */ | |
464 void set_stems (n1,n2,symb) | |
465 int n1,n2; | |
466 struct SYMBOL symb[]; | |
467 { | |
468 int beam,j,k,n,stem,laststem; | |
469 float avg,slen,lasty,dy; | |
470 | |
471 /* set stem directions; near middle, use previous direction */ | |
472 beam=0; | |
473 laststem=0; | |
474 for (j=n1; j<n2; j++) { | |
475 if (symb[j].type!=NOTE) laststem=0; | |
476 | |
477 if (symb[j].type==NOTE) { | |
478 | |
479 symb[j].stem=0; | |
480 if (symb[j].len<WHOLE) symb[j].stem=1; | |
481 if (symb[j].yav>=12) symb[j].stem=-symb[j].stem; | |
482 if ((symb[j].yav>11) && (symb[j].yav<13) && (laststem!=0)) { | |
483 dy=symb[j].yav-lasty; | |
484 if ((dy>-7) && (dy<7)) symb[j].stem=laststem; | |
485 } | |
486 | |
487 if (symb[j].word_st && (!symb[j].word_end)) { /* start of beam */ | |
488 avg=0; | |
489 n=0; | |
490 for (k=j;k<n2;k++) { | |
491 if (symb[k].type==NOTE) { | |
492 avg=avg+symb[k].yav; | |
493 n++; | |
494 } | |
495 if (symb[k].word_end) break; | |
496 } | |
497 avg=avg/n; | |
498 stem=1; | |
499 if (avg>=12) stem=-1; | |
500 if ((avg>11) && (avg<13) && (laststem!=0)) stem=laststem; | |
501 beam=1; | |
502 } | |
503 | |
504 if (beam) symb[j].stem=stem; | |
505 if (symb[j].word_end) beam=0; | |
506 if (bagpipe) symb[j].stem=-1; | |
507 if (symb[j].len>=WHOLE) symb[j].stem=0; | |
508 laststem=symb[j].stem; | |
509 if (symb[j].len>=HALF) laststem=0; | |
510 lasty=symb[j].yav; | |
511 } | |
512 } | |
513 | |
514 /* shift notes in chords (need stem direction to do this) */ | |
515 for (j=n1;j<n2;j++) | |
516 if (symb[j].type==NOTE) set_head_directions (&symb[j]); | |
517 | |
518 /* set height of stem end, without considering beaming for now */ | |
519 for (j=n1; j<n2; j++) if (symb[j].type==NOTE) { | |
520 slen=STEM; | |
521 if (symb[j].npitch>1) slen=STEM_CH; | |
522 if (symb[j].flags==3) slen += 4; | |
523 if (symb[j].flags==4) slen += 9; | |
524 if ((symb[j].flags>2) && (symb[j].stem==1)) slen -= 1; | |
525 if (symb[j].stem==1) { | |
526 symb[j].y=symb[j].ymn; | |
527 symb[j].ys=symb[j].ymx+slen; | |
528 } | |
529 else if (symb[j].stem==-1) { | |
530 symb[j].y=symb[j].ymx; | |
531 symb[j].ys=symb[j].ymn-slen; | |
532 } | |
533 else { | |
534 symb[j].y=symb[j].ymx; | |
535 symb[j].ys=symb[j].ymx; | |
536 } | |
537 } | |
538 } | |
539 | |
540 /* ----- set_sym_times: set time axis; also count through bars ----- */ | |
541 int set_sym_times (n1,n2,symb,meter0) | |
542 int n1,n2; | |
543 struct SYMBOL symb[]; | |
544 struct METERSTR meter0; | |
545 { | |
546 int i,pp,qq,rr,meter1,meter2,count,bnum,lastb,bsave; | |
547 int qtab[] = {0,0,3,2,3,0,2,0,3,0}; | |
548 float time,factor,fullmes; | |
549 | |
550 meter1=meter0.meter1; | |
551 meter2=meter0.meter2; | |
552 | |
553 lastb=bnum=0; | |
554 bsave=1; | |
555 | |
556 time=0.0; | |
557 factor=1.0; | |
558 for (i=n1;i<n2;i++) { | |
559 symb[i].time=time; | |
560 | |
561 /* count through bar numbers, put into symb.t */ | |
562 if (symb[i].type==BAR) { | |
563 fullmes=(WHOLE*meter1)/meter2; | |
564 if (bnum==0) { | |
565 bnum=barinit; | |
566 if (fullmes<time+0.001) bnum++; | |
567 symb[i].t=bnum; | |
568 lastb=i; | |
569 } | |
570 else if (time-symb[lastb].time>=fullmes-0.001) { | |
571 bnum++; | |
572 while (symb[i+1].type==BAR) {i++; symb[i].time=time; } | |
573 symb[i].t=bnum; | |
574 lastb=i; | |
575 } | |
576 if (symb[i].v>1) { | |
577 bnum=bsave; | |
578 symb[i].t=0; | |
579 } | |
580 if (symb[i].v==1) bsave=bnum; | |
581 } | |
582 | |
583 if ((symb[i].type==NOTE)||(symb[i].type==REST)) { | |
584 if (symb[i].p_plet) { | |
585 pp=symb[i].p_plet; | |
586 qq=symb[i].q_plet; | |
587 rr=symb[i].r_plet; | |
588 if (qq==0) { | |
589 qq=qtab[pp]; | |
590 if (qq==0) { | |
591 qq=2; | |
592 if (meter1%3==0) qq=3; | |
593 } | |
594 } | |
595 factor=((float)qq)/((float)pp); | |
596 count=rr; | |
597 } | |
598 time=time+factor*symb[i].len; | |
599 if (count>0) count--; | |
600 if (count==0) factor=1; | |
601 } | |
602 | |
603 if (symb[i].type==TIMESIG) { /* maintain meter as we go along */ | |
604 meter1=symb[i].u; | |
605 meter2=symb[i].v; | |
606 } | |
607 | |
608 } | |
609 | |
610 return bnum; | |
611 | |
612 } | |
613 | |
614 /* ----- set_sym_widths: set widths and prefered space --- */ | |
615 /* This routine sets the minimal left and right widths wl,wr | |
616 so that successive symbols are still separated when | |
617 no extra glue is put between them. It also sets the prefered | |
618 spacings pl,pr for good output and xl,xr for expanded layout. | |
619 All distances in pt relative to the symbol center. */ | |
620 | |
621 #define AT_LEAST(a,b) if((a)<(b)) a=b; | |
622 void set_sym_widths (ns1,ns2,symb,ivc) | |
623 int ns1,ns2,ivc; | |
624 struct SYMBOL symb[]; | |
625 { | |
626 int i,n,j0,j,m,n1,n2,bt,k,sl,k1,k2,got_note,ok; | |
627 float xx,w,swfac,spc,dur,yy; | |
628 char t[81],tt[81]; | |
629 | |
630 swfac=1.0; | |
631 if (strstr(cfmt.vocalfont.name,"Times-Roman")) swfac=1.00; | |
632 if (strstr(cfmt.vocalfont.name,"Times-Bold")) swfac=1.05; | |
633 if (strstr(cfmt.vocalfont.name,"Helvetica")) swfac=1.10; | |
634 if (strstr(cfmt.vocalfont.name,"Helvetica-Bold")) swfac=1.15; | |
635 | |
636 got_note=0; | |
637 for (i=ns1;i<ns2;i++) { | |
638 switch (symb[i].type) { | |
639 | |
640 case INVISIBLE: /* empty space; shrink,space,stretch from u,v,w */ | |
641 symb[i].wl=symb[i].wr=0.5*symb[i].u; | |
642 symb[i].pl=symb[i].pr=0.5*symb[i].v; | |
643 symb[i].xl=symb[i].xr=0.5*symb[i].w; | |
644 break; | |
645 | |
646 case NOTE: | |
647 case REST: | |
648 got_note=1; | |
649 dur=symb[i].len; | |
650 symb[i].wl=symb[i].wr=4.5; | |
651 if (symb[i].head==H_EMPTY) {symb[i].wl=6.0; symb[i].wr=14.0;} | |
652 if (symb[i].head==H_OVAL) {symb[i].wl=8.0; symb[i].wr=18.0;} | |
653 symb[i].pl=symb[i].xl=symb[i].wl; | |
654 symb[i].pr=symb[i].xr=symb[i].wr; | |
655 | |
656 /* room for shifted heads and accidental signs */ | |
657 for (m=0;m<symb[i].npitch;m++) { | |
658 xx=symb[i].shhd[m]; | |
659 AT_LEAST (symb[i].wr, xx+6); | |
660 AT_LEAST (symb[i].wl, -xx+6); | |
661 if (symb[i].accs[m]) { | |
662 xx=xx-symb[i].shac[m]; | |
663 AT_LEAST (symb[i].wl, -xx+3); | |
664 } | |
665 AT_LEAST (symb[i].xl, -xx+3); | |
666 symb[i].pl=symb[i].wl; | |
667 symb[i].xl=symb[i].wl; | |
668 } | |
669 | |
670 /* room for slide */ | |
671 for (k=0;k<symb[i].dc.n;k++) { | |
672 if (symb[i].dc.t[k]==D_SLIDE) symb[i].wl += 10; | |
673 } | |
674 | |
675 /* room for grace notes */ | |
676 if (symb[i].gr.n>0) { | |
677 xx=GSPACE0; | |
678 if (symb[i].gr.a[0]) xx=xx+3.5; | |
679 for (j=1;j<symb[i].gr.n;j++) { | |
680 xx=xx+GSPACE; | |
681 if (symb[i].gr.a[j]) xx=xx+4; | |
682 } | |
683 symb[i].wl = symb[i].wl + xx+1; | |
684 symb[i].pl = symb[i].pl + xx+1; | |
685 symb[i].xl = symb[i].xl + xx+1; | |
686 } | |
687 | |
688 /* space for flag if stem goes up on standalone note */ | |
689 if (symb[i].word_st && symb[i].word_end) | |
690 if ((symb[i].stem==1) && symb[i].flags>0) | |
691 AT_LEAST (symb[i].wr, 12); | |
692 | |
693 /* leave room for dots */ | |
694 if (symb[i].dots>0) { | |
695 AT_LEAST (symb[i].wr,12+symb[i].xmx); | |
696 if (symb[i].dots>=2) symb[i].wr=symb[i].wr+3.5; | |
697 n=(int) symb[i].y; | |
698 /* special case: standalone with up-stem and flags */ | |
699 if (symb[i].flags && (symb[i].stem==1) && !(n%6)) | |
700 if ((symb[i].word_st==1) && (symb[i].word_end==1)) { | |
701 symb[i].wr=symb[i].wr+DOTSHIFT; | |
702 symb[i].pr=symb[i].pr+DOTSHIFT; | |
703 symb[i].xr=symb[i].xr+DOTSHIFT; | |
704 } | |
705 } | |
706 | |
707 /* extra space when down stem follows up stem */ | |
708 j0=preceded_by_note(i,ns2,symb); | |
709 if ((j0>=0) && (symb[j0].stem==1) && (symb[i].stem==-1)) | |
710 AT_LEAST (symb[i].wl, 7); | |
711 | |
712 /* make sure helper lines don't overlap */ | |
713 if ((j0>=0) && (symb[i].y>27) && (symb[j0].y>27)) | |
714 AT_LEAST (symb[i].wl, 7.5); | |
715 | |
716 /* leave room guitar chord */ | |
717 if (strlen(symb[i].text)>0) { | |
718 /* special case: guitar chord under ending 1 or 2 */ | |
719 /* leave some room to the left of the note */ | |
720 if ((i>0) && (symb[i-1].type==BAR)) { | |
721 bt=symb[i-1].v; | |
722 if (bt) AT_LEAST (symb[i].wl, 18); | |
723 } | |
724 /* rest is same for all guitar chord cases */ | |
725 tex_str(symb[i].text,t,&w); | |
726 xx=cfmt.gchordfont.size*w; | |
727 xx=xx*1.05; /* extra space mainly for helvetica font */ | |
728 spc=xx*GCHPRE; | |
729 k1=prec_note(i,ns2,symb); | |
730 k2=next_note(i,ns2,symb); | |
731 if (spc>8.0) spc=8.0; | |
732 if ((k1>0) && (strlen(symb[k1].text)>0)) | |
733 AT_LEAST (symb[i].wl, spc); | |
734 if ((k2>0) && (strlen(symb[k2].text)>0)) | |
735 AT_LEAST (symb[i].wr, xx-spc); | |
736 } | |
737 | |
738 /* leave room for vocals under note */ | |
739 for (j=0;j<NWLINE;j++) { | |
740 if (symb[i].wordp[j]) { | |
741 sl=tex_str(symb[i].wordp[j],t,&w); | |
742 xx=swfac*cfmt.vocalfont.size*(w+2*cwid(' ')); | |
743 AT_LEAST (symb[i].wl,xx*VOCPRE); | |
744 AT_LEAST (symb[i].wr,xx*(1.0-VOCPRE)); | |
745 } | |
746 } | |
747 | |
748 AT_LEAST (symb[i].pl, symb[i].wl); | |
749 AT_LEAST (symb[i].xl, symb[i].wl); | |
750 AT_LEAST (symb[i].pr, symb[i].wr); | |
751 AT_LEAST (symb[i].xr, symb[i].wr); | |
752 break; | |
753 | |
754 case BAR: | |
755 symb[i].wl=symb[i].wr=0; | |
756 if (symb[i].u==B_SNGL) symb[i].wl=symb[i].wr=3; | |
757 else if (symb[i].u==B_DBL) { symb[i].wl=7; symb[i].wr=4; } | |
758 else if (symb[i].u==B_LREP) { symb[i].wl=3; symb[i].wr=12; } | |
759 else if (symb[i].u==B_RREP) { symb[i].wl=12; symb[i].wr=3; } | |
760 else if (symb[i].u==B_DREP) symb[i].wl=symb[i].wr=12; | |
761 else if (symb[i].u==B_FAT1) { symb[i].wl=3; symb[i].wr=9; } | |
762 else if (symb[i].u==B_FAT2) { symb[i].wl=9; symb[i].wr=3; } | |
763 | |
764 if (ivc==ivc0) { /* bar numbers and labels next */ | |
765 ok=0; | |
766 if ((cfmt.barnums>0) && (symb[i].t%cfmt.barnums==0)) ok=1; | |
767 if (strlen(symb[i].text)>0) ok=1; | |
768 if (ok) { | |
769 if (strlen(symb[i].text)>0) { | |
770 tex_str(symb[i].text,t,&w); | |
771 xx=cfmt.barlabelfont.size*w*0.5; | |
772 } | |
773 else { | |
774 sprintf (tt,"%d",symb[i].t); | |
775 tex_str(tt,t,&w); | |
776 xx=cfmt.barnumfont.size*w*0.5; | |
777 } | |
778 yy=60; | |
779 if (!got_note) yy=0; | |
780 if ((i>0) && (symb[i-1].type==NOTE)) { | |
781 yy=symb[i-1].ymx; | |
782 if (symb[i-1].stem==1) yy=yy+26; | |
783 } | |
784 if ((i>0) && (strlen(symb[i-1].text)>0)) yy=60; | |
785 AT_LEAST (symb[i].wl, 2); | |
786 if (yy>BNUMHT-4.0) AT_LEAST (symb[i].wl, xx+1); | |
787 if (!got_note) AT_LEAST (symb[i].wl, xx+1); | |
788 yy=0; | |
789 if (symb[i+1].type==NOTE) yy=symb[i+1].ymx; | |
790 if (yy>BNUMHT-4.0) AT_LEAST (symb[i].wr, xx+2); | |
791 if (strlen(symb[i+1].text)>0) AT_LEAST (symb[i].wr, xx+4); | |
792 } | |
793 } | |
794 | |
795 symb[i].pl=symb[i].wl; | |
796 symb[i].pr=symb[i].wr; | |
797 symb[i].xl=symb[i].wl; | |
798 symb[i].xr=symb[i].wr; | |
799 break; | |
800 | |
801 case CLEF: | |
802 symb[i].wl=symb[i].wr=symb[i].xl=13.5; | |
803 symb[i].pl=symb[i].pr=symb[i].xr=11.5; | |
804 break; | |
805 | |
806 case KEYSIG: | |
807 n1=symb[i].u; | |
808 n2=symb[i].v; | |
809 if (n2>=n1) { | |
810 symb[i].wl=2; | |
811 symb[i].wr=5*(n2-n1+1)+2; | |
812 symb[i].pl=symb[i].wl; | |
813 symb[i].pr=symb[i].wr; | |
814 symb[i].xl=symb[i].wl; | |
815 symb[i].xr=symb[i].wr; | |
816 } | |
817 else { | |
818 symb[i].wl=symb[i].pl=symb[i].xl=3; | |
819 symb[i].wr=symb[i].pr=symb[i].xr=3; | |
820 } | |
821 break; | |
822 | |
823 case TIMESIG: | |
824 symb[i].wl=8+4*(strlen(symb[i].text)-1); | |
825 symb[i].wr=symb[i].wl+4; | |
826 symb[i].pl=symb[i].wl; | |
827 symb[i].pr=symb[i].wr; | |
828 symb[i].xl=symb[i].wl; | |
829 symb[i].xr=symb[i].wr; | |
830 break; | |
831 | |
832 default: | |
833 printf (">>> cannot set width for sym type %d\n", symb[i].type); | |
834 symb[i].wl=symb[i].wr=symb[i].xl=0; | |
835 symb[i].pl=symb[i].pr=symb[i].xr=0; | |
836 break; | |
837 } | |
838 | |
839 } | |
840 } | |
841 | |
842 | |
843 | |
844 /* ----- contract_keysigs: delete duplicate keysigs at staff start ---- … | |
845 /* Depending on line breaks, a key and/or meter change can come | |
846 at the start of a staff. Solution: scan through symbols from start | |
847 of line as long as sym is a CLEF, KEYSIG, or TIMESIG. Remove all | |
848 these, but set flags so that set_initsyms will draw the | |
849 key and meter which result at the end of the scan. */ | |
850 int contract_keysigs (ip1) | |
851 int ip1; | |
852 { | |
853 int i,k,v,t,n3,sf,jp1,m,mtop; | |
854 | |
855 mtop=10000; | |
856 for (v=0;v<nvoice;v++) { | |
857 i=ip1; | |
858 m=0; | |
859 for (;;) { | |
860 m++; | |
861 k=xp[i].p[v]; | |
862 if (k>=0) { | |
863 if (symv[v][k].type==CLEF) { | |
864 voice[v].key.ktype=symv[v][k].u; | |
865 symv[v][k].type=INVISIBLE; | |
866 } | |
867 else if (symv[v][k].type==KEYSIG) { | |
868 sf=symv[v][k].v; | |
869 n3=symv[v][k].w; | |
870 if (n3-1<sf) sf=n3-1; | |
871 t =symv[v][k].t; | |
872 if (t==A_FT) sf=-sf; | |
873 if (t==A_NT) sf=0; | |
874 voice[v].key.sf=sf; | |
875 symv[v][k].type=INVISIBLE; | |
876 } | |
877 else if (symv[v][k].type==TIMESIG) { | |
878 voice[v].meter.insert=1; | |
879 voice[v].meter.meter1=symv[v][k].u; | |
880 voice[v].meter.meter2=symv[v][k].v; | |
881 voice[v].meter.mflag =symv[v][k].w; | |
882 strcpy(voice[v].meter.top,symv[v][k].text); | |
883 symv[v][k].type=INVISIBLE; | |
884 } | |
885 else | |
886 break; | |
887 } | |
888 i=xp[i].next; | |
889 if (i==XP_END) { | |
890 i=xp[i].prec; | |
891 break; | |
892 } | |
893 } | |
894 if (m<mtop && i>=0) {mtop=m; jp1=i; } | |
895 } | |
896 | |
897 /* set glue for first symbol */ | |
898 xp[jp1].shrink = xp[jp1].wl+3; | |
899 xp[jp1].space = xp[jp1].wl+9; | |
900 xp[jp1].stretch= xp[jp1].wl+16; | |
901 | |
902 return jp1; | |
903 | |
904 } | |
905 | |
906 /* ----- set_initsyms: set symbols at start of staff ----- */ | |
907 int set_initsyms (v,wid0) | |
908 int v; | |
909 float *wid0; | |
910 { | |
911 int k,t,n; | |
912 float x; | |
913 | |
914 k=0; | |
915 | |
916 /* add clef */ | |
917 sym_st[v][k]=zsym; | |
918 sym_st[v][k].type = CLEF; | |
919 sym_st[v][k].u = voice[ivc].key.ktype; | |
920 sym_st[v][k].v = 0; | |
921 k++; | |
922 | |
923 /* add keysig */ | |
924 sym_st[v][k]=zsym; | |
925 sym_st[v][k].type = KEYSIG; | |
926 n=voice[ivc].key.sf; | |
927 t=A_SH; | |
928 if (n<0) { n=-n; t=A_FT; } | |
929 sym_st[v][k].u = 1; | |
930 sym_st[v][k].v = n; | |
931 sym_st[v][k].w = 100; | |
932 sym_st[v][k].t = t; | |
933 k++; | |
934 | |
935 /* add timesig */ | |
936 if (voice[ivc].meter.insert) { | |
937 sym_st[v][k]=zsym; | |
938 sym_st[v][k].type = TIMESIG; | |
939 sym_st[v][k].u = voice[ivc].meter.meter1; | |
940 sym_st[v][k].v = voice[ivc].meter.meter2; | |
941 sym_st[v][k].w = voice[ivc].meter.mflag; | |
942 strcpy(sym_st[v][k].text,voice[ivc].meter.top); | |
943 k++; | |
944 voice[ivc].meter.insert=0; | |
945 } | |
946 | |
947 if (voice[ivc].insert_btype) { | |
948 sym_st[v][k].type = BAR; | |
949 sym_st[v][k].u=voice[ivc].insert_btype; | |
950 sym_st[v][k].v=voice[ivc].insert_num; | |
951 sym_st[v][k].t=voice[ivc].insert_bnum; | |
952 strcpy(sym_st[v][k].text,voice[ivc].insert_text); | |
953 voice[ivc].insert_btype=0; | |
954 voice[ivc].insert_bnum=0; | |
955 k++; | |
956 } | |
957 | |
958 n=k; | |
959 set_sym_widths (0,n,sym_st[v],ivc); | |
960 | |
961 x=0; | |
962 for (k=0;k<n;k++) { | |
963 x=x+sym_st[v][k].wl; | |
964 sym_st[v][k].x=x; | |
965 x=x+sym_st[v][k].wr; | |
966 } | |
967 | |
968 *wid0=x+voice[v].insert_space; | |
969 return n; | |
970 | |
971 } | |
972 | |
973 | |
974 /* ----- print_poslist ----- */ | |
975 void print_poslist () | |
976 { | |
977 int i,n,typ,vv; | |
978 | |
979 printf ("\n----------- xpos list -----------\n"); | |
980 printf (" num ptr type time dur width tfac" | |
981 " shrk spac stre eol vptr\n"); | |
982 | |
983 n=0; | |
984 i=xp[XP_START].next; | |
985 for (;;) { | |
986 typ=xp[i].type; | |
987 printf ("%3d %3d %d ", n,i,typ); | |
988 if (typ==NOTE) printf ("NOTE"); | |
989 else if (typ==REST) printf ("REST"); | |
990 else if (typ==KEYSIG) printf ("KEY "); | |
991 else if (typ==TIMESIG) printf ("TSIG"); | |
992 else if (typ==BAR) printf ("BAR "); | |
993 else if (typ==CLEF) printf ("CLEF"); | |
994 else if (typ==INVISIBLE) printf ("INVS"); | |
995 else printf ("????"); | |
996 printf (" %7.2f %6.2f %4.1f %4.1f %5.2f %5.1f %5.1f %5.1f", | |
997 xp[i].time,xp[i].dur,xp[i].wl,xp[i].wr,xp[i].tfac, | |
998 xp[i].shrink,xp[i].space,xp[i].stretch); | |
999 if (xp[i].eoln) | |
1000 printf(" %d ",xp[i].eoln); | |
1001 else | |
1002 printf(" - "); | |
1003 for (vv=0;vv<nvoice;vv++) { | |
1004 if (xp[i].p[vv]>=0) | |
1005 printf(" %2d",xp[i].p[vv]); | |
1006 else | |
1007 printf(" -"); | |
1008 } | |
1009 printf ("\n"); | |
1010 i=xp[i].next; | |
1011 n++; | |
1012 if (i==XP_END) break; | |
1013 } | |
1014 | |
1015 } | |
1016 | |
1017 | |
1018 | |
1019 | |
1020 /* ----- insert_poslist: insert new element after element nins ----- */ | |
1021 int insert_poslist (nins) | |
1022 int nins; | |
1023 { | |
1024 int new,nxt,vv; | |
1025 | |
1026 new=ixpfree; | |
1027 ixpfree++; | |
1028 if (new>=XP_END) | |
1029 rxi("Too many symbols; use -maxs to increase limit, now ",maxSyms); | |
1030 | |
1031 nxt=xp[nins].next; | |
1032 xp[new].prec=nins; | |
1033 xp[new].next=nxt; | |
1034 xp[nins].next=new; | |
1035 xp[nxt].prec=new; | |
1036 for (vv=0;vv<nvoice;vv++) xp[new].p[vv]=-1; | |
1037 | |
1038 return new; | |
1039 | |
1040 } | |
1041 | |
1042 /* ----- set_poslist: make list of horizontal posits to align voices ---… | |
1043 void set_poslist () | |
1044 { | |
1045 int i,n,v,vv,typ,nok,nins; | |
1046 float tol=0.01; | |
1047 float d,tim; | |
1048 | |
1049 /* initialize xp with data from top nonempty voice, ivc0 */ | |
1050 v=ivc0; | |
1051 n=0; | |
1052 xp[0].next=1; | |
1053 for (i=0;i<voice[v].nsym;i++) { | |
1054 n++; | |
1055 xp[n].prec=n-1; | |
1056 xp[n].next=n+1; | |
1057 symv[v][i].p=n; | |
1058 for (vv=0;vv<nvoice;vv++) xp[n].p[vv]=-1; | |
1059 xp[n].p[v]=i; | |
1060 typ=symv[v][i].type; | |
1061 if (typ==REST) typ=NOTE; | |
1062 xp[n].type = typ; | |
1063 xp[n].time = symv[v][i].time; | |
1064 xp[n].dur = xp[n].tfac = 0; | |
1065 xp[n].shrink = xp[n].space = xp[n].stretch =0; | |
1066 xp[n].wl = xp[n].wr = 0; | |
1067 xp[n].eoln=symv[v][i].eoln; | |
1068 } | |
1069 xp[n].next=XP_END; | |
1070 xp[XP_END].prec=n; | |
1071 ixpfree=n+1; | |
1072 | |
1073 /* find or insert syms for other voices */ | |
1074 for (v=0;v<nvoice;v++) { | |
1075 if (voice[v].draw && v!=ivc0) { | |
1076 n=XP_START; | |
1077 for (i=0;i<voice[v].nsym;i++) { | |
1078 tim=symv[v][i].time; | |
1079 typ=symv[v][i].type; | |
1080 if (typ==REST) typ=NOTE; | |
1081 nok=-1; | |
1082 nins=n; | |
1083 for (;;) { | |
1084 n=xp[n].next; | |
1085 if (n==XP_END) break; | |
1086 d=xp[n].time-tim; | |
1087 if (xp[n].time<tim-tol) nins=n; | |
1088 if (d*d<tol*tol && xp[n].type==typ) { | |
1089 nok=n; | |
1090 break; | |
1091 } | |
1092 if (xp[n].time>tim+tol) break; | |
1093 } | |
1094 if (nok>0) | |
1095 n=nok; | |
1096 else { | |
1097 n=insert_poslist (nins); | |
1098 xp[n].type=typ; | |
1099 xp[n].time=tim; | |
1100 xp[n].dur = xp[n].tfac = 0; | |
1101 xp[n].shrink = xp[n].space = xp[n].stretch =0; | |
1102 xp[n].wl = xp[n].wr = 0; | |
1103 xp[n].eoln=0; | |
1104 } | |
1105 symv[v][i].p=n; | |
1106 xp[n].p[v]=i; | |
1107 } | |
1108 } | |
1109 } | |
1110 | |
1111 /*| print_poslist (); |*/ | |
1112 | |
1113 } | |
1114 | |
1115 | |
1116 /* ----- set_xpwid: set symbol widths and tfac in xp list ----- */ | |
1117 void set_xpwid() | |
1118 { | |
1119 int i,j,k,i1,i2,k1,k2,v,nsm; | |
1120 float fac,dy,ff,wv,wx; | |
1121 | |
1122 /* set all tfacs to 1.0 */ | |
1123 i=i1=xp[XP_START].next; | |
1124 for (;;) { | |
1125 xp[i].tfac=1.0; | |
1126 xp[i].wl=xp[i].wr=WIDTH_MIN; | |
1127 i2=i; | |
1128 i=xp[i].next; | |
1129 if (i==XP_END) break; | |
1130 } | |
1131 | |
1132 /* loop over voices. first voice last, assumed most important */ | |
1133 for (v=nvoice-1;v>=0;v--) { | |
1134 nsm=voice[v].nsym; | |
1135 | |
1136 /* first symbol and last symbol */ | |
1137 k1=symv[v][0].p; | |
1138 k2=symv[v][nsm-1].p; | |
1139 if (k1==i1 && symv[v][0].wl>xp[k1].wl) xp[k1].wl=symv[v][0].wl; | |
1140 if (k2==i2 && symv[v][nsm-1].wr>xp[k2].wr) xp[k2].wr=symv[v][nsm-1].… | |
1141 | |
1142 /* loop over symbol nn pairs */ | |
1143 for (i=1;i<nsm;i++) { | |
1144 j=i-1; | |
1145 k1=symv[v][j].p; | |
1146 k2=symv[v][i].p; | |
1147 if (xp[k1].next==k2) { | |
1148 if (symv[v][j].wr>xp[k1].wr) xp[k1].wr=symv[v][j].wr; | |
1149 if (symv[v][i].wl>xp[k2].wl) xp[k2].wl=symv[v][i].wl; | |
1150 | |
1151 if (symv[v][j].type==NOTE && symv[v][i].type==NOTE) { | |
1152 fac=1.0; | |
1153 /* reduce distance under a beam */ | |
1154 if (symv[v][i].word_st==0) fac=fac*fnnp; | |
1155 /* reduce distance for large jumps in pitch */ | |
1156 dy=symv[v][i].y-symv[v][j].y; | |
1157 if (dy<0) dy=-dy; | |
1158 ff=1-0.010*dy; | |
1159 if (ff<0.9) ff=0.9; | |
1160 fac=fac*ff; | |
1161 xp[k2].tfac=fac; | |
1162 } | |
1163 } | |
1164 } | |
1165 } | |
1166 | |
1167 /* check for all nn pairs in voice, in case some syms very wide */ | |
1168 for (v=nvoice-1;v>=0;v--) { | |
1169 nsm=voice[v].nsym; | |
1170 for (i=1;i<nsm;i++) { | |
1171 j=i-1; | |
1172 k1=symv[v][j].p; | |
1173 k2=symv[v][i].p; | |
1174 if (xp[k1].next!=k2) { | |
1175 wv=symv[v][j].wr+symv[v][i].wl; | |
1176 wx=xp[k1].wr+xp[k2].wl; | |
1177 k=k1; | |
1178 for (;;) { | |
1179 k=xp[k].next; | |
1180 if (k==k2) break; | |
1181 wx=wx+xp[k].wl+xp[k].wr; | |
1182 } | |
1183 if(wx<wv) { | |
1184 fac=wv/wx; | |
1185 xp[k1].wr=fac*xp[k1].wr; | |
1186 xp[k2].wl=fac*xp[k2].wl; | |
1187 k=k1; | |
1188 for (;;) { | |
1189 k=xp[k].next; | |
1190 if (k==k2) break; | |
1191 xp[k].wl=fac*xp[k].wl; | |
1192 xp[k].wr=fac*xp[k].wr; | |
1193 } | |
1194 | |
1195 } | |
1196 } | |
1197 } | |
1198 } | |
1199 | |
1200 } | |
1201 | |
1202 | |
1203 /* ----- set_spaces: set the shrink,space,stretch distances ----- */ | |
1204 void set_spaces () | |
1205 { | |
1206 int i,j,n,nxt,typ,typl,meter1,meter2; | |
1207 float w0,w1,w2; | |
1208 float vbnp,vbnx,vnbp,vnbx; | |
1209 | |
1210 /* note lengths for spaces at bars. Use dcefault meter for now */ | |
1211 meter1=default_meter.meter1; | |
1212 meter2=default_meter.meter2; | |
1213 vbnp=(rbnp*meter1*BASE)/meter2; | |
1214 vbnx=(rbnx*meter1*BASE)/meter2; | |
1215 vnbp=(rnbp*meter1*BASE)/meter2; | |
1216 vnbx=(rnbx*meter1*BASE)/meter2; | |
1217 | |
1218 /* redefine durations as differences in start times */ | |
1219 n=0; | |
1220 i=xp[XP_START].next; | |
1221 for (;;) { | |
1222 nxt=xp[i].next; | |
1223 if (nxt!=XP_END) xp[i].dur=xp[nxt].time-xp[i].time; | |
1224 i=nxt; | |
1225 n++; | |
1226 if (i==XP_END) break; | |
1227 } | |
1228 | |
1229 i=xp[XP_START].next; | |
1230 j=-1; | |
1231 typl=0; | |
1232 for (;;) { | |
1233 nxt=xp[i].next; | |
1234 typ=xp[i].type; | |
1235 | |
1236 /* shrink distance is sum of left and right widths */ | |
1237 if (j>=0) | |
1238 xp[i].shrink=xp[j].wr+xp[i].wl; | |
1239 else | |
1240 xp[i].shrink=xp[i].wl; | |
1241 xp[i].space=xp[i].stretch=xp[i].shrink; | |
1242 | |
1243 if (xp[i].type==NOTE) { | |
1244 | |
1245 if (typl==NOTE) { /* note after another note */ | |
1246 w1 = lnnp*nwid(xp[j].dur); | |
1247 w2 = lnnp*nwid(xp[i].dur); | |
1248 xp[i].space = bnnp*w1 + (1-bnnp)*0.5*(w1+w2); | |
1249 w1 = lnnx*xwid(xp[j].dur); | |
1250 w2 = lnnx*xwid(xp[i].dur); | |
1251 xp[i].stretch = bnnx*w1 + (1-bnnx)*0.5*(w1+w2); | |
1252 } | |
1253 | |
1254 else { /* note at start of bar */ | |
1255 w1 = lbnp*nwid(xp[i].dur); | |
1256 w0 = lbnp*nwid(vbnp); | |
1257 if (w0>w1) w0=w1; | |
1258 xp[i].space = bbnp*w1 + (1-bbnp)*w0 + (j>=0 ? xp[j].wr : 0); | |
1259 if (xp[i].space<14.0) xp[i].space=14.0; | |
1260 w1 = lbnx*xwid(xp[i].dur); | |
1261 w0 = lbnx*xwid(vbnp); | |
1262 if (w0>w1) w0=w1; | |
1263 xp[i].stretch = bbnx*w1 + (1-bbnx)*w0 + (j>=0 ? xp[j].wr : 0); | |
1264 if (xp[i].stretch<18.0) xp[i].stretch=18.0; | |
1265 if (xp[i].shrink<12.0) xp[i].shrink=12.0; | |
1266 } | |
1267 } | |
1268 | |
1269 else { /* some other symbol after note */ | |
1270 if (typl==NOTE) { | |
1271 w1 = lnbp*nwid(xp[j].dur); | |
1272 w0 = lnbp*nwid(vnbp); | |
1273 xp[i].space = bnbp*w1 + (1-bnbp)*w0 + xp[i].wl; | |
1274 if (xp[i].space<13.0) xp[i].space=13.0; | |
1275 w1 = lnbx*xwid(xp[j].dur); | |
1276 w0 = lnbx*xwid(vnbx); | |
1277 xp[i].stretch = bnbx*w1 + (1-bnbx)*w0 + xp[i].wl; | |
1278 if (xp[i].stretch<17.0) xp[i].stretch=17.0; | |
1279 } | |
1280 } | |
1281 | |
1282 /* multiply space and stretch by factors tfac */ | |
1283 xp[i].space = xp[i].space*xp[i].tfac; | |
1284 xp[i].stretch = xp[i].stretch*xp[i].tfac; | |
1285 | |
1286 /* make sure that shrink < space < stretch */ | |
1287 if (xp[i].space<xp[i].shrink) xp[i].space=xp[i].shrink; | |
1288 if (xp[i].stretch<xp[i].space) xp[i].stretch=xp[i].space; | |
1289 | |
1290 j=i; | |
1291 typl=typ; | |
1292 i=nxt; | |
1293 | |
1294 if (i==XP_END) break; | |
1295 } | |
1296 | |
1297 if (verbose>=11) print_poslist (); | |
1298 | |
1299 } | |
1300 | |
1301 /* ----- check_overflow: returns upper limit which fits on staff ------ … | |
1302 int check_overflow (ip1,ip2,width) | |
1303 int ip1,ip2; | |
1304 float width; | |
1305 { | |
1306 | |
1307 int i,jp2,lastcut,nbar,need_note; | |
1308 float space,shrink,stretch,alfa,alfa0; | |
1309 | |
1310 /* max shrink is alfa0 */ | |
1311 alfa0=ALFA_X; | |
1312 if (cfmt.continueall) alfa0=cfmt.maxshrink; | |
1313 if (gmode==G_SHRINK) alfa0=1.0; | |
1314 if (gmode==G_SPACE) alfa0=0.0; | |
1315 if (gmode==G_STRETCH) alfa0=1.0; | |
1316 | |
1317 jp2=ip2; | |
1318 space=shrink=stretch=0; | |
1319 lastcut=-1; | |
1320 nbar=0; | |
1321 need_note=1; | |
1322 i=ip1; | |
1323 for (;;) { | |
1324 space=space+xp[i].space; | |
1325 shrink=shrink+xp[i].shrink; | |
1326 stretch=stretch+xp[i].stretch; | |
1327 alfa=0; | |
1328 if (space>shrink) { | |
1329 alfa=(space-width)/(space-shrink); | |
1330 if (xp[i].type!=BAR) | |
1331 alfa=((space+8)-width)/(space-shrink); | |
1332 } | |
1333 | |
1334 if (alfa>alfa0) { | |
1335 if (!cfmt.continueall) { | |
1336 if (verbose<=3) printf ("\n"); | |
1337 printf ("+++ Overfull after %d bar%s in staff %d\n", | |
1338 nbar, nbar==1 ? "" : "s", mline); | |
1339 } | |
1340 jp2=i; | |
1341 if (i==ip1) jp2=xp[i].next; | |
1342 if (lastcut>=0) jp2=xp[lastcut].next; | |
1343 break; | |
1344 } | |
1345 /* The need_note business is to cut at the first of consecutive bars… | |
1346 if (xp[i].type==NOTE) need_note=0; | |
1347 if (xp[i].type==BAR && need_note==0) {lastcut=i; need_note=1; nbar++… | |
1348 if (xp[i].type==KEYSIG) lastcut=i; | |
1349 i=xp[i].next; | |
1350 if (i==ip2) break; | |
1351 } | |
1352 | |
1353 return jp2; | |
1354 | |
1355 } | |
1356 | |
1357 | |
1358 /* ----- set_glue --------- */ | |
1359 float set_glue (ip1,ip2,width) | |
1360 int ip1,ip2; | |
1361 float width; | |
1362 { | |
1363 | |
1364 int i,j; | |
1365 float space,shrink,stretch,alfa,beta,glue,w,x,d1,d2,w1; | |
1366 float alfa0,beta0; | |
1367 | |
1368 alfa0=ALFA_X; /* max shrink and stretch */ | |
1369 if (cfmt.continueall) alfa0=cfmt.maxshrink; | |
1370 if (gmode==G_SHRINK) alfa0=1.0; | |
1371 if (gmode==G_SPACE) alfa0=0.0; | |
1372 if (gmode==G_STRETCH) alfa0=1.0; | |
1373 beta0=BETA_X; | |
1374 if (cfmt.continueall) beta0=BETA_C; | |
1375 | |
1376 | |
1377 space=shrink=stretch=0; | |
1378 i=ip1; | |
1379 for (;;) { | |
1380 space=space+xp[i].space; | |
1381 shrink=shrink+xp[i].shrink; | |
1382 stretch=stretch+xp[i].stretch; | |
1383 j=i; | |
1384 i=xp[i].next; | |
1385 if (i==ip2) break; | |
1386 } | |
1387 | |
1388 /* add extra space if last symbol is not a bar */ | |
1389 if (xp[j].type!=BAR) { | |
1390 d1=d2=xp[j].wr+3; | |
1391 if (xp[j].type==NOTE) d2 = lnbp*nwid(xp[j].dur)+xp[j].wr; | |
1392 if (d2<d1) d2=d1; | |
1393 shrink = shrink + d1; | |
1394 space = space + d2; | |
1395 stretch = stretch + d2; | |
1396 } | |
1397 | |
1398 /* select alfa and beta */ | |
1399 alfa=beta=0; | |
1400 if (space>width) { | |
1401 alfa=99; | |
1402 if (space>shrink) alfa=(space-width)/(space-shrink); | |
1403 } | |
1404 else { | |
1405 beta=99; | |
1406 if (stretch>space) beta=(width-space)/(stretch-space); | |
1407 if (!cfmt.stretchstaff) beta=0; | |
1408 } | |
1409 | |
1410 if (gmode==G_SHRINK) { alfa=1; beta=0;} /* force minimal spacing … | |
1411 if (gmode==G_STRETCH) { alfa=0; beta=1;} /* force stretched spacin… | |
1412 if (gmode==G_SPACE) { alfa=beta=0; } /* force natural spacing … | |
1413 | |
1414 /*| if (alfa>alfa0) { alfa=alfa0; beta=0; } |*/ | |
1415 | |
1416 if (beta>beta0) { | |
1417 if (!cfmt.continueall) { | |
1418 if (verbose<=3) printf ("\n"); | |
1419 printf ("+++ Underfull (%.0fpt of %.0fpt) in staff %d\n", | |
1420 (beta0*stretch+(1-beta0)*space)*cfmt.scale, | |
1421 cfmt.staffwidth,mline); | |
1422 } | |
1423 alfa=0; | |
1424 if (!cfmt.stretchstaff) beta=0; | |
1425 if ((!cfmt.stretchlast) && (ip2==XP_END)) { | |
1426 w1=alfa_last*shrink+beta_last*stretch+(1-alfa_last-beta_last)*spac… | |
1427 if (w1<width) { | |
1428 alfa=alfa_last; /* shrink undefull last line same as previous… | |
1429 beta=beta_last; | |
1430 } | |
1431 } | |
1432 } | |
1433 | |
1434 w=alfa*shrink+beta*stretch+(1-alfa-beta)*space; | |
1435 if (verbose>=5) { | |
1436 if (alfa>0) printf ("Shrink staff %.0f%%", 100*alfa); | |
1437 else if (beta>0) printf ("Stretch staff %.0f%%", 100*beta); | |
1438 else printf ("No shrink or stretch"); | |
1439 printf (" to width %.0f (%.0f,%.0f,%.0f)\n",w,shrink,space,stretch); | |
1440 } | |
1441 | |
1442 /* now calculate the x positions */ | |
1443 x=0; | |
1444 i=ip1; | |
1445 for (;;) { | |
1446 glue=alfa*xp[i].shrink+beta*xp[i].stretch+(1-alfa-beta)*xp[i].space; | |
1447 x=x+glue; | |
1448 xp[i].x=x; | |
1449 if (verbose>22) printf ("pos[%d]: type=%d pos=%.2f\n", i,xp[i].type… | |
1450 i=xp[i].next; | |
1451 if (i==ip2) break; | |
1452 } | |
1453 | |
1454 alfa_last=alfa; | |
1455 beta_last=beta; | |
1456 return w; | |
1457 | |
1458 } | |
1459 | |
1460 | |
1461 /* ----- adjust_group: even out spacings for one group of notes --- */ | |
1462 /* Here we repeat the whole glue thing, in rudimentary form */ | |
1463 void adjust_group(i1,i2) | |
1464 int i1,i2; | |
1465 { | |
1466 int j; | |
1467 float dx,x,spa,shr,str,hp,hx,alfa,beta,dur1; | |
1468 | |
1469 dx=sym[i2].x-sym[i1].x; | |
1470 shr=sym[i1].wr+sym[i2].wl; | |
1471 for (j=i1+1;j<i2;j++) shr=shr+sym[j].wl+sym[j].wr; | |
1472 dur1=sym[i1].len; | |
1473 hp=lnnp*nwid(dur1); | |
1474 hx=lnnx*xwid(dur1); | |
1475 spa = (i2-i1)*hp; | |
1476 str = (i2-i1)*hx; | |
1477 | |
1478 alfa=beta=0; | |
1479 if (dx>spa) | |
1480 beta=(dx-spa)/(str-spa); | |
1481 else | |
1482 alfa=(dx-spa)/(shr-spa); | |
1483 | |
1484 x=sym[i1].x; | |
1485 for (j=i1+1;j<=i2;j++) { | |
1486 x=x+alfa*(sym[j-1].wr+sym[j].wl)+beta*hx+(1-alfa-beta)*hp; | |
1487 sym[j].x=x; | |
1488 } | |
1489 | |
1490 } | |
1491 | |
1492 | |
1493 /* ----- adjust_spacings: even out triplet spacings etc --- */ | |
1494 void adjust_spacings (n) | |
1495 int n; | |
1496 { | |
1497 int i,i1,count,beam,num; | |
1498 | |
1499 /* adjust the n-plets */ | |
1500 count=0; | |
1501 for (i=1;i<n;i++) { | |
1502 if ((sym[i].type==NOTE)||(sym[i].type==REST)) { | |
1503 if (sym[i].p_plet) { | |
1504 i1=i; | |
1505 count=sym[i].r_plet; | |
1506 } | |
1507 if (count>0 && sym[i].len!=sym[i1].len) count=0; | |
1508 if (count==1) adjust_group (i1,i); | |
1509 if (count>0) count--; | |
1510 } | |
1511 else | |
1512 count=0; | |
1513 } | |
1514 | |
1515 /* adjust beamed notes of equal duration */ | |
1516 beam=0; | |
1517 for (i=1;i<n;i++) { | |
1518 if ((sym[i].type==NOTE)||(sym[i].type==REST)) { | |
1519 if (sym[i].word_st && (!sym[i].word_end)) { | |
1520 i1=i; | |
1521 beam=1; | |
1522 if (sym[i].p_plet) beam=0; /* don't do nplets here */ | |
1523 } | |
1524 if (beam && sym[i].len!=sym[i1].len) beam=0; | |
1525 if (beam && sym[i].word_end) { | |
1526 num=i-i1+1; | |
1527 if (num>2 && num<4) adjust_group (i1,i); | |
1528 } | |
1529 if (sym[i].word_end) beam=0; | |
1530 } | |
1531 else | |
1532 beam=0; | |
1533 } | |
1534 | |
1535 } | |
1536 | |
1537 | |
1538 /* ----- adjust_rests: position single rests in bar center */ | |
1539 void adjust_rests (n,v) | |
1540 int n,v; | |
1541 { | |
1542 int i,ok; | |
1543 | |
1544 for (i=2;i<n-1;i++) { | |
1545 if ((sym[i].type==REST) && sym[i].fullmes) { | |
1546 | |
1547 ok=1; | |
1548 if ((sym[i-1].type==REST) || (sym[i-1].type==NOTE)) ok=0; | |
1549 if ((sym[i+1].type==REST) || (sym[i+1].type==NOTE)) ok=0; | |
1550 | |
1551 if (ok) { | |
1552 sym[i].head = H_OVAL; | |
1553 sym[i].dots = 0; | |
1554 sym[i].x = 0.5*(sym[i-1].x+sym[i+1].x); | |
1555 } | |
1556 | |
1557 } | |
1558 } | |
1559 | |
1560 } | |
1561 | |
1562 | |
1563 | |
1564 /* ----- copy_vsyms: copy selected syms for voice to v sym --- */ | |
1565 int copy_vsyms (v,ip1,ip2,wid0) | |
1566 int v,ip1,ip2; | |
1567 float wid0; | |
1568 { | |
1569 int i,n,m,k; | |
1570 float d1,d2,r,x; | |
1571 | |
1572 /* copy staff initialization symbols */ | |
1573 n=0; | |
1574 for (i=0;i<nsym_st[v];i++) { | |
1575 sym[n]=sym_st[v][i]; | |
1576 n++; | |
1577 } | |
1578 | |
1579 /* copy real symbols, shifted by wid0 */ | |
1580 i=ip1; | |
1581 m=0; | |
1582 for (;;) { | |
1583 k=xp[i].p[v]; | |
1584 if (k >= 0) { | |
1585 sym[n]=symv[v][k]; | |
1586 sym[n].x=xp[i].x+wid0; | |
1587 n++; | |
1588 m++; | |
1589 } | |
1590 i=xp[i].next; | |
1591 if (i==ip2) break; | |
1592 } | |
1593 | |
1594 /* adjust things for more pretty output.. */ | |
1595 adjust_rests (n,v); | |
1596 if (mvoice>1) adjust_spacings (n); | |
1597 | |
1598 /* small random shifts make the output more human... */ | |
1599 for (i=1;i<n-1;i++) { | |
1600 if ((sym[i].type==NOTE) || (sym[i].type==REST)) { | |
1601 d1=sym[i].x-sym[i-1].x; | |
1602 d2=sym[i+1].x-sym[i].x; | |
1603 r=RANFAC*d1; | |
1604 if (d2<d1) r=RANFAC*d2; | |
1605 if (r>RANCUT) r=RANCUT; | |
1606 x=ranf(-r,r); | |
1607 sym[i].x=sym[i].x+x; | |
1608 } | |
1609 } | |
1610 | |
1611 return n; | |
1612 | |
1613 } | |
1614 | |
1615 | |
1616 /* ----- draw_timesig ------- */ | |
1617 void draw_timesig (x,s) | |
1618 struct SYMBOL s; | |
1619 float x; | |
1620 { | |
1621 if (s.w==1) | |
1622 PUT1("%.1f csig\n", x) | |
1623 else if (s.w==2) | |
1624 PUT1("%.1f ctsig\n", x) | |
1625 else | |
1626 /* PUT3("%.1f (%d) (%d) tsig\n", x, s.u, s.v) */ | |
1627 PUT3("%.1f (%s) (%d) tsig\n", x, s.text, s.v) | |
1628 } | |
1629 | |
1630 /* ----- draw_keysig: return sf for this key ----- */ | |
1631 int draw_keysig (x,s) | |
1632 struct SYMBOL s; | |
1633 float x; | |
1634 { | |
1635 float p; | |
1636 int i,n1,n2,n3,t,yad,sf; | |
1637 int sh_pos[8]={0, 24,15,27,18,9,21,15}; | |
1638 int ft_pos[8]={0, 12,21,9,18,6,15,3}; | |
1639 | |
1640 n1=s.u; /* which symbol to start with */ | |
1641 n2=s.v; /* up to which symbol to go */ | |
1642 n3=s.w; /* draw neutrals instead starting from this one … | |
1643 t =s.t; /* type of symbol: sharp or flat */ | |
1644 | |
1645 yad = 0; | |
1646 if (voice[ivc].key.ktype==BASS) yad = -6; | |
1647 if (voice[ivc].key.ktype==ALTO) yad = -3; | |
1648 | |
1649 if (n2>7) { | |
1650 printf ("+++ Keysig seems to have %d symbols ???\n", n2); | |
1651 return 0; | |
1652 } | |
1653 | |
1654 sf=0; | |
1655 if (t==A_SH) { | |
1656 p=x; | |
1657 for (i=n1;i<=n2;i++) { | |
1658 if (i>=n3) | |
1659 PUT2("%.1f %d nt0 ",p,sh_pos[i]+yad) | |
1660 else { | |
1661 sf++; | |
1662 PUT2("%.1f %d sh0 ",p,sh_pos[i]+yad) | |
1663 } | |
1664 p=p+5; | |
1665 } | |
1666 PUT0("\n") | |
1667 } | |
1668 else if (t==A_FT) { | |
1669 p=x; | |
1670 for (i=n1;i<=n2;i++) { | |
1671 if (i>=n3) | |
1672 PUT2("%.1f %d nt0 ", p, ft_pos[i]+yad) | |
1673 else { | |
1674 sf--; | |
1675 PUT2("%.1f %d ft0 ", p, ft_pos[i]+yad) | |
1676 } | |
1677 p=p+5; | |
1678 } | |
1679 PUT0("\n") | |
1680 } | |
1681 else | |
1682 bug ("wrong type in draw_keysig", 0); | |
1683 | |
1684 return sf; | |
1685 } | |
1686 | |
1687 | |
1688 /* ----- draw_bar ------- */ | |
1689 void draw_bar (x,s) | |
1690 struct SYMBOL s; | |
1691 float x; | |
1692 { | |
1693 | |
1694 if (s.u==B_SNGL) /* draw the bar */ | |
1695 PUT1("%.1f bar\n", x) | |
1696 else if (s.u==B_DBL) | |
1697 PUT1("%.1f dbar\n", x) | |
1698 else if (s.u==B_LREP) | |
1699 PUT2("%.1f fbar1 %.1f rdots\n", x, x+10) | |
1700 else if (s.u==B_RREP) { | |
1701 PUT2("%.1f fbar2 %.1f rdots\n", x, x-10) | |
1702 } | |
1703 else if (s.u==B_DREP) { | |
1704 PUT2("%.1f fbar1 %.1f rdots\n", x-1, x+9) | |
1705 PUT2("%.1f fbar2 %.1f rdots\n", x+1, x-9) | |
1706 } | |
1707 else if (s.u==B_FAT1) | |
1708 PUT1("%.1f fbar1\n", x) | |
1709 else if (s.u==B_FAT2) | |
1710 PUT1("%.1f fbar2\n", x) | |
1711 else if (s.u==B_INVIS) | |
1712 ; | |
1713 else | |
1714 printf (">>> dont know how to draw bar type %d\n", s.u); | |
1715 | |
1716 PUT0("\n") | |
1717 | |
1718 } | |
1719 | |
1720 | |
1721 /* ----- draw_barnums ------- */ | |
1722 void draw_barnums (fp) | |
1723 FILE *fp; | |
1724 { | |
1725 int i,last,ok,got_note; | |
1726 | |
1727 last=0; | |
1728 got_note=0; | |
1729 for (i=0;i<nsym;i++) { | |
1730 if ((sym[i].type==NOTE)||(sym[i].type==REST)) got_note=1; | |
1731 | |
1732 if ((sym[i].type==BAR) && (strlen(sym[i].text)>0)) { | |
1733 if (last != 2) set_font (fp, cfmt.barlabelfont, 0); | |
1734 PUT3 (" %.1f %.1f M (%s) cshow ", sym[i].x, BNUMHT, sym[i].text) | |
1735 last=2; | |
1736 } | |
1737 | |
1738 if ((sym[i].type==BAR) && sym[i].t) { | |
1739 ok=0; | |
1740 if ((cfmt.barnums>0) && (sym[i].t%cfmt.barnums==0)) ok=1; | |
1741 if ((cfmt.barnums==0) && (!got_note)) ok=1; | |
1742 if ((cfmt.barnums!=0) && ((strlen(sym[i].text)>0))) ok=0; | |
1743 | |
1744 if (ok) { | |
1745 if (last != 1) set_font (fp, cfmt.barnumfont, 0); | |
1746 /*| if ((mvoice>1) && (cfmt.barnums==0)) |*/ | |
1747 if (cfmt.barnums==0) | |
1748 PUT1 (" 0 38 M (%d) rshow ", sym[i].t) | |
1749 else | |
1750 PUT3 (" %.1f %.1f M (%d) cshow ", sym[i].x, BNUMHT, sym[i].t) | |
1751 last=1; | |
1752 } | |
1753 } | |
1754 } | |
1755 PUT0("\n"); | |
1756 | |
1757 } | |
1758 | |
1759 | |
1760 /* ----- update_endings: remember where to draw endings ------- */ | |
1761 void update_endings (x,s) | |
1762 struct SYMBOL s; | |
1763 float x; | |
1764 { | |
1765 int i; | |
1766 | |
1767 if (num_ending>0) { | |
1768 i=num_ending-1; | |
1769 if (ending[i].num==1) | |
1770 mes1++; | |
1771 else { | |
1772 mes2++; | |
1773 if (mes2==mes1) ending[i].b=x; | |
1774 } | |
1775 } | |
1776 | |
1777 if (s.v) { | |
1778 if (num_ending>0) | |
1779 if (ending[num_ending-1].num==1) ending[num_ending-1].b=x-3; | |
1780 ending[num_ending].a=x; | |
1781 ending[num_ending].b=-1; | |
1782 ending[num_ending].num=s.v; | |
1783 if (s.v==1) mes1=0; | |
1784 else mes2=0; | |
1785 num_ending++; | |
1786 } | |
1787 | |
1788 } | |
1789 | |
1790 | |
1791 | |
1792 /* ----- set_ending: determine limits of ending box ------- */ | |
1793 void set_ending (i) | |
1794 int i; | |
1795 { | |
1796 int num,j,j0,j1,mes,mesmax; | |
1797 float top; | |
1798 | |
1799 num=sym[i].v; | |
1800 mesmax=0; | |
1801 if (num==2) mesmax=mes1; | |
1802 | |
1803 mes=0; | |
1804 j0=j1=-1; | |
1805 for (j=i+1;j<nsym;j++) { | |
1806 if (sym[j].type==BAR) { | |
1807 if (sym[j].u!=B_INVIS) mes++; | |
1808 if (mes==1) j1=j; | |
1809 if (sym[j].u==B_RREP || sym[j].u==B_DREP || sym[j].u==B_FAT2 || | |
1810 sym[j].u==B_LREP || sym[j].u==B_FAT1 || sym[j].v>0) { | |
1811 j0=j; | |
1812 break; | |
1813 } | |
1814 if (mes==mesmax) { | |
1815 j0=j; | |
1816 break; | |
1817 } | |
1818 } | |
1819 } | |
1820 top=-1; | |
1821 if (j0==-1) j0=j1; | |
1822 if (j0>=0) top=sym[j0].x; | |
1823 | |
1824 ending[num_ending].num=num; | |
1825 ending[num_ending].a=sym[i].x; | |
1826 ending[num_ending].b=top; | |
1827 if (num==1) ending[num_ending].b=top-3; | |
1828 ending[num_ending].type=E_CLOSED; | |
1829 if (sym[j0].type==BAR && sym[j0].u==B_SNGL) ending[num_ending].type=E_… | |
1830 num_ending++; | |
1831 | |
1832 if (num==1) mes1=mes; | |
1833 if (num==2) mes1=0; | |
1834 | |
1835 } | |
1836 | |
1837 | |
1838 /* ----- draw_endings ------- */ | |
1839 void draw_endings () | |
1840 { | |
1841 int i; | |
1842 | |
1843 for (i=0;i<num_ending;i++) { | |
1844 if (ending[i].b<0) | |
1845 PUT3("%.1f %.1f (%d) end2\n", | |
1846 ending[i].a, ending[i].a+50, ending[i].num) | |
1847 else { | |
1848 if (ending[i].type==E_CLOSED) { | |
1849 PUT3("%.1f %.1f (%d) end1\n", | |
1850 ending[i].a, ending[i].b, ending[i].num) | |
1851 } | |
1852 else { | |
1853 PUT3("%.1f %.1f (%d) end2\n", | |
1854 ending[i].a, ending[i].b, ending[i].num) | |
1855 } | |
1856 } | |
1857 } | |
1858 num_ending=0; | |
1859 | |
1860 } | |
1861 | |
1862 /* ----- draw_rest ----- */ | |
1863 void draw_rest (x,yy,s,gchy) | |
1864 struct SYMBOL s; | |
1865 float x,yy; | |
1866 float *gchy; | |
1867 { | |
1868 | |
1869 int y,i,k,deco; | |
1870 float dotx,doty; | |
1871 | |
1872 *gchy=38; | |
1873 if (s.invis) return; | |
1874 | |
1875 y=(int) s.y; | |
1876 PUT2("%.2f %.0f", x, yy) | |
1877 | |
1878 if (s.head==H_OVAL) PUT0(" r1") | |
1879 else if (s.head==H_EMPTY) PUT0(" r2") | |
1880 else { | |
1881 if (s.flags==0) PUT0(" r4") | |
1882 else if (s.flags==1) PUT0(" r8") | |
1883 else if (s.flags==2) PUT0(" r16") | |
1884 else if (s.flags==3) PUT0(" r32") | |
1885 else PUT0(" r64") | |
1886 } | |
1887 | |
1888 if (y%6) { dotx=6.5; doty=0; } /* dots */ | |
1889 else { dotx=6.5; doty=3; } | |
1890 if (s.head==H_OVAL) { dotx=8; doty=-3; } | |
1891 if (s.head==H_EMPTY) { dotx=8; doty=3; } | |
1892 for (i=0;i<s.dots;i++) { | |
1893 PUT2(" %.1f %.1f dt", dotx, doty) | |
1894 dotx=dotx+3.5; | |
1895 } | |
1896 | |
1897 | |
1898 for (k=s.dc.n-1;k>=0;k--) { | |
1899 deco=s.dc.t[k]; | |
1900 if (deco==D_HOLD) PUT1(" %.1f hld", 27.0) | |
1901 } | |
1902 | |
1903 PUT0("\n") | |
1904 } | |
1905 | |
1906 /* ----- draw_gracenotes ----- */ | |
1907 void draw_gracenotes (x,w,d,s) | |
1908 struct SYMBOL *s; | |
1909 float x,w,d; | |
1910 { | |
1911 int i,n,y,acc,ii,m; | |
1912 float xg[20],yg[20],lg,px[20],py[20],xx,yy; | |
1913 float s1,sx,sy,sxx,sxy,a,b,delta,lmin; | |
1914 float x0,y0,x1,y1,x2,y2,x3,y3,bet1,bet2,dy1,dy2,dx,dd,fac,facx; | |
1915 | |
1916 n=s->gr.n; | |
1917 if (n==0) return; | |
1918 | |
1919 facx=0.3; | |
1920 fac=d/w-1; | |
1921 if (fac<0) fac=0; | |
1922 fac=1+(fac*facx)/(fac+facx); | |
1923 | |
1924 dx=0; | |
1925 for (m=0;m<s->npitch;m++) { /* room for accidentals */ | |
1926 dd=-s->shhd[m]; | |
1927 if (s->accs[m]) dd=-s->shhd[m]+s->shac[m]; | |
1928 if ((s->accs[m]==A_FT)||(s->accs[m]==A_NT)) dd=dd-2; | |
1929 if (dx<dd) dx=dd; | |
1930 } | |
1931 | |
1932 xx=x-fac*(dx+GSPACE0); | |
1933 for (i=n-1;i>=0;i--) { /* set note positions */ | |
1934 yg[i]=3*(s->gr.p[i]-18)+s->yadd; | |
1935 if (i==n-1) { /* some subtle shifts.. */ | |
1936 if(yg[i]>=s->ymx) xx=xx+1; /* gnote above a bit clos… | |
1937 if((yg[i]<s->ymn-7)&&(n==1)) xx=xx-2; /* below with flag further… | |
1938 } | |
1939 | |
1940 if (i<n-1) { | |
1941 if (yg[i]>yg[i+1]+8) xx=xx+fac*1.8; | |
1942 } | |
1943 | |
1944 xg[i]=xx; | |
1945 xx=xx-fac*GSPACE; | |
1946 if (s->gr.a[i]) xx=xx-3.5; | |
1947 } | |
1948 | |
1949 if (n>1) { | |
1950 s1=sx=sy=sxx=sxy=0; /* linear fit through stems */ | |
1951 for (i=0;i<n;i++) { | |
1952 px[i]=xg[i]+GSTEM_XOFF; | |
1953 py[i]=yg[i]+GSTEM; | |
1954 s1 += 1; sx += px[i]; sy += py[i]; | |
1955 sxx += px[i]*px[i]; sxy += px[i]*py[i]; | |
1956 } | |
1957 delta=s1*sxx-sx*sx; /* beam fct: y=ax+b */ | |
1958 a=(s1*sxy-sx*sy)/delta; | |
1959 if (a>BEAM_SLOPE) a=BEAM_SLOPE; | |
1960 if (a<-BEAM_SLOPE) a=-BEAM_SLOPE; | |
1961 b=(sy-a*sx)/s1; | |
1962 | |
1963 if (bagpipe) { a=0; b=35; } | |
1964 | |
1965 lmin=100; /* shift to get min stems */ | |
1966 for (i=0;i<n;i++) { | |
1967 px[i]=xg[i]+GSTEM_XOFF; | |
1968 py[i]=a*px[i]+b; | |
1969 lg=py[i]-yg[i]; | |
1970 if (lg<lmin) lmin=lg; | |
1971 } | |
1972 if (lmin<10) b=b+10-lmin; | |
1973 } | |
1974 | |
1975 for (i=0;i<n;i++) { /* draw grace notes */ | |
1976 if (n>1) { | |
1977 px[i]=xg[i]+GSTEM_XOFF; | |
1978 py[i]=a*px[i]+b; | |
1979 lg=py[i]-yg[i]; | |
1980 PUT3("%.1f %.1f %.1f gnt ", xg[i],yg[i],lg) | |
1981 } | |
1982 else { | |
1983 lg=GSTEM; | |
1984 PUT3("%.1f %.1f %.1f gn1 ", xg[i],yg[i],lg) | |
1985 } | |
1986 | |
1987 acc=s->gr.a[i]; | |
1988 if (acc==A_SH) PUT2("%.1f %.1f gsh0 ",xg[i]-4.5,yg[i]) | |
1989 if (acc==A_FT) PUT2("%.1f %.1f gft0 ",xg[i]-4.5,yg[i]) | |
1990 if (acc==A_NT) PUT2("%.1f %.1f gnt0 ",xg[i]-4.5,yg[i]) | |
1991 if (acc==A_DS) PUT2("%.1f %.1f gds0 ",xg[i]-4.5,yg[i]) | |
1992 if (acc==A_DF) PUT2("%.1f %.1f gdf0 ",xg[i]-4.5,yg[i]) | |
1993 | |
1994 y = (int)yg[i]; /* helper lines */ | |
1995 if (y<=-6) { | |
1996 if (y%6) PUT2("%.1f %d ghl ",xg[i], y+3) | |
1997 else PUT2("%.1f %d ghl ",xg[i], y) | |
1998 } | |
1999 if (y>=30) { | |
2000 if (y%6) PUT2("%.1f %d ghl ",xg[i], y-3) | |
2001 else PUT2("%.1f %d ghl ",xg[i], y) | |
2002 } | |
2003 } | |
2004 | |
2005 if (n>1) /* beam */ | |
2006 if (bagpipe) | |
2007 PUT4("%.1f %.1f %.1f %.1f gbm3 ", px[0],py[0],px[n-1],py[n-1]) | |
2008 else | |
2009 PUT4("%.1f %.1f %.1f %.1f gbm2 ", px[0],py[0],px[n-1],py[n-1]) | |
2010 | |
2011 | |
2012 bet1=0.2; /* slur */ | |
2013 bet2=0.8; | |
2014 yy=1000; | |
2015 for (i=n-1;i>=0;i--) if (yg[i]<=yy) {yy=yg[i]; ii=i;} | |
2016 x0=xg[ii]; | |
2017 y0=yg[ii]-5; | |
2018 if (ii>0) { x0=x0-4; y0=y0+1; } | |
2019 x3=x-1; | |
2020 y3=s->ymn-5; | |
2021 dy1=(x3-x0)*0.4; | |
2022 if (dy1>3) dy1=3; | |
2023 dy2=dy1; | |
2024 | |
2025 if (yg[ii]>s->ymn+7){ | |
2026 x0=xg[ii]-1; | |
2027 y0=yg[ii]-4.5; | |
2028 y3=s->ymn+1.5; | |
2029 x3=x-dx-5.5; | |
2030 dy2=(y0-y3)*0.2; | |
2031 dy1=(y0-y3)*0.8; | |
2032 bet1=0.0; | |
2033 } | |
2034 | |
2035 if (y3>y0+4) { | |
2036 y3=y0+4; | |
2037 x0=xg[ii]+2; | |
2038 y0=yg[ii]-4; | |
2039 } | |
2040 | |
2041 x1=bet1*x3+(1-bet1)*x0; | |
2042 y1=bet1*y3+(1-bet1)*y0-dy1; | |
2043 x2=bet2*x3+(1-bet2)*x0; | |
2044 y2=bet2*y3+(1-bet2)*y0-dy2; | |
2045 | |
2046 PUT4(" %.1f %.1f %.1f %.1f", x1,y1,x2,y2); | |
2047 PUT4(" %.1f %.1f %.1f %.1f gsl\n", x3,y3,x0,y0); | |
2048 | |
2049 } | |
2050 | |
2051 /* ----- draw_basic_note: draw m-th head with accidentals and dots -- */ | |
2052 void draw_basic_note (x,w,d,s,m) | |
2053 struct SYMBOL *s; | |
2054 float x,w,d; | |
2055 int m; | |
2056 { | |
2057 int y,i,yy; | |
2058 float dotx,doty,xx,dx,avail,add,fac; | |
2059 | |
2060 y=3*(s->pits[m]-18)+s->yadd; /* height on staff */ | |
2061 | |
2062 xx=x+s->shhd[m]; /* draw head */ | |
2063 PUT2("%.1f %d", xx, y) | |
2064 if (s->head==H_OVAL) PUT0(" HD") | |
2065 if (s->head==H_EMPTY) PUT0(" Hd") | |
2066 if (s->head==H_FULL) PUT0(" hd") | |
2067 if (s->shhd[m]) { | |
2068 yy=0; | |
2069 if (y>=30) { yy=y; if (yy%6) yy=yy-3; } | |
2070 if (y<=-6) { yy=y; if (yy%6) yy=yy+3; } | |
2071 if (yy) PUT1(" %d hl", yy) | |
2072 } | |
2073 | |
2074 if (s->dots) { /* add dots */ | |
2075 if (y%6) { dotx=8; doty=0; } | |
2076 else { dotx=8; doty=3; } | |
2077 if (s->stem==-1) | |
2078 dotx=dotx+s->xmx-s->shhd[m]; | |
2079 else | |
2080 dotx=dotx+s->xmx-s->shhd[m]; | |
2081 if (s->dots && s->flags && (s->stem==1) && !(y%6)) | |
2082 if ((s->word_st==1) && (s->word_end==1) && (s->npitch==1)) | |
2083 dotx=dotx+DOTSHIFT; | |
2084 if (s->head==H_EMPTY) dotx=dotx+1; | |
2085 if (s->head==H_OVAL) dotx=dotx+2; | |
2086 for (i=0;i<s->dots;i++) { | |
2087 PUT2(" %.1f %.1f dt", dotx, doty) | |
2088 dotx=dotx+3.5; | |
2089 } | |
2090 } | |
2091 | |
2092 if (s->accs[m]) { /* add accidentals */ | |
2093 fac=1.0; | |
2094 avail=d-w-3; | |
2095 add=0.3*avail; | |
2096 fac=1+add/s->wl; | |
2097 if (fac<1) fac=1; | |
2098 if (fac>1.2) fac=1.2; | |
2099 dx=fac*s->shac[m]; | |
2100 if (s->accs[m]==A_SH) PUT1(" %.1f sh", dx) | |
2101 if (s->accs[m]==A_NT) PUT1(" %.1f nt", dx) | |
2102 if (s->accs[m]==A_FT) PUT1(" %.1f ft", dx) | |
2103 if (s->accs[m]==A_DS) PUT1(" %.1f dsh", dx) | |
2104 if (s->accs[m]==A_DF) PUT1(" %.1f dft", dx) | |
2105 } | |
2106 } | |
2107 | |
2108 | |
2109 /* ----- draw_decorations ----- */ | |
2110 float draw_decorations (x,s,tp) | |
2111 struct SYMBOL *s; | |
2112 float x; | |
2113 float *tp; | |
2114 { | |
2115 int y,sig,k,deco,m; | |
2116 float yc,xc,y1,top,top1,dx,dy; | |
2117 | |
2118 | |
2119 top=-1000; | |
2120 for (k=s->dc.n-1;k>=0;k--) { /* decos close to head */ | |
2121 deco=s->dc.t[k]; | |
2122 | |
2123 /* if ((deco==D_STACC)||(deco==D_EMBAR)) { */ /* dot or bar mark */ | |
2124 if (deco==D_STACC) { /* dot */ | |
2125 sig=1; if (s->stem==1) sig=-1; | |
2126 y=s->y+6*sig; | |
2127 if (y<top+3) y=top+3; | |
2128 if (!(y%6) && (y>=0) && (y<=24)) y+=3*sig; | |
2129 if (top<y) top=y; | |
2130 if (deco==D_STACC) PUT1(" %d stc",y) | |
2131 else PUT1(" %d emb",y) | |
2132 } | |
2133 | |
2134 if (deco==D_SLIDE) { /* slide */ | |
2135 yc=s->ymn; | |
2136 xc=5; | |
2137 for (m=0;m<s->npitch;m++) { | |
2138 dx=5-s->shhd[m]; | |
2139 if (s->head==H_OVAL) dx=dx+2.5; | |
2140 if (s->accs[m]) dx=4-s->shhd[m]+s->shac[m]; | |
2141 dy=3*(s->pits[m]-18)+s->yadd-yc; | |
2142 if ((dy<10) && (dx>xc)) xc=dx; | |
2143 } | |
2144 yc=s->ymn; | |
2145 PUT2(" %.1f %.1f sld", yc, xc) | |
2146 } | |
2147 } | |
2148 | |
2149 top1=top; | |
2150 for (k=s->dc.n-1;k>=0;k--) { /* decos further away */ | |
2151 deco=s->dc.t[k]; | |
2152 | |
2153 if (deco==D_EMBAR) { /* bar */ | |
2154 yc=s->ymx+6; | |
2155 if (s->stem==1) yc=s->ys+4; | |
2156 if (yc<28) yc=28; | |
2157 if (yc<top+3) yc=top+3; | |
2158 if (top<yc+2) top=yc+2; | |
2159 PUT1(" %.2f emb", yc) | |
2160 } | |
2161 | |
2162 if ((deco==D_GRACE)||(deco==D_HAT)||(deco==D_ATT)) { /* gracing,hat,… | |
2163 yc=s->ymx+9; | |
2164 if (s->stem==1) yc=s->ys+5; | |
2165 if (yc<30) yc=30; | |
2166 if (yc<top+4) yc=top+4; | |
2167 if (top<yc+2) top=yc+2; | |
2168 if (deco==D_GRACE) PUT1(" %.2f grm", yc) | |
2169 else if (deco==D_HAT) PUT1(" %.2f hat", yc) | |
2170 else PUT1(" %.2f att", yc) | |
2171 } | |
2172 | |
2173 if (deco==D_ROLL) { /* roll sign */ | |
2174 y=s->y; | |
2175 if (s->stem==1) { | |
2176 yc=s->y-5; | |
2177 if (yc>-2) yc=-2; | |
2178 PUT1(" %.2f cpd", yc) | |
2179 } | |
2180 else { | |
2181 yc=s->y+5; | |
2182 if (s->dots && (!(y%6))) yc=s->y+6; | |
2183 if (yc<26) yc=26; | |
2184 if (yc<top+1) yc=top+1; | |
2185 if (top<yc+8) top=yc+8; | |
2186 PUT1(" %.2f cpu", yc) | |
2187 } | |
2188 } | |
2189 | |
2190 if (deco==D_HOLD) { /* hold sign */ | |
2191 yc=27; | |
2192 if (s->stem==1) | |
2193 y1=s->ys+4; | |
2194 else | |
2195 y1=s->ymx+6; | |
2196 if (yc<y1) yc=y1; | |
2197 if (yc<top+4) yc=top+4; | |
2198 if (top<yc+12) top=yc+12; | |
2199 PUT1(" %.1f hld", yc) | |
2200 } | |
2201 | |
2202 if (deco==D_TRILL) { /* trill sign */ | |
2203 yc=30; | |
2204 if (s->stem==1) | |
2205 y1=s->ys+5; | |
2206 else | |
2207 y1=s->ymx+7; | |
2208 if (yc<y1) yc=y1; | |
2209 if (yc<top+1) yc=top+1; | |
2210 if (top<yc+8) top=yc+8; | |
2211 PUT1(" %.1f trl", yc) | |
2212 } | |
2213 | |
2214 if ((deco==D_UPBOW)||(deco==D_DOWNBOW)) { /* bowing signs */ | |
2215 yc=21; | |
2216 if (s->stem==1) | |
2217 y1=s->ys+4; | |
2218 else | |
2219 y1=s->ymx+8; | |
2220 if (yc<y1) yc=y1; | |
2221 if (yc<top+4) yc=top+4; | |
2222 if (top<yc+10) top=yc+10; | |
2223 if (deco==D_UPBOW) PUT1(" %.1f upb", yc) | |
2224 if (deco==D_DOWNBOW) PUT1(" %.1f dnb", yc) | |
2225 } | |
2226 } | |
2227 *tp=top; | |
2228 return top1; | |
2229 } | |
2230 | |
2231 | |
2232 /* ----- draw_note ----- */ | |
2233 float draw_note (x,w,d,s,fl,gchy) | |
2234 struct SYMBOL *s; | |
2235 float x,w,d; | |
2236 float *gchy; | |
2237 int fl; | |
2238 { | |
2239 char c,cc; | |
2240 int y,i,m,k; | |
2241 float yc,slen,slen0,top,top2,xx; | |
2242 slen0=STEM; | |
2243 | |
2244 draw_gracenotes (x, w, d, s); /* draw grace notes */ | |
2245 | |
2246 c = 'd'; cc='u'; | |
2247 if (s->stem==1) { c='u'; cc='d'; } | |
2248 slen=s->stem*(s->ys-s->y); | |
2249 | |
2250 for (m=0;m<s->npitch;m++) { | |
2251 if (m>0) PUT0(" ") | |
2252 draw_basic_note (x,w,d,s,m); /* draw note heads */ | |
2253 xx=3*(s->pits[m]-18)+s->yadd-s->y; | |
2254 xx=xx*xx; | |
2255 if (xx<0.01) { /* add stem */ | |
2256 if (s->stem) PUT2(" %.1f s%c",slen,c) | |
2257 if (fl && (s->flags>0)) /* add flags */ | |
2258 PUT3(" %.1f f%d%c",slen,s->flags,c) | |
2259 } | |
2260 if ((m>0) && (s->pits[m]==s->pits[m-1])) { /* unions */ | |
2261 if (s->stem) PUT2(" %.2f s%c",slen0,cc) | |
2262 if (s->flags>0) | |
2263 PUT3(" %.1f f%d%c",slen0,s->flags,cc) | |
2264 } | |
2265 } | |
2266 | |
2267 top=draw_decorations (x,s,&top2); /* add decorations */ | |
2268 | |
2269 y = s->ymn; /* lower helper lines… | |
2270 if (y<=-6) { | |
2271 for (i=-6;i>=y;i=i-6) PUT1(" %d hl", i) | |
2272 if (s->head==H_OVAL) PUT0("1") | |
2273 } | |
2274 y = s->ymx; /* upper helper lines… | |
2275 if (y>=30) { | |
2276 for (i=30;i<=y;i=i+6) PUT1(" %d hl", i) | |
2277 if (s->head==H_OVAL) PUT0("1") | |
2278 } | |
2279 | |
2280 *gchy=38; | |
2281 if (strlen(s->text)>0) { /* position guitar ch… | |
2282 yc=*gchy; | |
2283 if (yc<y+8) yc=y+8; | |
2284 if (yc<s->ys+4) yc=s->ys+4; | |
2285 for (k=0;k<s->dc.n;k++) { | |
2286 if ((s->dc.t[k]==D_GRACE) && (yc<y+12)) yc=y+12; | |
2287 } | |
2288 if (yc<top2) yc=top2; | |
2289 *gchy=yc; | |
2290 } | |
2291 | |
2292 PUT0("\n") | |
2293 | |
2294 return top; | |
2295 | |
2296 } | |
2297 | |
2298 | |
2299 /* ----- vsh: up/down shift needed to get k*6 ----- */ | |
2300 float vsh (x,dir) | |
2301 int dir; | |
2302 float x; | |
2303 { | |
2304 int ix,iy,ir; | |
2305 float x1,xx; | |
2306 x1=x*dir; | |
2307 ix=x1+600.999; | |
2308 ir=ix%6; | |
2309 iy=ix-600; | |
2310 if (ir>0) iy=iy+6-ir; | |
2311 xx=iy*dir; | |
2312 return xx-x; | |
2313 } | |
2314 | |
2315 | |
2316 /* ----- rnd3: up/down shift needed to get k*3 ----- */ | |
2317 float rnd3(x) | |
2318 float x; | |
2319 { | |
2320 int ix,iy,ir; | |
2321 float xx; | |
2322 | |
2323 ix=x+600.999-1.5; | |
2324 ir=ix%3; | |
2325 iy=ix-600; | |
2326 if (ir>0) iy=iy+3-ir; | |
2327 xx=iy; | |
2328 return xx-x; | |
2329 } | |
2330 | |
2331 | |
2332 /* ----- rnd6: up/down shift needed to get k*6 ----- */ | |
2333 float rnd6(x) | |
2334 float x; | |
2335 { | |
2336 int ix,iy,ir; | |
2337 float xx; | |
2338 | |
2339 ix=x+600.999-3.0; | |
2340 ir=ix%6; | |
2341 iy=ix-600; | |
2342 if (ir>0) iy=iy+6-ir; | |
2343 xx=iy; | |
2344 return xx-x; | |
2345 } | |
2346 | |
2347 | |
2348 /* ----- b_pos ----- */ | |
2349 float b_pos (stem,flags,b) | |
2350 int stem,flags; | |
2351 float b; | |
2352 { | |
2353 float bb,d1,d2,add; | |
2354 float top,bot; | |
2355 | |
2356 if (stem==1) { | |
2357 top=b; | |
2358 bot=b-(flags-1)*BEAM_SHIFT-BEAM_DEPTH; | |
2359 if (bot>26) return b; | |
2360 } | |
2361 else { | |
2362 bot=b; | |
2363 top=b+(flags-1)*BEAM_SHIFT+BEAM_DEPTH; | |
2364 if (top<-2) return b; | |
2365 } | |
2366 | |
2367 d1=rnd6(top-BEAM_OFFSET); | |
2368 d2=rnd6(bot+BEAM_OFFSET); | |
2369 add=d1; | |
2370 if (d1*d1>d2*d2) add=d2; | |
2371 bb=b+add; | |
2372 | |
2373 /* printf ("stem %d top %.1f, bot%.1f, choices %.1f %.1f => %.1f\n", | |
2374 stem, top,bot, d1,d2, add); */ | |
2375 /* printf ("b_pos(%d) b=%.1f to %.1f\n", stem,b,bb); */ | |
2376 | |
2377 return bb; | |
2378 } | |
2379 | |
2380 | |
2381 /* ----- calculate_beam ----- */ | |
2382 int calculate_beam (i0,bm) | |
2383 int i0; | |
2384 struct BEAM *bm; | |
2385 { | |
2386 int j,j1,j2,i,stem,notes,flags; | |
2387 float x,y,ys,a,b,max_stem_err,stem_err,min_stem,slen,yyg,yg,try; | |
2388 float s,sx,sy,sxx,sxy,syy,delta,hh,dev,dev2,a0; | |
2389 | |
2390 j1=i0; /* find first and last note in beam */ | |
2391 j2=-1; | |
2392 stem=sym[j1].stem; | |
2393 for (j=i0;j<nsym;j++) | |
2394 if (sym[j].word_end) { | |
2395 j2=j; | |
2396 break; | |
2397 } | |
2398 if (j2==-1) { | |
2399 return 0; | |
2400 } | |
2401 | |
2402 notes=flags=0; /* set x positions, count notes and flag… | |
2403 for (j=j1;j<=j2;j++) { | |
2404 if(sym[j].type==NOTE) { | |
2405 sym[j].xs=sym[j].x+stem*STEM_XOFF; | |
2406 sym[j].stem=stem; | |
2407 if (sym[j].flags>flags) flags=sym[j].flags; | |
2408 notes++; | |
2409 } | |
2410 } | |
2411 | |
2412 s=sx=sy=sxx=sxy=syy=0; /* linear fit through stem ends */ | |
2413 for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) { | |
2414 x=sym[j].xs; | |
2415 y=sym[j].ymx+STEM*stem; | |
2416 s += 1; sx += x; sy += y; | |
2417 sxx += x*x; sxy += x*y; syy += y*y; | |
2418 } | |
2419 | |
2420 delta=s*sxx-sx*sx; /* beam fct: y=ax+b */ | |
2421 a=(s*sxy-sx*sy)/delta; | |
2422 b=(sy-a*sx)/s; | |
2423 | |
2424 /* the next few lines modify the slope of the beam */ | |
2425 if (notes>=3) { | |
2426 hh=syy-a*sxy-b*sy; /* flatten if notes not in line */ | |
2427 dev=0; | |
2428 if (hh>0) { | |
2429 dev2=hh/(notes-2); | |
2430 if (dev2>0.5) a=BEAM_FLATFAC*a; | |
2431 } | |
2432 } | |
2433 | |
2434 | |
2435 if (a>=0) a=BEAM_SLOPE*a/(BEAM_SLOPE+a); /* max steepness for beam */ | |
2436 else a=BEAM_SLOPE*a/(BEAM_SLOPE-a); | |
2437 | |
2438 | |
2439 /* to decide if to draw flat etc. use normalized slope a0 */ | |
2440 a0=a*(sym[j2].xs-sym[j1].xs)/(20*(notes-1)); | |
2441 | |
2442 if ((a0<BEAM_THRESH) && (a0>-BEAM_THRESH)) a=0; /* flat below threshh… | |
2443 | |
2444 b=(sy-a*sx)/s; /* recalculate b for new slope */ | |
2445 | |
2446 /* if (flags>1) b=b+2*stem;*/ /* leave a bit more room if several … | |
2447 | |
2448 if (bagpipe) { b=-11; a=0; } | |
2449 | |
2450 max_stem_err=0; /* check stem lengths */ | |
2451 for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) { | |
2452 if (sym[j].npitch==1) { | |
2453 min_stem=STEM_MIN; | |
2454 if (sym[j].flags==2) min_stem=STEM_MIN2; | |
2455 if (sym[j].flags==3) min_stem=STEM_MIN3; | |
2456 if (sym[j].flags==4) min_stem=STEM_MIN4; | |
2457 } | |
2458 else { | |
2459 min_stem=STEM_CH_MIN; | |
2460 if (sym[j].flags==2) min_stem=STEM_CH_MIN2; | |
2461 if (sym[j].flags==3) min_stem=STEM_CH_MIN3; | |
2462 if (sym[j].flags==4) min_stem=STEM_CH_MIN4; | |
2463 } | |
2464 min_stem=min_stem+BEAM_DEPTH+BEAM_SHIFT*(sym[j].flags-1); | |
2465 ys=a*sym[j].xs+b; | |
2466 if (stem==1) slen=ys-sym[j].ymx; | |
2467 else slen=sym[j].ymn-ys; | |
2468 stem_err=min_stem-slen; | |
2469 if (stem_err>max_stem_err) max_stem_err=stem_err; | |
2470 } | |
2471 | |
2472 if (max_stem_err>0) /* shift beam if stems too short… | |
2473 b=b+stem*max_stem_err; | |
2474 | |
2475 for (j=j1+1;j<=j2;j++) if (sym[j].type==NOTE) { /* room for gracenote… | |
2476 for (i=0;i<sym[j].gr.n;i++) { | |
2477 yyg=a*(sym[j].x-GSPACE0)+b; | |
2478 yg=3*(sym[j].gr.p[i]-18)+sym[j].yadd; | |
2479 if (stem==1) { | |
2480 try=(yg+GSTEM)-(yyg-BEAM_DEPTH-2); | |
2481 if (try>0) b=b+try; | |
2482 } | |
2483 else { | |
2484 try=(yg)-(yyg+BEAM_DEPTH+7); | |
2485 if (try<0) b=b+try; | |
2486 } | |
2487 } | |
2488 } | |
2489 | |
2490 if ((a<0.01) && (a>-0.01)) /* shift flat beams onto staff lines … | |
2491 b=b_pos (stem,flags,b); | |
2492 | |
2493 for (j=j1;j<=j2;j++) if (sym[j].type==NOTE) { /* final stems */ | |
2494 sym[j].ys=a*sym[j].xs+b; | |
2495 } | |
2496 | |
2497 bm->i1=j1; /* save beam parameters in struct */ | |
2498 bm->i2=j2; | |
2499 bm->a=a; | |
2500 bm->b=b; | |
2501 bm->stem=stem; | |
2502 bm->t=stem*BEAM_DEPTH; | |
2503 return 1; | |
2504 } | |
2505 | |
2506 | |
2507 /* ----- rest_under_beam ----- */ | |
2508 float rest_under_beam (x,head,bm) | |
2509 float x; | |
2510 int head; | |
2511 struct BEAM *bm; | |
2512 { | |
2513 float y,tspace,bspace; | |
2514 int j1,j2,j,nf,iy; | |
2515 | |
2516 tspace=9; | |
2517 bspace=11; | |
2518 if ((head==H_OVAL)||(head==H_EMPTY)) tspace=bspace=4; | |
2519 | |
2520 j1=bm->i1; | |
2521 j2=bm->i2; | |
2522 nf=0; | |
2523 for (j=j1;j<=j2;j++) | |
2524 if ((sym[j].type==NOTE)||(sym[j].flags>nf)) nf=sym[j].flags; | |
2525 | |
2526 if (bm->stem==1) { | |
2527 y=bm->a*x+bm->b; | |
2528 y=y-BEAM_DEPTH-(nf-1)*BEAM_SHIFT; | |
2529 y=y-tspace; | |
2530 if (y>12) y=12; | |
2531 } | |
2532 else { | |
2533 y=bm->a*x+bm->b; | |
2534 y=y+BEAM_DEPTH+(nf-1)*BEAM_SHIFT; | |
2535 y=y+bspace; | |
2536 if (y<12) y=12; | |
2537 } | |
2538 | |
2539 if ((head==H_OVAL)||(head==H_EMPTY)) { | |
2540 iy=(y+3.0)/6.0; | |
2541 y=6*iy; | |
2542 } | |
2543 | |
2544 return y; | |
2545 } | |
2546 | |
2547 /* ----- draw_beam_num: draw number on a beam ----- */ | |
2548 void draw_beam_num (bm,num,xn) | |
2549 struct BEAM *bm; | |
2550 int num; | |
2551 float xn; | |
2552 { | |
2553 float yn; | |
2554 | |
2555 if (bm->stem==-1) | |
2556 yn=bm->a*xn+bm->b-12; | |
2557 else | |
2558 yn=bm->a*xn+bm->b+4; | |
2559 | |
2560 PUT3("%.1f %.1f (%d) bnum\n", xn, yn, num) | |
2561 | |
2562 } | |
2563 | |
2564 | |
2565 /* ----- draw_beam: draw a single beam ----- */ | |
2566 void draw_beam (x1,x2,dy,bm) | |
2567 float x1,x2,dy; | |
2568 struct BEAM *bm; | |
2569 { | |
2570 float y1,y2; | |
2571 | |
2572 y1=bm->a*x1+bm->b-bm->stem*dy; | |
2573 y2=bm->a*x2+bm->b-bm->stem*dy; | |
2574 PUT5("%.1f %.1f %.1f %.1f %.1f bm\n", x1,y1,x2,y2,bm->t) | |
2575 } | |
2576 | |
2577 /* ----- draw_beams: draw the beams for one word ----- */ | |
2578 void draw_beams (bm) | |
2579 struct BEAM *bm; | |
2580 { | |
2581 int j,j1,j2,j3,inbeam,k1,k2,num,p,r; | |
2582 float x1,x2,xn; | |
2583 | |
2584 j1=bm->i1; | |
2585 j2=bm->i2; | |
2586 | |
2587 /* make first beam over whole word */ | |
2588 x1=sym[j1].xs; | |
2589 x2=sym[j2].xs; | |
2590 num=sym[j1].u; | |
2591 | |
2592 for (j=j1;j<=j2;j++) { /* numbers for nplets on same beam */ | |
2593 if (sym[j].p_plet>0) { | |
2594 p=sym[j].p_plet; | |
2595 r=sym[j].r_plet; | |
2596 j3=j+r-1; | |
2597 if (j3<=j2) { | |
2598 xn=0.5*(sym[j].xs+sym[j3].xs); | |
2599 draw_beam_num (bm,p,xn); | |
2600 sym[j].p_plet=0; | |
2601 } | |
2602 } | |
2603 } | |
2604 | |
2605 draw_beam (x1,x2,0.0,bm); | |
2606 | |
2607 /* second beams where two or more flags */ | |
2608 k1=0; | |
2609 inbeam=0; | |
2610 for (j=j1;j<=j2;j++) { | |
2611 if (sym[j].type!=NOTE) continue; | |
2612 if ((!inbeam) && (sym[j].flags>=2)) { | |
2613 k1=j; | |
2614 inbeam=1; | |
2615 } | |
2616 if (inbeam && ((sym[j].flags<2) || (j==j2))) { | |
2617 if ((sym[j].flags>=2) && (j==j2)) k2=j; | |
2618 x1=sym[k1].xs; | |
2619 x2=sym[k2].xs; | |
2620 inbeam=0; | |
2621 if (k1==k2) { | |
2622 if (k1==j1) draw_beam (x1+BEAM_STUB,x1,BEAM_SHIFT,bm); | |
2623 else draw_beam (x1-BEAM_STUB,x1,BEAM_SHIFT,bm); | |
2624 } | |
2625 else | |
2626 draw_beam (x1,x2,BEAM_SHIFT,bm); | |
2627 inbeam=0; | |
2628 } | |
2629 k2=j; | |
2630 } | |
2631 | |
2632 /* third beams where three or more flags */ | |
2633 k1=0; | |
2634 inbeam=0; | |
2635 for (j=j1;j<=j2;j++) { | |
2636 if (sym[j].type!=NOTE) continue; | |
2637 if ((!inbeam) && (sym[j].flags>=3)) { | |
2638 k1=j; | |
2639 inbeam=1; | |
2640 } | |
2641 if (inbeam && ((sym[j].flags<3) || (j==j2))) { | |
2642 if ((sym[j].flags>=3) && (j==j2)) k2=j; | |
2643 x1=sym[k1].xs; | |
2644 x2=sym[k2].xs; | |
2645 inbeam=0; | |
2646 if (k1==k2) { | |
2647 if (k1==j1) draw_beam (x1+BEAM_STUB,x1,2*BEAM_SHIFT,bm); | |
2648 else draw_beam (x1-BEAM_STUB,x1,2*BEAM_SHIFT,bm); | |
2649 } | |
2650 else | |
2651 draw_beam (x1,x2,2*BEAM_SHIFT,bm); | |
2652 inbeam=0; | |
2653 } | |
2654 k2=j; | |
2655 } | |
2656 | |
2657 /* fourth beams where four or more flags */ | |
2658 k1=0; | |
2659 inbeam=0; | |
2660 for (j=j1;j<=j2;j++) { | |
2661 if (sym[j].type!=NOTE) continue; | |
2662 if ((!inbeam) && (sym[j].flags>=4)) { | |
2663 k1=j; | |
2664 inbeam=1; | |
2665 } | |
2666 if (inbeam && ((sym[j].flags<4) || (j==j2))) { | |
2667 if ((sym[j].flags>=4) && (j==j2)) k2=j; | |
2668 x1=sym[k1].xs; | |
2669 x2=sym[k2].xs; | |
2670 inbeam=0; | |
2671 if (k1==k2) { | |
2672 if (k1==j1) draw_beam (x1+BEAM_STUB,x1,3*BEAM_SHIFT,bm); | |
2673 else draw_beam (x1-BEAM_STUB,x1,3*BEAM_SHIFT,bm); | |
2674 } | |
2675 else | |
2676 draw_beam (x1,x2,3*BEAM_SHIFT,bm); | |
2677 inbeam=0; | |
2678 } | |
2679 k2=j; | |
2680 } | |
2681 | |
2682 } | |
2683 | |
2684 /* ----- extreme: return min or max, depending on s ----- */ | |
2685 float extreme (s, a, b) | |
2686 float s,a,b; | |
2687 { | |
2688 | |
2689 if (s>0) { | |
2690 if (a>b) return a; | |
2691 return b; | |
2692 } | |
2693 else { | |
2694 if (a<b) return a; | |
2695 return b; | |
2696 } | |
2697 } | |
2698 | |
2699 /* ----- draw_bracket ----- */ | |
2700 void draw_bracket (p,j1,j2) | |
2701 int p,j1,j2; | |
2702 { | |
2703 float x1,x2,y1,y2,xm,ym,s,s0,xx,yy,yx,dy; | |
2704 int j; | |
2705 | |
2706 x1=sym[j1].x-4; | |
2707 x2=sym[j2].x+4; | |
2708 y1=sym[j1].ymx+10; | |
2709 y2=sym[j2].ymx+10; | |
2710 | |
2711 if (sym[j1].stem==1) { y1=sym[j1].ys+4; x1=x1+3; } | |
2712 if (sym[j2].stem==1) { y2=sym[j2].ys+4; x2=x2+3; } | |
2713 | |
2714 if (y1<30) y1=30; | |
2715 if (y2<30) y2=30; | |
2716 | |
2717 xm=0.5*(x1+x2); | |
2718 ym=0.5*(y1+y2); | |
2719 | |
2720 s=(y2-y1)/(x2-x1); | |
2721 s0=(sym[j2].ymx-sym[j1].ymx)/(x2-x1); | |
2722 if (s0>0) { | |
2723 if (s<0) s=0; if (s>s0) s=s0; | |
2724 } | |
2725 else { | |
2726 if (s>0) s=0; if (s<s0) s=s0; | |
2727 } | |
2728 if (s*s < 0.2*0.2) s=0; /* flat if below limit */ | |
2729 | |
2730 | |
2731 dy=0; /* shift up bracket if needed */ | |
2732 for (j=j1;j<=j2;j++) { | |
2733 if ((sym[j].type==NOTE) || (sym[j].type==REST)) { | |
2734 xx=sym[j].x; | |
2735 yy=ym+(xx-xm)*s; | |
2736 yx=sym[j].ymx+10; | |
2737 if (sym[j].stem==1) yx=sym[j].ys+5; | |
2738 if (yx-yy>dy) dy=yx-yy; | |
2739 } | |
2740 } | |
2741 ym=ym+dy; | |
2742 y1=ym+s*(x1-xm); | |
2743 y2=ym+s*(x2-xm); | |
2744 | |
2745 /* shift up guitar chords, if needed */ | |
2746 for (j=j1;j<=j2;j++) { | |
2747 if ((sym[j].type==NOTE) || (sym[j].type==REST)) { | |
2748 xx=sym[j].x; | |
2749 yy=ym+(xx-xm)*s; | |
2750 if (sym[j].gchy<yy+4) sym[j].gchy=yy+4; | |
2751 } | |
2752 } | |
2753 | |
2754 xx=xm-6; | |
2755 yy=ym+s*(xx-xm); | |
2756 PUT4("%.1f %.1f %.1f %.1f hbr ", x1,y1,xx,yy) | |
2757 | |
2758 xx=xm+6; | |
2759 yy=ym+s*(xx-xm); | |
2760 PUT4("%.1f %.1f %.1f %.1f hbr ", x2,y2,xx,yy) | |
2761 | |
2762 yy=0.5*(y1+y2); | |
2763 PUT3("%.1f %.1f (%d) bnum\n", xm, yy-4, p) | |
2764 | |
2765 } | |
2766 | |
2767 /* ----- draw_nplet_brackets ----- */ | |
2768 void draw_nplet_brackets () | |
2769 { | |
2770 int i,j,k,p,r,c; | |
2771 | |
2772 for (i=0;i<nsym;i++) { | |
2773 if ((sym[i].type==NOTE) || (sym[i].type==REST)) { | |
2774 if (sym[i].p_plet>0) { | |
2775 p=sym[i].p_plet; | |
2776 r=sym[i].r_plet; | |
2777 c=r; | |
2778 k=i; | |
2779 for (j=i;j<nsym;j++) { | |
2780 if ((sym[j].type==NOTE) || (sym[j].type==REST)) { | |
2781 c--; | |
2782 k=j; | |
2783 if (c==0) break; | |
2784 } | |
2785 } | |
2786 draw_bracket (p,i,k); | |
2787 } | |
2788 } | |
2789 } | |
2790 } | |
2791 | |
2792 | |
2793 /* ----- slur_direction: decide whether slur goes up or down --- */ | |
2794 float slur_direction (k1,k2) | |
2795 int k1,k2; | |
2796 { | |
2797 float s; | |
2798 int i,are_stems,are_downstems,are_bars,y_max,notes; | |
2799 | |
2800 are_stems=are_downstems=are_bars=0; | |
2801 notes=0; | |
2802 y_max=300; | |
2803 for (i=k1;i<=k2;i++) { | |
2804 if (sym[i].type==BAR) are_bars=1; | |
2805 if (sym[i].type==NOTE) { | |
2806 notes++; | |
2807 if (sym[i].stem != 0 ) are_stems=1; | |
2808 if (sym[i].stem == -1 ) are_downstems=1; | |
2809 if (sym[i].ymn<y_max) y_max=sym[i].ymn; | |
2810 } | |
2811 } | |
2812 s=-1; | |
2813 if (are_downstems) s=1; | |
2814 if (!are_stems) { | |
2815 s=1; | |
2816 if (y_max<12) s=-1; | |
2817 } | |
2818 | |
2819 /* next line tries to put long phrasings on top */ | |
2820 if (are_bars && (notes>5)) s=1; | |
2821 | |
2822 return s; | |
2823 } | |
2824 | |
2825 /* ----- output_slur: output slur -- --- */ | |
2826 void output_slur (x1,y1,x2,y2,s,height,shift) | |
2827 float x1,y1,x2,y2,s,height,shift; | |
2828 { | |
2829 float alfa,beta,mx,my,xx1,yy1,xx2,yy2,dx,dy,dz,a,add; | |
2830 | |
2831 alfa=0.3; | |
2832 beta=0.45; | |
2833 | |
2834 /* for wide flat slurs, make shape more square */ | |
2835 dy=y2-y1; | |
2836 if (dy<0) dy=-dy; | |
2837 dx=x2-x1; | |
2838 if (dx<0) dx=-dx; | |
2839 a=dy/dx; | |
2840 if ((a<0.7) && dx>40) { | |
2841 add=0.2*(dx-40)/100; | |
2842 alfa=0.3+add; | |
2843 if (alfa>0.7) alfa=0.7; | |
2844 } | |
2845 | |
2846 | |
2847 /* alfa, beta, and height determine Bezier control points pp1,pp2 | |
2848 * | |
2849 * X====alfa===|===alfa=====X | |
2850 * / | \ | |
2851 * pp1 | pp2 | |
2852 * / height \ | |
2853 * beta | beta | |
2854 * / | \ | |
2855 * p1 m p2 | |
2856 * | |
2857 */ | |
2858 | |
2859 | |
2860 mx=0.5*(x1+x2); | |
2861 my=0.5*(y1+y2); | |
2862 | |
2863 xx1=mx+alfa*(x1-mx); | |
2864 yy1=my+alfa*(y1-my)+height; | |
2865 xx1=x1+beta*(xx1-x1); | |
2866 yy1=y1+beta*(yy1-y1); | |
2867 | |
2868 xx2=mx+alfa*(x2-mx); | |
2869 yy2=my+alfa*(y2-my)+height; | |
2870 xx2=x2+beta*(xx2-x2); | |
2871 yy2=y2+beta*(yy2-y2); | |
2872 | |
2873 dx=0.03*(x2-x1); | |
2874 if (dx>10.0) dx=10.0; | |
2875 dy=1.0; | |
2876 dz=0.20; | |
2877 if (x2-x1>100) dz=dz+0.001*(x2-x1); | |
2878 if (dz>0.6) dz=0.6; | |
2879 | |
2880 PUT4("%.1f %.1f %.1f %.1f ", | |
2881 xx2-dx, yy2+shift+s*dy, xx1+dx, yy1+shift+s*dy) | |
2882 PUT3("%.1f %.1f 0 %.1f ", x1,y1+shift+s*dz,s*dz) | |
2883 PUT4("%.1f %.1f %.1f %.1f ", xx1,yy1+shift,xx2,yy2+shift) | |
2884 PUT4("%.1f %.1f %.1f %.1f SL\n", x2,y2+shift, x1,y1+shift) | |
2885 | |
2886 | |
2887 /*PUT4("%.2f %.2f %.2f %.2f ", xx1,yy1+shift,xx2,yy2+shift) | |
2888 PUT4("%.2f %.2f %.2f %.2f sl\n", x2,y2+shift, x1,y1+shift)*/ | |
2889 | |
2890 return; | |
2891 } | |
2892 | |
2893 /* ----- draw_slur (not a pretty routine, this) ----- */ | |
2894 void draw_slur (k1,k2,nn,level) | |
2895 int k1,k2,level,nn; | |
2896 { | |
2897 float x01,x02,y01,y02; | |
2898 float x1,y1,x2,y2,yy,height,addx,addy; | |
2899 float s,shift,hmin,a; | |
2900 float x,y,z,h,dx,dy; | |
2901 int i; | |
2902 | |
2903 s=slur_direction (k1,k2); | |
2904 | |
2905 /* fix endpoints */ | |
2906 if (sym[k1].type==NOTE) { /* here if k1 points to note */ | |
2907 x01=sym[k1].x; | |
2908 yy=sym[k1].ymn; if (s>0) yy=sym[k1].ymx; | |
2909 y01=extreme(s,yy+s*6,sym[k1].ys+s*2); | |
2910 if (sym[k1].word_end) { | |
2911 yy=sym[k1].ymn; if (s>0) yy=sym[k1].ymx; | |
2912 y01=yy+s*6; | |
2913 if ((sym[k1].stem==1)&&(s==1)) x01=x01+4; | |
2914 } | |
2915 if ((s>0) && (y01<sym[k1].dc.top+2.5)) y01=sym[k1].dc.top+2.5; | |
2916 } | |
2917 | |
2918 if (sym[k2].type==NOTE) { /* here if k2 points to note */ | |
2919 x02=sym[k2].x; | |
2920 yy=sym[k2].ymn; if (s>0) yy=sym[k2].ymx; | |
2921 y02=extreme(s,yy+s*6,sym[k2].ys+s*2); | |
2922 if (sym[k2].word_st) { | |
2923 yy=sym[k2].ymn; if (s>0) yy=sym[k2].ymx; | |
2924 y02=yy+s*6; | |
2925 if ((sym[k2].stem==-1)&&(s==-1)) x02=x02-3; | |
2926 } | |
2927 if ((s>0) && (y02<sym[k2].dc.top+2.5)) y02=sym[k2].dc.top+2.5; | |
2928 } | |
2929 | |
2930 if (sym[k1].type!=NOTE) { | |
2931 x01=sym[k1].x+sym[k1].wr; | |
2932 y01=y02+1.2*s; | |
2933 if (nn>1) { | |
2934 if(s==1) { if (y01<28) y01=28; } | |
2935 else { if (y01>-4) y01=-4; } | |
2936 } | |
2937 } | |
2938 | |
2939 if (sym[k2].type!=NOTE) { | |
2940 x02=sym[k2].x; | |
2941 y02=y01+1.2*s; | |
2942 if (nn>1) { | |
2943 if (s==1) {if (y02<28) y02=28; } | |
2944 else {if (y02>-4) y02=-4; } | |
2945 } | |
2946 } | |
2947 | |
2948 /* shift endpoints */ | |
2949 addx=0.04*(x02-x01); | |
2950 if (addx>3.0) addx=3.0; | |
2951 addy=0.02*(x02-x01); | |
2952 if (addy>3.0) addy=3.0; | |
2953 x1 = x01+addx; | |
2954 x2 = x02-addx; | |
2955 y1=y01+s*addy; | |
2956 y2=y02+s*addy; | |
2957 | |
2958 a=(y2-y1)/(x2-x1); /* slur steepness */ | |
2959 if (a > SLUR_SLOPE) a= SLUR_SLOPE; | |
2960 if (a < -SLUR_SLOPE) a=-SLUR_SLOPE; | |
2961 if (a>0) { | |
2962 if (s == 1) y1=y2-a*(x2-x1); | |
2963 if (s == -1) y2=y1+a*(x2-x1); | |
2964 } | |
2965 else { | |
2966 if (s == -1) y1=y2-a*(x2-x1); | |
2967 if (s == 1) y2=y1+a*(x2-x1); | |
2968 } | |
2969 | |
2970 /* for big vertical jump, shift endpoints */ | |
2971 y=y2-y1; if (y>8) y=8; if (y<-8) y=-8; | |
2972 z=y; if(z<0) z=-z; dx=0.5*z; dy=0.3*z; | |
2973 if (y>0) { | |
2974 if (s==1) { x2=x2-dx; y2=y2-dy; } | |
2975 if (s==-1) { x1=x1+dx; y1=y1+dy; } | |
2976 } | |
2977 else { | |
2978 if (s==1) { x1=x1+dx; y1=y1-dy; } | |
2979 if (s==-1) { x2=x2-dx; y2=y2+dy; } | |
2980 } | |
2981 | |
2982 h=0; | |
2983 for (i=k1+1; i<k2; i++) | |
2984 if (sym[i].type==NOTE) { | |
2985 x = sym[i].x; | |
2986 yy = sym[i].ymn; if (s>0) yy=sym[i].ymx; | |
2987 y = extreme (s, yy+6*s, sym[i].ys+2*s); | |
2988 z = (y2*(x-x1)+y1*(x2-x))/(x2-x1); | |
2989 h = extreme (s, h, y-z); | |
2990 } | |
2991 | |
2992 y1=y1+0.4*h; | |
2993 y2=y2+0.4*h; | |
2994 h=0.6*h; | |
2995 | |
2996 hmin=s*(0.03*(x2-x1)+8); | |
2997 if (nn>3) hmin=s*(0.12*(x2-x1)+12); | |
2998 height = extreme (s, hmin, 3.0*h); | |
2999 height = extreme (-s, height, s*50); | |
3000 | |
3001 y=y2-y1; if (y<0) y=-y; | |
3002 if ((s==1) && (height< 0.8*y)) height=0.8*y; | |
3003 if ((s==-1) && (height>-0.8*y)) height=-0.8*y; | |
3004 | |
3005 shift=3*s*level; | |
3006 | |
3007 output_slur (x1,y1,x2,y2,s,height,shift); | |
3008 | |
3009 return; | |
3010 } | |
3011 | |
3012 | |
3013 /* ----- prev_scut, next_scut: find place to terminate/start slur --- */ | |
3014 int next_scut (i) | |
3015 int i; | |
3016 { | |
3017 int j,cut,ok; | |
3018 | |
3019 cut=nsym-1; | |
3020 for (j=i+1;j<nsym;j++) { | |
3021 ok=0; | |
3022 if (sym[j].type==BAR) { | |
3023 if (sym[j].u==B_RREP) ok=1; | |
3024 if (sym[j].u==B_DREP) ok=1; | |
3025 if (sym[j].u==B_FAT1) ok=1; | |
3026 if (sym[j].u==B_FAT2) ok=1; | |
3027 if (sym[j].v==2) ok=1; | |
3028 } | |
3029 if(ok) { | |
3030 cut=j; | |
3031 break; | |
3032 } | |
3033 } | |
3034 return cut; | |
3035 } | |
3036 | |
3037 int prev_scut(i) | |
3038 int i; | |
3039 { | |
3040 int j,cut,ok; | |
3041 | |
3042 cut=-1; | |
3043 for (j=i;j>=0;j--) { | |
3044 ok=0; | |
3045 if (sym[j].type==BAR) { | |
3046 if (sym[j].u==B_LREP) ok=1; | |
3047 if (sym[j].u==B_DREP) ok=1; | |
3048 if (sym[j].u==B_FAT1) ok=1; | |
3049 if (sym[j].u==B_FAT2) ok=1; | |
3050 if (sym[j].v==2) ok=1; | |
3051 } | |
3052 if(ok) { | |
3053 cut=j; | |
3054 break; | |
3055 } | |
3056 } | |
3057 | |
3058 if (cut==-1) { /* return sym before first note */ | |
3059 cut=0; | |
3060 for (j=0;j<nsym;j++) { | |
3061 if((sym[j].type==REST) || (sym[j].type==NOTE)) { | |
3062 cut=j-1; | |
3063 break; | |
3064 } | |
3065 } | |
3066 } | |
3067 | |
3068 return cut; | |
3069 } | |
3070 | |
3071 | |
3072 /* ----- draw_chord_slurs ----- */ | |
3073 void draw_chord_slurs(k1,k2,nh1,nh2,nslur,mhead1,mhead2,job) | |
3074 int k1,k2,nh1,nh2,nslur,mhead1[MAXHD],mhead2[MAXHD],job; | |
3075 { | |
3076 | |
3077 int i,pbot,ptop,m1,m2,p1,p2,y,cut; | |
3078 float s,x1,y1,x2,y2,height,shift,addx,addy; | |
3079 | |
3080 if (nslur==0) return; | |
3081 | |
3082 pbot=1000; | |
3083 ptop=-1000; | |
3084 for (i=0;i<sym[k1].npitch;i++) { | |
3085 p1=sym[k1].pits[i]; | |
3086 if (p1<pbot) pbot=p1; | |
3087 if (p1>ptop) ptop=p1; | |
3088 } | |
3089 | |
3090 for (i=0;i<nslur;i++) { | |
3091 m1=mhead1[i]; | |
3092 m2=mhead2[i]; | |
3093 p1=sym[k1].pits[m1]; | |
3094 p2=sym[k2].pits[m2]; | |
3095 s=slur_direction (k1,k2); | |
3096 if (p1==pbot) s=-1; | |
3097 if (p1==ptop) s=1; | |
3098 | |
3099 x1=sym[k1].x; | |
3100 x2=sym[k2].x; | |
3101 if (job==2) { | |
3102 cut=next_scut(k1); | |
3103 x2=sym[cut].x; | |
3104 if (cut==k1) x2=x1+30; | |
3105 } | |
3106 | |
3107 if (job==1) { | |
3108 cut=prev_scut(k1); | |
3109 x1=sym[cut].x; | |
3110 if (cut==k1) x2=x1-30; | |
3111 } | |
3112 | |
3113 addx=0.04*(x2-x1); | |
3114 if (addx>3.0) addx=3.0; | |
3115 addy=0.02*(x2-x1); | |
3116 if (addy>3.0) addy=3.0; | |
3117 | |
3118 x1=x1+3+addx; | |
3119 x2=x2-3-addx; | |
3120 if ((s==1) && (sym[k1].stem==1)) x1=x1+1.5; | |
3121 if ((s==-1) && (sym[k2].stem==-1)) x2=x2-1.5; | |
3122 | |
3123 y=3*(p1-18)+sym[k1].yadd; | |
3124 y1=y2=y+s*(4+addy); | |
3125 y=3*(p2-18)+sym[k2].yadd; | |
3126 y2=y+s*(4+addy); | |
3127 | |
3128 if ((s==1) && !(y%6) && (sym[k1].dots>0)) { | |
3129 y2=y1=y+s*(5.5+addy); | |
3130 x1=x1-2; | |
3131 x2=x2+2; | |
3132 } | |
3133 height=s*(0.04*(x2-x1)+5); | |
3134 shift=0; | |
3135 output_slur (x1,y1,x2,y2,s,height,shift); | |
3136 } | |
3137 | |
3138 } | |
3139 | |
3140 | |
3141 | |
3142 /* ----- draw_slurs: draw slurs/ties between neighboring notes/chords */ | |
3143 void draw_slurs (k1,k2,job) | |
3144 int k1,k2,job; | |
3145 { | |
3146 int i,m1,m2; | |
3147 int mhead1[MAXHD],mhead2[MAXHD],nslur,nh1,nh2; | |
3148 | |
3149 if (nbuf+100>BUFFSZ) | |
3150 rx ("PS output exceeds reserved space per staff", | |
3151 " -- increase BUFFSZ1"); | |
3152 | |
3153 nslur=0; | |
3154 | |
3155 if (job==2) { /* half slurs from last note in line … | |
3156 nh1=sym[k1].npitch; | |
3157 for (i=1;i<=nh1;i++) { | |
3158 for (m1=0;m1<nh1;m1++) { | |
3159 if (sym[k1].sl1[m1]==i) { | |
3160 nslur=nslur+1; | |
3161 mhead1[nslur-1]=m1; | |
3162 } | |
3163 if (sym[k1].ti1[m1]) { | |
3164 nslur=nslur+1; | |
3165 mhead1[nslur-1]=m1; | |
3166 } | |
3167 } | |
3168 } | |
3169 draw_chord_slurs(k1,k1,nh1,nh1,nslur,mhead1,mhead1,job); | |
3170 return; | |
3171 } | |
3172 | |
3173 if (job==1) { /* half slurs to first note in line */ | |
3174 nh1=sym[k1].npitch; | |
3175 for (i=1;i<=nh1;i++) { | |
3176 for (m1=0;m1<nh1;m1++) { | |
3177 if (sym[k1].sl2[m1]==i) { | |
3178 nslur=nslur+1; | |
3179 mhead1[nslur-1]=m1; | |
3180 } | |
3181 if (sym[k1].ti2[m1]) { | |
3182 nslur=nslur+1; | |
3183 mhead1[nslur-1]=m1; | |
3184 } | |
3185 } | |
3186 } | |
3187 draw_chord_slurs(k1,k1,nh1,nh1,nslur,mhead1,mhead1,job); | |
3188 return; | |
3189 } | |
3190 | |
3191 /* real 2-note case: set up list of slurs/ties to draw */ | |
3192 if ((sym[k1].type==NOTE) && (sym[k2].type==NOTE)) { | |
3193 nh1=sym[k1].npitch; | |
3194 nh2=sym[k2].npitch; | |
3195 | |
3196 for (m1=0;m1<nh1;m1++) { | |
3197 if (sym[k1].ti1[m1]) { | |
3198 for (m2=0;m2<nh2;m2++) { | |
3199 if (sym[k2].pits[m2]==sym[k1].pits[m1]) { | |
3200 nslur++; | |
3201 mhead1[nslur-1]=m1; | |
3202 mhead2[nslur-1]=m2; | |
3203 break; | |
3204 } | |
3205 } | |
3206 } | |
3207 } | |
3208 | |
3209 for (i=1;i<=nh1;i++) { | |
3210 for (m1=0;m1<nh1;m1++) { | |
3211 if (sym[k1].sl1[m1]==i) { | |
3212 nslur++; | |
3213 mhead1[nslur-1]=m1; | |
3214 mhead2[nslur-1]=-1; | |
3215 for (m2=0;m2<nh2;m2++) { | |
3216 if (sym[k2].sl2[m2]==i) mhead2[nslur-1]=m2; | |
3217 } | |
3218 if (mhead2[nslur-1]==-1) nslur--; | |
3219 } | |
3220 } | |
3221 } | |
3222 } | |
3223 | |
3224 draw_chord_slurs(k1,k2,nh1,nh2,nslur,mhead1,mhead2,job); | |
3225 } | |
3226 | |
3227 | |
3228 | |
3229 /* ----- draw_phrasing: draw phrasing slur between two symbols --- */ | |
3230 void draw_phrasing (k1,k2,level) | |
3231 int k1,k2,level; | |
3232 { | |
3233 int nn,i; | |
3234 | |
3235 if (k1==k2) return; | |
3236 if (nbuf+100>BUFFSZ) | |
3237 rx ("PS output exceeds reserved space per staff", | |
3238 " -- increase BUFFSZ1"); | |
3239 nn=0; | |
3240 for (i=k1;i<=k2;i++) | |
3241 if ((sym[i].type==NOTE)||(sym[i].type==REST)) nn++; | |
3242 | |
3243 draw_slur (k1,k2,nn,level); | |
3244 | |
3245 } | |
3246 | |
3247 /* ----- draw_all_slurs: draw all slurs/ties between neighboring notes … | |
3248 void draw_all_slurs () | |
3249 { | |
3250 int i,i1,i2; | |
3251 | |
3252 i1=-1; | |
3253 for (i=0;i<nsym;i++) { | |
3254 if (sym[i].type==NOTE) { | |
3255 i1=i; | |
3256 break; | |
3257 } | |
3258 } | |
3259 if (i1<0) return; | |
3260 draw_slurs(i1,i1,1); | |
3261 | |
3262 for (;;) { | |
3263 i2=-1; | |
3264 for (i=i1+1;i<nsym;i++) { | |
3265 if (sym[i].type==NOTE) { | |
3266 i2=i; | |
3267 break; | |
3268 } | |
3269 } | |
3270 if (i2<0) break; | |
3271 draw_slurs(i1,i2,0); | |
3272 i1=i2; | |
3273 } | |
3274 | |
3275 draw_slurs(i1,i1,2); | |
3276 | |
3277 } | |
3278 | |
3279 /* ----- draw_all_phrasings: draw all phrasing slurs for one staff -----… | |
3280 void draw_all_phrasings () | |
3281 { | |
3282 int i,j,k,cut,pass,num; | |
3283 | |
3284 for (pass=0;;pass++) { | |
3285 num=0; | |
3286 for (i=0;i<nsym;i++) { | |
3287 | |
3288 if (sym[i].slur_st) { | |
3289 k=-1; /* find matching slur end */ | |
3290 for (j=i+1;j<nsym;j++) { | |
3291 if (sym[j].slur_st && (!sym[j].slur_end)) break; | |
3292 if (sym[j].slur_end) { | |
3293 k=j; | |
3294 break; | |
3295 } | |
3296 } | |
3297 if (k>=0) { | |
3298 cut=next_scut(i); | |
3299 if (cut<k) { | |
3300 draw_phrasing (i,cut,pass); | |
3301 cut=prev_scut(k); | |
3302 draw_phrasing (cut,k,pass); | |
3303 } | |
3304 else { | |
3305 draw_phrasing (i,k,pass); | |
3306 } | |
3307 num++; | |
3308 sym[i].slur_st--; | |
3309 sym[k].slur_end--; | |
3310 } | |
3311 } | |
3312 } | |
3313 if (num==0) break; | |
3314 } | |
3315 | |
3316 /* do unbalanced slurs still left over */ | |
3317 | |
3318 for (i=0;i<nsym;i++) { | |
3319 if (sym[i].slur_end) { | |
3320 cut=prev_scut(i); | |
3321 draw_phrasing (cut,i,0); | |
3322 } | |
3323 if (sym[i].slur_st) { | |
3324 cut=next_scut(i); | |
3325 draw_phrasing (i,cut,0); | |
3326 } | |
3327 } | |
3328 | |
3329 } | |
3330 | |
3331 /* ----- check_bars1 ---------- */ | |
3332 void check_bars1 (ip1,ip2) | |
3333 int ip1,ip2; | |
3334 { | |
3335 int v,i,j,k1,k2; | |
3336 float dx; | |
3337 | |
3338 /* check for inelegant bar combinations within one line */ | |
3339 i=j=ip1; | |
3340 for (;;) { | |
3341 if (xp[i].type==BAR && xp[j].type==BAR && i!=j) { | |
3342 dx=0; | |
3343 for (v=0;v<nvoice;v++) { | |
3344 k1=xp[j].p[v]; | |
3345 k2=xp[i].p[v]; | |
3346 if (k1>=0 && k2>=0) { | |
3347 if (symv[v][k1].u==B_RREP && symv[v][k2].u==B_LREP) { | |
3348 symv[v][k2].u=B_DREP; | |
3349 symv[v][k1].u=B_INVIS; | |
3350 dx=-4.0; | |
3351 } | |
3352 } | |
3353 } | |
3354 xp[i].x=xp[i].x+dx; | |
3355 } | |
3356 j=i; | |
3357 i=xp[i].next; | |
3358 if (i==ip2) break; | |
3359 } | |
3360 | |
3361 } | |
3362 | |
3363 | |
3364 /* ----- check_bars2 ---------- */ | |
3365 void check_bars2 (ip1,ip2) | |
3366 int ip1,ip2; | |
3367 { | |
3368 int i,ip,v; | |
3369 | |
3370 /* check whether to split up last bar over two lines */ | |
3371 ip=xp[ip2].prec; | |
3372 for (v=0;v<nvoice;v++) { | |
3373 strcpy(voice[v].insert_text,""); | |
3374 voice[v].insert_bnum = 0; | |
3375 voice[v].insert_space = 0; | |
3376 voice[v].insert_num = 0; | |
3377 voice[v].insert_btype = 0; | |
3378 | |
3379 i=xp[ip].p[v]; | |
3380 if (i>=0) { | |
3381 if (symv[v][i].type==BAR) { | |
3382 if (symv[v][i].u==B_LREP) { | |
3383 symv[v][i].u=B_SNGL; | |
3384 voice[v].insert_btype=B_LREP; | |
3385 voice[v].insert_num=0; | |
3386 } | |
3387 else if (symv[v][i].u==B_DREP) { | |
3388 symv[v][i].u=B_RREP; | |
3389 voice[v].insert_btype=B_LREP; | |
3390 voice[v].insert_num=0; | |
3391 } | |
3392 else if ((symv[v][i].u==B_RREP) && (symv[v][i].v!=0)) { | |
3393 voice[v].insert_btype=B_INVIS; | |
3394 voice[v].insert_num=symv[v][i].v; | |
3395 symv[v][i].v=0; | |
3396 } | |
3397 else if ((symv[v][i].u==B_SNGL) && (symv[v][i].v!=0)) { | |
3398 voice[v].insert_btype=B_INVIS; | |
3399 voice[v].insert_num=symv[v][i].v; | |
3400 symv[v][i].v=0; | |
3401 } | |
3402 | |
3403 /* if number or label on last bar, move to next line */ | |
3404 if (symv[v][i].t || (strlen(symv[v][i].text)>0)) { | |
3405 if (symv[v][i+1].type==BAR) { | |
3406 if (symv[v][i+1].t==0) symv[v][i+1].t=symv[v][i].t; | |
3407 if (strlen(symv[v][i+1].text)==0) | |
3408 strcpy(symv[v][i+1].text,symv[v][i].text); | |
3409 } | |
3410 else { | |
3411 if (!voice[v].insert_btype) voice[v].insert_btype=B_INVIS; | |
3412 voice[v].insert_space=symv[v][i].wr; | |
3413 voice[v].insert_bnum=symv[v][i].t; | |
3414 strcpy(voice[v].insert_text,symv[v][i].text); | |
3415 strcpy(symv[v][i].text,""); | |
3416 symv[v][i].t=0; | |
3417 } | |
3418 } | |
3419 | |
3420 | |
3421 } | |
3422 } | |
3423 } | |
3424 | |
3425 | |
3426 } | |
3427 | |
3428 | |
3429 | |
3430 /* ----- draw_vocals ----- */ | |
3431 void draw_vocals (fp,nwl,botnote,bspace,botpos) | |
3432 FILE *fp; | |
3433 float botnote,bspace; | |
3434 float *botpos; | |
3435 int nwl; | |
3436 { | |
3437 int i,hyflag,l,j; | |
3438 float x,x0,yword,lastx,spc,vfsize,w,swfac,lskip; | |
3439 char word[81],t[81]; | |
3440 | |
3441 if (nwl<=0) return; | |
3442 vfsize=cfmt.vocalfont.size; | |
3443 lskip=1.1*vfsize; | |
3444 set_font (fp, cfmt.vocalfont, 0); | |
3445 yword=-cfmt.vocalspace; | |
3446 swfac=1.05; | |
3447 if (strstr(cfmt.vocalfont.name,"Helvetica")) swfac=1.10; | |
3448 if (botnote-cfmt.vocalfont.size<yword) | |
3449 yword=botnote-cfmt.vocalfont.size; | |
3450 | |
3451 for (j=0;j<nwl;j++) { | |
3452 hyflag=0; | |
3453 lastx=-10; | |
3454 for (i=0;i<nsym;i++) { | |
3455 if (sym[i].wordp[j]) { | |
3456 strcpy(word,sym[i].wordp[j]); | |
3457 x0=sym[i].x; | |
3458 l=strlen(word); | |
3459 | |
3460 if (hyflag) { | |
3461 tex_str (word,t,&w); | |
3462 spc=x0-VOCPRE*vfsize*swfac*w-lastx; | |
3463 x = lastx+0.5*spc-0.5*swfac*vfsize*cwid('-'); | |
3464 PUT2("%.1f %.1f whf ",x,yword) | |
3465 hyflag=0; | |
3466 } | |
3467 | |
3468 if ((l>1) && (word[l-1]=='^')) { | |
3469 word[l-1]='\0'; | |
3470 hyflag=1; | |
3471 } | |
3472 | |
3473 if ((l==1) && (word[0]=='_')) { | |
3474 if (lastx<0) lastx=sym[i-1].x+sym[i-1].wr; | |
3475 PUT3("%.1f %.1f %.1f wln ", lastx+3, sym[i].x+1, yword) | |
3476 } | |
3477 else if ((l==1) && (word[0]=='^')) { | |
3478 PUT2("%.1f %.1f whf ", x0, yword) | |
3479 lastx=x0+vfsize*swfac*w; | |
3480 } | |
3481 else { | |
3482 tex_str (word,t,&w); | |
3483 if (isdig(word[0])) | |
3484 x0=x0-3*vfsize*swfac*cwid('1'); | |
3485 else | |
3486 x0=x0-VOCPRE*vfsize*swfac*w; | |
3487 if (strcmp(t," ")) PUT3("(%s) %.1f %.1f wd ", t, x0, yword) | |
3488 lastx=x0+vfsize*swfac*w; | |
3489 } | |
3490 } | |
3491 } | |
3492 if (hyflag) PUT2("%.1f %.1f whf ",lastx+5,yword) | |
3493 yword=yword-lskip; | |
3494 } | |
3495 *botpos=yword + lskip - bspace; | |
3496 } | |
3497 | |
3498 /* ----- draw_symbols: draw symbols at proper positions on staff ----- */ | |
3499 void draw_symbols (fp,bspace,bpos,is_top) | |
3500 FILE *fp; | |
3501 float bspace,*bpos; | |
3502 int is_top; | |
3503 { | |
3504 int i,inbeam,j,nwl; | |
3505 float x,y,top,xl,d,w,gchy,botnote,botpos,spc,swfac; | |
3506 struct BEAM bm; | |
3507 char t[81]; | |
3508 | |
3509 inbeam=do_words=0; | |
3510 botnote=0; | |
3511 nwl=0; | |
3512 for (i=0;i<nsym;i++) { /* draw the symbols */ | |
3513 | |
3514 for (j=0;j<NWLINE;j++) | |
3515 if (sym[i].wordp[j]) { | |
3516 if (j+1>nwl) nwl=j+1; | |
3517 } | |
3518 if (nbuf+100>BUFFSZ) | |
3519 rx ("PS output exceeds reserved space per staff", | |
3520 " -- increase BUFFSZ1"); | |
3521 x=sym[i].x; | |
3522 | |
3523 switch (sym[i].type) { | |
3524 | |
3525 case NOTE: | |
3526 xl=0; w=sym[i].wl; | |
3527 if (i>0) { xl=sym[i-1].x; w=w+sym[i-1].wr; } | |
3528 d=x-xl; | |
3529 | |
3530 if (sym[i].word_st && !sym[i].word_end) { | |
3531 if (calculate_beam (i,&bm)) inbeam=1; | |
3532 } | |
3533 if (inbeam) { | |
3534 top=draw_note(x,w,d,&sym[i],0,&gchy); | |
3535 if (i==bm.i2) { | |
3536 inbeam=0; | |
3537 draw_beams (&bm); | |
3538 } | |
3539 } | |
3540 else { | |
3541 top=draw_note(x,w,d,&sym[i],1,&gchy); | |
3542 } | |
3543 sym[i].gchy=gchy; | |
3544 sym[i].dc.top=top; | |
3545 if (sym[i].ymn-5<botnote) botnote=sym[i].ymn-5; | |
3546 break; | |
3547 | |
3548 case REST: | |
3549 y=sym[i].y; | |
3550 if (inbeam) y=rest_under_beam (sym[i].x,sym[i].head,&bm); | |
3551 draw_rest(x,y,sym[i],&gchy); | |
3552 sym[i].gchy=gchy; | |
3553 break; | |
3554 | |
3555 case BAR: | |
3556 if (sym[i].v) set_ending(i); | |
3557 draw_bar (x,sym[i]); | |
3558 break; | |
3559 | |
3560 case CLEF: | |
3561 if (sym[i].u==TREBLE) { | |
3562 if (sym[i].v) PUT1("%.1f stclef\n", x) | |
3563 else PUT1("%.1f tclef\n", x) | |
3564 } | |
3565 else if (sym[i].u==BASS) { | |
3566 if (sym[i].v) PUT1("%.1f sbclef\n", x) | |
3567 else PUT1("%.1f bclef\n", x) | |
3568 } | |
3569 else if (sym[i].u==ALTO) { | |
3570 if (sym[i].v) PUT1("%.1f scclef\n", x) | |
3571 else PUT1("%.1f cclef\n", x) | |
3572 } | |
3573 else | |
3574 bug("unknown clef type", 0); | |
3575 voice[ivc].key.ktype=sym[i].u; | |
3576 break; | |
3577 | |
3578 case TIMESIG: | |
3579 draw_timesig (x,sym[i]); | |
3580 break; | |
3581 | |
3582 case KEYSIG: | |
3583 voice[ivc].key.sf=draw_keysig (x,sym[i]); | |
3584 break; | |
3585 | |
3586 case INVISIBLE: | |
3587 break; | |
3588 | |
3589 default: | |
3590 printf (">>> cannot draw symbol type %d\n", sym[i].type); | |
3591 } | |
3592 } | |
3593 | |
3594 draw_nplet_brackets (); | |
3595 | |
3596 /*| if (voice[ivc].do_gch) draw_barnums (fp); |*/ | |
3597 | |
3598 | |
3599 if (ivc==ivc0) draw_barnums (fp); | |
3600 | |
3601 | |
3602 /* draw guitar chords */ | |
3603 if (voice[ivc].do_gch) { | |
3604 set_font(fp,cfmt.gchordfont,0); | |
3605 swfac=1.0; | |
3606 if (strstr(cfmt.gchordfont.name,"Times-Roman")) swfac=1.00; | |
3607 if (strstr(cfmt.gchordfont.name,"Times-Bold")) swfac=1.05; | |
3608 if (strstr(cfmt.gchordfont.name,"Helvetica")) swfac=1.10; | |
3609 if (strstr(cfmt.gchordfont.name,"Helvetica-Bold")) swfac=1.15; | |
3610 | |
3611 for (i=0;i<nsym;i++) { | |
3612 if ((sym[i].type==NOTE)||(sym[i].type==REST)) { | |
3613 if (strlen(sym[i].text)>0) { | |
3614 tex_str (sym[i].text,t,&w); | |
3615 w=cfmt.gchordfont.size*w; | |
3616 spc=w*GCHPRE; | |
3617 if (spc>8.0) spc=8.0; | |
3618 PUT3("%.1f %.1f (%s) gc ", sym[i].x-spc, sym[i].gchy, t) | |
3619 } | |
3620 } | |
3621 } | |
3622 } | |
3623 | |
3624 | |
3625 draw_all_slurs (); | |
3626 draw_all_phrasings (); | |
3627 | |
3628 /*| if (is_top) draw_endings (); |*/ | |
3629 if (ivc==ivc0) draw_endings (); | |
3630 num_ending=0; | |
3631 | |
3632 botpos=-bspace; | |
3633 if (botnote<botpos) botpos=botnote; | |
3634 | |
3635 if (nwl>0) draw_vocals (fp,nwl,botnote,bspace,&botpos); | |
3636 | |
3637 *bpos=botpos; | |
3638 | |
3639 } | |
3640 | |
3641 | |
3642 /* ----- draw_sysbars: draw bars extending over staves----- */ | |
3643 void draw_sysbars (fp,ip1,ip2,wid0,h1,dh) | |
3644 FILE *fp; | |
3645 int ip1,ip2; | |
3646 float wid0,h1,dh; | |
3647 { | |
3648 int i,v,ok,u,uu,p; | |
3649 float x; | |
3650 | |
3651 PUT2 ("gsave 0 %.2f T 1.0 %.4f scale ",h1,dh/24.0) | |
3652 i=ip1; | |
3653 for (;;) { | |
3654 if (xp[i].type==BAR) { | |
3655 p=xp[i].p[ivc0]; | |
3656 u=symv[ivc0][p].u; | |
3657 if (u==B_LREP) u=B_FAT1; | |
3658 if (u==B_RREP) u=B_FAT2; | |
3659 ok=1; | |
3660 for (v=0;v<nvoice;v++) { | |
3661 if (v!=ivc0 && voice[v].draw) { | |
3662 p=xp[i].p[v]; | |
3663 if (p<0) ok=0; | |
3664 else { | |
3665 uu=symv[v][p].u; | |
3666 if (uu==B_LREP) uu=B_FAT1; | |
3667 if (uu==B_RREP) uu=B_FAT2; | |
3668 if (uu!=u) ok=0; | |
3669 } | |
3670 } | |
3671 } | |
3672 | |
3673 if (ok) { | |
3674 x=xp[i].x+wid0; | |
3675 if (u==B_SNGL) | |
3676 PUT1("%.1f bar ", x) | |
3677 else if (u==B_DBL) | |
3678 PUT1("%.1f dbar ", x) | |
3679 else if (u==B_FAT1) | |
3680 PUT1("%.1f fbar1 ", x) | |
3681 else if (u==B_FAT2) | |
3682 PUT1("%.1f fbar2 ", x) | |
3683 else if (u==B_DREP) { | |
3684 PUT1("%.1f fbar1 ", x-1) | |
3685 PUT1("%.1f fbar2 ", x+1) | |
3686 } | |
3687 } | |
3688 } | |
3689 | |
3690 i=xp[i].next; | |
3691 if (i==ip2) break; | |
3692 } | |
3693 | |
3694 PUT0 (" 0.0 bar grestore\n") | |
3695 | |
3696 } | |
3697 | |
3698 | |
3699 /* ----- count_symbols: count number of "real" symbols ---- */ | |
3700 int count_symbols () | |
3701 { | |
3702 int i,c; | |
3703 | |
3704 c=0; | |
3705 for (i=0;i<nsym;i++) { | |
3706 switch (sym[i].type) { | |
3707 case NOTE: | |
3708 case REST: | |
3709 case BAR: | |
3710 c++; | |
3711 } | |
3712 } | |
3713 return c; | |
3714 | |
3715 } | |
3716 | |
3717 /* ----- select_piece: choose limits for piece to put on one staff ---- … | |
3718 int select_piece (ip1) | |
3719 int ip1; | |
3720 { | |
3721 int i,num,ltype,count_this; | |
3722 | |
3723 /* find next symbol marked as eol */ | |
3724 i=ip1; | |
3725 for (;;) { | |
3726 if (xp[i].eoln) break; | |
3727 if (xp[i].next==XP_END) break; | |
3728 i=xp[i].next; | |
3729 } | |
3730 i=xp[i].next; | |
3731 if (cfmt.barsperstaff==0) return i; | |
3732 | |
3733 /* find first note or rest */ | |
3734 i=ip1; | |
3735 for (;;) { | |
3736 if (xp[i].type==NOTE || xp[i].type==REST) | |
3737 if (xp[i].type==NOTE || xp[i].type==REST) break; | |
3738 i=xp[i].next; | |
3739 if (i==XP_END) return i; | |
3740 } | |
3741 i=xp[i].next; | |
3742 if (i==XP_END) return i; | |
3743 | |
3744 /* count bars until number is reached */ | |
3745 num=0; | |
3746 ltype=0; | |
3747 for (;;) { | |
3748 count_this=0; | |
3749 if (xp[i].type==BAR) { | |
3750 count_this=1; | |
3751 if (ltype==BAR) count_this=0; | |
3752 } | |
3753 num=num+count_this; | |
3754 ltype=xp[i].type; | |
3755 i=xp[i].next; | |
3756 if (i==XP_END) return i; | |
3757 if (num==cfmt.barsperstaff) return i; | |
3758 } | |
3759 i=xp[i].next; | |
3760 | |
3761 return i; | |
3762 | |
3763 } | |
3764 | |
3765 /* ----- is_topvc: check for top voice of set staved together --- */ | |
3766 int is_topvc (jv) | |
3767 int jv; | |
3768 { | |
3769 int iv,kv,ok; | |
3770 | |
3771 ok=0; | |
3772 for (iv=0;iv<jv;iv++) { | |
3773 if (voice[iv].staves >= jv-iv+1) { | |
3774 for (kv=iv;kv<jv;kv++) | |
3775 if (voice[kv].draw) ok=1; | |
3776 } | |
3777 } | |
3778 | |
3779 return 1-ok; | |
3780 } | |
3781 | |
3782 | |
3783 /* ----- vc_select: set flags for voice selection from -V option --- */ | |
3784 int vc_select () | |
3785 { | |
3786 char *s; | |
3787 int i,a,b,n; | |
3788 | |
3789 if (strlen(vcselstr)==0) return nvoice; | |
3790 | |
3791 for (i=0;i<nvoice;i++) voice[i].select=0; | |
3792 s=vcselstr; | |
3793 for (;;) { | |
3794 if (*s==0) break; | |
3795 if (!sscanf(s,"%d%n",&a,&n)) break; | |
3796 s+=n; | |
3797 b=a; | |
3798 if (*s=='-') { | |
3799 s++; | |
3800 if (*s==0) break; | |
3801 if (!sscanf(s,"%d%n",&b,&n)) break; | |
3802 s+=n; | |
3803 } | |
3804 for (i=a-1;i<b;i++) | |
3805 if (i>=0 && i<nvoice) voice[i].select=1; | |
3806 | |
3807 | |
3808 if (*s==0) { | |
3809 n=0; | |
3810 for (i=0;i<nvoice;i++) if (voice[i].select) n++; | |
3811 if (verbose>=4) { | |
3812 printf ("Selection <%s> selected voices:",vcselstr); | |
3813 for (i=0;i<nvoice;i++) if (voice[i].select) printf(" %d",i+1); | |
3814 printf ("\n"); | |
3815 } | |
3816 return n; | |
3817 } | |
3818 if (*s==',') s++; | |
3819 else break; | |
3820 } | |
3821 | |
3822 rx ("Bad voice selection: -V ", vcselstr); | |
3823 return 0; | |
3824 } | |
3825 | |
3826 /* ----- voice_label: label voice, or just return length if job==0 -- */ | |
3827 float voice_label (fp, label, h, xc, dx0, job) | |
3828 FILE *fp; | |
3829 char *label; | |
3830 float xc,dx0,h; | |
3831 int job; | |
3832 { | |
3833 float w,wid,dy,xcc; | |
3834 char lab[81],t[81]; | |
3835 int n,i; | |
3836 char *p,*q,*l[10]; | |
3837 | |
3838 if (strlen(label)==0) return 0.0; | |
3839 | |
3840 strcpy(lab,label); | |
3841 n=0; | |
3842 p=lab; | |
3843 l[0]=p; | |
3844 while (q=strstr(p,"\\\\")) { *q='\0'; p=q+2; n++; l[n]=p; } | |
3845 n++; | |
3846 | |
3847 wid=0; | |
3848 for (i=0;i<n;i++) { | |
3849 tex_str(l[i],t,&w); | |
3850 w=cfmt.voicefont.size*w; | |
3851 if (w>wid) wid=w; | |
3852 if (job!=0) { | |
3853 xcc=xc; | |
3854 if (xcc+0.5*w>dx0) xcc=dx0-0.5*w; | |
3855 dy = 8.0 + 0.5*cfmt.voicefont.size*(n-1-2*i) + h; | |
3856 PUT3 (" %.2f %.2f M (%s) cshow\n",xcc,dy,t) | |
3857 } | |
3858 } | |
3859 return wid; | |
3860 } | |
3861 | |
3862 | |
3863 | |
3864 /* ----- mstave_deco: draw decorations over multiple staves ----- */ | |
3865 void mstave_deco (fp,ip1,ip2,wid0,hsys,htab) | |
3866 FILE *fp; | |
3867 int ip1,ip2; | |
3868 float hsys,wid0,htab[]; | |
3869 { | |
3870 int iv,jv,nv; | |
3871 float hbot,htop,ht,x0,y0,wid,wc,wcb,w,wmin; | |
3872 float wmin1=15.0, wmin2=10.0; /* space to staff */ | |
3873 | |
3874 wmin=wmin2; | |
3875 if (do_indent) wmin=wmin1; | |
3876 | |
3877 /* draw bar lines */ | |
3878 if (mvoice>1) { | |
3879 for (iv=0;iv<nvoice;iv++) { | |
3880 hbot=10000; htop=-hbot; nv=1; | |
3881 for (jv=iv;jv<iv+voice[iv].staves;jv++) { | |
3882 if (voice[jv].draw) nv++; | |
3883 if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv]; | |
3884 if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv]; | |
3885 } | |
3886 if ((hbot<htop-0.001) && (nv>1)) | |
3887 draw_sysbars (fp,ip1,ip2,wid0,hsys-htop,htop-hbot+24.0); | |
3888 } | |
3889 PUT1 ("gsave 1.0 %.4f scale 0.0 bar grestore\n", (hsys+24.0)/24.0) | |
3890 } | |
3891 | |
3892 /* next part draws voice names (except on braces) */ | |
3893 set_font (fp, cfmt.voicefont, 0); | |
3894 nv=0; | |
3895 for (iv=0;iv<nvoice;iv++) if (voice[iv].draw) nv++; | |
3896 | |
3897 /* get max label width, then center labels above each other */ | |
3898 wid=w=0; | |
3899 for (iv=0;iv<nvoice;iv++) { | |
3900 if (voice[iv].draw) { | |
3901 if (do_indent) | |
3902 w=voice_label (fp, voice[iv].name, 0.0,0.0,0.0, 0); | |
3903 else if (nv>1) | |
3904 w=voice_label (fp, voice[iv].sname, 0.0,0.0,0.0, 0); | |
3905 if (w>wid) wid=w; | |
3906 } | |
3907 } | |
3908 wc=wcb=0.5*wid+wmin; | |
3909 if (wcb<18.0) wcb=18.0; /* label on brace needs a bit more room */ | |
3910 | |
3911 for (iv=0;iv<nvoice;iv++) { | |
3912 if (voice[iv].draw && (voice[iv].brace==0) ) { | |
3913 y0=hsys-htab[iv]; | |
3914 if (do_indent) | |
3915 voice_label (fp, voice[iv].name,y0,-wc,-wmin,1); | |
3916 else if (nv>1) | |
3917 voice_label (fp,voice[iv].sname,y0,-wc,-wmin,1); | |
3918 } | |
3919 } | |
3920 | |
3921 /* braces and brackets */ | |
3922 for (iv=0;iv<nvoice;iv++) { | |
3923 hbot=10000; htop=-hbot; nv=0; | |
3924 for (jv=iv;jv<iv+voice[iv].brace;jv++) { | |
3925 if (voice[jv].draw) nv++; | |
3926 if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv]; | |
3927 if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv]; | |
3928 } | |
3929 if (hbot<htop+0.001) { | |
3930 ht=htop-hbot+24.0; | |
3931 y0=hsys-htop+0.5*ht; | |
3932 x0=-8; | |
3933 ht=ht-2.0; | |
3934 if (voice[iv].brace==1) ht=ht+15.0; | |
3935 if (voice[iv].brace>2) ht=ht-8.0; | |
3936 if ((nv>1)||(voice[iv].brace==1)) | |
3937 PUT3 (" %.4f %.1f %.1f brace\n", ht/120.0, x0, y0) | |
3938 if (do_indent) | |
3939 voice_label (fp, voice[iv].name, y0-12.0,-wcb,-wmin,1); | |
3940 else if (nv>1) | |
3941 voice_label (fp, voice[iv].sname,y0-12.0,-wcb,-wmin,1); | |
3942 } | |
3943 | |
3944 hbot=10000; htop=-hbot; nv=0; | |
3945 for (jv=iv;jv<iv+voice[iv].bracket;jv++) { | |
3946 if (voice[jv].draw) nv++; | |
3947 if (voice[jv].draw && (htab[jv]<hbot)) hbot=htab[jv]; | |
3948 if (voice[jv].draw && (htab[jv]>htop)) htop=htab[jv]; | |
3949 } | |
3950 if ((hbot<htop+0.001) && ((nv>1)||(voice[iv].bracket==1))) | |
3951 PUT2 ("\n %.1f -3 %.1f bracket\n", htop-hbot+24.0+6.0, hsys-htop-3… | |
3952 | |
3953 } | |
3954 | |
3955 } | |
3956 | |
3957 | |
3958 | |
3959 /* ----- output_music: output for parsed symbol list ----- */ | |
3960 void output_music (fp) | |
3961 FILE *fp; | |
3962 { | |
3963 int ip1,ip2,mv,is_top,nsel,b,bnum; | |
3964 float realwidth,staffwidth,wid0,widv,lscale,lwidth,bpos; | |
3965 float spa1,spa2,hsys,htab[40],extra,indent,spax; | |
3966 | |
3967 /* save current meter and key, to continue after P: or T: field */ | |
3968 for (ivc=0;ivc<nvoice;ivc++) { | |
3969 voice[ivc].meter1 = voice[ivc].meter; | |
3970 voice[ivc].key1 = voice[ivc].key; | |
3971 } | |
3972 | |
3973 if (!file_initialized && !epsf) { | |
3974 init_ps (fout,infostr,0,0.0,0.0,0.0,0.0); | |
3975 init_page (fout); | |
3976 } | |
3977 | |
3978 if (nvoice==0) { init_parse_params(); return; } | |
3979 if (verbose>=10) print_vsyms (); | |
3980 | |
3981 alfa_last=0.1; beta_last=0.0; | |
3982 lwidth=cfmt.staffwidth; | |
3983 lscale=cfmt.scale; | |
3984 check_margin (cfmt.leftmargin); | |
3985 | |
3986 /* dump buffer if not enough space for a staff line */ | |
3987 check_buffer (fp, BUFFSZ1); | |
3988 | |
3989 /* initialize meter and key for voices */ | |
3990 for (ivc=0;ivc<nvoice;ivc++) { | |
3991 voice[ivc].meter = voice[ivc].meter0; | |
3992 voice[ivc].key = voice[ivc].key0; | |
3993 if (!do_meter) voice[ivc].meter.insert=0; | |
3994 } | |
3995 | |
3996 /* setup for horizontal positioning, decide which voices to draw */ | |
3997 nsel=vc_select (); | |
3998 for (ivc=0;ivc<nvoice;ivc++) | |
3999 if (!voice[ivc].select) voice[ivc].nsym=0; | |
4000 | |
4001 mvoice=0; | |
4002 ivc0=-1; | |
4003 for (ivc=0;ivc<nvoice;ivc++) { | |
4004 voice[ivc].draw=0; | |
4005 if (voice[ivc].nsym>0) { | |
4006 mvoice++; | |
4007 if (ivc0<0) ivc0=ivc; | |
4008 voice[ivc].draw=1; | |
4009 } | |
4010 } | |
4011 if (mvoice==0) { init_parse_params(); return; } | |
4012 | |
4013 for (ivc=0;ivc<nvoice;ivc++) { | |
4014 if (voice[ivc].draw) { | |
4015 set_sym_chars (0,voice[ivc].nsym,symv[ivc]); | |
4016 set_beams (0,voice[ivc].nsym,symv[ivc]); | |
4017 set_stems (0,voice[ivc].nsym,symv[ivc]); | |
4018 b=set_sym_times(0,voice[ivc].nsym,symv[ivc],voice[ivc].meter0); | |
4019 set_sym_widths (0,voice[ivc].nsym,symv[ivc],ivc); | |
4020 if (ivc==ivc0) bnum=b; | |
4021 } | |
4022 } | |
4023 barinit=bnum; | |
4024 | |
4025 if (mvoice==1) | |
4026 set_style_pars (cfmt.strict1); | |
4027 else | |
4028 set_style_pars (cfmt.strict2); | |
4029 | |
4030 set_poslist (); | |
4031 set_xpwid (); | |
4032 set_spaces (); | |
4033 | |
4034 /* loop over pieces to output */ | |
4035 ip1=xp[XP_START].next; | |
4036 for (;;) { | |
4037 mline++; | |
4038 ip1=contract_keysigs (ip1); | |
4039 wid0=0; | |
4040 for (ivc=0;ivc<nvoice;ivc++) { | |
4041 nsym_st[ivc]=set_initsyms (ivc, &widv); | |
4042 if (widv>wid0) wid0=widv; | |
4043 } | |
4044 indent = (do_indent==1) ? cfmt.indent : 0.0; | |
4045 | |
4046 ip2=select_piece (ip1); | |
4047 ip2=check_overflow (ip1,ip2,lwidth/lscale-wid0-indent); | |
4048 if (verbose>5) printf ("output posits %d to %d\n",ip1,ip2-1); | |
4049 realwidth=set_glue (ip1,ip2,lwidth/lscale-wid0-indent); | |
4050 check_bars1 (ip1,ip2); | |
4051 check_bars2 (ip1,ip2); | |
4052 | |
4053 spa1=spa2=cfmt.staffsep; | |
4054 if (mvoice>1) { | |
4055 spa1=cfmt.systemsep; | |
4056 spa2=cfmt.sysstaffsep; | |
4057 } | |
4058 | |
4059 hsys=0; | |
4060 mv=0; | |
4061 for (ivc=0;ivc<nvoice;ivc++) { | |
4062 if (voice[ivc].draw) { | |
4063 mv++; | |
4064 nsym=copy_vsyms (ivc,ip1,ip2,wid0); | |
4065 PUT2("\n%% --- ln %d vc %d \n", mline,ivc+1) | |
4066 if (mv==1) bskip(lscale*(0.5*spa1+24.0)); | |
4067 else bskip(lscale*(0.5*spa2+24.0)); | |
4068 PUT3("gsave %.3f %.3f scale %.2f setlinewidth\n", | |
4069 lscale, lscale, BASEWIDTH) | |
4070 if (do_indent) PUT1(" %.2f 0 T ",indent) | |
4071 staffwidth=realwidth+wid0; | |
4072 PUT1("%.2f staff\n", staffwidth) | |
4073 htab[ivc]=hsys; | |
4074 spax=spa2+voice[ivc].sep; | |
4075 if (voice[ivc].sep>1000.0) spax=voice[ivc].sep-2000.0; | |
4076 | |
4077 is_top=is_topvc(ivc); | |
4078 draw_symbols (fp,0.5*spa2+spax-spa2,&bpos,is_top); | |
4079 | |
4080 if (mv==mvoice) mstave_deco (fp,ip1,ip2,wid0,hsys,htab); | |
4081 | |
4082 PUT0("grestore\n") | |
4083 bskip(-lscale*bpos); | |
4084 hsys=hsys+0.5*spa2+24.0-bpos; | |
4085 } | |
4086 } | |
4087 | |
4088 extra=-bpos-0.5*spa2; | |
4089 if (mvoice>1) bskip(lscale*(spa1+bpos-0.5*spa1+extra)); | |
4090 buffer_eob (fp); | |
4091 | |
4092 do_meter=do_indent=0; | |
4093 ip1=ip2; | |
4094 if (ip1==XP_END) break; | |
4095 } | |
4096 | |
4097 | |
4098 /* set things to continue parsing */ | |
4099 for (ivc=0;ivc<nvoice;ivc++) { | |
4100 voice[ivc].nsym=0; | |
4101 voice[ivc].meter0 = voice[ivc].meter = voice[ivc].meter1; | |
4102 voice[ivc].key0 = voice[ivc].key = voice[ivc].key1; | |
4103 } | |
4104 init_parse_params (); | |
4105 | |
4106 } | |
4107 | |
4108 /* ----- process_textblock ----- */ | |
4109 void process_textblock(fpin,fp,job) | |
4110 FILE *fp,*fpin; | |
4111 int job; | |
4112 { | |
4113 char w1[81],ln[BSIZE],ln1[BSIZE]; | |
4114 float lwidth,baseskip,parskip; | |
4115 int i,ll,add_final_nl; | |
4116 | |
4117 baseskip = cfmt.textfont.size * cfmt.lineskipfac; | |
4118 parskip = cfmt.textfont.size * cfmt.parskipfac; | |
4119 add_final_nl=0; | |
4120 if (job==OBEYLINES) add_final_nl=1; | |
4121 lwidth=cfmt.staffwidth; | |
4122 output_music (fp); | |
4123 buffer_eob (fp); | |
4124 set_font (fp, cfmt.textfont, 0); | |
4125 ntxt=0; | |
4126 for (i=0;i<100;i++) { | |
4127 if (feof(fpin)) rx("EOF reached scanning text block",""); | |
4128 strcpy (ln, ""); | |
4129 abc2ps_getline(ln, BSIZE, fpin); | |
4130 ll=strlen(ln); | |
4131 linenum++; | |
4132 if ((verbose>=5) || (vb>=10) ) printf ("%3d %s \n", linenum, ln); | |
4133 if ((ln[0]=='%') && (ln[1]=='%')) { | |
4134 strcpy(ln1,ln+2); | |
4135 strcpy(ln,ln1); | |
4136 } | |
4137 | |
4138 strcpy(w1,""); | |
4139 sscanf(ln,"%s",w1); | |
4140 if (!strcmp(w1,"endtext")) break; | |
4141 | |
4142 if (job!=SKIP) { | |
4143 if (str_isblank(ln)) { | |
4144 write_text_block (fp,job); | |
4145 ntxt=0; | |
4146 } | |
4147 else { | |
4148 add_to_text_block (ln,add_final_nl); | |
4149 } | |
4150 } | |
4151 } | |
4152 if (job!=SKIP) write_text_block (fp,job); | |
4153 } | |
4154 | |
4155 | |
4156 /* ----- process_pscomment ----- */ | |
4157 void process_pscomment (fpin,fp,line) | |
4158 FILE *fp,*fpin; | |
4159 char line[]; | |
4160 { | |
4161 char w[81],fstr[81],unum1[41],unum2[41],unum3[41]; | |
4162 float h1,h2,len,lwidth; | |
4163 int i,nch,job; | |
4164 | |
4165 lwidth=cfmt.staffwidth; | |
4166 line[0]=' '; | |
4167 line[1]=' '; | |
4168 for (i=0;i<strlen(line);i++) if (line[i]=='%') line[i]='\0'; | |
4169 strcpy(w," "); | |
4170 sscanf(line,"%s%n", w, &nch); | |
4171 | |
4172 if (!strcmp(w,"begintext")) { | |
4173 if (epsf && !within_block) return; | |
4174 strcpy(fstr,""); | |
4175 sscanf(line, "%*s %s", fstr); | |
4176 if (str_isblank(fstr)) strcpy(fstr,"obeylines"); | |
4177 if (!strcmp(fstr,"obeylines")) job=OBEYLINES; | |
4178 else if (!strcmp(fstr,"align")) job=ALIGN; | |
4179 else if (!strcmp(fstr,"skip")) job=SKIP; | |
4180 else if (!strcmp(fstr,"ragged")) job=RAGGED; | |
4181 else rx("bad argument for begintext: ",fstr); | |
4182 if (within_block && !do_this_tune) job=SKIP; | |
4183 process_textblock (fpin,fp,job); | |
4184 return; | |
4185 } | |
4186 | |
4187 if (!strcmp(w,"text") || !strcmp(w,"center")) { | |
4188 if (epsf && !within_block) return; | |
4189 if (within_block && !do_this_tune) return; | |
4190 output_music (fp); | |
4191 set_font (fp, cfmt.textfont, 0); | |
4192 ntxt=0; | |
4193 add_to_text_block (line+nch+1,1); | |
4194 if (!strcmp(w,"text")) | |
4195 write_text_block (fp,OBEYLINES); | |
4196 else | |
4197 write_text_block (fp,OBEYCENTER); | |
4198 buffer_eob (fp); | |
4199 } | |
4200 | |
4201 else if (!strcmp(w,"sep")) { | |
4202 if (within_block && !do_this_tune) return; | |
4203 output_music (fp); | |
4204 strcpy(unum1,""); | |
4205 strcpy(unum2,""); | |
4206 strcpy(unum3,""); | |
4207 sscanf(line,"%*s %s %s %s", unum1,unum2,unum3); | |
4208 g_unum(unum1,unum1,&h1); | |
4209 g_unum(unum2,unum2,&h2); | |
4210 g_unum(unum3,unum3,&len); | |
4211 if (h1*h1<0.00001) h1=0.5*CM; | |
4212 if (h2*h2<0.00001) h2=h1; | |
4213 if (len*len<0.0001) len=3.0*CM; | |
4214 bskip (h1); | |
4215 PUT2("%.1f %.1f sep0\n", lwidth/2-len/2, lwidth/2+len/2); | |
4216 bskip (h2); | |
4217 buffer_eob (fp); | |
4218 } | |
4219 | |
4220 else if (!strcmp(w,"vskip")) { | |
4221 if (within_block && !do_this_tune) return; | |
4222 output_music (fp); | |
4223 strcpy(unum1,""); | |
4224 sscanf(line,"%*s %s", unum1); | |
4225 g_unum(unum1,unum1,&h1); | |
4226 if (h1*h1<0.00001) h1=0.5*CM; | |
4227 bskip (h1); | |
4228 buffer_eob (fp); | |
4229 } | |
4230 | |
4231 else if (!strcmp(w,"newpage")) { | |
4232 if (within_block && !do_this_tune) return; | |
4233 output_music (fp); | |
4234 write_buffer (fp); | |
4235 use_buffer=0; | |
4236 write_pagebreak (fp); | |
4237 } | |
4238 | |
4239 else { | |
4240 if (within_block) { | |
4241 interpret_format_line (line,&cfmt); | |
4242 ops_into_fmt (&cfmt); | |
4243 | |
4244 } | |
4245 else { | |
4246 interpret_format_line (line,&dfmt); | |
4247 ops_into_fmt (&dfmt); | |
4248 cfmt=dfmt; | |
4249 } | |
4250 } | |
4251 | |
4252 | |
4253 } | |
4254 | |
4255 /* ----- check_selected ----- */ | |
4256 void check_selected(fp,xref_str,npat,pat,sel_all,search_field) | |
4257 FILE *fp; | |
4258 int npat,sel_all,search_field; | |
4259 char xref_str[],pat[][STRL1]; | |
4260 { | |
4261 | |
4262 if (!do_this_tune) { | |
4263 if (is_selected(xref_str,npat,pat,sel_all,search_field)) { | |
4264 do_this_tune=1; | |
4265 verbose=vb; | |
4266 clear_buffer (); | |
4267 /* set to 0 to permit staff breaks in a tune */ | |
4268 use_buffer=1; | |
4269 write_tunetop(fp); | |
4270 } | |
4271 } | |
4272 } | |
4273 | |
4274 | |
4275 /* ----- process_header: call at end of header ----- */ | |
4276 void process_header (fp,xref_str,npat,pat,sel_all,search_field) | |
4277 FILE *fp; | |
4278 int npat,sel_all,search_field; | |
4279 char xref_str[],pat[][STRL1]; | |
4280 { | |
4281 | |
4282 if ((vb>15) || ((verbose>10)&&within_block)) | |
4283 printf ("End of header.. process header data\n"); | |
4284 | |
4285 check_selected(fp,xref_str,npat,pat,sel_all,search_field); | |
4286 if (do_this_tune) { | |
4287 tunenum++; | |
4288 if (verbose>=3) | |
4289 printf ("---- start %d (%s) ----\n", xrefnum, info.title); | |
4290 fflush (stdout); | |
4291 set_keysig (info.key, &default_key, 1); | |
4292 halftones=get_halftones (default_key, transpose); | |
4293 set_transtab (halftones,&default_key); | |
4294 set_meter (info.meter,&default_meter); | |
4295 set_dlen (info.len, &default_meter); | |
4296 check_margin (cfmt.leftmargin); | |
4297 write_heading (fp); | |
4298 nvoice=0; | |
4299 init_parse_params (); | |
4300 default_meter.insert=1; | |
4301 mline=0; | |
4302 do_indent=do_meter=1; | |
4303 barinit=1; | |
4304 writenum=0; | |
4305 } | |
4306 within_tune=1; | |
4307 } | |
4308 | |
4309 /* ----- close_tune ----- */ | |
4310 void close_tune (fp) | |
4311 FILE *fp; | |
4312 { | |
4313 char fnm[81],finf[MAXINF]; | |
4314 FILE *feps; | |
4315 | |
4316 if (do_this_tune) { | |
4317 output_music (fp); | |
4318 put_words (fp); | |
4319 if (cfmt.writehistory) put_history (fp); | |
4320 if (epsf) { | |
4321 close_output_file (); | |
4322 if (choose_outname) { | |
4323 epsf_title (info.title, fnm); | |
4324 strcat (fnm,".eps"); | |
4325 } | |
4326 else { | |
4327 nepsf++; | |
4328 sprintf (fnm, "%s%03d.eps", outf, nepsf); | |
4329 } | |
4330 sprintf (finf, "%s (%d)", in_file[0], xrefnum); | |
4331 if ((feps = fopen (fnm,"w")) == NULL) | |
4332 rx ("Cannot open output file ", fnm); | |
4333 init_ps (feps, finf, 1, | |
4334 cfmt.leftmargin-5, posy+bposy-5, | |
4335 cfmt.leftmargin+cfmt.staffwidth+5, | |
4336 cfmt.pageheight-cfmt.topmargin); | |
4337 init_epsf (feps); | |
4338 write_buffer (feps); | |
4339 printf ("\n[%s] %s", fnm, info.title); | |
4340 close_epsf (feps); | |
4341 fclose (feps); | |
4342 in_page=0; | |
4343 init_pdims (); | |
4344 } | |
4345 else { | |
4346 buffer_eob (fp); | |
4347 write_buffer (fp); | |
4348 if ((verbose==0) && (tunenum%10==0)) printf ("."); | |
4349 if (verbose==2) printf ("%s - ", info.title); | |
4350 } | |
4351 verbose=0; | |
4352 } | |
4353 info=default_info; | |
4354 within_tune=within_block=do_this_tune=0; | |
4355 | |
4356 } | |
4357 | |
4358 | |
4359 /* ----- process_line ----- */ | |
4360 void process_line (fp,type,xref_str,npat,pat,sel_all,search_field) | |
4361 FILE *fp; | |
4362 int type,npat,sel_all,search_field; | |
4363 char xref_str[],pat[][STRL1]; | |
4364 { | |
4365 | |
4366 if ((vb>15) || ((verbose>10)&&within_block)) { | |
4367 printf ("process_line, type %d ", type); | |
4368 print_linetype(type); | |
4369 } | |
4370 | |
4371 switch (type) { | |
4372 | |
4373 case XREF: /* start of new block */ | |
4374 if (!epsf) write_buffer (fp); /* flush stuff left from %% lines */ | |
4375 if (within_block) printf ("\n+++ Last tune not closed properly\n"); | |
4376 get_default_info (); | |
4377 within_block = 1; | |
4378 within_tune = 0; | |
4379 do_this_tune = 0; | |
4380 numtitle=0; | |
4381 ntext=0; | |
4382 init_pdims(); | |
4383 cfmt=dfmt; | |
4384 break; | |
4385 | |
4386 case TITLE: | |
4387 if (!within_block) break; | |
4388 if (within_tune) { /* title within tune */ | |
4389 if (do_this_tune ) { | |
4390 output_music (fp); | |
4391 write_inside_title (fp); | |
4392 do_meter=do_indent=1; | |
4393 barinit=1; | |
4394 } | |
4395 } | |
4396 else | |
4397 check_selected(fp,xref_str,npat,pat,sel_all,search_field); | |
4398 break; | |
4399 | |
4400 case TEMPO: | |
4401 if (!within_block) break; | |
4402 if (within_tune) { /* tempo within tune */ | |
4403 if (do_this_tune ) { | |
4404 output_music (fp); | |
4405 write_inside_tempo(fp); | |
4406 } | |
4407 } | |
4408 else | |
4409 check_selected(fp,xref_str,npat,pat,sel_all,search_field); | |
4410 break; | |
4411 | |
4412 case KEY: | |
4413 if (!within_block) break; | |
4414 if (within_tune) { | |
4415 if (do_this_tune) handle_inside_field(type); | |
4416 } | |
4417 else { /* end of header.. start now */ | |
4418 /*| process_header (fp,xref_str,npat,pat,sel_all,search_field); |*/ | |
4419 } | |
4420 break; | |
4421 | |
4422 case METER: | |
4423 if (!within_block) break; | |
4424 if (do_this_tune && within_tune) handle_inside_field(type); | |
4425 break; | |
4426 | |
4427 case DLEN: | |
4428 if (!within_block) break; | |
4429 if (do_this_tune && within_tune) handle_inside_field(type); | |
4430 break; | |
4431 | |
4432 case PARTS: | |
4433 if (!within_block) break; | |
4434 if (do_this_tune && within_tune) { | |
4435 output_music (fp); | |
4436 write_parts(fp); | |
4437 } | |
4438 break; | |
4439 | |
4440 case VOICE: | |
4441 if (do_this_tune && within_block) { | |
4442 if (!within_tune) | |
4443 printf ("+++ Voice field not allowed in header: V:%s\n", lvoicei… | |
4444 else | |
4445 ivc=switch_voice (lvoiceid); | |
4446 } | |
4447 break; | |
4448 | |
4449 } | |
4450 } | |
4451 | |
4452 /* ----- process_file ----- */ | |
4453 void process_file (fpin,fpout,xref_str,npat,pat,sel_all,search_field) | |
4454 FILE *fpin,*fpout; | |
4455 int npat,sel_all,search_field; | |
4456 char xref_str[],pat[][STRL1]; | |
4457 { | |
4458 char line[BSIZE]; | |
4459 int type,nsym0; | |
4460 | |
4461 within_tune=within_block=do_this_tune=0; | |
4462 linenum=0; | |
4463 numtitle=0; | |
4464 reset_info (&default_info); | |
4465 info=default_info; | |
4466 verbose=0; | |
4467 if (vb>=20) db=3; | |
4468 if (vb>=25) db=5; | |
4469 | |
4470 type=read_line (fpin,line); | |
4471 | |
4472 for (;;) { | |
4473 | |
4474 /* header is completed at first MUSIC or VOICE line */ | |
4475 if ((type==MUSIC) || (type==VOICE)) { | |
4476 if (within_block && !within_tune) | |
4477 process_header (fpout,xref_str,npat,pat,sel_all,search_field); | |
4478 } | |
4479 | |
4480 /* tune terminates at BLANK or EOF */ | |
4481 if ((type==BLANK) || (type==E_O_F)) close_tune (fpout); | |
4482 if (type==E_O_F) break; | |
4483 | |
4484 if (type==PSCOMMENT) process_pscomment(fpin,fpout,line); | |
4485 if ((type==MUSIC) && do_this_tune) parse_music_line (line); | |
4486 process_line (fpout,type,xref_str,npat,pat,sel_all,search_field); | |
4487 type=read_line (fpin,line); | |
4488 } | |
4489 if (!epsf) { | |
4490 buffer_eob (fpout); | |
4491 write_buffer (fpout); | |
4492 } | |
4493 | |
4494 } | |
4495 | |
4496 |